authorgravatar for rb.lymn@gmail.comRobbie Lyman <rb.lymn@gmail.com> 2026-08-09 10:52:49-04:00
committergravatar for rb.lymn@gmail.comRobbie Lyman <rb.lymn@gmail.com> 2026-08-09 13:02:43-04:00
logcad75a7106cadd971f4cdc0ec4f3ee0fbe2adf09
tree21c6cdcc1cfc63135e851e929882170032744bae
parentccbfd60e32be0412ed12f7d3bfd979dfc5c69e94
parentcb7c6e391872d2922a688c77def805883b69eba8

fix(ArrayList): clarify pointer stability rules

This commit also makes `pointer_stability` a non default init. This was done initially to verify that methods like `toManaged` behave properly with respect to pointer stability, but does require changes outside of `array_list.zig`. Initialization with `init()` or `.empty` appears to be preferred enough that this is minimally breaking.

744 files changed, 31566 insertions(+), 20491 deletions(-)

.forgejo/workflows/ci.yaml+3-3
......@@ -153,7 +153,7 @@ jobs:
153153 fetch-depth: 0
154154 - name: Build and Test
155155 run: sh ci/s390x-linux-debug.sh
156 timeout-minutes: 420
156 timeout-minutes: 480
157157 s390x-linux-release:
158158 runs-on: [self-hosted, s390x-linux]
159159 steps:
......@@ -174,7 +174,7 @@ jobs:
174174 fetch-depth: 0
175175 - name: Build and Test
176176 run: sh ci/x86_64-freebsd-debug.sh
177 timeout-minutes: 120
177 timeout-minutes: 1440
178178 x86_64-freebsd-release:
179179 runs-on: [self-hosted, x86_64-freebsd]
180180 steps:
......@@ -184,7 +184,7 @@ jobs:
184184 fetch-depth: 0
185185 - name: Build and Test
186186 run: sh ci/x86_64-freebsd-release.sh
187 timeout-minutes: 120
187 timeout-minutes: 1440
188188
189189 x86_64-linux-debug:
190190 runs-on: [self-hosted, x86_64-linux]
CMakeLists.txt+8-13
......@@ -358,6 +358,8 @@ set(ZIG_STAGE2_SOURCES
358358 src/codegen/c/type/render_defs.zig
359359 src/codegen/llvm.zig
360360 src/codegen/llvm/bindings.zig
361 src/codegen/loongarch/abi.zig
362 src/codegen/s390x/abi.zig
361363 src/crash_report.zig
362364 src/dev.zig
363365 src/libs/freebsd.zig
......@@ -600,24 +602,17 @@ if(MSVC)
600602 set(ZIG2_COMPILE_FLAGS "/Od")
601603 set(ZIG2_LINK_FLAGS "/STACK:16777216 /FORCE:MULTIPLE")
602604else()
603 set(ZIG_WASM2C_COMPILE_FLAGS "-std=c99 -O2")
604 set(ZIG1_COMPILE_FLAGS "-std=c99 -Os -fno-strict-aliasing")
605 set(ZIG2_COMPILE_FLAGS "-std=c99 -O0 -fno-sanitize=undefined -fno-stack-protector -fno-strict-aliasing")
605 set(ZIG_WASM2C_COMPILE_FLAGS "-std=c99")
606 set(ZIG1_COMPILE_FLAGS "-std=c99 -Oz -fno-strict-aliasing")
607 set(ZIG2_COMPILE_FLAGS "-std=c99 -Oz -fno-sanitize=undefined -fno-stack-protector -fno-strict-aliasing")
608 if(CMAKE_C_COMPILER_ID STREQUAL "Clang" AND ZIG_HOST_TARGET_ARCH STREQUAL "s390x")
609 string(REPLACE -Oz -O0 ZIG2_COMPILE_FLAGS "${ZIG2_COMPILE_FLAGS}") # llvm 22 assertion failure
610 endif()
606611 # Must match the condition in build.zig.
607612 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)?$")
608613 set(ZIG1_COMPILE_FLAGS "${ZIG1_COMPILE_FLAGS} -ffunction-sections -fdata-sections")
609614 set(ZIG2_COMPILE_FLAGS "${ZIG2_COMPILE_FLAGS} -ffunction-sections -fdata-sections")
610615 endif()
611 if(APPLE)
612 set(ZIG2_LINK_FLAGS "-Wl,-stack_size,0x10000000")
613 elseif(MINGW)
614 set(ZIG2_LINK_FLAGS "-Wl,--stack,0x10000000")
615 # Solaris/illumos ld(1) does not provide a --stack-size option.
616 elseif(CMAKE_HOST_SOLARIS)
617 unset(ZIG2_LINK_FLAGS)
618 else()
619 set(ZIG2_LINK_FLAGS "-Wl,-z,stack-size=0x10000000")
620 endif()
621616 if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
622617 # Prevent GCC from miscompiling 'zig2.c'. See also 'GCC_BUG_119085_PRESENT' workaround details in 'bootstrap.c'.
623618 if (
bootstrap.c+2-2
......@@ -56,7 +56,7 @@ static void panic(const char *reason) {
5656 #define GCC_BUG_119085_PRESENT 0
5757#endif
5858
59#if defined(__WIN32__)
59#if defined(_WIN32)
6060#error TODO write the functionality for executing child process into this build script
6161#else
6262
......@@ -99,7 +99,7 @@ static void print_and_run(const char **argv) {
9999static const char *get_host_os(void) {
100100 const char *host_os = getenv("ZIG_HOST_TARGET_OS");
101101 if (host_os != NULL) return host_os;
102#if defined(__WIN32__)
102#if defined(_WIN32)
103103 return "windows";
104104#elif defined(__APPLE__)
105105 return "macos";
build.zig+11-11
......@@ -207,7 +207,7 @@ pub fn build(b: *std.Build) !void {
207207
208208 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: {
209209 if (strip == true) break :blk @as(u32, 0);
210 if (optimize != .Debug) break :blk 0;
210 if (optimize != .debug) break :blk 0;
211211 break :blk 4;
212212 };
213213
......@@ -256,7 +256,7 @@ pub fn build(b: *std.Build) !void {
256256 exe.root_module.link_libc = true;
257257 }
258258
259 const is_debug = optimize == .Debug;
259 const is_debug = optimize == .debug;
260260 const enable_debug_extensions = b.option(bool, "debug-extensions", "Enable commands and options useful for debugging the compiler") orelse is_debug;
261261 const enable_logging = b.option(bool, "log", "Enable debug logging with --debug-log") orelse is_debug;
262262
......@@ -403,8 +403,8 @@ pub fn build(b: *std.Build) !void {
403403 if (tracy) |tracy_dir| {
404404 const tracy_mod = b.createModule(.{
405405 .target = target,
406 // Always build Tracy in ReleaseFast so that it doesn't make Debug compiler builds unusable.
407 .optimize = .ReleaseFast,
406 // Always build Tracy in ReleaseFast so that it doesn't make -Odebug compiler builds unusable.
407 .optimize = .fast,
408408 .root_source_file = null,
409409 .link_libc = true,
410410 .link_libcpp = true,
......@@ -434,19 +434,19 @@ pub fn build(b: *std.Build) !void {
434434 var chosen_opt_modes_buf: [4]std.lang.OptimizeMode = undefined;
435435 var chosen_mode_index: usize = 0;
436436 if (!skip_debug) {
437 chosen_opt_modes_buf[chosen_mode_index] = .Debug;
437 chosen_opt_modes_buf[chosen_mode_index] = .debug;
438438 chosen_mode_index += 1;
439439 }
440440 if (!skip_release_safe) {
441 chosen_opt_modes_buf[chosen_mode_index] = .ReleaseSafe;
441 chosen_opt_modes_buf[chosen_mode_index] = .safe;
442442 chosen_mode_index += 1;
443443 }
444444 if (!skip_release_fast) {
445 chosen_opt_modes_buf[chosen_mode_index] = .ReleaseFast;
445 chosen_opt_modes_buf[chosen_mode_index] = .fast;
446446 chosen_mode_index += 1;
447447 }
448448 if (!skip_release_small) {
449 chosen_opt_modes_buf[chosen_mode_index] = .ReleaseSmall;
449 chosen_opt_modes_buf[chosen_mode_index] = .small;
450450 chosen_mode_index += 1;
451451 }
452452 const optimize_modes = chosen_opt_modes_buf[0..chosen_mode_index];
......@@ -622,7 +622,7 @@ pub fn build(b: *std.Build) !void {
622622 .use_llvm = use_llvm,
623623 .use_lld = use_llvm,
624624 .zig_lib_dir = b.path("lib"),
625 .max_rss = 2_700_000_000,
625 .max_rss = 3_000_000_000,
626626 });
627627 if (link_libc) {
628628 unit_tests.root_module.link_libc = true;
......@@ -763,9 +763,8 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
763763 .optimize = .ReleaseSmall,
764764 .target = b.resolveTargetQuery(std.Target.Query.parse(.{
765765 .arch_os_abi = "wasm32-wasi",
766 // * `extended_const` is not supported by the `wasm-opt` version in CI.
767766 // * `nontrapping_bulk_memory_len0` is supported by `wasm2c`.
768 .cpu_features = "baseline-extended_const+nontrapping_bulk_memory_len0",
767 .cpu_features = "baseline+nontrapping_bulk_memory_len0",
769768 }) catch unreachable),
770769 });
771770
......@@ -809,6 +808,7 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
809808 "-Oz",
810809 "--enable-bulk-memory",
811810 "--enable-mutable-globals",
811 "--enable-extended-const",
812812 "--enable-nontrapping-float-to-int",
813813 "--enable-sign-ext",
814814 });
ci/x86_64-freebsd-debug.sh+1-7
......@@ -46,13 +46,7 @@ export ZIG_LIB_DIR="$PWD/../lib"
4646stage3-debug/bin/zig build test docs \
4747 --maxrss ${ZSF_MAX_RSS:-0} \
4848 -Dstatic-llvm \
49 -Dskip-spirv \
50 -Dskip-wasm \
51 -Dskip-linux \
52 -Dskip-netbsd \
53 -Dskip-openbsd \
54 -Dskip-windows \
55 -Dskip-darwin \
49 -Dskip-non-native \
5650 --search-prefix "$PREFIX" \
5751 --test-timeout 2m
5852
ci/x86_64-freebsd-release.sh+1-7
......@@ -46,13 +46,7 @@ export ZIG_LIB_DIR="$PWD/../lib"
4646stage3-release/bin/zig build test docs \
4747 --maxrss ${ZSF_MAX_RSS:-0} \
4848 -Dstatic-llvm \
49 -Dskip-spirv \
50 -Dskip-wasm \
51 -Dskip-linux \
52 -Dskip-netbsd \
53 -Dskip-openbsd \
54 -Dskip-windows \
55 -Dskip-darwin \
49 -Dskip-non-native \
5650 --search-prefix "$PREFIX" \
5751 --test-timeout 2m
5852
ci/x86_64-linux-debug.sh+1-1
......@@ -44,7 +44,7 @@ ninja install
4444
4545# Must be done after zig cc is finished.
4646export ZIG_LIB_DIR="$PWD/../lib"
47export ZIG_DEBUG_MAKER=1
47export ZIG_DEBUG_CMD=1
4848
4949# simultaneously test building self-hosted without LLVM and with 32-bit arm
5050stage3-debug/bin/zig build \
doc/langref.html.in+6-2
......@@ -1119,6 +1119,10 @@
11191119 otherwise the optimizer figures out all the values at compile-time,
11201120 which operates in strict mode.</p>
11211121 {#code|float_mode_exe.zig#}
1122 {#shell_samp#}$ zig build-exe float_mode_exe.zig float_mode_obj.o -O fast
1123$ ./float_mode_exe
1124optimized = 0.001
1125strict = 0.0009765625{#end_shell_samp#}
11221126
11231127 {#see_also|@setFloatMode|Division by Zero#}
11241128 {#header_close#}
......@@ -5848,7 +5852,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
58485852 {#header_open|@Union#}
58495853 <pre>{#syntax#}@Union(
58505854 comptime layout: std.lang.Type.ContainerLayout,
5851 /// Either the integer tag type, or the integer backing type, depending on `layout`.
5855 /// Either the enum tag type, or the integer backing type, depending on `layout`.
58525856 comptime ArgType: ?type,
58535857 comptime field_names: []const []const u8,
58545858 comptime field_types: *const [field_names.len]type,
......@@ -7499,7 +7503,7 @@ fn readU32Be() u32 {}
74997503 <pre>{#syntax#}errdefer{#endsyntax#}</pre>
75007504 </th>
75017505 <td>
7502 {#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.
7506 {#syntax#}errdefer{#endsyntax#} will execute an expression when control flow leaves the current block if the function returns an error.
75037507 <ul>
75047508 <li>See also {#link|errdefer#}</li>
75057509 </ul>
doc/langref/test_packed_structs.zig-1
......@@ -1,5 +1,4 @@
11const std = @import("std");
2const native_endian = @import("builtin").target.cpu.arch.endian();
32const expectEqual = std.testing.expectEqual;
43
54const Full = packed struct {
lib/build-web/time_report.zig+3-3
......@@ -84,7 +84,7 @@ pub fn compileResultMessage(msg_bytes: []u8) error{ OutOfMemory, WriteFailed }!v
8484 defer gpa.free(slowest_decls);
8585
8686 for (slowest_files) |*file_out| {
87 const i = std.mem.indexOfScalar(u8, trailing, 0) orelse @panic("malformed CompileResult message");
87 const i = std.mem.findScalar(u8, trailing, 0) orelse @panic("malformed CompileResult message");
8888 file_out.* = .{
8989 .name = trailing[0..i],
9090 .ns_sema = 0,
......@@ -95,7 +95,7 @@ pub fn compileResultMessage(msg_bytes: []u8) error{ OutOfMemory, WriteFailed }!v
9595 }
9696
9797 for (slowest_decls) |*decl_out| {
98 const i = std.mem.indexOfScalar(u8, trailing, 0) orelse @panic("malformed CompileResult message");
98 const i = std.mem.findScalar(u8, trailing, 0) orelse @panic("malformed CompileResult message");
9999 const file_idx = std.mem.readInt(u32, trailing[i..][1..5], .little);
100100 const sema_count = std.mem.readInt(u32, trailing[i..][5..9], .little);
101101 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 {
258258 defer table_html.deinit(gpa);
259259
260260 for (durations) |test_ns| {
261 const test_name_len = std.mem.indexOfScalar(u8, trailing[offset..], 0) orelse @panic("malformed RunTestResult message");
261 const test_name_len = std.mem.findScalar(u8, trailing[offset..], 0) orelse @panic("malformed RunTestResult message");
262262 const test_name = trailing[offset..][0..test_name_len];
263263 offset += test_name_len + 1;
264264 try table_html.print(gpa, "<tr><th scope=\"row\"><code>{f}</code></th>", .{fmtEscapeHtml(test_name)});
lib/c/malloc.zig+2-2
......@@ -59,8 +59,8 @@ const Header = packed struct(u64) {
5959 }
6060
6161 const safety = switch (builtin.mode) {
62 .Debug, .ReleaseSafe => true,
63 .ReleaseFast, .ReleaseSmall => false,
62 .debug, .safe => true,
63 .fast, .small => false,
6464 };
6565 const max_addr_bits = switch (safety) {
6666 true => 48, // Ensures space for Canary bits.
lib/compiler/Maker.zig+339-78
......@@ -11,6 +11,7 @@ const File = std.Io.File;
1111const Io = std.Io;
1212const Dir = std.Io.Dir;
1313const Path = std.Build.Cache.Path;
14const Reader = std.Io.Reader;
1415const Writer = std.Io.Writer;
1516const assert = std.debug.assert;
1617const fatal = std.process.fatal;
......@@ -19,6 +20,8 @@ const log = std.log;
1920const mem = std.mem;
2021const process = std.process;
2122const Color = std.zig.Color;
23const Client = std.zig.Client;
24const Server = std.zig.Server;
2225const EnvVar = std.zig.EnvVar;
2326const default_local_zig_cache_basename = std.zig.default_local_zig_cache_basename;
2427const stringToEnum = std.meta.stringToEnum;
......@@ -51,10 +54,14 @@ max_rss_mutex: Io.Mutex,
5154skip_oom_steps: bool,
5255unit_test_timeout_ns: ?u64,
5356watch: bool,
57protocol_server: ?*AvoidableServer,
58protocol_server_mutex: Io.Mutex,
5459web_server: ?*AvoidableWebServer,
5560/// Allocated into `gpa`.
5661memory_blocked_steps: std.ArrayList(Configuration.Step.Index),
5762/// Allocated into `gpa`.
63initial_steps: std.array_hash_map.Auto(Configuration.Step.Index, void),
64/// Allocated into `gpa`.
5865step_stack: std.array_hash_map.Auto(Configuration.Step.Index, void),
5966pkg_config: PkgConfig,
6067
......@@ -67,12 +74,13 @@ var stdio_buffer_allocation: [256]u8 = undefined;
6774var stdout_writer_allocation: Io.File.Writer = undefined;
6875var debug_maker_leaks: bool = false;
6976
77const AvoidableServer = if (builtin.single_threaded) void else Server;
7078const AvoidableWebServer = if (builtin.single_threaded) void else WebServer;
7179
72const is_debug_mode = builtin.mode == .Debug;
80const is_debug_mode = builtin.mode == .debug;
7381const use_safe_allocator = switch (builtin.mode) {
74 .Debug, .ReleaseSafe => true,
75 .ReleaseFast, .ReleaseSmall => false,
82 .debug, .safe => true,
83 .fast, .small => false,
7684};
7785
7886const InstallPaths = struct {
......@@ -216,6 +224,7 @@ pub fn main(init: process.Init.Minimal) !void {
216224 var watch = false;
217225 var fuzz: ?Fuzz.Mode = null;
218226 var debounce_interval_ms: u16 = 50;
227 var listen: bool = false;
219228 var webui_listen: ?Io.net.IpAddress = null;
220229 var debug_pkg_config = false;
221230 var run_args: ?[]const []const u8 = null;
......@@ -242,6 +251,12 @@ pub fn main(init: process.Init.Minimal) !void {
242251 }
243252 }
244253
254 if (EnvVar.ZIG_BUILD_SUMMARY.get(&graph.environ_map)) |str| {
255 if (stringToEnum(Summary, str)) |value| {
256 summary = value;
257 }
258 }
259
245260 try configure_argv.ensureUnusedCapacity(arena, 16);
246261 try cached_passthru_configure.ensureUnusedCapacity(arena, 16);
247262
......@@ -416,6 +431,8 @@ pub fn main(init: process.Init.Minimal) !void {
416431 next_arg, err,
417432 });
418433 };
434 } else if (mem.eql(u8, arg, "--listen=-")) {
435 listen = true;
419436 } else if (mem.eql(u8, arg, "--webui")) {
420437 if (webui_listen == null) webui_listen = .{ .ip6 = .loopback(0) };
421438 } else if (mem.startsWith(u8, arg, "--webui=")) {
......@@ -553,7 +570,7 @@ pub fn main(init: process.Init.Minimal) !void {
553570 }
554571
555572 const early_exit_mode = fetch_only or help_menu or steps_menu or print_configuration != .none;
556 const server_mode = !early_exit_mode and (watch or webui_listen != null or fuzz != null);
573 const server_mode = !early_exit_mode and (watch or webui_listen != null or fuzz != null or listen);
557574
558575 process.raiseFileDescriptorLimit();
559576
......@@ -631,20 +648,31 @@ pub fn main(init: process.Init.Minimal) !void {
631648 .sub_path = "zig-out",
632649 };
633650
634 const install_lib_path: Path = if (override_lib_dir) |cwd_relative| .{
635 .root_dir = .cwd(),
636 .sub_path = cwd_relative,
637 } else try install_prefix_path.join(arena, "lib");
651 // These three overrides are meant to be relative to the install prefix,
652 // not current working directory, unless absolute paths are used.
653 const install_lib_path: Path = if (override_lib_dir) |lib_dir|
654 if (Dir.path.isAbsolute(lib_dir)) .{
655 .root_dir = .cwd(),
656 .sub_path = lib_dir,
657 } else try install_prefix_path.join(arena, lib_dir)
658 else
659 try install_prefix_path.join(arena, "lib");
638660
639 const install_bin_path: Path = if (override_bin_dir) |cwd_relative| .{
640 .root_dir = .cwd(),
641 .sub_path = cwd_relative,
642 } else try install_prefix_path.join(arena, "bin");
661 const install_bin_path: Path = if (override_bin_dir) |bin_dir|
662 if (Dir.path.isAbsolute(bin_dir)) .{
663 .root_dir = .cwd(),
664 .sub_path = bin_dir,
665 } else try install_prefix_path.join(arena, bin_dir)
666 else
667 try install_prefix_path.join(arena, "bin");
643668
644 const install_include_path: Path = if (override_include_dir) |cwd_relative| .{
645 .root_dir = .cwd(),
646 .sub_path = cwd_relative,
647 } else try install_prefix_path.join(arena, "include");
669 const install_include_path: Path = if (override_include_dir) |include_dir|
670 if (Dir.path.isAbsolute(include_dir)) .{
671 .root_dir = .cwd(),
672 .sub_path = include_dir,
673 } else try install_prefix_path.join(arena, include_dir)
674 else
675 try install_prefix_path.join(arena, "include");
648676
649677 const now = Io.Clock.Timestamp.now(io, .awake);
650678
......@@ -661,6 +689,25 @@ pub fn main(init: process.Init.Minimal) !void {
661689 break :ws &web_server_allocation;
662690 } else null;
663691
692 var stdin_buffer: [256]u8 = undefined;
693 var stdout_buffer: [256]u8 = undefined;
694 var stdin_reader = Io.File.stdin().reader(io, &stdin_buffer);
695 var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer);
696
697 var protocol_server_allocation: AvoidableServer = undefined;
698 const protocol_server: ?*AvoidableServer = if (listen) s: {
699 if (builtin.single_threaded) fatal("--listen is not yet supported on single-threaded hosts", .{});
700 if (watch) fatal("using '--watch' and '--listen' together is not supported", .{});
701 if (fuzz != null) fatal("using '--fuzz' and '--listen' together is not supported", .{});
702 if (step_names.items.len > 0) fatal("build steps must be provided over the protocol instead of using CLI arguments", .{});
703 protocol_server_allocation = .{
704 .in = &stdin_reader.interface,
705 .out = &stdout_writer.interface,
706 };
707 try serveBSPHandshake(&protocol_server_allocation);
708 break :s &protocol_server_allocation;
709 } else null;
710
664711 while (true) {
665712 // If this fails, we can still start the server and wait for user
666713 // to request a rebuild. If it returns error.FailedButCacheIntact
......@@ -731,16 +778,25 @@ pub fn main(init: process.Init.Minimal) !void {
731778
732779 .watch = watch,
733780 .web_server = web_server,
781 .protocol_server = protocol_server,
782 .protocol_server_mutex = .init,
734783 .memory_blocked_steps = .empty,
784 .initial_steps = .empty,
735785 .step_stack = .empty,
736786 .pkg_config = .{ .debug = debug_pkg_config },
737787
738788 .error_style = error_style,
739789 .multiline_errors = multiline_errors,
740 .summary = summary orelse if (watch or webui_listen != null) .new else .failures,
790 .summary = summary orelse if (listen)
791 .none
792 else if (watch or webui_listen != null)
793 .new
794 else
795 .failures,
741796 };
742797 defer {
743798 maker.memory_blocked_steps.deinit(gpa);
799 maker.initial_steps.deinit(gpa);
744800 maker.step_stack.deinit(gpa);
745801 }
746802
......@@ -749,7 +805,91 @@ pub fn main(init: process.Init.Minimal) !void {
749805 maker.max_rss_is_default = true;
750806 }
751807
752 maker.prepare(step_names.items) catch |err| switch (err) {
808 if (protocol_server) |s| {
809 try s.serveStringMessage(.bsp_configuration, try arena.print("{f}", .{scanned_config.path}));
810
811 var w: ?Watch = null;
812
813 const Event = union(enum) {
814 message: Reader.Error!Client.Message.Header,
815 fs_event: if (Watch.have_impl) @typeInfo(@TypeOf(Watch.wait)).@"fn".return_type.? else noreturn,
816 };
817
818 var select_buffer: [2]Event = undefined;
819 var select: Io.Select(Event) = .init(io, &select_buffer);
820 defer select.cancelDiscard();
821
822 try select.concurrent(.message, Server.receiveMessage, .{s});
823
824 var in_debounce = false;
825 loop: switch (try select.await()) {
826 .message => |payload| {
827 const header: Client.Message.Header = try payload;
828 switch (header.tag) {
829 .exit => {
830 cleanExit(io, &scanned_config);
831 process.exit(0);
832 },
833 .bsp_build_steps => {
834 // Cancel existing file watching
835 select.cancelDiscard();
836 in_debounce = false;
837
838 const body = try s.in.takeStruct(Client.Message.BuildSteps, .little);
839 const steps = try s.in.readSliceEndianAlloc(gpa, Configuration.Step.Index, body.step_count, .little);
840 defer gpa.free(steps);
841 if (body.flags.watch and !Watch.have_impl) fatal("file watching is unavailable", .{});
842
843 try select.concurrent(.message, Server.receiveMessage, .{s});
844
845 maker.watch = body.flags.watch;
846 maker.prepare(steps) catch |err| switch (err) {
847 error.DependencyLoopDetected, error.InsufficientMemory => {
848 // TODO handle DependencyLoopDetected as error.FailedButCacheIntact
849 // and handle InsufficientMemory as error.AlreadyReported
850 _ = io.lockStderr(&.{}, graph.stderr_mode) catch {};
851 process.exit(1);
852 },
853 else => |e| return e,
854 };
855
856 try maker.makeSteps(main_progress_node, null);
857
858 if (body.flags.watch) {
859 if (!Watch.have_impl) unreachable;
860 if (w == null) w = try .init(&maker);
861
862 try w.?.update(maker.step_stack.keys());
863 try select.concurrent(.fs_event, Watch.wait, .{ &w.?, if (in_debounce) .{ .ms = debounce_interval_ms } else .none });
864 }
865
866 continue :loop try select.await();
867 },
868 else => fatal("unsupported message: {t}", .{header.tag}),
869 }
870 },
871 .fs_event => |payload| {
872 if (!Watch.have_impl) unreachable;
873 switch (try payload) {
874 .timeout => {
875 assert(in_debounce);
876 markFailedStepsDirty(&maker);
877 try maker.makeSteps(main_progress_node, null);
878 in_debounce = false;
879 },
880 .dirty => in_debounce = true,
881 .clean => {},
882 }
883 try select.concurrent(.fs_event, Watch.wait, .{ &w.?, if (in_debounce) .{ .ms = debounce_interval_ms } else .none });
884 continue :loop try select.await();
885 },
886 }
887 }
888
889 const initial_steps = try maker.resolveTopLevelSteps(step_names.items);
890 defer gpa.free(initial_steps);
891
892 maker.prepare(initial_steps) catch |err| switch (err) {
753893 error.DependencyLoopDetected, error.InsufficientMemory => {
754894 // TODO handle DependencyLoopDetected as error.FailedButCacheIntact
755895 // and handle InsufficientMemory as error.AlreadyReported
......@@ -774,18 +914,7 @@ pub fn main(init: process.Init.Minimal) !void {
774914 error.WriteFailed => return stderr.file_writer.err.?,
775915 };
776916 }) {
777 if (web_server) |ws| ws.startBuild();
778
779 try maker.makeStepNames(step_names.items, main_progress_node, fuzz);
780
781 if (web_server) |ws| {
782 if (fuzz) |mode| if (mode != .forever) fatal(
783 "error: limited fuzzing is not implemented yet for --webui",
784 .{},
785 );
786
787 ws.finishBuild(.{ .fuzz = fuzz != null });
788 }
917 try maker.makeSteps(main_progress_node, fuzz);
789918
790919 if (web_server) |ws| {
791920 const c = &scanned_config.configuration;
......@@ -850,6 +979,9 @@ pub fn main(init: process.Init.Minimal) !void {
850979 _ = io.lockStderr(&.{}, graph.stderr_mode) catch {};
851980 process.exit(1);
852981 }
982 if (protocol_server != null) {
983 fatal("(zig build system) TODO send error messages to client when build.zig compilation fails", .{});
984 }
853985 if (watch and can_fs_watch) {
854986 fatal("(zig build system) TODO set up fs watching even when build.zig compilation fails", .{});
855987 } else {
......@@ -1330,7 +1462,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {
13301462 if (config_man) |man| for (configuration.path_deps) |path_dep| {
13311463 switch (path_dep.flags.mode) {
13321464 .directory => {}, // TODO
1333 .contents => try man.addPathPost(confPathDepToCachePath(graph, &configuration, path_dep)),
1465 .contents => try man.addPathPost(try confPathDepToCachePath(arena, graph, &configuration, path_dep)),
13341466 .metadata => {}, // TODO
13351467 }
13361468 };
......@@ -1433,7 +1565,6 @@ fn cmdFetch(gpa: Allocator, graph: *Graph, args: []const []const u8) !void {
14331565
14341566 const color: Color = Color.settingFromEnvironment(environ_map);
14351567 var opt_path_or_url: ?[]const u8 = null;
1436 var override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map);
14371568 var override_local_cache_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_CACHE_DIR.get(environ_map);
14381569 var override_pkg_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_PKG_DIR.get(environ_map);
14391570 var debug_hash: bool = false;
......@@ -1449,8 +1580,6 @@ fn cmdFetch(gpa: Allocator, graph: *Graph, args: []const []const u8) !void {
14491580 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
14501581 try Io.File.stdout().writeStreamingAll(io, usage_fetch);
14511582 return process.cleanExit(io);
1452 } else if (mem.eql(u8, arg, "--global-cache-dir")) {
1453 override_global_cache_dir = nextArgOrFatal(args, &arg_i);
14541583 } else if (mem.eql(u8, arg, "--cache-dir")) {
14551584 override_local_cache_dir = nextArgOrFatal(args, &arg_i);
14561585 } else if (mem.eql(u8, arg, "--pkg-dir")) {
......@@ -1730,7 +1859,6 @@ const usage_fetch =
17301859 \\
17311860 \\Options:
17321861 \\ -h, --help Print this help and exit
1733 \\ --global-cache-dir [path] Override path to global Zig cache directory
17341862 \\ --cache-dir [path] Override path to local cache directory
17351863 \\ --pkg-dir [path] Override path to local package directory
17361864 \\ --debug-hash Print verbose hash information to stdout
......@@ -1991,7 +2119,7 @@ fn markFailedStepsDirty(maker: *Maker) void {
19912119 for (all_steps) |step_index| {
19922120 const step = maker.stepByIndex(step_index);
19932121 switch (step.state) {
1994 .dependency_failure, .failure, .skipped => _ = maker.invalidateResult(step),
2122 .dependency_failure, .dependency_skipped, .failure, .skipped => _ = maker.invalidateResult(step),
19952123 else => continue,
19962124 }
19972125 }
......@@ -2020,11 +2148,37 @@ pub fn stepByIndex(maker: *const Maker, i: Configuration.Step.Index) *Step {
20202148 return &maker.steps[@backingInt(i)];
20212149}
20222150
2023fn prepare(maker: *Maker, step_names: []const []const u8) !void {
2151fn resolveTopLevelSteps(maker: *Maker, step_names: []const []const u8) ![]const Configuration.Step.Index {
2152 const gpa = maker.gpa;
2153 const c = &maker.scanned_config.configuration;
2154
2155 if (step_names.len == 0) {
2156 return try gpa.dupe(Configuration.Step.Index, &.{c.default_step});
2157 }
2158
2159 var result: std.array_hash_map.Auto(Configuration.Step.Index, void) = .empty;
2160 defer result.deinit(gpa);
2161
2162 try result.ensureTotalCapacity(gpa, step_names.len);
2163
2164 for (0..step_names.len) |i| {
2165 const step_name = step_names[step_names.len - i - 1];
2166 const s = maker.scanned_config.top_level_steps.get(step_name) orelse {
2167 log.info("to list available steps: zig build -l", .{});
2168 fatal("no such step: {s}", .{step_name});
2169 };
2170 result.putAssumeCapacity(s, {});
2171 }
2172
2173 return try gpa.dupe(Configuration.Step.Index, result.keys());
2174}
2175
2176fn prepare(maker: *Maker, step_indices: []const Configuration.Step.Index) !void {
20242177 const gpa = maker.gpa;
20252178 const graph = maker.graph;
20262179 const arena = graph.arena;
20272180 const seed: u32 = graph.random_seed;
2181 const initial_steps = &maker.initial_steps;
20282182 const step_stack = &maker.step_stack;
20292183 const c = &maker.scanned_config.configuration;
20302184
......@@ -2033,18 +2187,15 @@ fn prepare(maker: *Maker, step_names: []const []const u8) !void {
20332187 step.* = .{ .extended = .init(step_index.ptr(c).flags(c).tag) };
20342188 }
20352189
2036 if (step_names.len == 0) {
2037 try step_stack.put(gpa, c.default_step, {});
2038 } else {
2039 try step_stack.ensureUnusedCapacity(gpa, step_names.len);
2040 for (0..step_names.len) |i| {
2041 const step_name = step_names[step_names.len - i - 1];
2042 const s = maker.scanned_config.top_level_steps.get(step_name) orelse {
2043 log.info("to list available steps: zig build -l", .{});
2044 fatal("no such step: {s}", .{step_name});
2045 };
2046 step_stack.putAssumeCapacity(s, {});
2047 }
2190 try initial_steps.ensureUnusedCapacity(gpa, step_indices.len);
2191 try step_stack.ensureUnusedCapacity(gpa, step_indices.len);
2192
2193 initial_steps.clearRetainingCapacity();
2194 step_stack.clearRetainingCapacity();
2195
2196 for (step_indices) |step| {
2197 initial_steps.putAssumeCapacity(step, {});
2198 step_stack.putAssumeCapacity(step, {});
20482199 }
20492200
20502201 const starting_steps = try arena.dupe(Configuration.Step.Index, step_stack.keys());
......@@ -2085,6 +2236,7 @@ fn prepare(maker: *Maker, step_names: []const []const u8) !void {
20852236 }
20862237 }
20872238 if (any_problems) {
2239 log.info("use --skip-oom-steps to proceed, skipping memory limited steps", .{});
20882240 if (maker.max_rss_is_default) {
20892241 log.info("use --maxrss {d} to proceed, risking system memory exhaustion", .{max_needed});
20902242 }
......@@ -2093,9 +2245,8 @@ fn prepare(maker: *Maker, step_names: []const []const u8) !void {
20932245 }
20942246}
20952247
2096fn makeStepNames(
2248fn makeSteps(
20972249 maker: *Maker,
2098 step_names: []const []const u8,
20992250 parent_progress_node: std.Progress.Node,
21002251 fuzz: ?Fuzz.Mode,
21012252) !void {
......@@ -2106,6 +2257,12 @@ fn makeStepNames(
21062257 const top_level_steps = &maker.scanned_config.top_level_steps;
21072258 const c = &maker.scanned_config.configuration;
21082259
2260 if (maker.web_server) |ws| ws.startBuild();
2261
2262 if (maker.protocol_server) |s| {
2263 try s.serveBodylessMessage(.bsp_build_started);
2264 }
2265
21092266 {
21102267 // Collect the initial set of tasks (those with no outstanding dependencies) into a buffer,
21112268 // then spawn them. The buffer is so that we don't race with `makeStep` and end up thinking
......@@ -2131,6 +2288,19 @@ fn makeStepNames(
21312288 try group.await(io);
21322289 }
21332290
2291 if (maker.web_server) |ws| {
2292 if (fuzz) |mode| if (mode != .forever) fatal(
2293 "error: limited fuzzing is not implemented yet for --webui",
2294 .{},
2295 );
2296
2297 ws.finishBuild(.{ .fuzz = fuzz != null });
2298 }
2299
2300 if (maker.protocol_server) |s| {
2301 try s.serveBodylessMessage(.bsp_build_completed);
2302 }
2303
21342304 assert(maker.memory_blocked_steps.items.len == 0);
21352305
21362306 var test_pass_count: usize = 0;
......@@ -2164,7 +2334,7 @@ fn makeStepNames(
21642334 .precheck_unstarted => unreachable,
21652335 .precheck_started => unreachable,
21662336 .precheck_done => unreachable,
2167 .dependency_failure => pending_count += 1,
2337 .dependency_failure, .dependency_skipped => pending_count += 1,
21682338 .success => success_count += 1,
21692339 .skipped, .skipped_oom => skipped_count += 1,
21702340 .failure => {
......@@ -2283,7 +2453,7 @@ fn makeStepNames(
22832453 defer step_stack_copy.deinit(gpa);
22842454
22852455 var print_node: PrintNode = .{ .parent = null };
2286 if (step_names.len == 0) {
2456 if (maker.initial_steps.count() == 0) {
22872457 print_node.last = true;
22882458 printTreeStep(maker, c.default_step, t, &print_node, &step_stack_copy) catch |err| switch (err) {
22892459 error.Canceled => |e| return e,
......@@ -2291,10 +2461,10 @@ fn makeStepNames(
22912461 };
22922462 } else {
22932463 const last_index = if (maker.summary == .all) top_level_steps.count() else blk: {
2294 var i: usize = step_names.len;
2464 var i: usize = maker.initial_steps.count();
22952465 while (i > 0) {
22962466 i -= 1;
2297 const step_index = top_level_steps.get(step_names[i]).?;
2467 const step_index = maker.initial_steps.keys()[i];
22982468 const step = maker.stepByIndex(step_index);
22992469 const found = switch (maker.summary) {
23002470 .all, .line, .none => unreachable,
......@@ -2305,8 +2475,7 @@ fn makeStepNames(
23052475 }
23062476 break :blk top_level_steps.count();
23072477 };
2308 for (step_names, 0..) |step_name, i| {
2309 const step_index = top_level_steps.get(step_name).?;
2478 for (maker.initial_steps.keys(), 0..) |step_index, i| {
23102479 print_node.last = i + 1 == last_index;
23112480 printTreeStep(maker, step_index, t, &print_node, &step_stack_copy) catch |err| switch (err) {
23122481 error.Canceled => |e| return e,
......@@ -2317,7 +2486,7 @@ fn makeStepNames(
23172486 w.writeByte('\n') catch {};
23182487 }
23192488
2320 if (maker.watch or maker.web_server != null) return;
2489 if (maker.watch or maker.web_server != null or maker.protocol_server != null) return;
23212490
23222491 const code: u8 = code: {
23232492 if (failure_count == 0) break :code 0; // success
......@@ -2392,6 +2561,15 @@ fn makeStep(
23922561 defer step_prog_node.end();
23932562
23942563 if (maker.web_server) |ws| ws.updateStepStatus(step_index, .wip);
2564 if (maker.protocol_server) |s| {
2565 maker.protocol_server_mutex.lockUncancelable(io);
2566 defer maker.protocol_server_mutex.unlock(io);
2567
2568 s.serveU32Message(
2569 .bsp_step_started,
2570 @backingInt(step_index),
2571 ) catch @panic("TODO propagate error when failing to send protocol message");
2572 }
23952573
23962574 const new_state: Step.State = for (deps) |dep_index| {
23972575 const dep_make_step = maker.stepByIndex(dep_index);
......@@ -2402,10 +2580,14 @@ fn makeStep(
24022580
24032581 .failure,
24042582 .dependency_failure,
2405 .skipped_oom,
24062583 => break .dependency_failure,
24072584
2408 .success, .skipped => {},
2585 .dependency_skipped,
2586 .skipped_oom,
2587 .skipped,
2588 => break .dependency_skipped,
2589
2590 .success => {},
24092591 }
24102592 } else if (Step.make(step_index, maker, step_prog_node)) state: {
24112593 break :state .success;
......@@ -2417,25 +2599,46 @@ fn makeStep(
24172599
24182600 @atomicStore(Step.State, &make_step.state, new_state, .monotonic);
24192601
2420 switch (new_state) {
2602 const success = switch (new_state) {
24212603 .precheck_unstarted => unreachable,
24222604 .precheck_started => unreachable,
24232605 .precheck_done => unreachable,
24242606
24252607 .failure,
24262608 .dependency_failure,
2609 .dependency_skipped,
24272610 .skipped_oom,
2428 => {
2429 if (maker.web_server) |ws| ws.updateStepStatus(step_index, .failure);
2430 std.Progress.setStatus(.failure_working);
2431 },
2611 .skipped,
2612 => false,
24322613
24332614 .success,
2434 .skipped,
2435 => {
2436 if (maker.web_server) |ws| ws.updateStepStatus(step_index, .success);
2437 },
2615 => true,
2616 };
2617
2618 if (maker.web_server) |ws| {
2619 ws.updateStepStatus(step_index, if (success) .success else .failure);
24382620 }
2621 if (maker.protocol_server != null) {
2622 maker.protocol_server_mutex.lockUncancelable(io);
2623 defer maker.protocol_server_mutex.unlock(io);
2624
2625 const status: Server.Message.BuildStepCompleted.Status = switch (new_state) {
2626 .precheck_unstarted => unreachable,
2627 .precheck_started => unreachable,
2628 .precheck_done => unreachable,
2629 .success => .success,
2630 .failure, .dependency_failure => .failure,
2631 .dependency_skipped, .skipped => .skipped,
2632 .skipped_oom => .skipped_oom,
2633 };
2634 serveBuildStepCompleted(
2635 maker,
2636 step_index,
2637 status,
2638 ) catch |err| std.debug.panic("TODO propagate error when failing to send protocol message: {t}", .{err});
2639 }
2640
2641 if (!success) std.Progress.setStatus(.failure_working);
24392642 }
24402643
24412644 // No matter the result, we want to display error/warning messages.
......@@ -2468,7 +2671,7 @@ fn makeStep(
24682671 maker.available_rss += max_rss;
24692672 dispatch_set.ensureUnusedCapacity(gpa, maker.memory_blocked_steps.items.len) catch
24702673 @panic("TODO eliminate memory allocation here");
2471 while (maker.memory_blocked_steps.getLast()) |candidate_index| {
2674 while (maker.memory_blocked_steps.last()) |candidate_index| {
24722675 const candidate_max_rss = candidate_index.ptr(c).max_rss.toBytes();
24732676 if (maker.available_rss < candidate_max_rss) break;
24742677 assert(maker.memory_blocked_steps.pop() == candidate_index);
......@@ -2579,6 +2782,12 @@ fn printStepStatus(maker: *Maker, step_index: Configuration.Step.Index, stderr:
25792782 try stderr.setColor(.reset);
25802783 },
25812784
2785 .dependency_skipped => {
2786 try stderr.setColor(.dim);
2787 try writer.writeAll(" transitive skip\n");
2788 try stderr.setColor(.reset);
2789 },
2790
25822791 .success => {
25832792 try stderr.setColor(.green);
25842793 if (s.result_cached) {
......@@ -2825,6 +3034,7 @@ fn constructGraphAndCheckForDependencyLoop(
28253034
28263035 // These don't happen until we actually run the step graph.
28273036 .dependency_failure => unreachable,
3037 .dependency_skipped => unreachable,
28283038 .success => unreachable,
28293039 .failure => unreachable,
28303040 .skipped => unreachable,
......@@ -2912,7 +3122,7 @@ pub fn printErrorMessages(
29123122 try stderr.setColor(.red);
29133123 try writer.writeAll("error:");
29143124 try stderr.setColor(.reset);
2915 if (std.mem.indexOfScalar(u8, msg, '\n') == null) {
3125 if (std.mem.findScalar(u8, msg, '\n') == null) {
29163126 try writer.print(" {s}\n", .{msg});
29173127 } else switch (multiline_errors) {
29183128 .indent => {
......@@ -2990,6 +3200,50 @@ fn cleanTmpFiles(maker: *Maker, steps: []const Configuration.Step.Index) void {
29903200 }
29913201}
29923202
3203fn serveBSPHandshake(s: *const std.zig.Server) !void {
3204 const handshake_header: Server.Message.Handshake = .{
3205 .version = Server.build_system_version,
3206 .flags = .{
3207 .file_system_watch_supported = Watch.have_impl,
3208 },
3209 };
3210 try s.serveMessageHeader(.{
3211 .tag = .bsp_handshake,
3212 .bytes_len = @sizeOf(Server.Message.Handshake),
3213 });
3214 try s.out.writeStruct(handshake_header, .little);
3215 try s.out.flush();
3216}
3217
3218fn serveBuildStepCompleted(
3219 maker: *Maker,
3220 step_index: Configuration.Step.Index,
3221 status: Server.Message.BuildStepCompleted.Status,
3222) !void {
3223 const s: *Server = maker.protocol_server.?;
3224 const step = maker.stepByIndex(step_index);
3225 const error_bundle = step.result_error_bundle;
3226
3227 const body: Server.Message.BuildStepCompleted = .{
3228 .step_index = step_index,
3229 .status = status,
3230 .error_bundle = .{
3231 .extra_len = @intCast(error_bundle.extra.len),
3232 .string_bytes_len = @intCast(error_bundle.string_bytes.len),
3233 },
3234 };
3235 const eb_bytes_len = @sizeOf(u32) * error_bundle.extra.len + error_bundle.string_bytes.len;
3236 const bytes_len = @sizeOf(Server.Message.BuildStepCompleted) + eb_bytes_len;
3237 try s.serveMessageHeader(.{
3238 .tag = .bsp_step_completed,
3239 .bytes_len = @intCast(bytes_len),
3240 });
3241 try s.out.writeStruct(body, .little);
3242 try s.out.writeSliceEndian(u32, error_bundle.extra, .little);
3243 try s.out.writeAll(error_bundle.string_bytes);
3244 try s.out.flush();
3245}
3246
29933247fn initStdoutWriter(io: Io) *Writer {
29943248 stdout_writer_allocation = Io.File.stdout().writerStreaming(io, &stdio_buffer_allocation);
29953249 return &stdout_writer_allocation.interface;
......@@ -3071,17 +3325,19 @@ pub fn packagePath(
30713325) Allocator.Error!Path {
30723326 const c = &maker.scanned_config.configuration;
30733327 const graph = maker.graph;
3074 const package = package_index.get(c) orelse return .{
3328
3329 if (package_index == .root) return .{
30753330 .root_dir = graph.build_root_directory,
30763331 .sub_path = sub_path,
30773332 };
3333
30783334 // Currently, neither configurer nor Maker is aware of the standard zig
30793335 // package path, and the root path is stored as a bare string rather than
30803336 // relative to a known base directory. Without changing that, we must
30813337 // construct a cwd relative path here.
30823338 return .{
30833339 .root_dir = .cwd(),
3084 .sub_path = try Dir.path.join(arena, &.{ package.root_path.slice(c), sub_path }),
3340 .sub_path = try Dir.path.join(arena, &.{ package_index.ptr(c).root_path.slice(c), sub_path }),
30853341 };
30863342}
30873343
......@@ -3687,7 +3943,12 @@ const Templates = struct {
36873943 }
36883944};
36893945
3690fn confPathDepToCachePath(graph: *const Graph, c: *const Configuration, path_dep: Configuration.PathDep) Path {
3946fn confPathDepToCachePath(
3947 arena: Allocator,
3948 graph: *const Graph,
3949 c: *const Configuration,
3950 path_dep: Configuration.PathDep,
3951) Allocator.Error!Path {
36913952 const sub_path = path_dep.sub.slice(c);
36923953 return switch (path_dep.flags.base) {
36933954 .cwd => .{
......@@ -3703,11 +3964,11 @@ fn confPathDepToCachePath(graph: *const Graph, c: *const Configuration, path_dep
37033964 .sub_path = sub_path,
37043965 },
37053966 .build_root => .{
3706 .root_dir = switch (path_dep.pkg.unwrap().?) {
3707 .root => graph.build_root_directory,
3708 _ => @panic("TODO"),
3967 .root_dir = graph.build_root_directory,
3968 .sub_path = switch (path_dep.pkg.unwrap().?) {
3969 .root => sub_path,
3970 else => |index| try Dir.path.join(arena, &.{ index.ptr(c).root_path.slice(c), sub_path }),
37093971 },
3710 .sub_path = sub_path,
37113972 },
37123973 .zig_lib => .{
37133974 .root_dir = graph.zig_lib_directory,
lib/compiler/Maker/Fetch.zig+3-3
......@@ -1164,7 +1164,7 @@ const FileType = enum {
11641164 if (cd_header[value_start] != '=') return null;
11651165 value_start += 1;
11661166
1167 var value_end = std.mem.indexOfPos(u8, cd_header, value_start, ";") orelse cd_header.len;
1167 var value_end = std.mem.findPos(u8, cd_header, value_start, ";") orelse cd_header.len;
11681168 if (cd_header[value_end - 1] == '\"') {
11691169 value_end -= 1;
11701170 }
......@@ -1344,7 +1344,7 @@ fn unpackResource(
13441344 return f.fail(f.location_tok, try eb.addString("missing 'Content-Type' header"));
13451345
13461346 // Extract the MIME type, ignoring charset and boundary directives
1347 const mime_type_end = std.mem.indexOf(u8, content_type, ";") orelse content_type.len;
1347 const mime_type_end = std.mem.find(u8, content_type, ";") orelse content_type.len;
13481348 const mime_type = content_type[0..mime_type_end];
13491349
13501350 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
14551455
14561456 var diagnostics: std.tar.Diagnostics = .{ .allocator = arena };
14571457
1458 std.tar.pipeToFileSystem(io, out_dir, reader, .{
1458 std.tar.extract(io, out_dir, reader, .{
14591459 .diagnostics = &diagnostics,
14601460 .strip_components = 0,
14611461 .mode_mode = .ignore,
lib/compiler/Maker/Fetch/git.zig+6-6
......@@ -336,7 +336,7 @@ pub const Repository = struct {
336336 fn next(iterator: *TreeIterator) !?Entry {
337337 if (iterator.pos == iterator.data.len) return null;
338338
339 const mode_end = mem.indexOfScalarPos(u8, iterator.data, iterator.pos, ' ') orelse return error.InvalidTree;
339 const mode_end = mem.findScalarPos(u8, iterator.data, iterator.pos, ' ') orelse return error.InvalidTree;
340340 const mode: packed struct {
341341 permission: u9,
342342 unused: u3,
......@@ -351,7 +351,7 @@ pub const Repository = struct {
351351 };
352352 iterator.pos = mode_end + 1;
353353
354 const name_end = mem.indexOfScalarPos(u8, iterator.data, iterator.pos, 0) orelse return error.InvalidTree;
354 const name_end = mem.findScalarPos(u8, iterator.data, iterator.pos, 0) orelse return error.InvalidTree;
355355 const name = iterator.data[iterator.pos..name_end :0];
356356 iterator.pos = name_end + 1;
357357
......@@ -823,7 +823,7 @@ pub const Session = struct {
823823 value: ?[]const u8 = null,
824824
825825 fn parse(data: []const u8) Capability {
826 return if (mem.indexOfScalar(u8, data, '=')) |separator_pos|
826 return if (mem.findScalar(u8, data, '=')) |separator_pos|
827827 .{ .key = data[0..separator_pos], .value = data[separator_pos + 1 ..] }
828828 else
829829 .{ .key = data };
......@@ -941,17 +941,17 @@ pub const Session = struct {
941941 .flush => return null,
942942 .data => |data| {
943943 const ref_data = Packet.normalizeText(data);
944 const oid_sep_pos = mem.indexOfScalar(u8, ref_data, ' ') orelse return error.InvalidRefPacket;
944 const oid_sep_pos = mem.findScalar(u8, ref_data, ' ') orelse return error.InvalidRefPacket;
945945 const oid = Oid.parse(it.format, data[0..oid_sep_pos]) catch return error.InvalidRefPacket;
946946
947 const name_sep_pos = mem.indexOfScalarPos(u8, ref_data, oid_sep_pos + 1, ' ') orelse ref_data.len;
947 const name_sep_pos = mem.findScalarPos(u8, ref_data, oid_sep_pos + 1, ' ') orelse ref_data.len;
948948 const name = ref_data[oid_sep_pos + 1 .. name_sep_pos];
949949
950950 var symref_target: ?[]const u8 = null;
951951 var peeled: ?Oid = null;
952952 var last_sep_pos = name_sep_pos;
953953 while (last_sep_pos < ref_data.len) {
954 const next_sep_pos = mem.indexOfScalarPos(u8, ref_data, last_sep_pos + 1, ' ') orelse ref_data.len;
954 const next_sep_pos = mem.findScalarPos(u8, ref_data, last_sep_pos + 1, ' ') orelse ref_data.len;
955955 const attribute = ref_data[last_sep_pos + 1 .. next_sep_pos];
956956 if (mem.startsWith(u8, attribute, "symref-target:")) {
957957 symref_target = attribute["symref-target:".len..];
lib/compiler/Maker/PkgConfig.zig+2
......@@ -63,6 +63,8 @@ pub fn run(
6363 }
6464 }
6565
66 step.clearFailedCommand(maker.gpa);
67
6668 return parsed;
6769}
6870
lib/compiler/Maker/ScannedConfig.zig+63-5
......@@ -12,10 +12,6 @@ top_level_steps: std.array_hash_map.String(Configuration.Step.Index),
1212path: std.Build.Cache.Path,
1313
1414pub fn print(sc: *const ScannedConfig, w: *Writer) Writer.Error!void {
15 std.log.err("TODO also print paths", .{});
16 std.log.err("TODO also print unlazy deps", .{});
17 std.log.err("TODO also print system integrations", .{});
18 std.log.err("TODO also print available options", .{});
1915 const c = &sc.configuration;
2016 var serializer: Serializer = .{ .writer = w };
2117 var s = try serializer.beginStruct(.{});
......@@ -45,6 +41,69 @@ pub fn print(sc: *const ScannedConfig, w: *Writer) Writer.Error!void {
4541 try tf.end();
4642 }
4743
44 {
45 var tf = try s.beginTupleField("path_deps", .{});
46 for (c.path_deps) |path_dep| {
47 var sf = try tf.beginStructField(.{});
48 try sf.field("base", @tagName(path_dep.flags.base), .{});
49 try sf.field("sub", path_dep.sub.slice(c), .{});
50 try sf.end();
51 }
52 try tf.end();
53 }
54
55 {
56 var tf = try s.beginTupleField("unlazy_deps", .{});
57 for (c.unlazy_deps) |dep| {
58 try tf.field(dep.slice(c), .{});
59 }
60 try tf.end();
61 }
62
63 {
64 var tf = try s.beginTupleField("system_integrations", .{});
65 for (c.system_integrations) |opt| {
66 var sf = try tf.beginStructField(.{});
67 try sf.field("name", opt.name.slice(c), .{});
68 try sf.field("status", opt.status, .{});
69 try sf.end();
70 }
71 try tf.end();
72 }
73
74 {
75 var tf = try s.beginTupleField("available_options", .{});
76 for (c.available_options) |opt| {
77 var sf = try tf.beginStructField(.{});
78 try sf.field("name", opt.name.slice(c), .{});
79 try sf.field("description", opt.description.slice(c), .{});
80 try sf.field("type", @tagName(opt.type), .{});
81 try sf.end();
82 }
83 try tf.end();
84 }
85
86 {
87 var tf = try s.beginTupleField("packages", .{});
88 for (c.packages) |package| {
89 var sf = try tf.beginStructField(.{});
90 try sf.field("dep_prefix", package.dep_prefix.slice(c), .{});
91 try sf.field("hash", package.hash.slice(c), .{});
92 try sf.field("root_path", package.root_path.slice(c), .{});
93
94 var dtf = try sf.beginTupleField("deps", .{});
95 for (package.deps.slice(c)) |dep| {
96 var dsf = try dtf.beginStructField(.{});
97 try sc.printStruct(&dsf, Configuration.Package.Dep, dep);
98 try dsf.end();
99 }
100 try dtf.end();
101
102 try sf.end();
103 }
104 try tf.end();
105 }
106
48107 try s.end();
49108}
50109
......@@ -341,7 +400,6 @@ pub fn printUsage(sc: *const ScannedConfig, graph: *Graph, w: *Writer) !void {
341400 \\ --error-limit [num] Set the maximum amount of distinct error values
342401 \\ --build-file [file] Override path to build.zig
343402 \\ --cache-dir [path] Override path to local Zig cache directory
344 \\ --global-cache-dir [path] Override path to global Zig cache directory
345403 \\ --zig-lib=[arg] Override path to Zig lib directory
346404 \\ --seed [integer] For shuffling dependency traversal order (default: random)
347405 \\ --cache-poison[=mode] Override configuration caching behavior
lib/compiler/Maker/Step.zig+13-8
......@@ -163,6 +163,9 @@ pub const State = enum {
163163 /// be re-evaluated.
164164 precheck_done,
165165 dependency_failure,
166 /// Handled exactly the same as `dependency_failure` except communicates
167 /// that the dependency didn't fail but rather was skipped.
168 dependency_skipped,
166169 success,
167170 failure,
168171 /// This state indicates that the step did not complete, however, it also did not fail,
......@@ -561,24 +564,26 @@ fn zigProcessUpdate(step_index: Configuration.Step.Index, maker: *Maker, zp: *Zi
561564 var result: ?Path = null;
562565 var eos_err: error{EndOfStream}!void = {};
563566
564 const stdout = zp.multi_reader.fileReader(0);
567 var client: std.zig.Client = .{
568 .in = zp.multi_reader.reader(0),
569 .out = undefined,
570 };
565571
566572 while (true) {
567 const Header = std.zig.Server.Message.Header;
568 const header = stdout.interface.takeStruct(Header, .little) catch |err| switch (err) {
569 error.EndOfStream => break,
570 error.ReadFailed => return stdout.err.?,
571 };
572 const body = stdout.interface.take(header.bytes_len) catch |err| switch (err) {
573 const header = client.receiveMessageWithMultiReader(&zp.multi_reader, .none) catch |err| switch (err) {
574 error.Timeout => unreachable,
573575 error.EndOfStream => |e| {
576 if (client.in.bufferedLen() == 0) break;
574577 // Better to report the crash with stderr below, but we set
575578 // this in case the child exits successfully while violating
576579 // this protocol.
577580 eos_err = e;
578581 break;
579582 },
580 error.ReadFailed => return stdout.err.?,
583 else => |e| return e,
581584 };
585 const body = client.in.take(header.bytes_len) catch unreachable;
586
582587 switch (header.tag) {
583588 .zig_version => {
584589 if (!std.mem.eql(u8, builtin.zig_version_string, body)) {
lib/compiler/Maker/Step/Compile.zig+2-2
......@@ -215,8 +215,8 @@ fn lowerZigArgs(
215215 try addBool(gpa, zig_args, "-ffuzz", fuzz);
216216
217217 {
218 var is_linking_libc = conf_comp.flags3.is_linking_libc;
219 var is_linking_libcpp = conf_comp.flags3.is_linking_libcpp;
218 var is_linking_libc = false;
219 var is_linking_libcpp = false;
220220
221221 // Stores system libraries that have already been seen for at least one
222222 // module, along with any C compiler arguments that need to be passed
lib/compiler/Maker/Step/ConfigHeader.zig+137
......@@ -93,6 +93,32 @@ pub fn make(
9393 else => |e| return e,
9494 };
9595 },
96 .meson => {
97 const tf = template_file.?;
98 const contents = tf.root_dir.handle.readFileAlloc(
99 io,
100 tf.sub_path,
101 arena,
102 input_size_limit,
103 ) catch |err| return step.fail(
104 maker,
105 "unable to read meson input file {f}: {t}",
106 .{ tf, err },
107 );
108
109 renderMeson(
110 maker,
111 step,
112 contents,
113 &aw,
114 value_pairs,
115 &value_map,
116 tf,
117 ) catch |err| switch (err) {
118 error.WriteFailed => return error.OutOfMemory,
119 else => |e| return e,
120 };
121 },
96122 .blank => {
97123 renderBlank(conf, &aw.writer, value_pairs, &value_map, include_path, include_guard_override) catch |err| switch (err) {
98124 error.WriteFailed => return error.OutOfMemory,
......@@ -370,6 +396,62 @@ fn renderCmake(
370396 if (any_errors) return error.MakeFailed;
371397}
372398
399fn renderMeson(
400 maker: *Maker,
401 step: *Step,
402 contents: []const u8,
403 aw: *Writer.Allocating,
404 value_pairs: []const Value.Pair,
405 value_map: *const ValueMap,
406 src_path: Path,
407) !void {
408 const w = &aw.writer;
409 const conf = &maker.scanned_config.configuration;
410 const newline = detectNewline(contents);
411
412 try w.writeAll(c_generated_line);
413 try w.writeAll(newline);
414
415 var any_errors = false;
416 var line_index: u32 = 0;
417 var line_it = std.mem.splitScalar(u8, contents, '\n');
418 // https://mesonbuild.com/Configuration.html
419 while (line_it.next()) |raw_line| : (line_index += 1) {
420 const last_line = line_it.index == line_it.buffer.len;
421 const line = std.mem.trimEnd(u8, raw_line, "\r");
422
423 const old_len = aw.written().len;
424 expandVariablesMeson(w, conf, line, value_pairs, value_map) catch |err| switch (err) {
425 error.MissingToken => {
426 try step.addError(maker, "{f}:{d}: error: missing define name", .{ src_path, line_index + 1 });
427 any_errors = true;
428 continue;
429 },
430 error.MissingValue => {
431 const name = aw.written()[old_len..];
432 defer aw.shrinkRetainingCapacity(old_len);
433
434 try step.addError(maker, "{f}:{d}: error: unspecified config header value: {q}", .{
435 src_path, line_index + 1, name,
436 });
437 any_errors = true;
438 continue;
439 },
440 else => {
441 try step.addError(maker, "{f}:{d}: unable to substitute variable: error: {t}", .{
442 src_path, line_index + 1, err,
443 });
444 any_errors = true;
445 continue;
446 },
447 };
448 if (!last_line) try w.writeAll(newline);
449 }
450
451 try ensureAllValuesUsed(maker, step, value_map, src_path);
452 if (any_errors) return error.MakeFailed;
453}
454
373455fn renderBlank(
374456 conf: *const Configuration,
375457 w: *Writer,
......@@ -432,6 +514,28 @@ fn renderValueC(conf: *const Configuration, w: *Writer, newline: []const u8, nam
432514 }
433515}
434516
517fn renderValueMeson(
518 conf: *const Configuration,
519 w: *Writer,
520 name: []const u8,
521 value: Value.Index,
522) !void {
523 switch (value.unpack(conf)) {
524 .undef => try w.print("/* #undef {s} */", .{name}),
525 .defined => try w.print("#define {s}", .{name}),
526 .bool => |b| {
527 if (b) {
528 try w.print("#define {s}", .{name});
529 } else {
530 try w.print("#undef {s}", .{name});
531 }
532 },
533 inline .u64, .i64 => |int| try w.print("#define {s} {d}", .{ name, int }),
534 .ident => |ident| try w.print("#define {s} {s}", .{ name, ident }),
535 .string => |string| try w.print("#define {s} \"{f}\"", .{ name, std.zig.fmtString(string) }),
536 }
537}
538
435539fn renderValueCIdent(w: *Writer, newline: []const u8, name: []const u8, ident: []const u8) Writer.Error!void {
436540 try w.print("#define {s}", .{name});
437541 if (ident.len > 0) {
......@@ -628,3 +732,36 @@ fn expandVariablesCmake(
628732
629733 return result.toOwnedSliceAssert();
630734}
735
736fn expandVariablesMeson(
737 w: *Writer,
738 conf: *const Configuration,
739 line: []const u8,
740 value_pairs: []const Value.Pair,
741 value_map: *const ValueMap,
742) !void {
743 const mesondefine = "#mesondefine";
744 if (std.mem.startsWith(u8, line, mesondefine)) {
745 const line_offset = mesondefine.len + 1;
746 if (line_offset > line.len) return error.MissingToken;
747
748 var it = std.mem.tokenizeAny(u8, line[line_offset..], " \t\r");
749 const name = it.next() orelse return error.MissingToken;
750
751 const index = value_map.getIndex(name) orelse {
752 // Report the missing key to the caller.
753 try w.writeAll(name);
754 return error.MissingValue;
755 };
756
757 const value = value_pairs[index].index;
758 value_map.values()[index] = true; // Mark as used.
759
760 try renderValueMeson(conf, w, name, value);
761
762 // comments/any other text passthrough unaffected
763 return try w.writeAll(line[line_offset + name.len ..]);
764 }
765
766 try expandVariablesAutoconfAt(w, line, conf, value_pairs, value_map);
767}
lib/compiler/Maker/Step/Run.zig+93-134
......@@ -64,9 +64,9 @@ pub fn make(
6464 }
6565 }
6666
67 for (conf_run.preopen_names.slice, conf_run.preopen_paths.slice) |name, path| {
68 man.hash.addBytesZ(name.slice(conf));
69 const cwd_path = try maker.resolveLazyPathIndex(arena, path, run_index);
67 for (conf_run.preopens.slice) |preopen| {
68 man.hash.addBytesZ(preopen.name.slice(conf));
69 const cwd_path = try maker.resolveLazyPathIndex(arena, preopen.path, run_index);
7070 man.hash.addBytes(try cwd_path.toString(arena));
7171 }
7272
......@@ -187,6 +187,11 @@ pub fn make(
187187 man.hash.addListOfBytes(run_args);
188188 }
189189 },
190 .enable_darling => thirdPartyToggle(&man.hash, &argv_list, conf, graph.enable_darling, arg.prefix.value, arg.suffix.value),
191 .enable_qemu => thirdPartyToggle(&man.hash, &argv_list, conf, graph.enable_qemu, arg.prefix.value, arg.suffix.value),
192 .enable_rosetta => thirdPartyToggle(&man.hash, &argv_list, conf, graph.enable_rosetta, arg.prefix.value, arg.suffix.value),
193 .enable_wasmtime => thirdPartyToggle(&man.hash, &argv_list, conf, graph.enable_wasmtime, arg.prefix.value, arg.suffix.value),
194 .enable_wine => thirdPartyToggle(&man.hash, &argv_list, conf, graph.enable_wine, arg.prefix.value, arg.suffix.value),
190195 }
191196 }
192197
......@@ -351,6 +356,29 @@ pub fn make(
351356 step.clearFailedCommand(gpa);
352357}
353358
359fn thirdPartyToggle(
360 man_hash: ?*Cache.HashHelper,
361 argv_list: *std.ArrayList([]const u8),
362 conf: *const Configuration,
363 setting: bool,
364 enable: ?Configuration.String,
365 disable: ?Configuration.String,
366) void {
367 if (setting) {
368 if (enable) |string| {
369 const slice = string.slice(conf);
370 if (man_hash) |h| h.addBytesZ(slice);
371 argv_list.appendAssumeCapacity(slice);
372 }
373 } else {
374 if (disable) |string| {
375 const slice = string.slice(conf);
376 if (man_hash) |h| h.addBytesZ(slice);
377 argv_list.appendAssumeCapacity(slice);
378 }
379 }
380}
381
354382/// Reads stdout of a Zig test process until a termination condition is reached:
355383/// * A write fails, indicating the child unexpectedly closed stdin
356384/// * A test (or a response from the test runner) times out
......@@ -384,13 +412,23 @@ fn waitZigTest(
384412 var sub_prog_node: ?std.Progress.Node = null;
385413 defer if (sub_prog_node) |n| n.end();
386414
415 const stdout = multi_reader.reader(0);
416 const stderr = multi_reader.reader(1);
417
418 var stdin_writer = child.stdin.?.writerStreaming(io, &.{});
419
420 var client: std.zig.Client = .{
421 .in = stdout,
422 .out = &stdin_writer.interface,
423 };
424
387425 if (opt_metadata.*) |*md| {
388426 // Previous unit test process died or was killed; we're continuing where it left off
389 requestNextTest(io, child.stdin.?, md, &sub_prog_node) catch |err| return .{ .write_failed = err };
427 requestNextTest(&client, md, &sub_prog_node) catch |err| return .{ .write_failed = err };
390428 } else {
391429 // Running unit tests normally
392430 run.fuzz_tests.clearRetainingCapacity();
393 sendMessage(io, child.stdin.?, .query_test_metadata) catch |err| return .{ .write_failed = err };
431 client.serveBodylessMessage(.query_test_metadata) catch |err| return .{ .write_failed = err };
394432 }
395433
396434 var active_test_index: ?u32 = null;
......@@ -410,10 +448,6 @@ fn waitZigTest(
410448 .raw = .fromNanoseconds(ns),
411449 } else null;
412450
413 const stdout = multi_reader.reader(0);
414 const stderr = multi_reader.reader(1);
415 const Header = std.zig.Server.Message.Header;
416
417451 while (true) {
418452 const timeout: Io.Timeout = t: {
419453 const opt_duration = if (active_test_index == null) response_timeout else test_timeout;
......@@ -421,46 +455,20 @@ fn waitZigTest(
421455 break :t .{ .deadline = last_update.addDuration(duration) };
422456 };
423457
424 // This block is exited when `stdout` contains enough bytes for a `Header`.
425 header_ready: {
426 if (stdout.buffered().len >= @sizeOf(Header)) {
427 // We already have one, no need to poll!
428 break :header_ready;
429 }
430
431 multi_reader.fill(64, timeout) catch |err| switch (err) {
432 error.Timeout => return .{ .timeout = .{
433 .active_test_index = active_test_index,
434 .ns_elapsed = @intCast(last_update.untilNow(io).raw.nanoseconds),
435 } },
436 error.EndOfStream => return .{ .no_poll = .{
437 .active_test_index = active_test_index,
438 .ns_elapsed = @intCast(last_update.untilNow(io).raw.nanoseconds),
439 } },
440 else => |e| return e,
441 };
442
443 continue;
444 }
445 // There is definitely a header available now -- read it.
446 const header = stdout.takeStruct(Header, .little) catch unreachable;
447
448 while (stdout.buffered().len < header.bytes_len) {
449 multi_reader.fill(64, timeout) catch |err| switch (err) {
450 error.Timeout => return .{ .timeout = .{
451 .active_test_index = active_test_index,
452 .ns_elapsed = @intCast(last_update.untilNow(io).raw.nanoseconds),
453 } },
454 error.EndOfStream => return .{ .no_poll = .{
455 .active_test_index = active_test_index,
456 .ns_elapsed = @intCast(last_update.untilNow(io).raw.nanoseconds),
457 } },
458 else => |e| return e,
459 };
460 }
461
462 const body = stdout.take(header.bytes_len) catch unreachable;
458 const header = client.receiveMessageWithMultiReader(multi_reader, timeout) catch |err| switch (err) {
459 error.Timeout => return .{ .timeout = .{
460 .active_test_index = active_test_index,
461 .ns_elapsed = @intCast(last_update.untilNow(io).raw.nanoseconds),
462 } },
463 error.EndOfStream => return .{ .no_poll = .{
464 .active_test_index = active_test_index,
465 .ns_elapsed = @intCast(last_update.untilNow(io).raw.nanoseconds),
466 } },
467 else => |e| return e,
468 };
469 const body = client.in.take(header.bytes_len) catch unreachable;
463470 var body_r: std.Io.Reader = .fixed(body);
471
464472 switch (header.tag) {
465473 .zig_version => {
466474 if (!std.mem.eql(u8, builtin.zig_version_string, body)) return step.fail(
......@@ -500,7 +508,7 @@ fn waitZigTest(
500508 active_test_index = null;
501509 last_update = .now(io, .awake);
502510
503 requestNextTest(io, child.stdin.?, &opt_metadata.*.?, &sub_prog_node) catch |err| return .{ .write_failed = err };
511 requestNextTest(&client, &opt_metadata.*.?, &sub_prog_node) catch |err| return .{ .write_failed = err };
504512 },
505513 .test_started => {
506514 active_test_index = opt_metadata.*.?.next_index - 1;
......@@ -551,7 +559,7 @@ fn waitZigTest(
551559 md.ns_per_test[tr_hdr.index] = @intCast(last_update.durationTo(now).raw.nanoseconds);
552560 last_update = now;
553561
554 requestNextTest(io, child.stdin.?, md, &sub_prog_node) catch |err| return .{ .write_failed = err };
562 requestNextTest(&client, md, &sub_prog_node) catch |err| return .{ .write_failed = err };
555563 },
556564 else => {}, // ignore other messages
557565 }
......@@ -575,7 +583,7 @@ const FuzzTestRunner = struct {
575583
576584 const Instance = struct {
577585 child: process.Child,
578 message: std.ArrayListAligned(u8, .@"4"),
586 message: std.array_list.Aligned(u8, .@"4"),
579587 broadcast_written: usize,
580588 stderr: std.ArrayList(u8),
581589 stdin_vec: [1][]u8,
......@@ -697,17 +705,18 @@ const FuzzTestRunner = struct {
697705
698706 for (0.., f.instances) |id, *instance| {
699707 const id32: u32 = @intCast(id);
708 var writer = instance.child.stdin.?.writerStreaming(io, &.{});
709 const client: std.zig.Client = .{
710 .in = undefined,
711 .out = &writer.interface,
712 };
700713 (switch (f.ctx.fuzz.mode) {
701 .forever => sendRunFuzzTestMessage(
702 io,
703 instance.child.stdin.?,
714 .forever => client.serveRunFuzzTestMessage(
704715 run.fuzz_tests.items,
705716 .forever,
706717 id32,
707718 ),
708 .limit => |limit| sendRunFuzzTestMessage(
709 io,
710 instance.child.stdin.?,
719 .limit => |limit| client.serveRunFuzzTestMessage(
711720 run.fuzz_tests.items,
712721 .iterations,
713722 limit.amount,
......@@ -1315,7 +1324,7 @@ pub const CachedTestMetadata = struct {
13151324 }
13161325};
13171326
1318fn requestNextTest(io: Io, in: Io.File, metadata: *TestMetadata, sub_prog_node: *?std.Progress.Node) !void {
1327fn requestNextTest(client: *std.zig.Client, metadata: *TestMetadata, sub_prog_node: *?std.Progress.Node) !void {
13191328 while (metadata.next_index < metadata.names.len) {
13201329 const i = metadata.next_index;
13211330 metadata.next_index += 1;
......@@ -1326,76 +1335,11 @@ fn requestNextTest(io: Io, in: Io.File, metadata: *TestMetadata, sub_prog_node:
13261335 if (sub_prog_node.*) |n| n.end();
13271336 sub_prog_node.* = metadata.prog_node.start(name, 0);
13281337
1329 try sendRunTestMessage(io, in, .run_test, i);
1338 try client.serveRunTest(i);
13301339 return;
13311340 } else {
13321341 metadata.next_index = std.math.maxInt(u32); // indicate that all tests are done
1333 try sendMessage(io, in, .exit);
1334 }
1335}
1336
1337fn sendMessage(io: Io, file: Io.File, tag: std.zig.Client.Message.Tag) !void {
1338 const header: std.zig.Client.Message.Header = .{
1339 .tag = tag,
1340 .bytes_len = 0,
1341 };
1342 var w = file.writerStreaming(io, &.{});
1343 w.interface.writeStruct(header, .little) catch |err| switch (err) {
1344 error.WriteFailed => return w.err.?,
1345 };
1346}
1347
1348fn sendRunTestMessage(io: Io, file: Io.File, tag: std.zig.Client.Message.Tag, index: u32) !void {
1349 const header: std.zig.Client.Message.Header = .{
1350 .tag = tag,
1351 .bytes_len = 4,
1352 };
1353 var w = file.writerStreaming(io, &.{});
1354 w.interface.writeStruct(header, .little) catch |err| switch (err) {
1355 error.WriteFailed => return w.err.?,
1356 };
1357 w.interface.writeInt(u32, index, .little) catch |err| switch (err) {
1358 error.WriteFailed => return w.err.?,
1359 };
1360}
1361
1362fn sendRunFuzzTestMessage(
1363 io: Io,
1364 file: Io.File,
1365 test_names: []const []const u8,
1366 kind: std.Build.abi.fuzz.LimitKind,
1367 amount_or_instance: u64,
1368) !void {
1369 const header: std.zig.Client.Message.Header = .{
1370 .tag = .start_fuzzing,
1371 .bytes_len = 1 + 8 + 4 + count: {
1372 var c: u32 = @intCast(test_names.len * 4);
1373 for (test_names) |name| {
1374 c += @intCast(name.len);
1375 }
1376 break :count c;
1377 },
1378 };
1379 var w = file.writerStreaming(io, &.{});
1380 w.interface.writeStruct(header, .little) catch |err| switch (err) {
1381 error.WriteFailed => return w.err.?,
1382 };
1383 w.interface.writeByte(@backingInt(kind)) catch |err| switch (err) {
1384 error.WriteFailed => return w.err.?,
1385 };
1386 w.interface.writeInt(u64, amount_or_instance, .little) catch |err| switch (err) {
1387 error.WriteFailed => return w.err.?,
1388 };
1389 w.interface.writeInt(u32, @intCast(test_names.len), .little) catch |err| switch (err) {
1390 error.WriteFailed => return w.err.?,
1391 };
1392 for (test_names) |test_name| {
1393 w.interface.writeInt(u32, @intCast(test_name.len), .little) catch |err| switch (err) {
1394 error.WriteFailed => return w.err.?,
1395 };
1396 w.interface.writeAll(test_name) catch |err| switch (err) {
1397 error.WriteFailed => return w.err.?,
1398 };
1342 try client.serveBodylessMessage(.exit);
13991343 }
14001344}
14011345
......@@ -1619,6 +1563,11 @@ pub fn rerunInFuzzMode(
16191563 .output_file => unreachable,
16201564 .output_directory => unreachable,
16211565 .passthru => unreachable,
1566 .enable_darling => thirdPartyToggle(null, &argv_list, conf, graph.enable_darling, arg.prefix.value, arg.suffix.value),
1567 .enable_qemu => thirdPartyToggle(null, &argv_list, conf, graph.enable_qemu, arg.prefix.value, arg.suffix.value),
1568 .enable_rosetta => thirdPartyToggle(null, &argv_list, conf, graph.enable_rosetta, arg.prefix.value, arg.suffix.value),
1569 .enable_wasmtime => thirdPartyToggle(null, &argv_list, conf, graph.enable_wasmtime, arg.prefix.value, arg.suffix.value),
1570 .enable_wine => thirdPartyToggle(null, &argv_list, conf, graph.enable_wine, arg.prefix.value, arg.suffix.value),
16221571 }
16231572 }
16241573
......@@ -1917,14 +1866,14 @@ fn runCommand(
19171866 },
19181867 .wasmtime => |bin_name| {
19191868 if (graph.enable_wasmtime) {
1920 try interp_argv.ensureUnusedCapacity(arena, 3 + argv.len + conf_run.preopen_names.slice.len);
1869 try interp_argv.ensureUnusedCapacity(arena, 3 + argv.len + conf_run.preopens.slice.len);
19211870 interp_argv.appendAssumeCapacity(bin_name);
19221871 interp_argv.appendAssumeCapacity("--dir=.");
1923 for (conf_run.preopen_names.slice, conf_run.preopen_paths.slice) |name, lazy_path| {
1924 const path = try maker.resolveLazyPath(arena, lazy_path.get(conf), run_index);
1872 for (conf_run.preopens.slice) |preopen| {
1873 const path = try maker.resolveLazyPath(arena, preopen.path.get(conf), run_index);
19251874 path.root_dir.handle.createDirPath(io, path.subPathOrDot()) catch |e|
19261875 return step.fail(maker, "failed creating directory {f}: {t}", .{ path, e });
1927 interp_argv.appendAssumeCapacity(try arena.print("--dir={f}::{s}", .{ path, name.slice(conf) }));
1876 interp_argv.appendAssumeCapacity(try arena.print("--dir={f}::{s}", .{ path, preopen.name.slice(conf) }));
19281877 }
19291878 // Wasmtime doeesn't inherit environment variables from the parent process
19301879 // by default. '-S inherit-env' was added in Wasmtime version 20.
......@@ -2204,7 +2153,7 @@ fn fmtSnapshotIndicatorLine(buf: []const u8, index: usize) std.fmt.Alt(
22042153}
22052154
22062155fn snapshotIndicatorLine(line: FmtIndicatorLine, w: *std.Io.Writer) std.Io.Writer.Error!void {
2207 const line_begin_index = if (std.mem.lastIndexOfScalar(u8, line.buf[0..line.index], '\n')) |line_begin|
2156 const line_begin_index = if (std.mem.findScalarLast(u8, line.buf[0..line.index], '\n')) |line_begin|
22082157 line_begin + 1
22092158 else
22102159 0;
......@@ -2285,25 +2234,35 @@ fn spawnChildAndCollect(
22852234 assert(conf_run.flags.stdio != .inherit);
22862235 break :s .pipe;
22872236 } else switch (conf_run.flags.stdio) {
2288 .infer_from_args => if (has_side_effects) .inherit else .ignore,
2237 .infer_from_args => if (maker.protocol_server == null and has_side_effects) .inherit else .ignore,
22892238 .inherit => .inherit,
22902239 .check => .ignore,
22912240 .zig_test => .pipe,
22922241 },
22932242 .stdout = if (conf_run.captured_stdout.value != null) .pipe else switch (conf_run.flags.stdio) {
2294 .infer_from_args => if (has_side_effects) .inherit else .ignore,
2243 .infer_from_args => if (maker.protocol_server == null and has_side_effects) .inherit else .ignore,
22952244 .inherit => .inherit,
22962245 .check => if (checksContainStdout(&conf_run)) .pipe else .ignore,
22972246 .zig_test => .pipe,
22982247 },
22992248 .stderr = if (conf_run.captured_stderr.value != null) .pipe else switch (conf_run.flags.stdio) {
2300 .infer_from_args => if (has_side_effects) .inherit else .pipe,
2301 .inherit => .inherit,
2249 .infer_from_args => if (maker.protocol_server == null and has_side_effects) .inherit else .pipe,
2250 .inherit => if (maker.protocol_server == null) .inherit else .pipe,
23022251 .check => .pipe,
23032252 .zig_test => .pipe,
23042253 },
23052254 };
23062255
2256 if (maker.protocol_server != null) {
2257 if (spawn_options.stdin == .inherit) {
2258 return step.fail(maker, "Cannot inherit stdin when running through over the build system protocol", .{});
2259 }
2260 if (spawn_options.stdout == .inherit) {
2261 return step.fail(maker, "Cannot inherit stdout when running through over the build system protocol", .{});
2262 }
2263 assert(spawn_options.stderr != .inherit);
2264 }
2265
23072266 if (conf_run.flags.stdio == .zig_test) {
23082267 try setColorEnvironmentVariables(&conf_run, environ_map, graph.stderr_mode.?);
23092268 const started: Io.Clock.Timestamp = .now(io, .awake);
lib/compiler/Maker/Step/TranslateC.zig+3-3
......@@ -49,9 +49,9 @@ pub fn make(
4949
5050 const opt: ?OptimizeMode = switch (conf_tc.flags.optimize) {
5151 .debug, .default => null, // Skip since it's the default
52 .safe => .ReleaseSafe,
53 .fast => .ReleaseFast,
54 .small => .ReleaseSmall,
52 .safe => .safe,
53 .fast => .fast,
54 .small => .small,
5555 };
5656 if (opt) |o| argv.appendAssumeCapacity(try arena.print("-O{t}", .{o}));
5757
lib/compiler/Maker/WebServer.zig+1-1
......@@ -501,7 +501,7 @@ fn serveRequest(ws: *WebServer, req: *http.Server.Request) !void {
501501 if (mem.eql(u8, target, "/main.js")) return serveLibFile(ws, req, "build-web/main.js", "application/javascript");
502502 if (mem.eql(u8, target, "/style.css")) return serveLibFile(ws, req, "build-web/style.css", "text/css");
503503 if (mem.eql(u8, target, "/time_report.css")) return serveLibFile(ws, req, "build-web/time_report.css", "text/css");
504 if (mem.eql(u8, target, "/main.wasm")) return serveClientWasm(ws, req, if (debug) .Debug else .ReleaseFast);
504 if (mem.eql(u8, target, "/main.wasm")) return serveClientWasm(ws, req, if (debug) .debug else .fast);
505505
506506 if (ws.fuzz) |*fuzz| {
507507 if (mem.eql(u8, target, "/sources.tar")) return fuzz.serveSourcesTar(req);
lib/compiler/aro/aro/Compilation.zig+1
......@@ -1601,6 +1601,7 @@ pub fn addSourceFromOwnedBuffer(comp: *Compilation, path: []const u8, buf: []u8,
16011601 var list: std.ArrayList(u8) = .{
16021602 .items = contents[0..i],
16031603 .capacity = contents.len,
1604 .pointer_stability = .{},
16041605 };
16051606 contents = try list.toOwnedSlice(comp.gpa);
16061607 }
lib/compiler/aro/aro/Diagnostics.zig+1-1
......@@ -510,7 +510,7 @@ pub fn formatArgs(w: *std.Io.Writer, fmt: []const u8, args: anytype) std.Io.Writ
510510
511511pub fn templateIndex(w: *std.Io.Writer, fmt: []const u8, template: []const u8) std.Io.Writer.Error!usize {
512512 const i = std.mem.indexOf(u8, fmt, template) orelse {
513 if (@import("builtin").mode == .Debug) {
513 if (@import("builtin").mode == .debug) {
514514 std.debug.panic("template `{s}` not found in format string `{s}`", .{ template, fmt });
515515 }
516516 try w.print("template `{s}` not found in format string `{s}` (this is a bug in arocc)", .{ template, fmt });
lib/compiler/aro/aro/Target.zig+3-3
......@@ -1559,15 +1559,15 @@ pub fn ptrBitWidth(target: *const Target) u16 {
15591559}
15601560
15611561pub fn cCharSignedness(target: *const Target) std.builtin.Signedness {
1562 return target.toZigTarget().cCharSignedness();
1562 return target.toZigTarget().cCharSignedness().?;
15631563}
15641564
15651565pub fn cTypeBitSize(target: *const Target, c_type: std.Target.CType) u16 {
1566 return target.toZigTarget().cTypeBitSize(c_type);
1566 return target.toZigTarget().cTypeBitSize(c_type).?;
15671567}
15681568
15691569pub fn cTypeAlignment(target: *const Target, c_type: std.Target.CType) u16 {
1570 return target.toZigTarget().cTypeAlignment(c_type);
1570 return target.toZigTarget().cTypeAlignment(c_type).?;
15711571}
15721572
15731573pub fn standardDynamicLinkerPath(target: *const Target) std.Target.DynamicLinker {
lib/compiler/aro/main.zig+1-1
......@@ -40,7 +40,7 @@ pub fn main(init: process.Init.Minimal) u8 {
4040 defer threaded.deinit();
4141 const io = threaded.io();
4242
43 const fast_exit = @import("builtin").mode != .Debug;
43 const fast_exit = @import("builtin").mode != .debug;
4444
4545 const args = init.args.toSlice(arena) catch {
4646 std.debug.print("out of memory\n", .{});
lib/compiler/configurer.zig+1-1
......@@ -83,7 +83,7 @@ pub fn main(init: process.Init.Minimal) !void {
8383 if (mem.cutPrefix(u8, arg, "-D")) |option_contents| {
8484 if (option_contents.len == 0)
8585 fatalWithHint("expected option name after '-D'", .{});
86 if (mem.indexOfScalar(u8, option_contents, '=')) |name_end| {
86 if (mem.findScalar(u8, option_contents, '=')) |name_end| {
8787 const option_name = option_contents[0..name_end];
8888 const option_value = option_contents[name_end + 1 ..];
8989 if (try builder.addUserInputOption(option_name, option_value))
lib/compiler/objcopy.zig+10-10
......@@ -214,11 +214,11 @@ fn cmdObjCopy(arena: Allocator, io: Io, args: []const []const u8) !void {
214214 if (listen) {
215215 var stdin_reader = Io.File.stdin().reader(io, &stdin_buffer);
216216 var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer);
217 var server = try Server.init(.{
217 var server: Server = .{
218218 .in = &stdin_reader.interface,
219219 .out = &stdout_writer.interface,
220 .zig_version = builtin.zig_version_string,
221 });
220 };
221 try server.serveStringMessage(.zig_version, builtin.zig_version_string);
222222
223223 var seen_update = false;
224224 while (true) {
......@@ -435,13 +435,13 @@ const BinaryElfOutput = struct {
435435
436436 var program_headers = elf_hdr.iterateProgramHeaders(in);
437437 while (try program_headers.next()) |phdr| {
438 if (phdr.p_type == elf.PT_LOAD) {
438 if (phdr.type == .LOAD) {
439439 const newSegment = try allocator.create(BinaryElfSegment);
440440
441 newSegment.physicalAddress = phdr.p_paddr;
442 newSegment.virtualAddress = phdr.p_vaddr;
443 newSegment.fileSize = @intCast(phdr.p_filesz);
444 newSegment.elfOffset = phdr.p_offset;
441 newSegment.physicalAddress = phdr.paddr;
442 newSegment.virtualAddress = phdr.vaddr;
443 newSegment.fileSize = @intCast(phdr.filesz);
444 newSegment.elfOffset = phdr.offset;
445445 newSegment.binaryOffset = 0;
446446 newSegment.firstSection = null;
447447
......@@ -495,8 +495,8 @@ const BinaryElfOutput = struct {
495495 return self;
496496 }
497497
498 fn sectionWithinSegment(section: *BinaryElfSection, segment: elf.Elf64_Phdr) bool {
499 return segment.p_offset <= section.elfOffset and (segment.p_offset + segment.p_filesz) >= (section.elfOffset + section.fileSize);
498 fn sectionWithinSegment(section: *BinaryElfSection, segment: elf.Elf64.Phdr) bool {
499 return segment.offset <= section.elfOffset and (segment.offset + segment.filesz) >= (section.elfOffset + section.fileSize);
500500 }
501501
502502 fn sectionValidForOutput(shdr: anytype) bool {
lib/compiler/reduce.zig+1-1
......@@ -400,7 +400,7 @@ fn parse(gpa: Allocator, io: Io, file_path: []const u8) !Ast {
400400 file_path,
401401 gpa,
402402 .limited(std.math.maxInt(u32)),
403 .fromByteUnits(1),
403 .@"1",
404404 0,
405405 ) catch |err| {
406406 fatal("unable to open '{s}': {s}", .{ file_path, @errorName(err) });
lib/compiler/resinator/compile.zig+3-3
......@@ -540,7 +540,7 @@ pub const Compiler = struct {
540540 // This currently only checks for NUL bytes, but it should probably also check for
541541 // platform-specific invalid characters like '*', '?', '"', '<', '>', '|' (Windows)
542542 // Related: https://github.com/ziglang/zig/pull/14533#issuecomment-1416888193
543 if (std.mem.indexOfScalar(u8, filename_utf8, 0) != null) {
543 if (std.mem.findScalar(u8, filename_utf8, 0) != null) {
544544 return self.addErrorDetailsAndFail(.{
545545 .err = .invalid_filename,
546546 .token = node.filename.getFirstToken(),
......@@ -2919,11 +2919,11 @@ fn validateSearchPath(path: []const u8) error{BadPathName}!void {
29192919 var component_iterator = std.fs.path.componentIterator(path);
29202920 while (component_iterator.next()) |component| {
29212921 // https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file
2922 if (std.mem.indexOfAny(u8, component.name, "\x00<>:\"|?*") != null) return error.BadPathName;
2922 if (std.mem.findAny(u8, component.name, "\x00<>:\"|?*") != null) return error.BadPathName;
29232923 }
29242924 },
29252925 else => {
2926 if (std.mem.indexOfScalar(u8, path, 0) != null) return error.BadPathName;
2926 if (std.mem.findScalar(u8, path, 0) != null) return error.BadPathName;
29272927 },
29282928 }
29292929}
lib/compiler/resinator/cvtres.zig+1-1
......@@ -1056,7 +1056,7 @@ pub const supported_targets = struct {
10561056 comptime {
10571057 const info = @typeInfo(Arch).@"enum";
10581058 for (info.field_names, info.field_values) |field_name, field_value| {
1059 _ = std.mem.indexOfScalar(Arch, ordered_for_display, @fromBackingInt(@intCast(field_value))) orelse {
1059 _ = std.mem.findScalar(Arch, ordered_for_display, @fromBackingInt(@intCast(field_value))) orelse {
10601060 @compileError(std.fmt.comptimePrint("'{s}' missing from ordered_for_display", .{field_name}));
10611061 };
10621062 }
lib/compiler/resinator/errors.zig+1-1
......@@ -506,7 +506,7 @@ pub const ErrorDetails = struct {
506506 // We know that the token slice is a well-formed #pragma code_page(N), so
507507 // we can skip to the first ( and then get the number that follows
508508 const token_slice = self.token.slice(source);
509 var number_start = std.mem.indexOfScalar(u8, token_slice, '(').? + 1;
509 var number_start = std.mem.findScalar(u8, token_slice, '(').? + 1;
510510 while (std.ascii.isWhitespace(token_slice[number_start])) {
511511 number_start += 1;
512512 }
lib/compiler/resinator/parse.zig+1-1
......@@ -1277,7 +1277,7 @@ pub const Parser = struct {
12771277 },
12781278 else => unreachable,
12791279 }
1280 @compileError("unreachable");
1280 comptime unreachable;
12811281 }
12821282
12831283 pub const OptionalParamParser = struct {
lib/compiler/resinator/source_mapping.zig+1-1
......@@ -538,7 +538,7 @@ pub fn handleLineCommand(allocator: Allocator, line_command: []const u8, current
538538 defer allocator.free(filename);
539539
540540 // \x00 bytes in the filename is incompatible with how StringTable works
541 if (std.mem.indexOfScalar(u8, filename, '\x00') != null) return error.InvalidLineCommand;
541 if (std.mem.findScalar(u8, filename, '\x00') != null) return error.InvalidLineCommand;
542542
543543 current_mapping.line_num = linenum;
544544 current_mapping.filename.clearRetainingCapacity();
lib/compiler/std-docs.zig+23-24
......@@ -142,9 +142,9 @@ fn serveRequest(request: *std.http.Server.Request, context: *Context) !void {
142142 {
143143 try serveDocsFile(request, context, "docs/main.js", "application/javascript");
144144 } else if (std.mem.eql(u8, request.head.target, "/main.wasm")) {
145 try serveWasm(request, context, .ReleaseFast);
145 try serveWasm(request, context, .fast);
146146 } else if (std.mem.eql(u8, request.head.target, "/debug/main.wasm")) {
147 try serveWasm(request, context, .Debug);
147 try serveWasm(request, context, .debug);
148148 } else if (std.mem.eql(u8, request.head.target, "/sources.tar") or
149149 std.mem.eql(u8, request.head.target, "/debug/sources.tar"))
150150 {
......@@ -346,29 +346,39 @@ fn buildWasmBinary(
346346 multi_reader.init(gpa, io, multi_reader_buffer.toStreams(), &.{ child.stdout.?, child.stderr.? });
347347 defer multi_reader.deinit();
348348
349 try sendMessage(io, child.stdin.?, .update);
350 try sendMessage(io, child.stdin.?, .exit);
349 const stdout = multi_reader.reader(0);
350
351 var stdin_buffer: [256]u8 = undefined;
352 var stdin_writer = child.stdin.?.writerStreaming(io, &stdin_buffer);
353
354 var client: std.zig.Client = .{
355 .in = stdout,
356 .out = &stdin_writer.interface,
357 };
358
359 try client.serveMessageHeader(.{ .tag = .update, .bytes_len = 0 });
360 try client.serveMessageHeader(.{ .tag = .exit, .bytes_len = 0 });
361 try client.out.flush();
351362
352363 var result: ?Cache.Path = null;
353364 var result_error_bundle = std.zig.ErrorBundle.empty;
354365
355 const stdout = multi_reader.fileReader(0);
356 const MessageHeader = std.zig.Server.Message.Header;
357
358366 var eos_err: error{EndOfStream}!void = {};
359367
360368 while (true) {
361 const header = stdout.interface.takeStruct(MessageHeader, .little) catch |err| switch (err) {
362 error.EndOfStream => break,
363 error.ReadFailed => return stdout.err.?,
364 };
365 const body = stdout.interface.take(header.bytes_len) catch |err| switch (err) {
369 const header = client.receiveMessageWithMultiReader(&multi_reader, .none) catch |err| switch (err) {
370 error.Timeout => unreachable,
366371 error.EndOfStream => |e| {
372 if (client.in.bufferedLen() == 0) break;
373 // Better to report the crash with stderr below, but we set
374 // this in case the child exits successfully while violating
375 // this protocol.
367376 eos_err = e;
368377 break;
369378 },
370 error.ReadFailed => return stdout.err.?,
379 else => |e| return e,
371380 };
381 const body = client.in.take(header.bytes_len) catch unreachable;
372382
373383 switch (header.tag) {
374384 .zig_version => {
......@@ -435,17 +445,6 @@ fn buildWasmBinary(
435445 };
436446}
437447
438fn sendMessage(io: Io, file: Io.File, tag: std.zig.Client.Message.Tag) !void {
439 const header: std.zig.Client.Message.Header = .{
440 .tag = tag,
441 .bytes_len = 0,
442 };
443 var w = file.writer(io, &.{});
444 w.interface.writeStruct(header, .little) catch |err| switch (err) {
445 error.WriteFailed => return w.err.?,
446 };
447}
448
449448fn openBrowserTab(io: Io, url: []const u8) !void {
450449 // Until https://github.com/ziglang/zig/issues/19205 is implemented, we
451450 // spawn and then leak a concurrent task for this child process.
lib/compiler/test_runner.zig+14-14
......@@ -78,11 +78,11 @@ fn mainServer(init: std.process.Init.Minimal) !void {
7878 @disableInstrumentation();
7979 stdin_reader = .initStreaming(.stdin(), runner_threaded_io, &stdin_buffer);
8080 stdout_writer = .initStreaming(.stdout(), runner_threaded_io, &stdout_buffer);
81 var server = try std.zig.Server.init(.{
81 var server: std.zig.Server = .{
8282 .in = &stdin_reader.interface,
8383 .out = &stdout_writer.interface,
84 .zig_version = builtin.zig_version_string,
85 });
84 };
85 try server.serveStringMessage(.zig_version, builtin.zig_version_string);
8686
8787 while (true) {
8888 const hdr = try server.receiveMessage();
......@@ -91,24 +91,23 @@ fn mainServer(init: std.process.Init.Minimal) !void {
9191 return std.process.exit(0);
9292 },
9393 .query_test_metadata => {
94 testing.allocator_instance = .init(std.heap.page_allocator, .{});
95 defer if (testing.allocator_instance.deinit() != 0) {
96 @panic("internal test runner memory leak");
97 };
94 var sa: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{});
95 defer if (sa.deinit() != 0) @panic("internal test runner memory leak");
96 const gpa = sa.allocator();
9897
9998 var string_bytes: std.ArrayList(u8) = .empty;
100 defer string_bytes.deinit(testing.allocator);
101 try string_bytes.append(testing.allocator, 0); // Reserve 0 for null.
99 defer string_bytes.deinit(gpa);
100 try string_bytes.append(gpa, 0); // Reserve 0 for null.
102101
103102 const test_fns = builtin.test_functions;
104 const names = try testing.allocator.alloc(u32, test_fns.len);
105 defer testing.allocator.free(names);
106 const expected_panic_msgs = try testing.allocator.alloc(u32, test_fns.len);
107 defer testing.allocator.free(expected_panic_msgs);
103 const names = try gpa.alloc(u32, test_fns.len);
104 defer gpa.free(names);
105 const expected_panic_msgs = try gpa.alloc(u32, test_fns.len);
106 defer gpa.free(expected_panic_msgs);
108107
109108 for (test_fns, names, expected_panic_msgs) |test_fn, *name, *expected_panic_msg| {
110109 name.* = @intCast(string_bytes.items.len);
111 try string_bytes.ensureUnusedCapacity(testing.allocator, test_fn.name.len + 1);
110 try string_bytes.ensureUnusedCapacity(gpa, test_fn.name.len + 1);
112111 string_bytes.appendSliceAssumeCapacity(test_fn.name);
113112 string_bytes.appendAssumeCapacity(0);
114113 expected_panic_msg.* = 0;
......@@ -377,6 +376,7 @@ pub fn mainSimple() anyerror!void {
377376 else => false,
378377 };
379378
379 testing.allocator_instance = .init(std.heap.page_allocator, .{});
380380 testing.io_instance = .init(testing.allocator, .{});
381381
382382 var passed: u64 = 0;
lib/compiler/translate-c/MacroTranslator.zig+1-1
......@@ -361,7 +361,7 @@ fn parseCNumLit(mt: *MacroTranslator) ParseError!ZigNode {
361361 return error.ParseError;
362362 },
363363 });
364 if (bytes.getLast().? == '.') {
364 if (bytes.last().? == '.') {
365365 bytes.appendAssumeCapacity('0');
366366 } else if (mem.findAny(u8, bytes.items, ".eEpP") == null) {
367367 bytes.appendSliceAssumeCapacity(".0");
lib/compiler/translate-c/main.zig+1-1
......@@ -9,7 +9,7 @@ const compiler_util = @import("../util.zig");
99
1010const Translator = @import("Translator.zig");
1111
12const fast_exit = @import("builtin").mode != .Debug;
12const fast_exit = @import("builtin").mode != .debug;
1313
1414pub fn main(init: process.Init) u8 {
1515 const gpa = init.gpa;
lib/compiler_rt.zig+193-177
......@@ -1,4 +1,5 @@
11const builtin = @import("builtin");
2const compiler_rt = @This();
23const ofmt_c = builtin.object_format == .c;
34const native_endian = builtin.cpu.arch.endian();
45
......@@ -84,144 +85,17 @@ comptime {
8485 // Float routines
8586 // conversion
8687 _ = @import("compiler_rt/extendf.zig");
87 _ = @import("compiler_rt/extendhfsf2.zig");
88 _ = @import("compiler_rt/extendhfdf2.zig");
89 _ = @import("compiler_rt/extendhftf2.zig");
90 _ = @import("compiler_rt/extendhfxf2.zig");
91 _ = @import("compiler_rt/extendsfdf2.zig");
92 _ = @import("compiler_rt/extendsftf2.zig");
93 _ = @import("compiler_rt/extendsfxf2.zig");
94 _ = @import("compiler_rt/extenddftf2.zig");
95 _ = @import("compiler_rt/extenddfxf2.zig");
96 _ = @import("compiler_rt/extendxftf2.zig");
97
9888 _ = @import("compiler_rt/truncf.zig");
99 _ = @import("compiler_rt/truncsfhf2.zig");
100 _ = @import("compiler_rt/truncdfhf2.zig");
101 _ = @import("compiler_rt/truncdfsf2.zig");
102 _ = @import("compiler_rt/truncxfhf2.zig");
103 _ = @import("compiler_rt/truncxfsf2.zig");
104 _ = @import("compiler_rt/truncxfdf2.zig");
105 _ = @import("compiler_rt/trunctfhf2.zig");
106 _ = @import("compiler_rt/trunctfsf2.zig");
107 _ = @import("compiler_rt/trunctfdf2.zig");
108 _ = @import("compiler_rt/trunctfxf2.zig");
109
11089 _ = @import("compiler_rt/int_from_float.zig");
111 _ = @import("compiler_rt/fixhfei.zig");
112 _ = @import("compiler_rt/fixsfsi.zig");
113 _ = @import("compiler_rt/fixsfdi.zig");
114 _ = @import("compiler_rt/fixsfti.zig");
115 _ = @import("compiler_rt/fixsfei.zig");
116 _ = @import("compiler_rt/fixdfsi.zig");
117 _ = @import("compiler_rt/fixdfdi.zig");
118 _ = @import("compiler_rt/fixdfti.zig");
119 _ = @import("compiler_rt/fixdfei.zig");
120 _ = @import("compiler_rt/fixtfsi.zig");
121 _ = @import("compiler_rt/fixtfdi.zig");
122 _ = @import("compiler_rt/fixtfti.zig");
123 _ = @import("compiler_rt/fixtfei.zig");
124 _ = @import("compiler_rt/fixxfsi.zig");
125 _ = @import("compiler_rt/fixxfdi.zig");
126 _ = @import("compiler_rt/fixxfei.zig");
127
128 _ = @import("compiler_rt/fixunshfsi.zig");
129 _ = @import("compiler_rt/fixunshfdi.zig");
130 _ = @import("compiler_rt/fixunshfti.zig");
131 _ = @import("compiler_rt/fixunshfei.zig");
132 _ = @import("compiler_rt/fixunssfsi.zig");
133 _ = @import("compiler_rt/fixunssfdi.zig");
134 _ = @import("compiler_rt/fixunssfti.zig");
135 _ = @import("compiler_rt/fixunssfei.zig");
136 _ = @import("compiler_rt/fixunsdfsi.zig");
137 _ = @import("compiler_rt/fixunsdfdi.zig");
138 _ = @import("compiler_rt/fixunsdfti.zig");
139 _ = @import("compiler_rt/fixunsdfei.zig");
140 _ = @import("compiler_rt/fixunstfsi.zig");
141 _ = @import("compiler_rt/fixunstfdi.zig");
142 _ = @import("compiler_rt/fixunstfti.zig");
143 _ = @import("compiler_rt/fixunstfei.zig");
144 _ = @import("compiler_rt/fixunsxfsi.zig");
145 _ = @import("compiler_rt/fixunsxfdi.zig");
146 _ = @import("compiler_rt/fixunsxfti.zig");
147 _ = @import("compiler_rt/fixunsxfei.zig");
148
14990 _ = @import("compiler_rt/float_from_int.zig");
150 _ = @import("compiler_rt/floatsihf.zig");
151 _ = @import("compiler_rt/floatsisf.zig");
152 _ = @import("compiler_rt/floatsidf.zig");
153 _ = @import("compiler_rt/floatsitf.zig");
154 _ = @import("compiler_rt/floatsixf.zig");
155 _ = @import("compiler_rt/floatdihf.zig");
156 _ = @import("compiler_rt/floatdisf.zig");
157 _ = @import("compiler_rt/floatdidf.zig");
158 _ = @import("compiler_rt/floatditf.zig");
159 _ = @import("compiler_rt/floatdixf.zig");
160 _ = @import("compiler_rt/floattihf.zig");
161 _ = @import("compiler_rt/floattisf.zig");
162 _ = @import("compiler_rt/floattidf.zig");
163 _ = @import("compiler_rt/floattitf.zig");
164 _ = @import("compiler_rt/floattixf.zig");
165 _ = @import("compiler_rt/floateihf.zig");
166 _ = @import("compiler_rt/floateisf.zig");
167 _ = @import("compiler_rt/floateidf.zig");
168 _ = @import("compiler_rt/floateitf.zig");
169 _ = @import("compiler_rt/floateixf.zig");
170 _ = @import("compiler_rt/floatunsihf.zig");
171 _ = @import("compiler_rt/floatunsisf.zig");
172 _ = @import("compiler_rt/floatunsidf.zig");
173 _ = @import("compiler_rt/floatunsitf.zig");
174 _ = @import("compiler_rt/floatunsixf.zig");
175 _ = @import("compiler_rt/floatundihf.zig");
176 _ = @import("compiler_rt/floatundisf.zig");
177 _ = @import("compiler_rt/floatundidf.zig");
178 _ = @import("compiler_rt/floatunditf.zig");
179 _ = @import("compiler_rt/floatundixf.zig");
180 _ = @import("compiler_rt/floatuntihf.zig");
181 _ = @import("compiler_rt/floatuntisf.zig");
182 _ = @import("compiler_rt/floatuntidf.zig");
183 _ = @import("compiler_rt/floatuntitf.zig");
184 _ = @import("compiler_rt/floatuntixf.zig");
185 _ = @import("compiler_rt/floatuneihf.zig");
186 _ = @import("compiler_rt/floatuneisf.zig");
187 _ = @import("compiler_rt/floatuneidf.zig");
188 _ = @import("compiler_rt/floatuneitf.zig");
189 _ = @import("compiler_rt/floatuneixf.zig");
19091
19192 // comparison
19293 _ = @import("compiler_rt/comparef.zig");
193 _ = @import("compiler_rt/cmpdf2.zig");
194 _ = @import("compiler_rt/cmptf2.zig");
195 _ = @import("compiler_rt/cmpxf2.zig");
196 _ = @import("compiler_rt/unorddf2.zig");
197 _ = @import("compiler_rt/gehf2.zig");
198 _ = @import("compiler_rt/gesf2.zig");
199 _ = @import("compiler_rt/gedf2.zig");
200 _ = @import("compiler_rt/gexf2.zig");
201 _ = @import("compiler_rt/getf2.zig");
20294
20395 // arithmetic
20496 _ = @import("compiler_rt/addf3.zig");
205 _ = @import("compiler_rt/addhf3.zig");
206 _ = @import("compiler_rt/addsf3.zig");
207 _ = @import("compiler_rt/adddf3.zig");
208 _ = @import("compiler_rt/addtf3.zig");
209 _ = @import("compiler_rt/addxf3.zig");
210
211 _ = @import("compiler_rt/subhf3.zig");
212 _ = @import("compiler_rt/subsf3.zig");
213 _ = @import("compiler_rt/subdf3.zig");
214 _ = @import("compiler_rt/subtf3.zig");
215 _ = @import("compiler_rt/subxf3.zig");
216
21797 _ = @import("compiler_rt/mulf3.zig");
218 _ = @import("compiler_rt/mulhf3.zig");
219 _ = @import("compiler_rt/mulsf3.zig");
220 _ = @import("compiler_rt/muldf3.zig");
221 _ = @import("compiler_rt/multf3.zig");
222 _ = @import("compiler_rt/mulxf3.zig");
22398
224 _ = @import("compiler_rt/divhf3.zig");
22599 _ = @import("compiler_rt/divsf3.zig");
226100 _ = @import("compiler_rt/divdf3.zig");
227101 _ = @import("compiler_rt/divxf3.zig");
......@@ -235,25 +109,17 @@ comptime {
235109 symbol(&__negsf2, "__negsf2");
236110 symbol(&__negdf2, "__negdf2");
237111 }
238 if (want_ppc_abi) symbol(&__negtf2, "__negkf2");
239 symbol(&__negtf2, "__negtf2");
112 if (want_ppc_abi) {
113 symbol(&__negtf2, "__negkf2");
114 } else {
115 symbol(&__negtf2, "__negtf2");
116 }
240117 symbol(&__negxf2, "__negxf2");
241118
242119 // other
243120 _ = @import("compiler_rt/powiXf2.zig");
244121 _ = @import("compiler_rt/mulc3.zig");
245 _ = @import("compiler_rt/mulhc3.zig");
246 _ = @import("compiler_rt/mulsc3.zig");
247 _ = @import("compiler_rt/muldc3.zig");
248 _ = @import("compiler_rt/mulxc3.zig");
249 _ = @import("compiler_rt/multc3.zig");
250
251122 _ = @import("compiler_rt/divc3.zig");
252 _ = @import("compiler_rt/divhc3.zig");
253 _ = @import("compiler_rt/divsc3.zig");
254 _ = @import("compiler_rt/divdc3.zig");
255 _ = @import("compiler_rt/divxc3.zig");
256 _ = @import("compiler_rt/divtc3.zig");
257123
258124 // Math routines. Alphabetically sorted.
259125 _ = @import("compiler_rt/cos.zig");
......@@ -279,7 +145,7 @@ comptime {
279145 _ = @import("compiler_rt/divmodei4.zig");
280146 _ = @import("compiler_rt/udivmodei4.zig");
281147
282 _ = @import("compiler_rt/limb64.zig");
148 if (builtin.cpu.arch.isWasm()) _ = @import("compiler_rt/limb64.zig");
283149
284150 // extra
285151 _ = @import("compiler_rt/os_version_check.zig");
......@@ -290,7 +156,7 @@ comptime {
290156 _ = @import("compiler_rt/clear_cache.zig");
291157 _ = @import("compiler_rt/hexagon.zig");
292158
293 if (@import("builtin").object_format != .c) {
159 if (builtin.object_format != .c) {
294160 if (builtin.zig_backend != .stage2_aarch64) _ = @import("compiler_rt/atomics.zig");
295161 _ = @import("compiler_rt/stack_probe.zig");
296162
......@@ -302,7 +168,6 @@ comptime {
302168 _ = @import("compiler_rt/memcpy.zig");
303169 if (!ofmt_c) {
304170 symbol(&memset, "memset");
305 symbol(&__memset, "__memset");
306171 }
307172 _ = @import("compiler_rt/memmove.zig");
308173 symbol(&memcmp, "memcmp");
......@@ -367,10 +232,7 @@ pub const want_aeabi = switch (builtin.abi) {
367232 .gnueabihf,
368233 .android,
369234 .androideabi,
370 => switch (builtin.cpu.arch) {
371 .arm, .armeb, .thumb, .thumbeb => true,
372 else => false,
373 },
235 => builtin.cpu.arch.isArm(),
374236 else => false,
375237};
376238
......@@ -444,19 +306,108 @@ pub const gnu_f16_abi = switch (builtin.cpu.arch) {
444306pub const want_sparc64_abi = builtin.cpu.arch == .sparc64;
445307pub const want_sparc32_abi = builtin.cpu.arch == .sparc;
446308
447pub fn F16T(comptime OtherType: type) type {
448 return switch (builtin.cpu.arch) {
449 .x86, .x86_64 => if (builtin.target.os.tag.isDarwin()) switch (OtherType) {
450 // Starting with LLVM 16, Darwin uses different abi for f16
451 // depending on the type of the other return/argument..???
452 f32, f64 => u16,
453 f80, f128 => f16,
454 else => unreachable,
455 } else f16,
456 else => f16,
309/// For operations converting between `f16` and another floating point type.
310pub fn f16Conv(comptime OtherType: type) type {
311 switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 16)) {
312 .hard => {},
313 .soft => return softFloatAbi(f16),
314 }
315 if (builtin.cpu.arch.isX86() and builtin.os.tag.isDarwin()) switch (OtherType) {
316 else => unreachable,
317 // Starting with LLVM 16, Darwin uses different abi for f16
318 // depending on the type of the other return/argument..???
319 f32, f64 => return softFloatAbi(f16),
320 f80, f128 => {},
321 };
322 return hardFloatAbi(f16);
323}
324pub const @"f16" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 16)) {
325 .hard => hardFloatAbi(f16),
326 .soft => softFloatAbi(f16),
327};
328pub const @"f32" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 32)) {
329 .hard => hardFloatAbi(f32),
330 .soft => softFloatAbi(f32),
331};
332pub const @"f64" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 64)) {
333 .hard => hardFloatAbi(f64),
334 .soft => softFloatAbi(f64),
335};
336pub const @"f80" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 80)) {
337 .hard => hardFloatAbi(f80),
338 .soft => struct {
339 pub const Abi = extern struct { mantissa: u64, exponent: u16 };
340 const Repr = packed struct { mantissa: u64, exponent: u16 };
341 pub inline fn toAbi(raw: f80) Abi {
342 const repr: Repr = @bitCast(raw);
343 return .{ .mantissa = repr.mantissa, .exponent = repr.exponent };
344 }
345 pub inline fn fromAbi(abi: Abi) f80 {
346 const repr: Repr = .{ .mantissa = abi.mantissa, .exponent = abi.exponent };
347 return @bitCast(repr);
348 }
349 pub const complex = complexAbi(f80, @This());
350 },
351};
352pub const @"f128" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 128)) {
353 .hard => hardFloatAbi(f128),
354 .soft => struct {
355 pub const Abi = switch (builtin.cpu.arch.endian()) {
356 .big => extern struct { hi: u64, lo: u64 },
357 .little => extern struct { lo: u64, hi: u64 },
358 };
359 const Repr = packed struct { lo: u64, hi: u64 };
360 pub inline fn toAbi(raw: f128) Abi {
361 const repr: Repr = @bitCast(raw);
362 return .{ .lo = repr.lo, .hi = repr.hi };
363 }
364 pub inline fn fromAbi(abi: Abi) f128 {
365 const repr: Repr = .{ .lo = abi.lo, .hi = abi.hi };
366 return @bitCast(repr);
367 }
368 pub const complex = complexAbi(f128, @This());
369 },
370};
371fn hardFloatAbi(comptime Float: type) type {
372 return struct {
373 pub const Abi = Float;
374 pub inline fn toAbi(raw: Float) Abi {
375 return raw;
376 }
377 pub inline fn fromAbi(abi: Abi) Float {
378 return abi;
379 }
380 pub const complex = complexAbi(Float, @This());
381 };
382}
383fn softFloatAbi(comptime Float: type) type {
384 return struct {
385 pub const Abi = @Int(.unsigned, @bitSizeOf(Float));
386 pub inline fn toAbi(raw: Float) Abi {
387 return @bitCast(raw);
388 }
389 pub inline fn fromAbi(abi: Abi) Float {
390 return @bitCast(abi);
391 }
392 pub const complex = complexAbi(Float, @This());
393 };
394}
395fn complexAbi(comptime Float: type, comptime float: type) type {
396 return struct {
397 pub const Abi = extern struct { real: float.Abi, imag: float.Abi };
398 pub inline fn toAbi(raw: Complex(Float)) Abi {
399 return .{ .real = float.toAbi(raw.real), .imag = float.toAbi(raw.imag) };
400 }
401 pub inline fn fromAbi(abi: Abi) Complex(Float) {
402 return .{ .real = float.fromAbi(abi.real), .imag = float.fromAbi(abi.imag) };
403 }
457404 };
458405}
459406
407pub fn Complex(comptime Float: type) type {
408 return struct { real: Float, imag: Float };
409}
410
460411pub fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void {
461412 switch (Z) {
462413 u16 => {
......@@ -589,31 +540,31 @@ pub inline fn fneg(a: anytype) @TypeOf(a) {
589540 return @bitCast(negated);
590541}
591542
592fn __negxf2(a: f80) callconv(.c) f80 {
593 return fneg(a);
543fn __neghf2(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
544 return compiler_rt.f16.toAbi(fneg(compiler_rt.f16.fromAbi(a)));
594545}
595546
596fn __neghf2(a: f16) callconv(.c) f16 {
597 return fneg(a);
547fn __negsf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
548 return compiler_rt.f32.toAbi(fneg(compiler_rt.f32.fromAbi(a)));
598549}
599550
600fn __negdf2(a: f64) callconv(.c) f64 {
601 return fneg(a);
551fn __negdf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
552 return compiler_rt.f64.toAbi(fneg(compiler_rt.f64.fromAbi(a)));
602553}
603554
604fn __aeabi_dneg(a: f64) callconv(.{ .arm_aapcs = .{} }) f64 {
605 return fneg(a);
555fn __negxf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
556 return compiler_rt.f80.toAbi(fneg(compiler_rt.f80.fromAbi(a)));
606557}
607558
608fn __negtf2(a: f128) callconv(.c) f128 {
609 return fneg(a);
559fn __negtf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
560 return compiler_rt.f128.toAbi(fneg(compiler_rt.f128.fromAbi(a)));
610561}
611562
612fn __negsf2(a: f32) callconv(.c) f32 {
563fn __aeabi_fneg(a: f32) callconv(.{ .arm_aapcs = .{} }) f32 {
613564 return fneg(a);
614565}
615566
616fn __aeabi_fneg(a: f32) callconv(.{ .arm_aapcs = .{} }) f32 {
567fn __aeabi_dneg(a: f64) callconv(.{ .arm_aapcs = .{} }) f64 {
617568 return fneg(a);
618569}
619570
......@@ -650,14 +601,80 @@ inline fn negXi2(comptime T: type, a: T) T {
650601 return -a;
651602}
652603
653pub fn memset(dest: ?[*]u8, c: u8, len: usize) callconv(.c) ?[*]u8 {
654 @setRuntimeSafety(false);
604fn memsetSmallPowerOf2(d: [*]u8, b: u8, comptime size: usize) void {
605 if (size > @sizeOf(usize)) {
606 d[0..size].* = @splat(b);
607 } else {
608 const T = @Int(.unsigned, 8 * size);
609 var splatted: T = 0; // Setting this to undefined causes a memset call and thus infinite recursion in Debug test-compiler-rt.
610 @as(*[size]u8, @ptrCast(&splatted)).* = @splat(b);
611 @as(*align(1) T, @ptrCast(d)).* = splatted;
612 }
613}
614
615fn shortMemset(
616 log_min: comptime_int,
617 log_max: comptime_int,
618 d: [*]u8,
619 b: u8,
620 len: usize,
621) void {
622 if (log_min + 1 != log_max) {
623 const mid = (log_min + log_max) / 2;
624 if (len > 1 << mid) {
625 shortMemset(mid, log_max, d, b, len);
626 } else {
627 shortMemset(log_min, mid, d, b, len);
628 }
629 } else {
630 const size = 1 << log_min;
631
632 memsetSmallPowerOf2(d, b, size);
633 memsetSmallPowerOf2(d + len - size, b, size);
634 }
635}
636
637fn fastMemset(dest: ?[*]u8, c: c_int, len: usize) callconv(.c) ?[*]u8 {
638 const b: u8 = @truncate(@as(c_uint, @bitCast(c)));
639 const n = std.simd.suggestVectorLength(u8) orelse @sizeOf(usize);
640
641 const d = dest.?;
642
643 if (len > 2 * n) {
644 memsetSmallPowerOf2(d, b, n);
645
646 const begin_aligned = std.mem.alignBackward(usize, @intFromPtr(d) + n, n);
647 const end_aligned = std.mem.alignForward(usize, @intFromPtr(d) + len - n, n);
648
649 const aligned_ptr: [*]align(n) u8 = @ptrFromInt(begin_aligned);
650
651 var i: usize = 0;
652 while (true) {
653 memsetSmallPowerOf2(aligned_ptr + n * i, b, n);
654
655 i += 1;
656 if (i == @divExact(end_aligned - begin_aligned, n))
657 break;
658 }
659
660 memsetSmallPowerOf2(d + len - n, b, n);
661 } else {
662 if (len == 0) return dest;
663
664 shortMemset(0, @ctz(@as(usize, 2 * n)), d, b, len);
665 }
666
667 return dest;
668}
669
670fn smallMemset(dest: ?[*]u8, c: c_int, len: usize) callconv(.c) ?[*]u8 {
671 const b: u8 = @truncate(@as(c_uint, @bitCast(c)));
655672
656673 if (len != 0) {
657674 var d = dest.?;
658675 var n = len;
659676 while (true) {
660 d[0] = c;
677 d[0] = b;
661678 n -= 1;
662679 if (n == 0) break;
663680 d += 1;
......@@ -667,11 +684,10 @@ pub fn memset(dest: ?[*]u8, c: u8, len: usize) callconv(.c) ?[*]u8 {
667684 return dest;
668685}
669686
670pub fn __memset(dest: ?[*]u8, c: u8, n: usize, dest_n: usize) callconv(.c) ?[*]u8 {
671 if (dest_n < n)
672 @panic("buffer overflow");
673 return memset(dest, c, n);
674}
687pub const memset = if (builtin.optimize == .small)
688 smallMemset
689else
690 fastMemset;
675691
676692pub fn bcmp(vl: [*]allowzero const u8, vr: [*]allowzero const u8, n: usize) callconv(.c) c_int {
677693 @setRuntimeSafety(false);
lib/compiler_rt/absv.zig+1-2
......@@ -14,8 +14,7 @@ pub inline fn absv(comptime ST: type, a: ST) ST {
1414 const sign: ST = a >> N - 1;
1515 x +%= sign;
1616 x ^= sign;
17 if (x < 0)
18 @panic("compiler_rt absv: overflow");
17 if (x < 0) @panic("integer overflow");
1918 return x;
2019}
2120
lib/compiler_rt/absvdi2.zig+3-2
......@@ -1,5 +1,6 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const absv = @import("./absv.zig").absv;
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const absv = @import("absv.zig").absv;
34
45comptime {
56 symbol(&__absvdi2, "__absvdi2");
lib/compiler_rt/absvsi2.zig+1-1
......@@ -1,6 +1,6 @@
11const compiler_rt = @import("../compiler_rt.zig");
22const symbol = compiler_rt.symbol;
3const absv = @import("./absv.zig").absv;
3const absv = @import("absv.zig").absv;
44
55comptime {
66 symbol(&__absvsi2, "__absvsi2");
lib/compiler_rt/absvti2.zig+3-2
......@@ -1,5 +1,6 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const absv = @import("./absv.zig").absv;
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const absv = @import("absv.zig").absv;
34
45comptime {
56 symbol(&__absvti2, "__absvti2");
lib/compiler_rt/adddf3.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const addf3 = @import("./addf3.zig").addf3;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_dadd, "__aeabi_dadd");
8 } else {
9 symbol(&__adddf3, "__adddf3");
10 }
11}
12
13fn __adddf3(a: f64, b: f64) callconv(.c) f64 {
14 return addf3(f64, a, b);
15}
16
17fn __aeabi_dadd(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 {
18 return addf3(f64, a, b);
19}
lib/compiler_rt/addf3.zig+132-1
......@@ -1,12 +1,143 @@
11const std = @import("std");
22const math = std.math;
33const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
45const normalize = compiler_rt.normalize;
56
7comptime {
8 symbol(&__addhf3, "__addhf3");
9 if (compiler_rt.want_aeabi) {
10 symbol(&__aeabi_fadd, "__aeabi_fadd");
11 symbol(&__aeabi_dadd, "__aeabi_dadd");
12 } else {
13 symbol(&__addsf3, "__addsf3");
14 symbol(&__adddf3, "__adddf3");
15 }
16 symbol(&__addxf3, "__addxf3");
17 if (compiler_rt.want_ppc_abi) {
18 symbol(&__addtf3, "__addkf3");
19 } else if (compiler_rt.want_sparc64_abi) {
20 symbol(&_Qp_add, "_Qp_add");
21 } else if (compiler_rt.want_sparc32_abi) {
22 symbol(&__addtf3, "_Q_add");
23 } else {
24 symbol(&__addtf3, "__addtf3");
25 }
26}
27
28fn __addhf3(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
29 return compiler_rt.f16.toAbi(add_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)));
30}
31pub fn add_f16(a: f16, b: f16) f16 {
32 return addf3(f16, a, b);
33}
34
35fn __addsf3(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
36 return compiler_rt.f32.toAbi(add_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)));
37}
38fn __aeabi_fadd(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 {
39 return add_f32(a, b);
40}
41pub fn add_f32(a: f32, b: f32) f32 {
42 return addf3(f32, a, b);
43}
44
45fn __adddf3(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
46 return compiler_rt.f64.toAbi(add_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)));
47}
48fn __aeabi_dadd(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 {
49 return add_f64(a, b);
50}
51pub fn add_f64(a: f64, b: f64) f64 {
52 return addf3(f64, a, b);
53}
54
55fn __addxf3(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
56 return compiler_rt.f80.toAbi(add_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b)));
57}
58pub fn add_f80(a: f80, b: f80) f80 {
59 return addf3(f80, a, b);
60}
61
62fn __addtf3(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
63 return compiler_rt.f128.toAbi(add_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)));
64}
65fn _Qp_add(c: *f128, a: *f128, b: *f128) callconv(.c) void {
66 c.* = add_f128(a.*, b.*);
67}
68pub fn add_f128(a: f128, b: f128) f128 {
69 return addf3(f128, a, b);
70}
71
72comptime {
73 symbol(&__subhf3, "__subhf3");
74 if (compiler_rt.want_aeabi) {
75 symbol(&__aeabi_fsub, "__aeabi_fsub");
76 symbol(&__aeabi_dsub, "__aeabi_dsub");
77 } else {
78 symbol(&__subsf3, "__subsf3");
79 symbol(&__subdf3, "__subdf3");
80 }
81 symbol(&__subxf3, "__subxf3");
82 if (compiler_rt.want_ppc_abi) {
83 symbol(&__subtf3, "__subkf3");
84 } else if (compiler_rt.want_sparc64_abi) {
85 symbol(&_Qp_sub, "_Qp_sub");
86 } else if (compiler_rt.want_sparc32_abi) {
87 symbol(&__subtf3, "_Q_sub");
88 } else {
89 symbol(&__subtf3, "__subtf3");
90 }
91}
92
93fn __subhf3(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
94 return compiler_rt.f16.toAbi(sub_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)));
95}
96pub fn sub_f16(a: f16, b: f16) f16 {
97 return add_f16(a, compiler_rt.fneg(b));
98}
99
100fn __subsf3(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
101 return compiler_rt.f32.toAbi(sub_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)));
102}
103fn __aeabi_fsub(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 {
104 return sub_f32(a, b);
105}
106pub fn sub_f32(a: f32, b: f32) f32 {
107 return add_f32(a, compiler_rt.fneg(b));
108}
109
110fn __subdf3(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
111 return compiler_rt.f64.toAbi(sub_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)));
112}
113fn __aeabi_dsub(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 {
114 return sub_f64(a, b);
115}
116pub fn sub_f64(a: f64, b: f64) f64 {
117 return add_f64(a, compiler_rt.fneg(b));
118}
119
120fn __subxf3(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
121 return compiler_rt.f80.toAbi(sub_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b)));
122}
123pub fn sub_f80(a: f80, b: f80) f80 {
124 return add_f80(a, compiler_rt.fneg(b));
125}
126
127fn __subtf3(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
128 return compiler_rt.f128.toAbi(sub_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)));
129}
130fn _Qp_sub(c: *f128, a: *const f128, b: *const f128) callconv(.c) void {
131 c.* = sub_f128(a.*, b.*);
132}
133pub fn sub_f128(a: f128, b: f128) f128 {
134 return add_f128(a, compiler_rt.fneg(b));
135}
136
6137/// Ported from:
7138///
8139/// https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/lib/builtins/fp_add_impl.inc
9pub inline fn addf3(comptime T: type, a: T, b: T) T {
140inline fn addf3(comptime T: type, a: T, b: T) T {
10141 const bits = @typeInfo(T).float.bits;
11142 const Z = @Int(.unsigned, bits);
12143
lib/compiler_rt/addf3_test.zig+7-6
......@@ -8,12 +8,13 @@ const builtin = @import("builtin");
88const math = std.math;
99const qnan128: f128 = @bitCast(@as(u128, 0x7fff800000000000) << 64);
1010
11const __addtf3 = @import("addtf3.zig").__addtf3;
12const __addxf3 = @import("addxf3.zig").__addxf3;
13const __subtf3 = @import("subtf3.zig").__subtf3;
11const impl = @import("addf3.zig");
12const add_f128 = impl.add_f128;
13const add_f80 = impl.add_f80;
14const sub_f128 = impl.sub_f128;
1415
1516fn test__addtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void {
16 const x = __addtf3(a, b);
17 const x = add_f128(a, b);
1718
1819 const rep: u128 = @bitCast(x);
1920 const hi: u64 = @intCast(rep >> 64);
......@@ -52,7 +53,7 @@ test "addtf3" {
5253}
5354
5455fn test__subtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void {
55 const x = __subtf3(a, b);
56 const x = sub_f128(a, b);
5657
5758 const rep: u128 = @bitCast(x);
5859 const hi: u64 = @intCast(rep >> 64);
......@@ -91,7 +92,7 @@ test "subtf3" {
9192const qnan80: f80 = @bitCast(@as(u80, @bitCast(math.nan(f80))) | (1 << (math.floatFractionalBits(f80) - 1)));
9293
9394fn test__addxf3(a: f80, b: f80, expected: u80) !void {
94 const x = __addxf3(a, b);
95 const x = add_f80(a, b);
9596 const rep: u80 = @bitCast(x);
9697
9798 if (rep == expected)
lib/compiler_rt/addhf3.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const addf3 = @import("./addf3.zig").addf3;
4
5comptime {
6 symbol(&__addhf3, "__addhf3");
7}
8
9fn __addhf3(a: f16, b: f16) callconv(.c) f16 {
10 return addf3(f16, a, b);
11}
lib/compiler_rt/addsf3.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const addf3 = @import("./addf3.zig").addf3;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_fadd, "__aeabi_fadd");
8 } else {
9 symbol(&__addsf3, "__addsf3");
10 }
11}
12
13fn __addsf3(a: f32, b: f32) callconv(.c) f32 {
14 return addf3(f32, a, b);
15}
16
17fn __aeabi_fadd(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 {
18 return addf3(f32, a, b);
19}
lib/compiler_rt/addtf3.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const addf3 = @import("./addf3.zig").addf3;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__addtf3, "__addkf3");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_add, "_Qp_add");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__addtf3, "_Q_add");
12 }
13 symbol(&__addtf3, "__addtf3");
14}
15
16pub fn __addtf3(a: f128, b: f128) callconv(.c) f128 {
17 return addf3(f128, a, b);
18}
19
20fn _Qp_add(c: *f128, a: *f128, b: *f128) callconv(.c) void {
21 c.* = addf3(f128, a.*, b.*);
22}
lib/compiler_rt/addvdi3.zig+3-2
......@@ -1,4 +1,5 @@
1const symbol = @import("../compiler_rt.zig").symbol;
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
23const testing = @import("std").testing;
34
45comptime {
......@@ -9,7 +10,7 @@ pub fn __addvdi3(a: i64, b: i64) callconv(.c) i64 {
910 const sum = a +% b;
1011 // Overflow occurred iff both operands have the same sign, and the sign of the sum does
1112 // not match it. In other words, iff the sum sign is not the sign of either operand.
12 if (((sum ^ a) & (sum ^ b)) < 0) @panic("compiler-rt: integer overflow");
13 if (((sum ^ a) & (sum ^ b)) < 0) @panic("integer overflow");
1314 return sum;
1415}
1516
lib/compiler_rt/addvsi3.zig+1-1
......@@ -10,7 +10,7 @@ pub fn __addvsi3(a: i32, b: i32) callconv(.c) i32 {
1010 const sum = a +% b;
1111 // Overflow occurred iff both operands have the same sign, and the sign of the sum does
1212 // not match it. In other words, iff the sum sign is not the sign of either operand.
13 if (((sum ^ a) & (sum ^ b)) < 0) @panic("compiler-rt: integer overflow");
13 if (((sum ^ a) & (sum ^ b)) < 0) @panic("integer overflow");
1414 return sum;
1515}
1616
lib/compiler_rt/addxf3.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const addf3 = @import("./addf3.zig").addf3;
4
5comptime {
6 symbol(&__addxf3, "__addxf3");
7}
8
9pub fn __addxf3(a: f80, b: f80) callconv(.c) f80 {
10 return addf3(f80, a, b);
11}
lib/compiler_rt/atomics.zig+1-1
......@@ -5,7 +5,7 @@ const arch = cpu.arch;
55const std = @import("std");
66
77const compiler_rt = @import("../compiler_rt.zig");
8const symbol = @import("../compiler_rt.zig").symbol;
8const symbol = compiler_rt.symbol;
99
1010// This parameter is true iff the target architecture supports the bare minimum
1111// to implement the atomic load/store intrinsics.
lib/compiler_rt/aulldiv.zig+1-1
......@@ -1,7 +1,7 @@
11const builtin = @import("builtin");
22
33const compiler_rt = @import("../compiler_rt.zig");
4const symbol = @import("../compiler_rt.zig").symbol;
4const symbol = compiler_rt.symbol;
55
66comptime {
77 if (compiler_rt.want_windows_x86_msvc_abi) {
lib/compiler_rt/cmpdf2.zig deleted-67
......@@ -1,67 +0,0 @@
1///! The quoted behavior definitions are from
2///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines
3const compiler_rt = @import("../compiler_rt.zig");
4const comparef = @import("./comparef.zig");
5const symbol = @import("../compiler_rt.zig").symbol;
6
7comptime {
8 if (compiler_rt.want_aeabi) {
9 symbol(&__aeabi_dcmpeq, "__aeabi_dcmpeq");
10 symbol(&__aeabi_dcmplt, "__aeabi_dcmplt");
11 symbol(&__aeabi_dcmple, "__aeabi_dcmple");
12 } else {
13 symbol(&__eqdf2, "__eqdf2");
14 symbol(&__nedf2, "__nedf2");
15 symbol(&__ledf2, "__ledf2");
16 symbol(&__cmpdf2, "__cmpdf2");
17 symbol(&__ltdf2, "__ltdf2");
18 }
19}
20
21/// "These functions calculate a <=> b. That is, if a is less than b, they return -1;
22/// if a is greater than b, they return 1; and if a and b are equal they return 0.
23/// If either argument is NaN they return 1..."
24///
25/// Note that this matches the definition of `__ledf2`, `__eqdf2`, `__nedf2`, `__cmpdf2`,
26/// and `__ltdf2`.
27fn __cmpdf2(a: f64, b: f64) callconv(.c) i32 {
28 return @backingInt(comparef.cmpf2(f64, comparef.LE, a, b));
29}
30
31/// "These functions return a value less than or equal to zero if neither argument is NaN,
32/// and a is less than or equal to b."
33pub fn __ledf2(a: f64, b: f64) callconv(.c) i32 {
34 return __cmpdf2(a, b);
35}
36
37/// "These functions return zero if neither argument is NaN, and a and b are equal."
38/// Note that due to some kind of historical accident, __eqdf2 and __nedf2 are defined
39/// to have the same return value.
40pub fn __eqdf2(a: f64, b: f64) callconv(.c) i32 {
41 return __cmpdf2(a, b);
42}
43
44/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal."
45/// Note that due to some kind of historical accident, __eqdf2 and __nedf2 are defined
46/// to have the same return value.
47pub fn __nedf2(a: f64, b: f64) callconv(.c) i32 {
48 return __cmpdf2(a, b);
49}
50
51/// "These functions return a value less than zero if neither argument is NaN, and a
52/// is strictly less than b."
53pub fn __ltdf2(a: f64, b: f64) callconv(.c) i32 {
54 return __cmpdf2(a, b);
55}
56
57fn __aeabi_dcmpeq(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
58 return @intFromBool(comparef.cmpf2(f64, comparef.LE, a, b) == .Equal);
59}
60
61fn __aeabi_dcmplt(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
62 return @intFromBool(comparef.cmpf2(f64, comparef.LE, a, b) == .Less);
63}
64
65fn __aeabi_dcmple(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
66 return @intFromBool(comparef.cmpf2(f64, comparef.LE, a, b) != .Greater);
67}
lib/compiler_rt/cmptf2.zig deleted-146
......@@ -1,146 +0,0 @@
1///! The quoted behavior definitions are from
2///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines
3const compiler_rt = @import("../compiler_rt.zig");
4const comparef = @import("./comparef.zig");
5const symbol = @import("../compiler_rt.zig").symbol;
6
7comptime {
8 if (compiler_rt.want_ppc_abi) {
9 symbol(&__eqtf2, "__eqkf2");
10 symbol(&__netf2, "__nekf2");
11 symbol(&__lttf2, "__ltkf2");
12 symbol(&__letf2, "__lekf2");
13 } else if (compiler_rt.want_sparc64_abi) {
14 symbol(&_Qp_cmp, "_Qp_cmp");
15 symbol(&_Qp_feq, "_Qp_feq");
16 symbol(&_Qp_fne, "_Qp_fne");
17 symbol(&_Qp_flt, "_Qp_flt");
18 symbol(&_Qp_fle, "_Qp_fle");
19 symbol(&_Qp_fgt, "_Qp_fgt");
20 symbol(&_Qp_fge, "_Qp_fge");
21 } else if (compiler_rt.want_sparc32_abi) {
22 symbol(&_Q_cmp, "_Q_cmp");
23 symbol(&_Q_feq, "_Q_feq");
24 symbol(&_Q_fne, "_Q_fne");
25 symbol(&_Q_flt, "_Q_flt");
26 symbol(&_Q_fle, "_Q_fle");
27 symbol(&_Q_fgt, "_Q_fgt");
28 symbol(&_Q_fge, "_Q_fge");
29 }
30 symbol(&__eqtf2, "__eqtf2");
31 symbol(&__netf2, "__netf2");
32 symbol(&__letf2, "__letf2");
33 symbol(&__cmptf2, "__cmptf2");
34 symbol(&__lttf2, "__lttf2");
35}
36
37/// "These functions calculate a <=> b. That is, if a is less than b, they return -1;
38/// if a is greater than b, they return 1; and if a and b are equal they return 0.
39/// If either argument is NaN they return 1..."
40///
41/// Note that this matches the definition of `__letf2`, `__eqtf2`, `__netf2`, `__cmptf2`,
42/// and `__lttf2`.
43fn __cmptf2(a: f128, b: f128) callconv(.c) i32 {
44 return @backingInt(comparef.cmpf2(f128, comparef.LE, a, b));
45}
46
47/// "These functions return a value less than or equal to zero if neither argument is NaN,
48/// and a is less than or equal to b."
49fn __letf2(a: f128, b: f128) callconv(.c) i32 {
50 return __cmptf2(a, b);
51}
52
53/// "These functions return zero if neither argument is NaN, and a and b are equal."
54/// Note that due to some kind of historical accident, __eqtf2 and __netf2 are defined
55/// to have the same return value.
56fn __eqtf2(a: f128, b: f128) callconv(.c) i32 {
57 return __cmptf2(a, b);
58}
59
60/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal."
61/// Note that due to some kind of historical accident, __eqtf2 and __netf2 are defined
62/// to have the same return value.
63fn __netf2(a: f128, b: f128) callconv(.c) i32 {
64 return __cmptf2(a, b);
65}
66
67/// "These functions return a value less than zero if neither argument is NaN, and a
68/// is strictly less than b."
69fn __lttf2(a: f128, b: f128) callconv(.c) i32 {
70 return __cmptf2(a, b);
71}
72
73const SparcFCMP = enum(i32) {
74 Equal = 0,
75 Less = 1,
76 Greater = 2,
77 Unordered = 3,
78};
79
80fn _Qp_cmp(a: *const f128, b: *const f128) callconv(.c) i32 {
81 return @backingInt(comparef.cmpf2(f128, SparcFCMP, a.*, b.*));
82}
83
84fn _Qp_feq(a: *const f128, b: *const f128) callconv(.c) bool {
85 return @as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b)))) == .Equal;
86}
87
88fn _Qp_fne(a: *const f128, b: *const f128) callconv(.c) bool {
89 return @as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b)))) != .Equal;
90}
91
92fn _Qp_flt(a: *const f128, b: *const f128) callconv(.c) bool {
93 return @as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b)))) == .Less;
94}
95
96fn _Qp_fgt(a: *const f128, b: *const f128) callconv(.c) bool {
97 return @as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b)))) == .Greater;
98}
99
100fn _Qp_fge(a: *const f128, b: *const f128) callconv(.c) bool {
101 return switch (@as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b))))) {
102 .Equal, .Greater => true,
103 .Less, .Unordered => false,
104 };
105}
106
107fn _Qp_fle(a: *const f128, b: *const f128) callconv(.c) bool {
108 return switch (@as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b))))) {
109 .Equal, .Less => true,
110 .Greater, .Unordered => false,
111 };
112}
113
114fn _Q_cmp(a: f128, b: f128) callconv(.c) i32 {
115 return @backingInt(comparef.cmpf2(f128, SparcFCMP, a, b));
116}
117
118fn _Q_feq(a: f128, b: f128) callconv(.c) bool {
119 return @as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b)))) == .Equal;
120}
121
122fn _Q_fne(a: f128, b: f128) callconv(.c) bool {
123 return @as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b)))) != .Equal;
124}
125
126fn _Q_flt(a: f128, b: f128) callconv(.c) bool {
127 return @as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b)))) == .Less;
128}
129
130fn _Q_fgt(a: f128, b: f128) callconv(.c) bool {
131 return @as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b)))) == .Greater;
132}
133
134fn _Q_fge(a: f128, b: f128) callconv(.c) bool {
135 return switch (@as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b))))) {
136 .Equal, .Greater => true,
137 .Less, .Unordered => false,
138 };
139}
140
141fn _Q_fle(a: f128, b: f128) callconv(.c) bool {
142 return switch (@as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b))))) {
143 .Equal, .Less => true,
144 .Greater, .Unordered => false,
145 };
146}
lib/compiler_rt/cmpxf2.zig deleted-49
......@@ -1,49 +0,0 @@
1///! The quoted behavior definitions are from
2///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const comparef = @import("./comparef.zig");
6
7comptime {
8 symbol(&__eqxf2, "__eqxf2");
9 symbol(&__nexf2, "__nexf2");
10 symbol(&__lexf2, "__lexf2");
11 symbol(&__cmpxf2, "__cmpxf2");
12 symbol(&__ltxf2, "__ltxf2");
13}
14
15/// "These functions calculate a <=> b. That is, if a is less than b, they return -1;
16/// if a is greater than b, they return 1; and if a and b are equal they return 0.
17/// If either argument is NaN they return 1..."
18///
19/// Note that this matches the definition of `__lexf2`, `__eqxf2`, `__nexf2`, `__cmpxf2`,
20/// and `__ltxf2`.
21fn __cmpxf2(a: f80, b: f80) callconv(.c) i32 {
22 return @backingInt(comparef.cmp_f80(comparef.LE, a, b));
23}
24
25/// "These functions return a value less than or equal to zero if neither argument is NaN,
26/// and a is less than or equal to b."
27fn __lexf2(a: f80, b: f80) callconv(.c) i32 {
28 return __cmpxf2(a, b);
29}
30
31/// "These functions return zero if neither argument is NaN, and a and b are equal."
32/// Note that due to some kind of historical accident, __eqxf2 and __nexf2 are defined
33/// to have the same return value.
34fn __eqxf2(a: f80, b: f80) callconv(.c) i32 {
35 return __cmpxf2(a, b);
36}
37
38/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal."
39/// Note that due to some kind of historical accident, __eqxf2 and __nexf2 are defined
40/// to have the same return value.
41fn __nexf2(a: f80, b: f80) callconv(.c) i32 {
42 return __cmpxf2(a, b);
43}
44
45/// "These functions return a value less than zero if neither argument is NaN, and a
46/// is strictly less than b."
47fn __ltxf2(a: f80, b: f80) callconv(.c) i32 {
48 return __cmpxf2(a, b);
49}
lib/compiler_rt/comparedf2_test.zig+17-73
......@@ -5,52 +5,12 @@
55const std = @import("std");
66const builtin = @import("builtin");
77
8const __eqdf2 = @import("./cmpdf2.zig").__eqdf2;
9const __ledf2 = @import("./cmpdf2.zig").__ledf2;
10const __ltdf2 = @import("./cmpdf2.zig").__ltdf2;
11const __nedf2 = @import("./cmpdf2.zig").__nedf2;
8const compiler_rt = @import("../compiler_rt.zig");
129
13const __gedf2 = @import("./gedf2.zig").__gedf2;
14const __gtdf2 = @import("./gedf2.zig").__gtdf2;
15
16const __unorddf2 = @import("./unorddf2.zig").__unorddf2;
17
18const TestVector = struct {
19 a: f64,
20 b: f64,
21 eqReference: c_int,
22 geReference: c_int,
23 gtReference: c_int,
24 leReference: c_int,
25 ltReference: c_int,
26 neReference: c_int,
27 unReference: c_int,
28};
29
30fn test__cmpdf2(vector: TestVector) bool {
31 if (__eqdf2(vector.a, vector.b) != vector.eqReference) {
32 return false;
33 }
34 if (__gedf2(vector.a, vector.b) != vector.geReference) {
35 return false;
36 }
37 if (__gtdf2(vector.a, vector.b) != vector.gtReference) {
38 return false;
39 }
40 if (__ledf2(vector.a, vector.b) != vector.leReference) {
41 return false;
42 }
43 if (__ltdf2(vector.a, vector.b) != vector.ltReference) {
44 return false;
45 }
46 if (__nedf2(vector.a, vector.b) != vector.neReference) {
47 return false;
48 }
49 if (__unorddf2(vector.a, vector.b) != vector.unReference) {
50 return false;
51 }
52 return true;
53}
10const impl = @import("comparef.zig");
11const Order = impl.Order;
12const cmp_f64 = impl.cmp_f64;
13const unord_f64 = impl.unord_f64;
5414
5515const arguments = [_]f64{
5616 std.math.nan(f64),
......@@ -73,36 +33,20 @@ const arguments = [_]f64{
7333 std.math.inf(f64),
7434};
7535
76fn generateVector(comptime a: f64, comptime b: f64) TestVector {
77 const leResult = if (a < b) -1 else if (a == b) 0 else 1;
78 const geResult = if (a > b) 1 else if (a == b) 0 else -1;
79 const unResult = if (a != a or b != b) 1 else 0;
80 return TestVector{
81 .a = a,
82 .b = b,
83 .eqReference = leResult,
84 .geReference = geResult,
85 .gtReference = geResult,
86 .leReference = leResult,
87 .ltReference = leResult,
88 .neReference = leResult,
89 .unReference = unResult,
90 };
91}
92
93const test_vectors = init: {
94 @setEvalBranchQuota(10000);
95 var vectors: [arguments.len * arguments.len]TestVector = undefined;
36test "compare f64" {
9637 for (arguments[0..], 0..) |arg_i, i| {
9738 for (arguments[0..], 0..) |arg_j, j| {
98 vectors[(i * arguments.len) + j] = generateVector(arg_i, arg_j);
39 const expected_unord = i == 0 or j == 0;
40 const expected_order: ?Order = if (expected_unord) null else switch (std.math.order(
41 if (i >= 9) i - 1 else i,
42 if (j >= 9) j - 1 else j,
43 )) {
44 .lt => .lt,
45 .eq => .eq,
46 .gt => .gt,
47 };
48 try std.testing.expect(expected_order == cmp_f64(arg_i, arg_j));
49 try std.testing.expect(expected_unord == unord_f64(arg_i, arg_j));
9950 }
10051 }
101 break :init vectors;
102};
103
104test "compare f64" {
105 for (test_vectors) |vector| {
106 try std.testing.expect(test__cmpdf2(vector));
107 }
10852}
lib/compiler_rt/comparef.zig+274-167
......@@ -1,163 +1,309 @@
1const builtin = @import("builtin");
12const std = @import("std");
23
34const compiler_rt = @import("../compiler_rt.zig");
45const symbol = compiler_rt.symbol;
56
6comptime {
7 if (compiler_rt.want_aeabi) {
8 symbol(&__aeabi_fcmpun, "__aeabi_fcmpun");
9 } else {
10 symbol(&__unordsf2, "__unordsf2");
11 }
12
13 symbol(&__unordxf2, "__unordxf2");
7const Unordered = if (builtin.cpu.arch == .avr)
8 i8
9else if (builtin.cpu.arch.isAARCH64())
10 i32
11else if (builtin.target.cTypeBitSize(.long).? >= builtin.target.ptrBitWidth())
12 c_long
13else
14 c_longlong;
15pub const Order = enum(Unordered) { lt = -1, eq = 0, gt = 1 };
16const SparcOrder = enum(i32) { eq = 0, lt = 1, gt = 2, un = 3 };
1417
15 symbol(&__eqhf2, "__eqhf2");
16 symbol(&__nehf2, "__nehf2");
17 symbol(&__lehf2, "__lehf2");
18comptime {
1819 symbol(&__cmphf2, "__cmphf2");
19 symbol(&__lthf2, "__lthf2");
20 symbol(&__cmphf2, "__eqhf2");
21 symbol(&__cmphf2, "__nehf2");
22 symbol(&__cmphf2, "__lthf2");
23 symbol(&__cmphf2, "__lehf2");
24 symbol(&__gehf2, "__gthf2");
25 symbol(&__gehf2, "__gehf2");
26 symbol(&__unordhf2, "__unordhf2");
2027
2128 if (compiler_rt.want_aeabi) {
2229 symbol(&__aeabi_fcmpeq, "__aeabi_fcmpeq");
2330 symbol(&__aeabi_fcmplt, "__aeabi_fcmplt");
2431 symbol(&__aeabi_fcmple, "__aeabi_fcmple");
32 symbol(&__aeabi_fcmpgt, "__aeabi_fcmpgt");
33 symbol(&__aeabi_fcmpge, "__aeabi_fcmpge");
34 symbol(&__aeabi_fcmpun, "__aeabi_fcmpun");
35
36 symbol(&__aeabi_dcmpeq, "__aeabi_dcmpeq");
37 symbol(&__aeabi_dcmplt, "__aeabi_dcmplt");
38 symbol(&__aeabi_dcmple, "__aeabi_dcmple");
39 symbol(&__aeabi_dcmpgt, "__aeabi_dcmpgt");
40 symbol(&__aeabi_dcmpge, "__aeabi_dcmpge");
41 symbol(&__aeabi_dcmpun, "__aeabi_dcmpun");
2542 } else {
26 symbol(&__eqsf2, "__eqsf2");
27 symbol(&__nesf2, "__nesf2");
28 symbol(&__lesf2, "__lesf2");
2943 symbol(&__cmpsf2, "__cmpsf2");
30 symbol(&__ltsf2, "__ltsf2");
44 symbol(&__cmpsf2, "__eqsf2");
45 symbol(&__cmpsf2, "__nesf2");
46 symbol(&__cmpsf2, "__ltsf2");
47 symbol(&__cmpsf2, "__lesf2");
48 symbol(&__gesf2, "__gtsf2");
49 symbol(&__gesf2, "__gesf2");
50 symbol(&__unordsf2, "__unordsf2");
51
52 symbol(&__cmpdf2, "__cmpdf2");
53 symbol(&__cmpdf2, "__eqdf2");
54 symbol(&__cmpdf2, "__nedf2");
55 symbol(&__cmpdf2, "__ltdf2");
56 symbol(&__cmpdf2, "__ledf2");
57 symbol(&__gedf2, "__gtdf2");
58 symbol(&__gedf2, "__gedf2");
59 symbol(&__unorddf2, "__unorddf2");
3160 }
3261
62 symbol(&__cmpxf2, "__cmpxf2");
63 symbol(&__cmpxf2, "__eqxf2");
64 symbol(&__cmpxf2, "__nexf2");
65 symbol(&__cmpxf2, "__ltxf2");
66 symbol(&__cmpxf2, "__lexf2");
67 symbol(&__gexf2, "__gtxf2");
68 symbol(&__gexf2, "__gexf2");
69 symbol(&__unordxf2, "__unordxf2");
70
3371 if (compiler_rt.want_ppc_abi) {
72 symbol(&__cmptf2, "__eqkf2");
73 symbol(&__cmptf2, "__nekf2");
74 symbol(&__cmptf2, "__ltkf2");
75 symbol(&__cmptf2, "__lekf2");
76 symbol(&__getf2, "__gtkf2");
77 symbol(&__getf2, "__gekf2");
3478 symbol(&__unordtf2, "__unordkf2");
79 } else if (compiler_rt.want_sparc64_abi) {
80 symbol(&_Qp_cmp, "_Qp_cmp");
81 symbol(&_Qp_feq, "_Qp_feq");
82 symbol(&_Qp_fne, "_Qp_fne");
83 symbol(&_Qp_flt, "_Qp_flt");
84 symbol(&_Qp_fle, "_Qp_fle");
85 symbol(&_Qp_fgt, "_Qp_fgt");
86 symbol(&_Qp_fge, "_Qp_fge");
87 } else if (compiler_rt.want_sparc32_abi) {
88 symbol(&_Q_cmp, "_Q_cmp");
89 symbol(&_Q_feq, "_Q_feq");
90 symbol(&_Q_fne, "_Q_fne");
91 symbol(&_Q_flt, "_Q_flt");
92 symbol(&_Q_fle, "_Q_fle");
93 symbol(&_Q_fgt, "_Q_fgt");
94 symbol(&_Q_fge, "_Q_fge");
95 } else {
96 symbol(&__cmptf2, "__cmptf2");
97 symbol(&__cmptf2, "__eqtf2");
98 symbol(&__cmptf2, "__netf2");
99 symbol(&__cmptf2, "__lttf2");
100 symbol(&__cmptf2, "__letf2");
101 symbol(&__getf2, "__gttf2");
102 symbol(&__getf2, "__getf2");
103 symbol(&__unordtf2, "__unordtf2");
35104 }
36 symbol(&__unordtf2, "__unordtf2");
37 symbol(&__unordhf2, "__unordhf2");
38}
39
40pub fn __unordhf2(a: f16, b: f16) callconv(.c) i32 {
41 return unordcmp(f16, a, b);
42105}
43106
44pub fn __unordtf2(a: f128, b: f128) callconv(.c) i32 {
45 return unordcmp(f128, a, b);
107fn __cmphf2(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) Order {
108 return cmp_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)) orelse .gt;
46109}
47
48/// "These functions calculate a <=> b. That is, if a is less than b, they return -1;
49/// if a is greater than b, they return 1; and if a and b are equal they return 0.
50/// If either argument is NaN they return 1..."
51///
52/// Note that this matches the definition of `__lesf2`, `__eqsf2`, `__nesf2`, `__cmpsf2`,
53/// and `__ltsf2`.
54fn __cmpsf2(a: f32, b: f32) callconv(.c) i32 {
55 return @backingInt(cmpf2(f32, LE, a, b));
110fn __gehf2(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) Order {
111 return cmp_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)) orelse .lt;
56112}
57
58/// "These functions return a value less than or equal to zero if neither argument is NaN,
59/// and a is less than or equal to b."
60pub fn __lesf2(a: f32, b: f32) callconv(.c) i32 {
61 return __cmpsf2(a, b);
113fn __unordhf2(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) Unordered {
114 return @intFromBool(unord_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)));
62115}
63
64/// "These functions return zero if neither argument is NaN, and a and b are equal."
65/// Note that due to some kind of historical accident, __eqsf2 and __nesf2 are defined
66/// to have the same return value.
67pub fn __eqsf2(a: f32, b: f32) callconv(.c) i32 {
68 return __cmpsf2(a, b);
116pub fn cmp_f16(a: f16, b: f16) ?Order {
117 return cmpf2(f16, a, b);
69118}
70
71/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal."
72/// Note that due to some kind of historical accident, __eqsf2 and __nesf2 are defined
73/// to have the same return value.
74pub fn __nesf2(a: f32, b: f32) callconv(.c) i32 {
75 return __cmpsf2(a, b);
119pub fn unord_f16(a: f16, b: f16) bool {
120 return unord(f16, a, b);
76121}
77122
78/// "These functions return a value less than zero if neither argument is NaN, and a
79/// is strictly less than b."
80pub fn __ltsf2(a: f32, b: f32) callconv(.c) i32 {
81 return __cmpsf2(a, b);
123fn __cmpsf2(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) Order {
124 return cmp_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)) orelse .gt;
82125}
83
84126fn __aeabi_fcmpeq(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
85 return @intFromBool(cmpf2(f32, LE, a, b) == .Equal);
127 return @intFromBool(cmp_f32(a, b) == .eq);
86128}
87
88129fn __aeabi_fcmplt(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
89 return @intFromBool(cmpf2(f32, LE, a, b) == .Less);
130 return @intFromBool(cmp_f32(a, b) == .lt);
90131}
91
92132fn __aeabi_fcmple(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
93 return @intFromBool(cmpf2(f32, LE, a, b) != .Greater);
133 return @intFromBool(cmp_f32(a, b) orelse .gt != .gt);
94134}
95
96/// "These functions calculate a <=> b. That is, if a is less than b, they return -1;
97/// if a is greater than b, they return 1; and if a and b are equal they return 0.
98/// If either argument is NaN they return 1..."
99///
100/// Note that this matches the definition of `__lehf2`, `__eqhf2`, `__nehf2`, `__cmphf2`,
101/// and `__lthf2`.
102fn __cmphf2(a: f16, b: f16) callconv(.c) i32 {
103 return @backingInt(cmpf2(f16, LE, a, b));
135fn __gesf2(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) Order {
136 return cmp_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)) orelse .lt;
104137}
105
106/// "These functions return a value less than or equal to zero if neither argument is NaN,
107/// and a is less than or equal to b."
108fn __lehf2(a: f16, b: f16) callconv(.c) i32 {
109 return __cmphf2(a, b);
138fn __aeabi_fcmpge(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
139 return @intFromBool(cmp_f32(a, b) orelse .lt != .lt);
110140}
111
112/// "These functions return zero if neither argument is NaN, and a and b are equal."
113/// Note that due to some kind of historical accident, __eqhf2 and __nehf2 are defined
114/// to have the same return value.
115fn __eqhf2(a: f16, b: f16) callconv(.c) i32 {
116 return __cmphf2(a, b);
141fn __aeabi_fcmpgt(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
142 return @intFromBool(cmp_f32(a, b) == .gt);
117143}
118
119/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal."
120/// Note that due to some kind of historical accident, __eqhf2 and __nehf2 are defined
121/// to have the same return value.
122fn __nehf2(a: f16, b: f16) callconv(.c) i32 {
123 return __cmphf2(a, b);
144fn __unordsf2(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) Unordered {
145 return @intFromBool(unord_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)));
124146}
125
126/// "These functions return a value less than zero if neither argument is NaN, and a
127/// is strictly less than b."
128fn __lthf2(a: f16, b: f16) callconv(.c) i32 {
129 return __cmphf2(a, b);
147fn __aeabi_fcmpun(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
148 return @intFromBool(unord_f32(a, b));
130149}
131
132fn __unordxf2(a: f80, b: f80) callconv(.c) i32 {
133 return unordcmp(f80, a, b);
150pub fn cmp_f32(a: f32, b: f32) ?Order {
151 return cmpf2(f32, a, b);
152}
153pub fn unord_f32(a: f32, b: f32) bool {
154 return unord(f32, a, b);
134155}
135156
136pub fn __unordsf2(a: f32, b: f32) callconv(.c) i32 {
137 return unordcmp(f32, a, b);
157fn __cmpdf2(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) Order {
158 return cmp_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)) orelse .gt;
159}
160fn __aeabi_dcmpeq(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
161 return @intFromBool(cmp_f64(a, b) == .eq);
162}
163fn __aeabi_dcmplt(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
164 return @intFromBool(cmp_f64(a, b) == .lt);
165}
166fn __aeabi_dcmple(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
167 return @intFromBool(cmp_f64(a, b) orelse .gt != .gt);
168}
169fn __gedf2(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) Order {
170 return cmp_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)) orelse .lt;
171}
172fn __aeabi_dcmpge(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
173 return @intFromBool(cmp_f64(a, b) orelse .lt != .lt);
174}
175fn __aeabi_dcmpgt(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
176 return @intFromBool(cmp_f64(a, b) == .gt);
177}
178fn __unorddf2(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) Unordered {
179 return @intFromBool(unord_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)));
180}
181fn __aeabi_dcmpun(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
182 return @intFromBool(unord_f64(a, b));
183}
184pub fn cmp_f64(a: f64, b: f64) ?Order {
185 return cmpf2(f64, a, b);
186}
187pub fn unord_f64(a: f64, b: f64) bool {
188 return unord(f64, a, b);
138189}
139190
140fn __aeabi_fcmpun(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
141 return unordcmp(f32, a, b);
191fn __cmpxf2(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) Order {
192 return cmp_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b)) orelse .gt;
193}
194fn __gexf2(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) Order {
195 return cmp_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b)) orelse .lt;
142196}
197fn __unordxf2(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) Unordered {
198 return @intFromBool(unord_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b)));
199}
200pub fn cmp_f80(a: f80, b: f80) ?Order {
201 const a_rep = std.math.F80.fromFloat(a);
202 const b_rep = std.math.F80.fromFloat(b);
203 const sig_bits = std.math.floatMantissaBits(f80);
204 const int_bit = 0x8000000000000000;
205 const sign_bit = 0x8000;
206 const special_exp = 0x7FFF;
143207
144pub const LE = enum(i32) {
145 Less = -1,
146 Equal = 0,
147 Greater = 1,
208 // If either a or b is NaN, they are unordered.
209 if ((a_rep.exp & special_exp == special_exp and a_rep.fraction ^ int_bit != 0) or
210 (b_rep.exp & special_exp == special_exp and b_rep.fraction ^ int_bit != 0))
211 return null;
148212
149 const Unordered: LE = .Greater;
150};
213 // If a and b are both zeros, they are equal.
214 if ((a_rep.fraction | b_rep.fraction) | ((a_rep.exp | b_rep.exp) & special_exp) == 0)
215 return .eq;
151216
152pub const GE = enum(i32) {
153 Less = -1,
154 Equal = 0,
155 Greater = 1,
217 if (@intFromBool(a_rep.exp == b_rep.exp) & @intFromBool(a_rep.fraction == b_rep.fraction) != 0) {
218 return .eq;
219 } else if (a_rep.exp & sign_bit != b_rep.exp & sign_bit) {
220 // signs are different
221 if (@as(i16, @bitCast(a_rep.exp)) < @as(i16, @bitCast(b_rep.exp))) {
222 return .lt;
223 } else {
224 return .gt;
225 }
226 } else {
227 const a_fraction = a_rep.fraction | (@as(u80, a_rep.exp) << sig_bits);
228 const b_fraction = b_rep.fraction | (@as(u80, b_rep.exp) << sig_bits);
229 if ((a_fraction < b_fraction) == (a_rep.exp & sign_bit == 0)) {
230 return .lt;
231 } else {
232 return .gt;
233 }
234 }
235}
236pub fn unord_f80(a: f80, b: f80) bool {
237 return unord(f80, a, b);
238}
156239
157 const Unordered: GE = .Less;
158};
240fn __cmptf2(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) Order {
241 return cmp_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)) orelse .gt;
242}
243fn __getf2(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) Order {
244 return cmp_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)) orelse .lt;
245}
246fn __unordtf2(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) Unordered {
247 return @intFromBool(unord_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)));
248}
249fn _Qp_cmp(a: *const f128, b: *const f128) callconv(.c) SparcOrder {
250 return switch (cmp_f128(a.*, b.*) orelse return .un) {
251 .lt => .lt,
252 .eq => .eq,
253 .gt => .gt,
254 };
255}
256fn _Qp_feq(a: *const f128, b: *const f128) callconv(.c) i32 {
257 return @intFromBool(cmp_f128(a.*, b.*) == .eq);
258}
259fn _Qp_fne(a: *const f128, b: *const f128) callconv(.c) i32 {
260 return @intFromBool(cmp_f128(a.*, b.*) != .eq);
261}
262fn _Qp_flt(a: *const f128, b: *const f128) callconv(.c) i32 {
263 return @intFromBool(cmp_f128(a.*, b.*) == .lt);
264}
265fn _Qp_fle(a: *const f128, b: *const f128) callconv(.c) i32 {
266 return @intFromBool((cmp_f128(a.*, b.*) orelse .gt) != .gt);
267}
268fn _Qp_fgt(a: *const f128, b: *const f128) callconv(.c) i32 {
269 return @intFromBool(cmp_f128(a.*, b.*) == .gt);
270}
271fn _Qp_fge(a: *const f128, b: *const f128) callconv(.c) i32 {
272 return @intFromBool((cmp_f128(a.*, b.*) orelse .lt) != .lt);
273}
274fn _Q_cmp(a: f128, b: f128) callconv(.c) SparcOrder {
275 return switch (cmp_f128(a, b) orelse return .un) {
276 .lt => .lt,
277 .eq => .eq,
278 .gt => .gt,
279 };
280}
281fn _Q_feq(a: f128, b: f128) callconv(.c) i32 {
282 return @intFromBool(cmp_f128(a, b) == .eq);
283}
284fn _Q_fne(a: f128, b: f128) callconv(.c) i32 {
285 return @intFromBool(cmp_f128(a, b) != .eq);
286}
287fn _Q_flt(a: f128, b: f128) callconv(.c) i32 {
288 return @intFromBool(cmp_f128(a, b) == .lt);
289}
290fn _Q_fle(a: f128, b: f128) callconv(.c) i32 {
291 return @intFromBool((cmp_f128(a, b) orelse .gt) != .gt);
292}
293fn _Q_fgt(a: f128, b: f128) callconv(.c) i32 {
294 return @intFromBool(cmp_f128(a, b) == .gt);
295}
296fn _Q_fge(a: f128, b: f128) callconv(.c) i32 {
297 return @intFromBool((cmp_f128(a, b) orelse .lt) != .lt);
298}
299pub fn cmp_f128(a: f128, b: f128) ?Order {
300 return cmpf2(f128, a, b);
301}
302pub fn unord_f128(a: f128, b: f128) bool {
303 return unord(f128, a, b);
304}
159305
160pub inline fn cmpf2(comptime T: type, comptime RT: type, a: T, b: T) RT {
306inline fn cmpf2(comptime T: type, a: T, b: T) ?Order {
161307 const bits = @typeInfo(T).float.bits;
162308 const srep_t = @Int(.signed, bits);
163309 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 {
175321 const bAbs = @as(rep_t, @bitCast(bInt)) & absMask;
176322
177323 // If either a or b is NaN, they are unordered.
178 if (aAbs > infRep or bAbs > infRep) return RT.Unordered;
324 if (aAbs > infRep or bAbs > infRep) return null;
179325
180326 // If a and b are both zeros, they are equal.
181 if ((aAbs | bAbs) == 0) return .Equal;
327 if ((aAbs | bAbs) == 0) return .eq;
182328
183329 // If at least one of a and b is positive, we get the same result comparing
184330 // a and b as signed integers as we would with a floating-point compare.
185331 if ((aInt & bInt) >= 0) {
186332 if (aInt < bInt) {
187 return .Less;
333 return .lt;
188334 } else if (aInt == bInt) {
189 return .Equal;
190 } else return .Greater;
335 return .eq;
336 } else return .gt;
191337 } else {
192338 // Otherwise, both are negative, so we need to flip the sense of the
193339 // comparison to get the correct result. (This assumes a twos- or ones-
194340 // complement integer representation; if integers are represented in a
195341 // sign-magnitude representation, then this flip is incorrect).
196342 if (aInt > bInt) {
197 return .Less;
343 return .lt;
198344 } else if (aInt == bInt) {
199 return .Equal;
200 } else return .Greater;
345 return .eq;
346 } else return .gt;
201347 }
202348}
203349
204pub inline fn cmp_f80(comptime RT: type, a: f80, b: f80) RT {
205 const a_rep = std.math.F80.fromFloat(a);
206 const b_rep = std.math.F80.fromFloat(b);
207 const sig_bits = std.math.floatMantissaBits(f80);
208 const int_bit = 0x8000000000000000;
209 const sign_bit = 0x8000;
210 const special_exp = 0x7FFF;
211
212 // If either a or b is NaN, they are unordered.
213 if ((a_rep.exp & special_exp == special_exp and a_rep.fraction ^ int_bit != 0) or
214 (b_rep.exp & special_exp == special_exp and b_rep.fraction ^ int_bit != 0))
215 return RT.Unordered;
216
217 // If a and b are both zeros, they are equal.
218 if ((a_rep.fraction | b_rep.fraction) | ((a_rep.exp | b_rep.exp) & special_exp) == 0)
219 return .Equal;
220
221 if (@intFromBool(a_rep.exp == b_rep.exp) & @intFromBool(a_rep.fraction == b_rep.fraction) != 0) {
222 return .Equal;
223 } else if (a_rep.exp & sign_bit != b_rep.exp & sign_bit) {
224 // signs are different
225 if (@as(i16, @bitCast(a_rep.exp)) < @as(i16, @bitCast(b_rep.exp))) {
226 return .Less;
227 } else {
228 return .Greater;
229 }
230 } else {
231 const a_fraction = a_rep.fraction | (@as(u80, a_rep.exp) << sig_bits);
232 const b_fraction = b_rep.fraction | (@as(u80, b_rep.exp) << sig_bits);
233 if ((a_fraction < b_fraction) == (a_rep.exp & sign_bit == 0)) {
234 return .Less;
235 } else {
236 return .Greater;
237 }
238 }
239}
240
241test "cmp_f80" {
242 inline for (.{ LE, GE }) |RT| {
243 try std.testing.expect(cmp_f80(RT, 1.0, 1.0) == RT.Equal);
244 try std.testing.expect(cmp_f80(RT, 0.0, -0.0) == RT.Equal);
245 try std.testing.expect(cmp_f80(RT, 2.0, 4.0) == RT.Less);
246 try std.testing.expect(cmp_f80(RT, 2.0, -4.0) == RT.Greater);
247 try std.testing.expect(cmp_f80(RT, -2.0, -4.0) == RT.Greater);
248 try std.testing.expect(cmp_f80(RT, -2.0, 4.0) == RT.Less);
249 }
350test cmp_f80 {
351 try std.testing.expect(cmp_f80(1.0, 1.0) == .eq);
352 try std.testing.expect(cmp_f80(0.0, -0.0) == .eq);
353 try std.testing.expect(cmp_f80(2.0, 4.0) == .lt);
354 try std.testing.expect(cmp_f80(2.0, -4.0) == .gt);
355 try std.testing.expect(cmp_f80(-2.0, -4.0) == .gt);
356 try std.testing.expect(cmp_f80(-2.0, 4.0) == .lt);
250357}
251358
252pub inline fn unordcmp(comptime T: type, a: T, b: T) i32 {
359inline fn unord(comptime T: type, a: T, b: T) bool {
253360 const rep_t = @Int(.unsigned, @typeInfo(T).float.bits);
254361
255362 const significandBits = std.math.floatMantissaBits(T);
......@@ -261,7 +368,7 @@ pub inline fn unordcmp(comptime T: type, a: T, b: T) i32 {
261368 const aAbs: rep_t = @as(rep_t, @bitCast(a)) & absMask;
262369 const bAbs: rep_t = @as(rep_t, @bitCast(b)) & absMask;
263370
264 return @intFromBool(aAbs > infRep or bAbs > infRep);
371 return aAbs > infRep or bAbs > infRep;
265372}
266373
267374test {
lib/compiler_rt/comparesf2_test.zig+17-73
......@@ -5,52 +5,12 @@
55const std = @import("std");
66const builtin = @import("builtin");
77
8const __eqsf2 = @import("./comparef.zig").__eqsf2;
9const __lesf2 = @import("./comparef.zig").__lesf2;
10const __ltsf2 = @import("./comparef.zig").__ltsf2;
11const __nesf2 = @import("./comparef.zig").__nesf2;
8const compiler_rt = @import("../compiler_rt.zig");
129
13const __gesf2 = @import("./gesf2.zig").__gesf2;
14const __gtsf2 = @import("./gesf2.zig").__gtsf2;
15
16const __unordsf2 = @import("./comparef.zig").__unordsf2;
17
18const TestVector = struct {
19 a: f32,
20 b: f32,
21 eqReference: c_int,
22 geReference: c_int,
23 gtReference: c_int,
24 leReference: c_int,
25 ltReference: c_int,
26 neReference: c_int,
27 unReference: c_int,
28};
29
30fn test__cmpsf2(vector: TestVector) bool {
31 if (__eqsf2(vector.a, vector.b) != vector.eqReference) {
32 return false;
33 }
34 if (__gesf2(vector.a, vector.b) != vector.geReference) {
35 return false;
36 }
37 if (__gtsf2(vector.a, vector.b) != vector.gtReference) {
38 return false;
39 }
40 if (__lesf2(vector.a, vector.b) != vector.leReference) {
41 return false;
42 }
43 if (__ltsf2(vector.a, vector.b) != vector.ltReference) {
44 return false;
45 }
46 if (__nesf2(vector.a, vector.b) != vector.neReference) {
47 return false;
48 }
49 if (__unordsf2(vector.a, vector.b) != vector.unReference) {
50 return false;
51 }
52 return true;
53}
10const impl = @import("comparef.zig");
11const Order = impl.Order;
12const cmp_f32 = impl.cmp_f32;
13const unord_f32 = impl.unord_f32;
5414
5515const arguments = [_]f32{
5616 std.math.nan(f32),
......@@ -73,36 +33,20 @@ const arguments = [_]f32{
7333 std.math.inf(f32),
7434};
7535
76fn generateVector(comptime a: f32, comptime b: f32) TestVector {
77 const leResult = if (a < b) -1 else if (a == b) 0 else 1;
78 const geResult = if (a > b) 1 else if (a == b) 0 else -1;
79 const unResult = if (a != a or b != b) 1 else 0;
80 return TestVector{
81 .a = a,
82 .b = b,
83 .eqReference = leResult,
84 .geReference = geResult,
85 .gtReference = geResult,
86 .leReference = leResult,
87 .ltReference = leResult,
88 .neReference = leResult,
89 .unReference = unResult,
90 };
91}
92
93const test_vectors = init: {
94 @setEvalBranchQuota(10000);
95 var vectors: [arguments.len * arguments.len]TestVector = undefined;
36test "compare f32" {
9637 for (arguments[0..], 0..) |arg_i, i| {
9738 for (arguments[0..], 0..) |arg_j, j| {
98 vectors[(i * arguments.len) + j] = generateVector(arg_i, arg_j);
39 const expected_unord = i == 0 or j == 0;
40 const expected_order: ?Order = if (expected_unord) null else switch (std.math.order(
41 i - @intFromBool(i >= 9),
42 j - @intFromBool(j >= 9),
43 )) {
44 .lt => .lt,
45 .eq => .eq,
46 .gt => .gt,
47 };
48 try std.testing.expect(expected_order == cmp_f32(arg_i, arg_j));
49 try std.testing.expect(expected_unord == unord_f32(arg_i, arg_j));
9950 }
10051 }
101 break :init vectors;
102};
103
104test "compare f32" {
105 for (test_vectors) |vector| {
106 try std.testing.expect(test__cmpsf2(vector));
107 }
10852}
lib/compiler_rt/cos.zig+64-51
......@@ -13,31 +13,34 @@ const expect = std.testing.expect;
1313const expectApproxEqAbs = std.testing.expectApproxEqAbs;
1414
1515const compiler_rt = @import("../compiler_rt.zig");
16const symbol = @import("../compiler_rt.zig").symbol;
16const symbol = compiler_rt.symbol;
1717const trig = @import("trig.zig");
1818const rem_pio2 = @import("rem_pio2.zig").rem_pio2;
1919const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f;
2020const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l;
2121
2222comptime {
23 symbol(&cosh, "__cosh");
24 symbol(&cosl, "__cosl");
23 symbol(&__cosh, "__cosh");
2524 symbol(&cosf, "cosf");
2625 symbol(&cos, "cos");
27 symbol(&cosx, "__cosx");
28 if (compiler_rt.want_ppc_abi) {
29 symbol(&cosq, "cosf128");
30 }
31 symbol(&cosq, "cosq");
26 symbol(&__cosx, "__cosx");
27 symbol(&cosq, "cosf128");
3228 symbol(&cosl, "cosl");
29 symbol(&cosl, "__cosl"); // required by musl
3330}
3431
35pub fn cosh(a: f16) callconv(.c) f16 {
32fn __cosh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
33 return compiler_rt.f16.toAbi(cos_f16(compiler_rt.f16.fromAbi(x)));
34}
35pub fn cos_f16(x: f16) f16 {
3636 // TODO: more efficient implementation
37 return @floatCast(cosf(a));
37 return @floatCast(cos_f32(x));
3838}
3939
40pub fn cosf(x: f32) callconv(.c) f32 {
40fn cosf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
41 return compiler_rt.f32.toAbi(cos_f32(compiler_rt.f32.fromAbi(x)));
42}
43pub fn cos_f32(x: f32) f32 {
4144 // Small multiples of pi/2 rounded to double precision.
4245 const c1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18
4346 const c2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18
......@@ -94,7 +97,10 @@ pub fn cosf(x: f32) callconv(.c) f32 {
9497 };
9598}
9699
97pub fn cos(x: f64) callconv(.c) f64 {
100fn cos(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
101 return compiler_rt.f64.toAbi(cos_f64(compiler_rt.f64.fromAbi(x)));
102}
103pub fn cos_f64(x: f64) f64 {
98104 var ix = @as(u64, @bitCast(x)) >> 32;
99105 ix &= 0x7fffffff;
100106
......@@ -123,7 +129,10 @@ pub fn cos(x: f64) callconv(.c) f64 {
123129 };
124130}
125131
126pub fn cosx(x: f80) callconv(.c) f80 {
132fn __cosx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
133 return compiler_rt.f80.toAbi(cos_f80(compiler_rt.f80.fromAbi(x)));
134}
135pub fn cos_f80(x: f80) f80 {
127136 const se = ld.signExponent(x) & 0x7fff;
128137 if (se == 0x7fff) {
129138 return x - x;
......@@ -147,7 +156,10 @@ pub fn cosx(x: f80) callconv(.c) f80 {
147156 };
148157}
149158
150pub fn cosq(x: f128) callconv(.c) f128 {
159fn cosq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
160 return compiler_rt.f128.toAbi(cos_f128(compiler_rt.f128.fromAbi(x)));
161}
162pub fn cos_f128(x: f128) f128 {
151163 const se = ld.signExponent(x) & 0x7fff;
152164 if (se == 0x7fff) {
153165 return x - x;
......@@ -173,20 +185,21 @@ pub fn cosq(x: f128) callconv(.c) f128 {
173185
174186pub fn cosl(x: c_longdouble) callconv(.c) c_longdouble {
175187 switch (@typeInfo(c_longdouble).float.bits) {
176 64 => return cos(x),
177 80 => return cosx(x),
178 128 => return cosq(x),
179 else => @compileError("unreachable"),
188 64 => return cos_f64(x),
189 80 => return cos_f80(x),
190 128 => return cos_f128(x),
191 else => comptime unreachable,
180192 }
181193}
182194
183195fn testCosSpecial(comptime T: type) !void {
184196 const f = switch (T) {
185 f32 => cosf,
186 f64 => cos,
187 f80 => cosx,
188 f128 => cosq,
189 else => @compileError("unimplemented"),
197 f16 => cos_f16,
198 f32 => cos_f32,
199 f64 => cos_f64,
200 f80 => cos_f80,
201 f128 => cos_f128,
202 else => comptime unreachable,
190203 };
191204
192205 try expect(f(0.0) == 1.0);
......@@ -198,13 +211,13 @@ fn testCosSpecial(comptime T: type) !void {
198211
199212test "cos32.normal" {
200213 const epsilon = math.floatEps(f32);
201 try expectApproxEqAbs(@as(f32, 1.0), cosf(0.0), epsilon);
202 try expectApproxEqAbs(@as(f32, 0.9800666), cosf(0.2), epsilon);
203 try expectApproxEqAbs(@as(f32, 0.6276231), cosf(0.8923), epsilon);
204 try expectApproxEqAbs(@as(f32, 0.0707372), cosf(1.5), epsilon);
205 try expectApproxEqAbs(@as(f32, 0.0707372), cosf(-1.5), epsilon);
206 try expectApproxEqAbs(@as(f32, 0.96913195), cosf(37.45), epsilon);
207 try expectApproxEqAbs(@as(f32, 0.40079966), cosf(89.123), epsilon);
214 try expectApproxEqAbs(@as(f32, 1.0), cos_f32(0.0), epsilon);
215 try expectApproxEqAbs(@as(f32, 0.9800666), cos_f32(0.2), epsilon);
216 try expectApproxEqAbs(@as(f32, 0.6276231), cos_f32(0.8923), epsilon);
217 try expectApproxEqAbs(@as(f32, 0.0707372), cos_f32(1.5), epsilon);
218 try expectApproxEqAbs(@as(f32, 0.0707372), cos_f32(-1.5), epsilon);
219 try expectApproxEqAbs(@as(f32, 0.96913195), cos_f32(37.45), epsilon);
220 try expectApproxEqAbs(@as(f32, 0.40079966), cos_f32(89.123), epsilon);
208221}
209222
210223test "cos32.special" {
......@@ -213,13 +226,13 @@ test "cos32.special" {
213226
214227test "cos64.normal" {
215228 const epsilon = math.floatEps(f64);
216 try expectApproxEqAbs(@as(f64, 1.0), cos(0.0), epsilon);
217 try expectApproxEqAbs(@as(f64, 0.9800665778412416), cos(0.2), epsilon);
218 try expectApproxEqAbs(@as(f64, 0.6276230983360804), cos(0.8923), epsilon);
219 try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos(1.5), epsilon);
220 try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos(-1.5), epsilon);
221 try expectApproxEqAbs(@as(f64, 0.9691317730707778), cos(37.45), epsilon);
222 try expectApproxEqAbs(@as(f64, 0.4008006809354791), cos(89.123), epsilon);
229 try expectApproxEqAbs(@as(f64, 1.0), cos_f64(0.0), epsilon);
230 try expectApproxEqAbs(@as(f64, 0.9800665778412416), cos_f64(0.2), epsilon);
231 try expectApproxEqAbs(@as(f64, 0.6276230983360804), cos_f64(0.8923), epsilon);
232 try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos_f64(1.5), epsilon);
233 try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos_f64(-1.5), epsilon);
234 try expectApproxEqAbs(@as(f64, 0.9691317730707778), cos_f64(37.45), epsilon);
235 try expectApproxEqAbs(@as(f64, 0.4008006809354791), cos_f64(89.123), epsilon);
223236}
224237
225238test "cos64.special" {
......@@ -228,13 +241,13 @@ test "cos64.special" {
228241
229242test "cos80.normal" {
230243 const epsilon = math.floatEps(f80);
231 try expectApproxEqAbs(@as(f80, 1.0), cosx(0.0), epsilon);
232 try expectApproxEqAbs(@as(f80, 0.98006657784124163112419651674816888), cosx(0.2), epsilon);
233 try expectApproxEqAbs(@as(f80, 0.62762309833608037003563995939286067), cosx(0.8923), epsilon);
234 try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cosx(1.5), epsilon);
235 try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cosx(-1.5), epsilon);
236 try expectApproxEqAbs(@as(f80, 0.9691317730707771246), cosx(37.45), epsilon);
237 try expectApproxEqAbs(@as(f80, 0.4008006809354834001), cosx(89.123), epsilon);
244 try expectApproxEqAbs(@as(f80, 1.0), cos_f80(0.0), epsilon);
245 try expectApproxEqAbs(@as(f80, 0.98006657784124163112419651674816888), cos_f80(0.2), epsilon);
246 try expectApproxEqAbs(@as(f80, 0.62762309833608037003563995939286067), cos_f80(0.8923), epsilon);
247 try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cos_f80(1.5), epsilon);
248 try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cos_f80(-1.5), epsilon);
249 try expectApproxEqAbs(@as(f80, 0.9691317730707771246), cos_f80(37.45), epsilon);
250 try expectApproxEqAbs(@as(f80, 0.4008006809354834001), cos_f80(89.123), epsilon);
238251}
239252
240253test "cos80.special" {
......@@ -243,13 +256,13 @@ test "cos80.special" {
243256
244257test "cos128.normal" {
245258 const epsilon = math.floatEps(f128);
246 try expectApproxEqAbs(@as(f128, 1.0), cosq(0.0), epsilon);
247 try expectApproxEqAbs(@as(f128, 0.98006657784124163112419651674816888), cosq(0.2), epsilon);
248 try expectApproxEqAbs(@as(f128, 0.62762309833608037003563995939286067), cosq(0.8923), epsilon);
249 try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cosq(1.5), epsilon);
250 try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cosq(-1.5), epsilon);
251 try expectApproxEqAbs(@as(f128, 0.96913177307077712443149563847233230), cosq(37.45), epsilon);
252 try expectApproxEqAbs(@as(f128, 0.40080068093548339848199454493704702), cosq(89.123), epsilon);
259 try expectApproxEqAbs(@as(f128, 1.0), cos_f128(0.0), epsilon);
260 try expectApproxEqAbs(@as(f128, 0.98006657784124163112419651674816888), cos_f128(0.2), epsilon);
261 try expectApproxEqAbs(@as(f128, 0.62762309833608037003563995939286067), cos_f128(0.8923), epsilon);
262 try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cos_f128(1.5), epsilon);
263 try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cos_f128(-1.5), epsilon);
264 try expectApproxEqAbs(@as(f128, 0.96913177307077712443149563847233230), cos_f128(37.45), epsilon);
265 try expectApproxEqAbs(@as(f128, 0.40080068093548339848199454493704702), cos_f128(89.123), epsilon);
253266}
254267
255268test "cos128.special" {
lib/compiler_rt/count0bits.zig+2-1
......@@ -1,6 +1,7 @@
11const builtin = @import("builtin");
22const std = @import("std");
3const symbol = @import("../compiler_rt.zig").symbol;
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
45
56comptime {
67 symbol(&__clzsi2, "__clzsi2");
lib/compiler_rt/divc3.zig+78-5
......@@ -7,12 +7,81 @@ const maxInt = std.math.maxInt;
77const minInt = std.math.minInt;
88const isFinite = std.math.isFinite;
99const copysign = std.math.copysign;
10const Complex = @import("mulc3.zig").Complex;
10
11const compiler_rt = @import("../compiler_rt.zig");
12const symbol = compiler_rt.symbol;
13const Complex = compiler_rt.Complex;
14
15comptime {
16 if (@import("builtin").zig_backend != .stage2_c) {
17 symbol(&__divhc3, "__divhc3");
18 symbol(&__divsc3, "__divsc3");
19 symbol(&__divdc3, "__divdc3");
20 symbol(&__divxc3, "__divxc3");
21 if (compiler_rt.want_ppc_abi) {
22 symbol(&__divtc3, "__divkc3");
23 } else {
24 symbol(&__divtc3, "__divtc3");
25 }
26 }
27}
28
29fn __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 {
30 return compiler_rt.f16.complex.toAbi(div_cf16(
31 compiler_rt.f16.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }),
32 compiler_rt.f16.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }),
33 ));
34}
35pub fn div_cf16(a: Complex(f16), b: Complex(f16)) Complex(f16) {
36 return divc3(f16, a, b);
37}
38
39fn __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 {
40 return compiler_rt.f32.complex.toAbi(div_cf32(
41 compiler_rt.f32.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }),
42 compiler_rt.f32.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }),
43 ));
44}
45pub fn div_cf32(a: Complex(f32), b: Complex(f32)) Complex(f32) {
46 return divc3(f32, a, b);
47}
48
49fn __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 {
50 return compiler_rt.f64.complex.toAbi(div_cf64(
51 compiler_rt.f64.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }),
52 compiler_rt.f64.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }),
53 ));
54}
55pub fn div_cf64(a: Complex(f64), b: Complex(f64)) Complex(f64) {
56 return divc3(f64, a, b);
57}
58
59fn __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 {
60 return compiler_rt.f80.complex.toAbi(div_cf80(
61 compiler_rt.f80.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }),
62 compiler_rt.f80.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }),
63 ));
64}
65pub fn div_cf80(a: Complex(f80), b: Complex(f80)) Complex(f80) {
66 return divc3(f80, a, b);
67}
68
69fn __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 {
70 return compiler_rt.f128.complex.toAbi(div_cf128(
71 compiler_rt.f128.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }),
72 compiler_rt.f128.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }),
73 ));
74}
75pub fn div_cf128(a: Complex(f128), b: Complex(f128)) Complex(f128) {
76 return divc3(f128, a, b);
77}
1178
1279/// Implementation based on Annex G of C17 Standard (N2176)
13pub inline fn divc3(comptime T: type, a: T, b: T, c_in: T, d_in: T) Complex(T) {
14 var c = c_in;
15 var d = d_in;
80inline fn divc3(comptime T: type, lhs: Complex(T), rhs: Complex(T)) Complex(T) {
81 const a = lhs.real;
82 const b = lhs.imag;
83 var c = rhs.real;
84 var d = rhs.imag;
1685
1786 // logbw used to prevent under/over-flow
1887 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) {
2392 break :b logbw;
2493 } else 0;
2594 const denom = c * c + d * d;
26 const result = Complex(T){
95 const result: Complex(T) = .{
2796 .real = scalbn((a * c + b * d) / denom, -ilogbw),
2897 .imag = scalbn((b * c - a * d) / denom, -ilogbw),
2998 };
......@@ -58,3 +127,7 @@ pub inline fn divc3(comptime T: type, a: T, b: T, c_in: T, d_in: T) Complex(T) {
58127
59128 return result;
60129}
130
131test {
132 _ = @import("divc3_test.zig");
133}
lib/compiler_rt/divc3_test.zig+28-51
......@@ -2,76 +2,53 @@ const std = @import("std");
22const math = std.math;
33const expect = std.testing.expect;
44
5const Complex = @import("./mulc3.zig").Complex;
6const __divhc3 = @import("./divhc3.zig").__divhc3;
7const __divsc3 = @import("./divsc3.zig").__divsc3;
8const __divdc3 = @import("./divdc3.zig").__divdc3;
9const __divxc3 = @import("./divxc3.zig").__divxc3;
10const __divtc3 = @import("./divtc3.zig").__divtc3;
5const Complex = @import("../compiler_rt.zig").Complex;
6
7const impl = @import("divc3.zig");
8const div_cf16 = impl.div_cf16;
9const div_cf32 = impl.div_cf32;
10const div_cf64 = impl.div_cf64;
11const div_cf80 = impl.div_cf80;
12const div_cf128 = impl.div_cf128;
1113
1214test "divc3" {
13 try testDiv(f16, __divhc3);
14 try testDiv(f32, __divsc3);
15 try testDiv(f64, __divdc3);
16 try testDiv(f80, __divxc3);
17 try testDiv(f128, __divtc3);
15 try testDiv(f16, div_cf16);
16 try testDiv(f32, div_cf32);
17 try testDiv(f64, div_cf64);
18 try testDiv(f80, div_cf80);
19 try testDiv(f128, div_cf128);
1820}
1921
20fn testDiv(comptime T: type, comptime f: fn (T, T, T, T) callconv(.c) Complex(T)) !void {
22fn testDiv(comptime T: type, comptime f: fn (Complex(T), Complex(T)) Complex(T)) !void {
2123 {
22 const a: T = 1.0;
23 const b: T = 0.0;
24 const c: T = -1.0;
25 const d: T = 0.0;
26
27 const result = f(a, b, c, d);
24 const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -1.0, .imag = 0.0 });
2825 try expect(result.real == -1.0);
29 try expect(result.imag == 0.0);
26 try expect(math.isNegativeZero(result.imag));
3027 }
3128 {
32 const a: T = 1.0;
33 const b: T = 0.0;
34 const c: T = -4.0;
35 const d: T = 0.0;
36
37 const result = f(a, b, c, d);
29 const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -4.0, .imag = 0.0 });
3830 try expect(result.real == -0.25);
39 try expect(result.imag == 0.0);
31 try expect(math.isNegativeZero(result.imag));
4032 }
4133 {
4234 // if the first operand is an infinity and the second operand is a finite number, then the
43 // result of the / operator is an infinity;
44 const a: T = -math.inf(T);
45 const b: T = 0.0;
46 const c: T = -4.0;
47 const d: T = 1.0;
48
49 const result = f(a, b, c, d);
50 try expect(result.real == math.inf(T));
51 try expect(result.imag == math.inf(T));
35 // resultult of the / operator is an infinity;
36 const result = f(.{ .real = -math.inf(T), .imag = 0.0 }, .{ .real = -4.0, .imag = 1.0 });
37 try expect(math.isPositiveInf(result.real));
38 try expect(math.isPositiveInf(result.imag));
5239 }
5340 {
5441 // if the first operand is a finite number and the second operand is an infinity, then the
5542 // result of the / operator is a zero;
56 const a: T = 17.2;
57 const b: T = 0.0;
58 const c: T = -math.inf(T);
59 const d: T = 0.0;
60
61 const result = f(a, b, c, d);
62 try expect(result.real == -0.0);
63 try expect(result.imag == 0.0);
43 const result = f(.{ .real = 17.2, .imag = 0.0 }, .{ .real = -math.inf(T), .imag = 0.0 });
44 try expect(math.isNegativeZero(result.real));
45 try expect(math.isNegativeZero(result.imag));
6446 }
6547 {
6648 // if the first operand is a nonzero finite number or an infinity and the second operand is
6749 // a zero, then the result of the / operator is an infinity
68 const a: T = 1.1;
69 const b: T = 0.1;
70 const c: T = 0.0;
71 const d: T = 0.0;
72
73 const result = f(a, b, c, d);
74 try expect(result.real == math.inf(T));
75 try expect(result.imag == math.inf(T));
50 const result = f(.{ .real = 1.1, .imag = 0.1 }, .{ .real = 0.0, .imag = 0.0 });
51 try expect(math.isPositiveInf(result.real));
52 try expect(math.isPositiveInf(result.imag));
7653 }
7754}
lib/compiler_rt/divdc3.zig deleted-13
......@@ -1,13 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const divc3 = @import("./divc3.zig");
3const Complex = @import("./mulc3.zig").Complex;
4
5comptime {
6 if (@import("builtin").zig_backend != .stage2_c) {
7 symbol(&__divdc3, "__divdc3");
8 }
9}
10
11pub fn __divdc3(a: f64, b: f64, c: f64, d: f64) callconv(.c) Complex(f64) {
12 return divc3.divc3(f64, a, b, c, d);
13}
lib/compiler_rt/divdf3.zig+4-4
......@@ -17,15 +17,15 @@ comptime {
1717 }
1818}
1919
20pub fn __divdf3(a: f64, b: f64) callconv(.c) f64 {
21 return div(a, b);
20fn __divdf3(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
21 return compiler_rt.f64.toAbi(div_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)));
2222}
2323
2424fn __aeabi_ddiv(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 {
25 return div(a, b);
25 return div_f64(a, b);
2626}
2727
28inline fn div(a: f64, b: f64) f64 {
28pub fn div_f64(a: f64, b: f64) f64 {
2929 const Z = @Int(.unsigned, 64);
3030 const SignedZ = @Int(.signed, 64);
3131
lib/compiler_rt/divdf3_test.zig+2-2
......@@ -6,7 +6,7 @@ const std = @import("std");
66const math = std.math;
77const testing = std.testing;
88
9const __divdf3 = @import("divdf3.zig").__divdf3;
9const div_f64 = @import("divdf3.zig").div_f64;
1010
1111const nanRep: u64 = @as(u64, @bitCast(math.nan(f64)));
1212const infRep: u64 = @as(u64, @bitCast(math.inf(f64)));
......@@ -30,7 +30,7 @@ fn compareResultD(result: f64, expected: u64) bool {
3030}
3131
3232fn test__divdf3(a: f64, b: f64, expected: u64) !void {
33 const x = __divdf3(a, b);
33 const x = div_f64(a, b);
3434 const ret = compareResultD(x, expected);
3535 try testing.expect(ret == true);
3636}
lib/compiler_rt/divhc3.zig deleted-14
......@@ -1,14 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const divc3 = @import("./divc3.zig");
4const Complex = @import("./mulc3.zig").Complex;
5
6comptime {
7 if (@import("builtin").zig_backend != .stage2_c) {
8 symbol(&__divhc3, "__divhc3");
9 }
10}
11
12pub fn __divhc3(a: f16, b: f16, c: f16, d: f16) callconv(.c) Complex(f16) {
13 return divc3.divc3(f16, a, b, c, d);
14}
lib/compiler_rt/divhf3.zig deleted-11
......@@ -1,11 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const divsf3 = @import("./divsf3.zig");
3
4comptime {
5 symbol(&__divhf3, "__divhf3");
6}
7
8pub fn __divhf3(a: f16, b: f16) callconv(.c) f16 {
9 // TODO: more efficient implementation
10 return @floatCast(divsf3.__divsf3(a, b));
11}
lib/compiler_rt/divmodei4.zig+1-1
......@@ -5,7 +5,7 @@ const std = @import("std");
55
66const compiler_rt = @import("../compiler_rt.zig");
77const udivmod = @import("udivmodei4.zig").divmod;
8const symbol = @import("../compiler_rt.zig").symbol;
8const symbol = compiler_rt.symbol;
99
1010comptime {
1111 symbol(&__divei4, "__divei4");
lib/compiler_rt/divsc3.zig deleted-13
......@@ -1,13 +0,0 @@
1const divc3 = @import("./divc3.zig");
2const Complex = @import("./mulc3.zig").Complex;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (@import("builtin").zig_backend != .stage2_c) {
7 symbol(&__divsc3, "__divsc3");
8 }
9}
10
11pub fn __divsc3(a: f32, b: f32, c: f32, d: f32) callconv(.c) Complex(f32) {
12 return divc3.divc3(f32, a, b, c, d);
13}
lib/compiler_rt/divsf3.zig+13-4
......@@ -9,6 +9,7 @@ const symbol = compiler_rt.symbol;
99const normalize = compiler_rt.normalize;
1010
1111comptime {
12 symbol(&__divhf3, "__divhf3");
1213 if (compiler_rt.want_aeabi) {
1314 symbol(&__aeabi_fdiv, "__aeabi_fdiv");
1415 } else {
......@@ -16,15 +17,23 @@ comptime {
1617 }
1718}
1819
19pub fn __divsf3(a: f32, b: f32) callconv(.c) f32 {
20 return div(a, b);
20fn __divhf3(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
21 return compiler_rt.f16.toAbi(div_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)));
22}
23pub fn div_f16(a: f16, b: f16) f16 {
24 // TODO: more efficient implementation
25 return @floatCast(div_f32(a, b));
26}
27
28fn __divsf3(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
29 return compiler_rt.f32.toAbi(div_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)));
2130}
2231
2332fn __aeabi_fdiv(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 {
24 return div(a, b);
33 return div_f32(a, b);
2534}
2635
27inline fn div(a: f32, b: f32) f32 {
36pub fn div_f32(a: f32, b: f32) f32 {
2837 const Z = @Int(.unsigned, 32);
2938
3039 const significandBits = std.math.floatMantissaBits(f32);
lib/compiler_rt/divsf3_test.zig+2-2
......@@ -6,7 +6,7 @@ const std = @import("std");
66const math = std.math;
77const testing = std.testing;
88
9const __divsf3 = @import("divsf3.zig").__divsf3;
9const div_f32 = @import("divsf3.zig").div_f32;
1010
1111const nanRep: u32 = @as(u32, @bitCast(math.nan(f32)));
1212const infRep: u32 = @as(u32, @bitCast(math.inf(f32)));
......@@ -30,7 +30,7 @@ fn compareResultF(result: f32, expected: u32) bool {
3030}
3131
3232fn test__divsf3(a: f32, b: f32, expected: u32) !void {
33 const x = __divsf3(a, b);
33 const x = div_f32(a, b);
3434 const ret = compareResultF(x, expected);
3535 try testing.expect(ret == true);
3636}
lib/compiler_rt/divtc3.zig deleted-16
......@@ -1,16 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const divc3 = @import("./divc3.zig");
3const Complex = @import("./mulc3.zig").Complex;
4const symbol = @import("../compiler_rt.zig").symbol;
5
6comptime {
7 if (@import("builtin").zig_backend != .stage2_c) {
8 if (compiler_rt.want_ppc_abi)
9 symbol(&__divtc3, "__divkc3");
10 symbol(&__divtc3, "__divtc3");
11 }
12}
13
14pub fn __divtc3(a: f128, b: f128, c: f128, d: f128) callconv(.c) Complex(f128) {
15 return divc3.divc3(f128, a, b, c, d);
16}
lib/compiler_rt/divtf3.zig+6-5
......@@ -13,19 +13,20 @@ comptime {
1313 symbol(&_Qp_div, "_Qp_div");
1414 } else if (compiler_rt.want_sparc32_abi) {
1515 symbol(&__divtf3, "_Q_div");
16 } else {
17 symbol(&__divtf3, "__divtf3");
1618 }
17 symbol(&__divtf3, "__divtf3");
1819}
1920
20pub fn __divtf3(a: f128, b: f128) callconv(.c) f128 {
21 return div(a, b);
21fn __divtf3(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
22 return compiler_rt.f128.toAbi(div_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)));
2223}
2324
2425fn _Qp_div(c: *f128, a: *const f128, b: *const f128) callconv(.c) void {
25 c.* = div(a.*, b.*);
26 c.* = div_f128(a.*, b.*);
2627}
2728
28inline fn div(a: f128, b: f128) f128 {
29pub fn div_f128(a: f128, b: f128) f128 {
2930 const Z = @Int(.unsigned, 128);
3031
3132 const significandBits = std.math.floatMantissaBits(f128);
lib/compiler_rt/divtf3_test.zig+2-2
......@@ -2,7 +2,7 @@ const std = @import("std");
22const math = std.math;
33const testing = std.testing;
44
5const __divtf3 = @import("divtf3.zig").__divtf3;
5const div_f128 = @import("divtf3.zig").div_f128;
66
77fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool {
88 const rep: u128 = @bitCast(result);
......@@ -24,7 +24,7 @@ fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool {
2424}
2525
2626fn test__divtf3(a: f128, b: f128, expectedHi: u64, expectedLo: u64) !void {
27 const x = __divtf3(a, b);
27 const x = div_f128(a, b);
2828 const ret = compareResultLD(x, expectedHi, expectedLo);
2929 try testing.expect(ret == true);
3030}
lib/compiler_rt/divxc3.zig deleted-13
......@@ -1,13 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const divc3 = @import("./divc3.zig");
3const Complex = @import("./mulc3.zig").Complex;
4
5comptime {
6 if (@import("builtin").zig_backend != .stage2_c) {
7 symbol(&__divxc3, "__divxc3");
8 }
9}
10
11pub fn __divxc3(a: f80, b: f80, c: f80, d: f80) callconv(.c) Complex(f80) {
12 return divc3.divc3(f80, a, b, c, d);
13}
lib/compiler_rt/divxf3.zig+4-1
......@@ -11,7 +11,10 @@ comptime {
1111 symbol(&__divxf3, "__divxf3");
1212}
1313
14pub fn __divxf3(a: f80, b: f80) callconv(.c) f80 {
14fn __divxf3(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
15 return compiler_rt.f80.toAbi(div_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b)));
16}
17pub fn div_f80(a: f80, b: f80) f80 {
1518 const T = f80;
1619 const Z = @Int(.unsigned, @bitSizeOf(T));
1720
lib/compiler_rt/divxf3_test.zig+3-3
......@@ -2,7 +2,7 @@ const std = @import("std");
22const math = std.math;
33const testing = std.testing;
44
5const __divxf3 = @import("divxf3.zig").__divxf3;
5const div_f80 = @import("divxf3.zig").div_f80;
66
77const nanRep: u80 = @as(u80, @bitCast(math.nan(f80)));
88const infRep: u80 = @as(u80, @bitCast(math.inf(f80)));
......@@ -19,14 +19,14 @@ fn compareResult(result: f80, expected: u80) bool {
1919}
2020
2121fn expect__divxf3_result(a: f80, b: f80, expected: u80) !void {
22 const x = __divxf3(a, b);
22 const x = div_f80(a, b);
2323 const ret = compareResult(x, expected);
2424 try testing.expect(ret == true);
2525}
2626
2727fn test__divxf3(a: f80, b: f80) !void {
2828 const integerBit = 1 << math.floatFractionalBits(f80);
29 const x = __divxf3(a, b);
29 const x = div_f80(a, b);
3030
3131 // Next float (assuming normal, non-zero result)
3232 const x_plus_eps: f80 = @bitCast((@as(u80, @bitCast(x)) + 1) | integerBit);
lib/compiler_rt/exp.zig+105-94
......@@ -14,26 +14,29 @@ const expect = std.testing.expect;
1414const expectEqual = std.testing.expectEqual;
1515
1616const compiler_rt = @import("../compiler_rt.zig");
17const symbol = @import("../compiler_rt.zig").symbol;
17const symbol = compiler_rt.symbol;
1818
1919comptime {
2020 symbol(&__exph, "__exph");
2121 symbol(&expf, "expf");
2222 symbol(&exp, "exp");
2323 symbol(&__expx, "__expx");
24 if (compiler_rt.want_ppc_abi) {
25 symbol(&expq, "expf128");
26 }
27 symbol(&expq, "expq");
24 symbol(&expq, "expf128");
2825 symbol(&expl, "expl");
2926}
3027
31pub fn __exph(a: f16) callconv(.c) f16 {
28fn __exph(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
29 return compiler_rt.f16.toAbi(exp_f16(compiler_rt.f16.fromAbi(x)));
30}
31pub fn exp_f16(x: f16) f16 {
3232 // TODO: more efficient implementation
33 return @floatCast(expf(a));
33 return @floatCast(exp_f32(x));
3434}
3535
36pub fn expf(x_: f32) callconv(.c) f32 {
36fn expf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
37 return compiler_rt.f32.toAbi(exp_f32(compiler_rt.f32.fromAbi(x)));
38}
39pub fn exp_f32(x_: f32) f32 {
3740 const half = [_]f32{ 0.5, -0.5 };
3841 const ln2hi = 6.9314575195e-1;
3942 const ln2lo = 1.4286067653e-6;
......@@ -108,7 +111,10 @@ pub fn expf(x_: f32) callconv(.c) f32 {
108111 }
109112}
110113
111pub fn exp(x_: f64) callconv(.c) f64 {
114fn exp(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
115 return compiler_rt.f64.toAbi(exp_f64(compiler_rt.f64.fromAbi(x)));
116}
117pub fn exp_f64(x_: f64) f64 {
112118 const half = [_]f64{ 0.5, -0.5 };
113119 const ln2hi: f64 = 6.93147180369123816490e-01;
114120 const ln2lo: f64 = 1.90821492927058770002e-10;
......@@ -189,116 +195,121 @@ pub fn exp(x_: f64) callconv(.c) f64 {
189195 }
190196}
191197
192pub fn __expx(a: f80) callconv(.c) f80 {
198fn __expx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
199 return compiler_rt.f80.toAbi(exp_f80(compiler_rt.f80.fromAbi(x)));
200}
201pub fn exp_f80(x: f80) f80 {
193202 // TODO: more efficient implementation
194 return @floatCast(expq(a));
203 return @floatCast(exp_f128(x));
195204}
196205
197const expq = @import("exp_f128.zig").exp;
206fn expq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
207 return compiler_rt.f128.toAbi(exp_f128(compiler_rt.f128.fromAbi(x)));
208}
209pub const exp_f128 = @import("exp_f128.zig").exp;
198210
199211pub fn expl(x: c_longdouble) callconv(.c) c_longdouble {
200212 switch (@typeInfo(c_longdouble).float.bits) {
201 64 => return exp(x),
202 80 => return __expx(x),
203 128 => return expq(x),
204 else => @compileError("unreachable"),
213 64 => return exp_f64(x),
214 80 => return exp_f80(x),
215 128 => return exp_f128(x),
216 else => comptime unreachable,
205217 }
206218}
207219
208220test "expf() special" {
209 try expectEqual(expf(0.0), 1.0);
210 try expectEqual(expf(-0.0), 1.0);
211 try expectEqual(expf(1.0), math.e);
212 try expectEqual(expf(math.ln2), 2.0);
213 try expectEqual(expf(math.inf(f32)), math.inf(f32));
214 try expect(math.isPositiveZero(expf(-math.inf(f32))));
215 try expect(math.isNan(expf(math.nan(f32))));
216 try expect(math.isNan(expf(math.snan(f32))));
221 try expectEqual(exp_f32(0.0), 1.0);
222 try expectEqual(exp_f32(-0.0), 1.0);
223 try expectEqual(exp_f32(1.0), math.e);
224 try expectEqual(exp_f32(math.ln2), 2.0);
225 try expectEqual(exp_f32(math.inf(f32)), math.inf(f32));
226 try expect(math.isPositiveZero(exp_f32(-math.inf(f32))));
227 try expect(math.isNan(exp_f32(math.nan(f32))));
228 try expect(math.isNan(exp_f32(math.snan(f32))));
217229}
218230
219231test "expf() sanity" {
220 try expectEqual(expf(-0x1.0223a0p+3), 0x1.490320p-12);
221 try expectEqual(expf(0x1.161868p+2), 0x1.34712ap+6);
222 try expectEqual(expf(-0x1.0c34b4p+3), 0x1.e06b1ap-13);
223 try expectEqual(expf(-0x1.a206f0p+2), 0x1.7dd484p-10);
224 try expectEqual(expf(0x1.288bbcp+3), 0x1.4abc80p+13);
225 try expectEqual(expf(0x1.52efd0p-1), 0x1.f04a9cp+0);
226 try expectEqual(expf(-0x1.a05cc8p-2), 0x1.54f1e0p-1);
227 try expectEqual(expf(0x1.1f9efap-1), 0x1.c0f628p+0);
228 try expectEqual(expf(0x1.8c5db0p-1), 0x1.1599b2p+1);
229 try expectEqual(expf(-0x1.5b86eap-1), 0x1.03b572p-1);
230 try expectEqual(expf(-0x1.57f25cp+2), 0x1.2fbea2p-8);
231 try expectEqual(expf(0x1.c7d310p+3), 0x1.76eefp+20);
232 try expectEqual(expf(0x1.19be70p+4), 0x1.52d3dep+25);
233 try expectEqual(expf(-0x1.ab6d70p+3), 0x1.a88adep-20);
234 try expectEqual(expf(-0x1.5ac18ep+2), 0x1.22b328p-8);
235 try expectEqual(expf(-0x1.925982p-1), 0x1.d2acc0p-2);
236 try expectEqual(expf(0x1.7221cep+3), 0x1.9c2ceap+16);
237 try expectEqual(expf(0x1.11a0d4p+4), 0x1.980ee6p+24);
238 try expectEqual(expf(-0x1.ae41a2p+1), 0x1.1c28d0p-5);
239 try expectEqual(expf(-0x1.329154p+4), 0x1.47ef94p-28);
232 try expectEqual(exp_f32(-0x1.0223a0p+3), 0x1.490320p-12);
233 try expectEqual(exp_f32(0x1.161868p+2), 0x1.34712ap+6);
234 try expectEqual(exp_f32(-0x1.0c34b4p+3), 0x1.e06b1ap-13);
235 try expectEqual(exp_f32(-0x1.a206f0p+2), 0x1.7dd484p-10);
236 try expectEqual(exp_f32(0x1.288bbcp+3), 0x1.4abc80p+13);
237 try expectEqual(exp_f32(0x1.52efd0p-1), 0x1.f04a9cp+0);
238 try expectEqual(exp_f32(-0x1.a05cc8p-2), 0x1.54f1e0p-1);
239 try expectEqual(exp_f32(0x1.1f9efap-1), 0x1.c0f628p+0);
240 try expectEqual(exp_f32(0x1.8c5db0p-1), 0x1.1599b2p+1);
241 try expectEqual(exp_f32(-0x1.5b86eap-1), 0x1.03b572p-1);
242 try expectEqual(exp_f32(-0x1.57f25cp+2), 0x1.2fbea2p-8);
243 try expectEqual(exp_f32(0x1.c7d310p+3), 0x1.76eefp+20);
244 try expectEqual(exp_f32(0x1.19be70p+4), 0x1.52d3dep+25);
245 try expectEqual(exp_f32(-0x1.ab6d70p+3), 0x1.a88adep-20);
246 try expectEqual(exp_f32(-0x1.5ac18ep+2), 0x1.22b328p-8);
247 try expectEqual(exp_f32(-0x1.925982p-1), 0x1.d2acc0p-2);
248 try expectEqual(exp_f32(0x1.7221cep+3), 0x1.9c2ceap+16);
249 try expectEqual(exp_f32(0x1.11a0d4p+4), 0x1.980ee6p+24);
250 try expectEqual(exp_f32(-0x1.ae41a2p+1), 0x1.1c28d0p-5);
251 try expectEqual(exp_f32(-0x1.329154p+4), 0x1.47ef94p-28);
240252}
241253
242254test "expf() boundary" {
243 try expectEqual(expf(0x1.62e42ep+6), 0x1.ffff08p+127); // The last value before the result gets infinite
244 try expectEqual(expf(0x1.62e430p+6), math.inf(f32)); // The first value that gives inf
245 try expectEqual(expf(0x1.fffffep+127), math.inf(f32)); // Max input value
246 try expectEqual(expf(0x1p-149), 1.0); // Min positive input value
247 try expectEqual(expf(-0x1p-149), 1.0); // Min negative input value
248 try expectEqual(expf(0x1p-126), 1.0); // First positive subnormal input
249 try expectEqual(expf(-0x1p-126), 1.0); // First negative subnormal input
250 try expectEqual(expf(-0x1.9fe368p+6), 0x1p-149); // The last value before the result flushes to zero
251 try expectEqual(expf(-0x1.9fe36ap+6), 0.0); // The first value at which the result flushes to zero
252 try expectEqual(expf(-0x1.5d589ep+6), 0x1.00004cp-126); // The last value before the result flushes to subnormal
253 try expectEqual(expf(-0x1.5d58a0p+6), 0x1.ffff98p-127); // The first value for which the result flushes to subnormal
254
255 try expectEqual(exp_f32(0x1.62e42ep+6), 0x1.ffff08p+127); // The last value before the result gets infinite
256 try expectEqual(exp_f32(0x1.62e430p+6), math.inf(f32)); // The first value that gives inf
257 try expectEqual(exp_f32(0x1.fffffep+127), math.inf(f32)); // Max input value
258 try expectEqual(exp_f32(0x1p-149), 1.0); // Min positive input value
259 try expectEqual(exp_f32(-0x1p-149), 1.0); // Min negative input value
260 try expectEqual(exp_f32(0x1p-126), 1.0); // First positive subnormal input
261 try expectEqual(exp_f32(-0x1p-126), 1.0); // First negative subnormal input
262 try expectEqual(exp_f32(-0x1.9fe368p+6), 0x1p-149); // The last value before the result flushes to zero
263 try expectEqual(exp_f32(-0x1.9fe36ap+6), 0.0); // The first value at which the result flushes to zero
264 try expectEqual(exp_f32(-0x1.5d589ep+6), 0x1.00004cp-126); // The last value before the result flushes to subnormal
265 try expectEqual(exp_f32(-0x1.5d58a0p+6), 0x1.ffff98p-127); // The first value for which the result flushes to subnormal
255266}
256267
257268test "exp() special" {
258 try expectEqual(exp(0.0), 1.0);
259 try expectEqual(exp(-0.0), 1.0);
269 try expectEqual(exp_f64(0.0), 1.0);
270 try expectEqual(exp_f64(-0.0), 1.0);
260271 // TODO: Accuracy error - off in the last bit in 64-bit, disagreeing with GCC
261272 // try expectEqual(exp(1.0), math.e);
262 try expectEqual(exp(math.ln2), 2.0);
263 try expectEqual(exp(math.inf(f64)), math.inf(f64));
264 try expect(math.isPositiveZero(exp(-math.inf(f64))));
265 try expect(math.isNan(exp(math.nan(f64))));
266 try expect(math.isNan(exp(math.snan(f64))));
273 try expectEqual(exp_f64(math.ln2), 2.0);
274 try expectEqual(exp_f64(math.inf(f64)), math.inf(f64));
275 try expect(math.isPositiveZero(exp_f64(-math.inf(f64))));
276 try expect(math.isNan(exp_f64(math.nan(f64))));
277 try expect(math.isNan(exp_f64(math.snan(f64))));
267278}
268279
269280test "exp() sanity" {
270 try expectEqual(exp(-0x1.02239f3c6a8f1p+3), 0x1.490327ea61235p-12);
271 try expectEqual(exp(0x1.161868e18bc67p+2), 0x1.34712ed238c04p+6);
272 try expectEqual(exp(-0x1.0c34b3e01e6e7p+3), 0x1.e06b1b6c18e64p-13);
273 try expectEqual(exp(-0x1.a206f0a19dcc4p+2), 0x1.7dd47f810e68cp-10);
274 try expectEqual(exp(0x1.288bbb0d6a1e6p+3), 0x1.4abc77496e07ep+13);
275 try expectEqual(exp(0x1.52efd0cd80497p-1), 0x1.f04a9c1080500p+0);
276 try expectEqual(exp(-0x1.a05cc754481d1p-2), 0x1.54f1e0fd3ea0dp-1);
277 try expectEqual(exp(0x1.1f9ef934745cbp-1), 0x1.c0f6266a6a547p+0);
278 try expectEqual(exp(0x1.8c5db097f7442p-1), 0x1.1599b1d4a25fbp+1);
279 try expectEqual(exp(-0x1.5b86ea8118a0ep-1), 0x1.03b5728a00229p-1);
280 try expectEqual(exp(-0x1.57f25b2b5006dp+2), 0x1.2fbea6a01cab9p-8);
281 try expectEqual(exp(0x1.c7d30fb825911p+3), 0x1.76eeed45a0634p+20);
282 try expectEqual(exp(0x1.19be709de7505p+4), 0x1.52d3eb7be6844p+25);
283 try expectEqual(exp(-0x1.ab6d6fba96889p+3), 0x1.a88ae12f985d6p-20);
284 try expectEqual(exp(-0x1.5ac18e27084ddp+2), 0x1.22b327da9cca6p-8);
285 try expectEqual(exp(-0x1.925981b093c41p-1), 0x1.d2acc046b55f7p-2);
286 try expectEqual(exp(0x1.7221cd18455f5p+3), 0x1.9c2cde8699cfbp+16);
287 try expectEqual(exp(0x1.11a0d4a51b239p+4), 0x1.980ef612ff182p+24);
288 try expectEqual(exp(-0x1.ae41a1079de4dp+1), 0x1.1c28d16bb3222p-5);
289 try expectEqual(exp(-0x1.329153103b871p+4), 0x1.47efa6ddd0d22p-28);
281 try expectEqual(exp_f64(-0x1.02239f3c6a8f1p+3), 0x1.490327ea61235p-12);
282 try expectEqual(exp_f64(0x1.161868e18bc67p+2), 0x1.34712ed238c04p+6);
283 try expectEqual(exp_f64(-0x1.0c34b3e01e6e7p+3), 0x1.e06b1b6c18e64p-13);
284 try expectEqual(exp_f64(-0x1.a206f0a19dcc4p+2), 0x1.7dd47f810e68cp-10);
285 try expectEqual(exp_f64(0x1.288bbb0d6a1e6p+3), 0x1.4abc77496e07ep+13);
286 try expectEqual(exp_f64(0x1.52efd0cd80497p-1), 0x1.f04a9c1080500p+0);
287 try expectEqual(exp_f64(-0x1.a05cc754481d1p-2), 0x1.54f1e0fd3ea0dp-1);
288 try expectEqual(exp_f64(0x1.1f9ef934745cbp-1), 0x1.c0f6266a6a547p+0);
289 try expectEqual(exp_f64(0x1.8c5db097f7442p-1), 0x1.1599b1d4a25fbp+1);
290 try expectEqual(exp_f64(-0x1.5b86ea8118a0ep-1), 0x1.03b5728a00229p-1);
291 try expectEqual(exp_f64(-0x1.57f25b2b5006dp+2), 0x1.2fbea6a01cab9p-8);
292 try expectEqual(exp_f64(0x1.c7d30fb825911p+3), 0x1.76eeed45a0634p+20);
293 try expectEqual(exp_f64(0x1.19be709de7505p+4), 0x1.52d3eb7be6844p+25);
294 try expectEqual(exp_f64(-0x1.ab6d6fba96889p+3), 0x1.a88ae12f985d6p-20);
295 try expectEqual(exp_f64(-0x1.5ac18e27084ddp+2), 0x1.22b327da9cca6p-8);
296 try expectEqual(exp_f64(-0x1.925981b093c41p-1), 0x1.d2acc046b55f7p-2);
297 try expectEqual(exp_f64(0x1.7221cd18455f5p+3), 0x1.9c2cde8699cfbp+16);
298 try expectEqual(exp_f64(0x1.11a0d4a51b239p+4), 0x1.980ef612ff182p+24);
299 try expectEqual(exp_f64(-0x1.ae41a1079de4dp+1), 0x1.1c28d16bb3222p-5);
300 try expectEqual(exp_f64(-0x1.329153103b871p+4), 0x1.47efa6ddd0d22p-28);
290301}
291302
292303test "exp() boundary" {
293 try expectEqual(exp(0x1.62e42fefa39efp+9), 0x1.fffffffffff2ap+1023); // The last value before the result gets infinite
294 try expectEqual(exp(0x1.62e42fefa39f0p+9), math.inf(f64)); // The first value that gives inf
295 try expectEqual(exp(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value
296 try expectEqual(exp(0x1p-1074), 1.0); // Min positive input value
297 try expectEqual(exp(-0x1p-1074), 1.0); // Min negative input value
298 try expectEqual(exp(0x1p-1022), 1.0); // First positive subnormal input
299 try expectEqual(exp(-0x1p-1022), 1.0); // First negative subnormal input
300 try expectEqual(exp(-0x1.74910d52d3051p+9), 0x1p-1074); // The last value before the result flushes to zero
301 try expectEqual(exp(-0x1.74910d52d3052p+9), 0.0); // The first value at which the result flushes to zero
302 try expectEqual(exp(-0x1.6232bdd7abcd2p+9), 0x1.000000000007cp-1022); // The last value before the result flushes to subnormal
303 try expectEqual(exp(-0x1.6232bdd7abcd3p+9), 0x1.ffffffffffcf8p-1023); // The first value for which the result flushes to subnormal
304 try expectEqual(exp_f64(0x1.62e42fefa39efp+9), 0x1.fffffffffff2ap+1023); // The last value before the result gets infinite
305 try expectEqual(exp_f64(0x1.62e42fefa39f0p+9), math.inf(f64)); // The first value that gives inf
306 try expectEqual(exp_f64(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value
307 try expectEqual(exp_f64(0x1p-1074), 1.0); // Min positive input value
308 try expectEqual(exp_f64(-0x1p-1074), 1.0); // Min negative input value
309 try expectEqual(exp_f64(0x1p-1022), 1.0); // First positive subnormal input
310 try expectEqual(exp_f64(-0x1p-1022), 1.0); // First negative subnormal input
311 try expectEqual(exp_f64(-0x1.74910d52d3051p+9), 0x1p-1074); // The last value before the result flushes to zero
312 try expectEqual(exp_f64(-0x1.74910d52d3052p+9), 0.0); // The first value at which the result flushes to zero
313 try expectEqual(exp_f64(-0x1.6232bdd7abcd2p+9), 0x1.000000000007cp-1022); // The last value before the result flushes to subnormal
314 try expectEqual(exp_f64(-0x1.6232bdd7abcd3p+9), 0x1.ffffffffffcf8p-1023); // The first value for which the result flushes to subnormal
304315}
lib/compiler_rt/exp2.zig+85-73
......@@ -19,19 +19,22 @@ comptime {
1919 symbol(&exp2f, "exp2f");
2020 symbol(&exp2, "exp2");
2121 symbol(&__exp2x, "__exp2x");
22 if (compiler_rt.want_ppc_abi) {
23 symbol(&exp2q, "exp2f128");
24 }
25 symbol(&exp2q, "exp2q");
22 symbol(&exp2q, "exp2f128");
2623 symbol(&exp2l, "exp2l");
2724}
2825
29pub fn __exp2h(x: f16) callconv(.c) f16 {
26fn __exp2h(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
27 return compiler_rt.f16.toAbi(exp2_f16(compiler_rt.f16.fromAbi(x)));
28}
29pub fn exp2_f16(x: f16) f16 {
3030 // TODO: more efficient implementation
31 return @floatCast(exp2f(x));
31 return @floatCast(exp2_f32(x));
3232}
3333
34pub fn exp2f(x: f32) callconv(.c) f32 {
34fn exp2f(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
35 return compiler_rt.f32.toAbi(exp2_f32(compiler_rt.f32.fromAbi(x)));
36}
37pub fn exp2_f32(x: f32) f32 {
3538 const tblsiz: u32 = @intCast(exp2ft.len);
3639 const redux: f32 = 0x1.8p23 / @as(f32, @floatFromInt(tblsiz));
3740 const P1: f32 = 0x1.62e430p-1;
......@@ -88,7 +91,10 @@ pub fn exp2f(x: f32) callconv(.c) f32 {
8891 return @floatCast(r * uk);
8992}
9093
91pub fn exp2(x: f64) callconv(.c) f64 {
94fn exp2(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
95 return compiler_rt.f64.toAbi(exp2_f64(compiler_rt.f64.fromAbi(x)));
96}
97pub fn exp2_f64(x: f64) f64 {
9298 const tblsiz: u32 = @intCast(exp2dt.len / 2);
9399 const redux: f64 = 0x1.8p52 / @as(f64, @floatFromInt(tblsiz));
94100 const P1: f64 = 0x1.62e42fefa39efp-1;
......@@ -156,19 +162,25 @@ pub fn exp2(x: f64) callconv(.c) f64 {
156162 return math.scalbn(r, ik);
157163}
158164
159pub fn __exp2x(x: f80) callconv(.c) f80 {
165fn __exp2x(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
166 return compiler_rt.f80.toAbi(exp2_f80(compiler_rt.f80.fromAbi(x)));
167}
168pub fn exp2_f80(x: f80) f80 {
160169 // TODO: more efficient implementation
161 return @floatCast(exp2q(x));
170 return @floatCast(exp2_f128(x));
162171}
163172
164pub const exp2q = @import("exp_f128.zig").exp2;
173fn exp2q(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
174 return compiler_rt.f128.toAbi(exp2_f128(compiler_rt.f128.fromAbi(x)));
175}
176pub const exp2_f128 = @import("exp_f128.zig").exp2;
165177
166178pub fn exp2l(x: c_longdouble) callconv(.c) c_longdouble {
167179 switch (@typeInfo(c_longdouble).float.bits) {
168 64 => return exp2(x),
169 80 => return __exp2x(x),
170 128 => return exp2q(x),
171 else => @compileError("unreachable"),
180 64 => return exp2_f64(x),
181 80 => return exp2_f80(x),
182 128 => return exp2_f128(x),
183 else => comptime unreachable,
172184 }
173185}
174186
......@@ -452,77 +464,77 @@ const exp2dt = [_]f64{
452464};
453465
454466test "exp2f() special" {
455 try expectEqual(exp2f(0.0), 1.0);
456 try expectEqual(exp2f(-0.0), 1.0);
457 try expectEqual(exp2f(1.0), 2.0);
458 try expectEqual(exp2f(-1.0), 0.5);
459 try expectEqual(exp2f(math.inf(f32)), math.inf(f32));
460 try expect(math.isPositiveZero(exp2f(-math.inf(f32))));
461 try expect(math.isNan(exp2f(math.nan(f32))));
462 try expect(math.isNan(exp2f(math.snan(f32))));
467 try expectEqual(exp2_f32(0.0), 1.0);
468 try expectEqual(exp2_f32(-0.0), 1.0);
469 try expectEqual(exp2_f32(1.0), 2.0);
470 try expectEqual(exp2_f32(-1.0), 0.5);
471 try expectEqual(exp2_f32(math.inf(f32)), math.inf(f32));
472 try expect(math.isPositiveZero(exp2_f32(-math.inf(f32))));
473 try expect(math.isNan(exp2_f32(math.nan(f32))));
474 try expect(math.isNan(exp2_f32(math.snan(f32))));
463475}
464476
465477test "exp2f() sanity" {
466 try expectEqual(exp2f(-0x1.0223a0p+3), 0x1.e8d134p-9);
467 try expectEqual(exp2f(0x1.161868p+2), 0x1.453672p+4);
468 try expectEqual(exp2f(-0x1.0c34b4p+3), 0x1.890ca0p-9);
469 try expectEqual(exp2f(-0x1.a206f0p+2), 0x1.622d4ep-7);
470 try expectEqual(exp2f(0x1.288bbcp+3), 0x1.340ecep+9);
471 try expectEqual(exp2f(0x1.52efd0p-1), 0x1.950eeep+0);
472 try expectEqual(exp2f(-0x1.a05cc8p-2), 0x1.824056p-1);
473 try expectEqual(exp2f(0x1.1f9efap-1), 0x1.79dfa2p+0);
474 try expectEqual(exp2f(0x1.8c5db0p-1), 0x1.b5ceacp+0);
475 try expectEqual(exp2f(-0x1.5b86eap-1), 0x1.3fd8bap-1);
478 try expectEqual(exp2_f32(-0x1.0223a0p+3), 0x1.e8d134p-9);
479 try expectEqual(exp2_f32(0x1.161868p+2), 0x1.453672p+4);
480 try expectEqual(exp2_f32(-0x1.0c34b4p+3), 0x1.890ca0p-9);
481 try expectEqual(exp2_f32(-0x1.a206f0p+2), 0x1.622d4ep-7);
482 try expectEqual(exp2_f32(0x1.288bbcp+3), 0x1.340ecep+9);
483 try expectEqual(exp2_f32(0x1.52efd0p-1), 0x1.950eeep+0);
484 try expectEqual(exp2_f32(-0x1.a05cc8p-2), 0x1.824056p-1);
485 try expectEqual(exp2_f32(0x1.1f9efap-1), 0x1.79dfa2p+0);
486 try expectEqual(exp2_f32(0x1.8c5db0p-1), 0x1.b5ceacp+0);
487 try expectEqual(exp2_f32(-0x1.5b86eap-1), 0x1.3fd8bap-1);
476488}
477489
478490test "exp2f() boundary" {
479 try expectEqual(exp2f(0x1.fffffep+6), 0x1.ffff4ep+127); // The last value before the result gets infinite
480 try expectEqual(exp2f(0x1p+7), math.inf(f32)); // The first value that gives infinite result
481 try expectEqual(exp2f(-0x1.2bccccp+7), 0x1p-149); // The last value before the result flushes to zero
482 try expectEqual(exp2f(-0x1.2cp+7), 0); // The first value at which the result flushes to zero
483 try expectEqual(exp2f(-0x1.f8p+6), 0x1p-126); // The last value before the result flushes to subnormal
484 try expectEqual(exp2f(-0x1.f80002p+6), 0x1.ffff50p-127); // The first value for which the result flushes to subnormal
485 try expectEqual(exp2f(0x1.fffffep+127), math.inf(f32)); // Max input value
486 try expectEqual(exp2f(0x1p-149), 1); // Min positive input value
487 try expectEqual(exp2f(-0x1p-149), 1); // Min negative input value
488 try expectEqual(exp2f(0x1p-126), 1); // First positive subnormal input
489 try expectEqual(exp2f(-0x1p-126), 1); // First negative subnormal input
491 try expectEqual(exp2_f32(0x1.fffffep+6), 0x1.ffff4ep+127); // The last value before the result gets infinite
492 try expectEqual(exp2_f32(0x1p+7), math.inf(f32)); // The first value that gives infinite result
493 try expectEqual(exp2_f32(-0x1.2bccccp+7), 0x1p-149); // The last value before the result flushes to zero
494 try expectEqual(exp2_f32(-0x1.2cp+7), 0); // The first value at which the result flushes to zero
495 try expectEqual(exp2_f32(-0x1.f8p+6), 0x1p-126); // The last value before the result flushes to subnormal
496 try expectEqual(exp2_f32(-0x1.f80002p+6), 0x1.ffff50p-127); // The first value for which the result flushes to subnormal
497 try expectEqual(exp2_f32(0x1.fffffep+127), math.inf(f32)); // Max input value
498 try expectEqual(exp2_f32(0x1p-149), 1); // Min positive input value
499 try expectEqual(exp2_f32(-0x1p-149), 1); // Min negative input value
500 try expectEqual(exp2_f32(0x1p-126), 1); // First positive subnormal input
501 try expectEqual(exp2_f32(-0x1p-126), 1); // First negative subnormal input
490502}
491503
492504test "exp2() special" {
493 try expectEqual(exp2(0.0), 1.0);
494 try expectEqual(exp2(-0.0), 1.0);
495 try expectEqual(exp2(1.0), 2.0);
496 try expectEqual(exp2(-1.0), 0.5);
497 try expectEqual(exp2(math.inf(f64)), math.inf(f64));
498 try expect(math.isPositiveZero(exp2(-math.inf(f64))));
499 try expect(math.isNan(exp2(math.nan(f64))));
500 try expect(math.isNan(exp2(math.snan(f64))));
505 try expectEqual(exp2_f64(0.0), 1.0);
506 try expectEqual(exp2_f64(-0.0), 1.0);
507 try expectEqual(exp2_f64(1.0), 2.0);
508 try expectEqual(exp2_f64(-1.0), 0.5);
509 try expectEqual(exp2_f64(math.inf(f64)), math.inf(f64));
510 try expect(math.isPositiveZero(exp2_f64(-math.inf(f64))));
511 try expect(math.isNan(exp2_f64(math.nan(f64))));
512 try expect(math.isNan(exp2_f64(math.snan(f64))));
501513}
502514
503515test "exp2() sanity" {
504 try expectEqual(exp2(-0x1.02239f3c6a8f1p+3), 0x1.e8d13c396f452p-9);
505 try expectEqual(exp2(0x1.161868e18bc67p+2), 0x1.4536746bb6f12p+4);
506 try expectEqual(exp2(-0x1.0c34b3e01e6e7p+3), 0x1.890ca0c00b9a2p-9);
507 try expectEqual(exp2(-0x1.a206f0a19dcc4p+2), 0x1.622d4b0ebc6c1p-7);
508 try expectEqual(exp2(0x1.288bbb0d6a1e6p+3), 0x1.340ec7f3e607ep+9);
509 try expectEqual(exp2(0x1.52efd0cd80497p-1), 0x1.950eef4bc5451p+0);
510 try expectEqual(exp2(-0x1.a05cc754481d1p-2), 0x1.824056efc687cp-1);
511 try expectEqual(exp2(0x1.1f9ef934745cbp-1), 0x1.79dfa14ab121ep+0);
512 try expectEqual(exp2(0x1.8c5db097f7442p-1), 0x1.b5cead2247372p+0);
513 try expectEqual(exp2(-0x1.5b86ea8118a0ep-1), 0x1.3fd8ba33216b9p-1);
516 try expectEqual(exp2_f64(-0x1.02239f3c6a8f1p+3), 0x1.e8d13c396f452p-9);
517 try expectEqual(exp2_f64(0x1.161868e18bc67p+2), 0x1.4536746bb6f12p+4);
518 try expectEqual(exp2_f64(-0x1.0c34b3e01e6e7p+3), 0x1.890ca0c00b9a2p-9);
519 try expectEqual(exp2_f64(-0x1.a206f0a19dcc4p+2), 0x1.622d4b0ebc6c1p-7);
520 try expectEqual(exp2_f64(0x1.288bbb0d6a1e6p+3), 0x1.340ec7f3e607ep+9);
521 try expectEqual(exp2_f64(0x1.52efd0cd80497p-1), 0x1.950eef4bc5451p+0);
522 try expectEqual(exp2_f64(-0x1.a05cc754481d1p-2), 0x1.824056efc687cp-1);
523 try expectEqual(exp2_f64(0x1.1f9ef934745cbp-1), 0x1.79dfa14ab121ep+0);
524 try expectEqual(exp2_f64(0x1.8c5db097f7442p-1), 0x1.b5cead2247372p+0);
525 try expectEqual(exp2_f64(-0x1.5b86ea8118a0ep-1), 0x1.3fd8ba33216b9p-1);
514526}
515527
516528test "exp2() boundary" {
517 try expectEqual(exp2(0x1.fffffffffffffp+9), 0x1.ffffffffffd3ap+1023); // The last value before the result gets infinite
518 try expectEqual(exp2(0x1p+10), math.inf(f64)); // The first value that gives infinite result
519 try expectEqual(exp2(-0x1.0cbffffffffffp+10), 0x1p-1074); // The last value before the result flushes to zero
520 try expectEqual(exp2(-0x1.0ccp+10), 0); // The first value at which the result flushes to zero
521 try expectEqual(exp2(-0x1.ffp+9), 0x1p-1022); // The last value before the result flushes to subnormal
522 try expectEqual(exp2(-0x1.ff00000000001p+9), 0x1.ffffffffffd3ap-1023); // The first value for which the result flushes to subnormal
523 try expectEqual(exp2(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value
524 try expectEqual(exp2(0x1p-1074), 1); // Min positive input value
525 try expectEqual(exp2(-0x1p-1074), 1); // Min negative input value
526 try expectEqual(exp2(0x1p-1022), 1); // First positive subnormal input
527 try expectEqual(exp2(-0x1p-1022), 1); // First negative subnormal input
529 try expectEqual(exp2_f64(0x1.fffffffffffffp+9), 0x1.ffffffffffd3ap+1023); // The last value before the result gets infinite
530 try expectEqual(exp2_f64(0x1p+10), math.inf(f64)); // The first value that gives infinite result
531 try expectEqual(exp2_f64(-0x1.0cbffffffffffp+10), 0x1p-1074); // The last value before the result flushes to zero
532 try expectEqual(exp2_f64(-0x1.0ccp+10), 0); // The first value at which the result flushes to zero
533 try expectEqual(exp2_f64(-0x1.ffp+9), 0x1p-1022); // The last value before the result flushes to subnormal
534 try expectEqual(exp2_f64(-0x1.ff00000000001p+9), 0x1.ffffffffffd3ap-1023); // The first value for which the result flushes to subnormal
535 try expectEqual(exp2_f64(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value
536 try expectEqual(exp2_f64(0x1p-1074), 1); // Min positive input value
537 try expectEqual(exp2_f64(-0x1p-1074), 1); // Min negative input value
538 try expectEqual(exp2_f64(0x1p-1022), 1); // First positive subnormal input
539 try expectEqual(exp2_f64(-0x1p-1022), 1); // First negative subnormal input
528540}
lib/compiler_rt/exp_f128.zig+2-2
......@@ -26,7 +26,7 @@ const exp_f128 = @This();
2626const std = @import("std");
2727const math = std.math;
2828
29pub fn exp(x: f128) callconv(.c) f128 {
29pub fn exp(x: f128) f128 {
3030 if (!math.isFinite(x)) {
3131 if (math.isNan(x)) {
3232 if (math.isSignalNan(x)) math.raiseInvalid();
......@@ -91,7 +91,7 @@ fn expPoly(r_hi: f128, r_lo: f128) f128 {
9191}
9292
9393/// Computes 2^x
94pub fn exp2(x: f128) callconv(.c) f128 {
94pub fn exp2(x: f128) f128 {
9595 if (!math.isFinite(x)) {
9696 if (math.isNan(x)) {
9797 if (math.isSignalNan(x)) math.raiseInvalid();
lib/compiler_rt/extenddftf2.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const extendf = @import("./extendf.zig").extendf;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__extenddftf2, "__extenddfkf2");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_dtoq, "_Qp_dtoq");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__extenddftf2, "_Q_dtoq");
12 }
13 symbol(&__extenddftf2, "__extenddftf2");
14}
15
16pub fn __extenddftf2(a: f64) callconv(.c) f128 {
17 return extendf(f128, f64, @as(u64, @bitCast(a)));
18}
19
20fn _Qp_dtoq(c: *f128, a: f64) callconv(.c) void {
21 c.* = extendf(f128, f64, @as(u64, @bitCast(a)));
22}
lib/compiler_rt/extenddfxf2.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const extend_f80 = @import("./extendf.zig").extend_f80;
4
5comptime {
6 symbol(&__extenddfxf2, "__extenddfxf2");
7}
8
9pub fn __extenddfxf2(a: f64) callconv(.c) f80 {
10 return extend_f80(f64, @as(u64, @bitCast(a)));
11}
lib/compiler_rt/extendf.zig+174-7
......@@ -1,10 +1,175 @@
11const std = @import("std");
22
3pub inline fn extendf(
4 comptime dst_t: type,
5 comptime src_t: type,
6 a: @Int(.unsigned, @typeInfo(src_t).float.bits),
7) dst_t {
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5
6comptime {
7 if (compiler_rt.want_aeabi) {
8 if (compiler_rt.gnu_f16_abi) {
9 symbol(&__aeabi_h2f, "__gnu_h2f_ieee");
10 } else {
11 symbol(&__aeabi_h2f, "__aeabi_h2f");
12 }
13 } else if (compiler_rt.gnu_f16_abi) {
14 symbol(&__extendhfsf2, "__gnu_h2f_ieee");
15 }
16 symbol(&__extendhfsf2, "__extendhfsf2");
17 symbol(&__extendhfdf2, "__extendhfdf2");
18 symbol(&__extendhfxf2, "__extendhfxf2");
19 if (compiler_rt.want_ppc_abi) {
20 symbol(&__extendhftf2, "__extendhfkf2");
21 } else {
22 symbol(&__extendhftf2, "__extendhftf2");
23 }
24
25 if (compiler_rt.want_aeabi) {
26 symbol(&__aeabi_f2d, "__aeabi_f2d");
27 } else {
28 symbol(&__extendsfdf2, "__extendsfdf2");
29 }
30 symbol(&__extendsfxf2, "__extendsfxf2");
31 if (compiler_rt.want_ppc_abi) {
32 symbol(&__extendsftf2, "__extendsfkf2");
33 } else if (compiler_rt.want_sparc64_abi) {
34 symbol(&_Qp_stoq, "_Qp_stoq");
35 } else if (compiler_rt.want_sparc32_abi) {
36 symbol(&__extendsftf2, "_Q_stoq");
37 } else {
38 symbol(&__extendsftf2, "__extendsftf2");
39 }
40
41 symbol(&__extenddfxf2, "__extenddfxf2");
42 if (compiler_rt.want_ppc_abi) {
43 symbol(&__extenddftf2, "__extenddfkf2");
44 } else if (compiler_rt.want_sparc64_abi) {
45 symbol(&_Qp_dtoq, "_Qp_dtoq");
46 } else if (compiler_rt.want_sparc32_abi) {
47 symbol(&__extenddftf2, "_Q_dtoq");
48 } else {
49 symbol(&__extenddftf2, "__extenddftf2");
50 }
51
52 if (compiler_rt.want_ppc_abi) {
53 symbol(&__extendxftf2, "__extendxfkf2");
54 } else {
55 symbol(&__extendxftf2, "__extendxftf2");
56 }
57}
58
59fn __extendhfsf2(a: compiler_rt.f16Conv(f32).Abi) callconv(.c) compiler_rt.f32.Abi {
60 return compiler_rt.f32.toAbi(f32_floatCast_f16(compiler_rt.f16Conv(f32).fromAbi(a)));
61}
62fn __aeabi_h2f(a: u16) callconv(.{ .arm_aapcs = .{} }) u32 {
63 return @bitCast(f32_floatCast_f16(@bitCast(a)));
64}
65pub fn f32_floatCast_f16(a: f16) f32 {
66 return extendf(f32, f16, a);
67}
68
69fn __extendhfdf2(a: compiler_rt.f16Conv(f64).Abi) callconv(.c) compiler_rt.f64.Abi {
70 return compiler_rt.f64.toAbi(f64_floatCast_f16(compiler_rt.f16Conv(f64).fromAbi(a)));
71}
72pub fn f64_floatCast_f16(a: f16) f64 {
73 return extendf(f64, f16, a);
74}
75
76fn __extendhfxf2(a: compiler_rt.f16Conv(f80).Abi) callconv(.c) compiler_rt.f80.Abi {
77 return compiler_rt.f80.toAbi(f80_floatCast_f16(compiler_rt.f16Conv(f80).fromAbi(a)));
78}
79pub fn f80_floatCast_f16(a: f16) f80 {
80 return extend_f80(f16, a);
81}
82
83fn __extendhftf2(a: compiler_rt.f16Conv(f128).Abi) callconv(.c) compiler_rt.f128.Abi {
84 return compiler_rt.f128.toAbi(f128_floatCast_f16(compiler_rt.f16Conv(f128).fromAbi(a)));
85}
86pub fn f128_floatCast_f16(a: f16) f128 {
87 return extendf(f128, f16, a);
88}
89
90fn __extendsfdf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f64.Abi {
91 return compiler_rt.f64.toAbi(f64_floatCast_f32(compiler_rt.f32.fromAbi(a)));
92}
93fn __aeabi_f2d(a: f32) callconv(.{ .arm_aapcs = .{} }) f64 {
94 return f64_floatCast_f32(a);
95}
96pub fn f64_floatCast_f32(a: f32) f64 {
97 return extendf(f64, f32, a);
98}
99
100fn __extendsfxf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f80.Abi {
101 return compiler_rt.f80.toAbi(f80_floatCast_f32(compiler_rt.f32.fromAbi(a)));
102}
103pub fn f80_floatCast_f32(a: f32) f80 {
104 return extend_f80(f32, a);
105}
106
107pub fn __extendsftf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f128.Abi {
108 return compiler_rt.f128.toAbi(f128_floatCast_f32(compiler_rt.f32.fromAbi(a)));
109}
110fn _Qp_stoq(c: *f128, a: f32) callconv(.c) void {
111 c.* = f128_floatCast_f32(a);
112}
113pub fn f128_floatCast_f32(a: f32) f128 {
114 return extendf(f128, f32, a);
115}
116
117fn __extenddfxf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f80.Abi {
118 return compiler_rt.f80.toAbi(f80_floatCast_f64(compiler_rt.f64.fromAbi(a)));
119}
120pub fn f80_floatCast_f64(a: f64) f80 {
121 return extend_f80(f64, a);
122}
123
124fn __extenddftf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f128.Abi {
125 return compiler_rt.f128.toAbi(f128_floatCast_f64(compiler_rt.f64.fromAbi(a)));
126}
127fn _Qp_dtoq(c: *f128, a: f64) callconv(.c) void {
128 c.* = f128_floatCast_f64(a);
129}
130pub fn f128_floatCast_f64(a: f64) f128 {
131 return extendf(f128, f64, a);
132}
133
134fn __extendxftf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f128.Abi {
135 return compiler_rt.f128.toAbi(f128_floatCast_f80(compiler_rt.f80.fromAbi(a)));
136}
137pub fn f128_floatCast_f80(a: f80) f128 {
138 const src_int_bit: u64 = 0x8000000000000000;
139 const src_sig_mask = ~src_int_bit;
140 const src_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit
141 const dst_sig_bits = std.math.floatMantissaBits(f128);
142
143 const dst_bits = @bitSizeOf(f128);
144
145 // Break a into a sign and representation of the absolute value
146 var a_rep: std.math.F80 = .fromFloat(a);
147 const sign = a_rep.exp & 0x8000;
148 a_rep.exp &= 0x7FFF;
149 var abs_result: u128 = undefined;
150
151 if (a_rep.exp == 0 and a_rep.fraction == 0) {
152 // zero
153 abs_result = 0;
154 } else if (a_rep.exp == 0x7FFF) {
155 // a is nan or infinite
156 abs_result = @as(u128, a_rep.fraction) << (dst_sig_bits - src_sig_bits);
157 abs_result |= @as(u128, a_rep.exp) << dst_sig_bits;
158 } else if (a_rep.fraction & src_int_bit != 0) {
159 // a is a normal value
160 abs_result = @as(u128, a_rep.fraction & src_sig_mask) << (dst_sig_bits - src_sig_bits);
161 abs_result |= @as(u128, a_rep.exp) << dst_sig_bits;
162 } else {
163 // a is denormal
164 abs_result = @as(u128, a_rep.fraction) << (dst_sig_bits - src_sig_bits);
165 }
166
167 // Apply the signbit to (dst_t)abs(a).
168 const result: u128 = abs_result | @as(u128, sign) << (dst_bits - 16);
169 return @bitCast(result);
170}
171
172inline fn extendf(comptime dst_t: type, comptime src_t: type, f: src_t) dst_t {
8173 const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits);
9174 const dst_rep_t = @Int(.unsigned, @typeInfo(dst_t).float.bits);
10175 const srcSigBits = std.math.floatMantissaBits(src_t);
......@@ -31,6 +196,7 @@ pub inline fn extendf(
31196
32197 const dstMinNormal: dst_rep_t = @as(dst_rep_t, 1) << dstSigBits;
33198
199 const a: src_rep_t = @bitCast(f);
34200 // Break a into a sign and representation of the absolute value
35201 const aRep: src_rep_t = @bitCast(a);
36202 const aAbs: src_rep_t = aRep & srcAbsMask;
......@@ -66,11 +232,11 @@ pub inline fn extendf(
66232 }
67233
68234 // Apply the signbit to (dst_t)abs(a).
69 const result: dst_rep_t align(@alignOf(dst_t)) = absResult | @as(dst_rep_t, sign) << (dstBits - srcBits);
235 const result: dst_rep_t = absResult | @as(dst_rep_t, sign) << (dstBits - srcBits);
70236 return @bitCast(result);
71237}
72238
73pub inline fn extend_f80(comptime src_t: type, a: @Int(.unsigned, @typeInfo(src_t).float.bits)) f80 {
239inline fn extend_f80(comptime src_t: type, f: src_t) f80 {
74240 const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits);
75241 const src_sig_bits = std.math.floatMantissaBits(src_t);
76242 const dst_int_bit = 0x8000000000000000;
......@@ -92,6 +258,7 @@ pub inline fn extend_f80(comptime src_t: type, a: @Int(.unsigned, @typeInfo(src_
92258
93259 var dst: std.math.F80 = undefined;
94260
261 const a: src_rep_t = @bitCast(f);
95262 // Break a into a sign and representation of the absolute value
96263 const a_abs = a & src_abs_mask;
97264 const sign: u16 = if (a & src_sign_mask != 0) 0x8000 else 0;
lib/compiler_rt/extendf_test.zig+94-95
......@@ -1,31 +1,37 @@
11const builtin = @import("builtin");
2
32const std = @import("std");
4const math = std.math;
3const testing = std.testing;
4
5const impl = @import("extendf.zig");
6
7const f32_floatCast_f16 = impl.f32_floatCast_f16;
8const f64_floatCast_f16 = impl.f64_floatCast_f16;
9const f80_floatCast_f16 = impl.f80_floatCast_f16;
10const f128_floatCast_f16 = impl.f128_floatCast_f16;
11
12const f64_floatCast_f32 = impl.f64_floatCast_f32;
13const f80_floatCast_f32 = impl.f80_floatCast_f32;
14const f128_floatCast_f32 = impl.f128_floatCast_f32;
515
6const __extendhfsf2 = @import("extendhfsf2.zig").__extendhfsf2;
7const __extendhftf2 = @import("extendhftf2.zig").__extendhftf2;
8const __extendsftf2 = @import("extendsftf2.zig").__extendsftf2;
9const __extenddftf2 = @import("extenddftf2.zig").__extenddftf2;
10const __extenddfxf2 = @import("extenddfxf2.zig").__extenddfxf2;
11const F16T = @import("../compiler_rt.zig").F16T;
16const f80_floatCast_f64 = impl.f80_floatCast_f64;
17const f128_floatCast_f64 = impl.f128_floatCast_f64;
1218
13fn test__extenddfxf2(a: f64, expected: u80) !void {
14 const x = __extenddfxf2(a);
19const f128_floatCast_f80 = impl.f128_floatCast_f80;
20
21fn test_f80_floatCast_f64(a: f64, expected: u80) !void {
22 const x = f80_floatCast_f64(a);
1523
1624 const rep: u80 = @bitCast(x);
1725 if (rep == expected)
1826 return;
19
2027 // test other possible NaN representation(signal NaN)
21 if (math.isNan(@as(f80, @bitCast(expected))) and math.isNan(x))
28 if (std.math.isNan(@as(f80, @bitCast(expected))) and std.math.isNan(x))
2229 return;
23
24 @panic("__extenddfxf2 test failure");
30 return error.TestFailure;
2531}
2632
27fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void {
28 const x = __extenddftf2(a);
33fn test_f128_floatCast_f64(a: f64, expected_hi: u64, expected_lo: u64) !void {
34 const x = f128_floatCast_f64(a);
2935
3036 const rep: u128 = @bitCast(x);
3137 const hi: u64 = @intCast(rep >> 64);
......@@ -33,7 +39,6 @@ fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void {
3339
3440 if (hi == expected_hi and lo == expected_lo)
3541 return;
36
3742 // test other possible NaN representation(signal NaN)
3843 if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) {
3944 if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and
......@@ -42,12 +47,11 @@ fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void {
4247 return;
4348 }
4449 }
45
46 @panic("__extenddftf2 test failure");
50 return error.TestFailure;
4751}
4852
49fn test__extendhfsf2(a: u16, expected: u32) !void {
50 const x = __extendhfsf2(@as(F16T(f32), @bitCast(a)));
53fn test_f32_floatCast_f16(a: u16, expected: u32) !void {
54 const x = f32_floatCast_f16(@bitCast(a));
5155 const rep: u32 = @bitCast(x);
5256
5357 if (rep == expected) {
......@@ -58,12 +62,11 @@ fn test__extendhfsf2(a: u16, expected: u32) !void {
5862 return;
5963 }
6064 }
61
6265 return error.TestFailure;
6366}
6467
65fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void {
66 const x = __extendsftf2(a);
68fn test_f128_floatCast_f32(a: f32, expected_hi: u64, expected_lo: u64) !void {
69 const x = f128_floatCast_f32(a);
6770
6871 const rep: u128 = @bitCast(x);
6972 const hi: u64 = @intCast(rep >> 64);
......@@ -71,7 +74,6 @@ fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void {
7174
7275 if (hi == expected_hi and lo == expected_lo)
7376 return;
74
7577 // test other possible NaN representation(signal NaN)
7678 if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) {
7779 if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and
......@@ -80,111 +82,108 @@ fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void {
8082 return;
8183 }
8284 }
83
8485 return error.TestFailure;
8586}
8687
87test "extenddfxf2" {
88test f80_floatCast_f64 {
8889 // qNaN
89 try test__extenddfxf2(makeQNaN64(), 0x7fffc000000000000000);
90 try test_f80_floatCast_f64(makeQNaN64(), 0x7fffc000000000000000);
9091
9192 // NaN
92 try test__extenddfxf2(makeNaN64(0x7100000000000), 0x7fffe080000000000000);
93 try test_f80_floatCast_f64(makeNaN64(0x7100000000000), 0x7fffe080000000000000);
9394 // This is bad?
9495
9596 // inf
96 try test__extenddfxf2(makeInf64(), 0x7fff8000000000000000);
97 try test_f80_floatCast_f64(makeInf64(), 0x7fff8000000000000000);
9798
9899 // zero
99 try test__extenddfxf2(0.0, 0x0);
100 try test_f80_floatCast_f64(0.0, 0x0);
100101
101 try test__extenddfxf2(0x0.a3456789abcdefp+6, 0x4004a3456789abcdf000);
102 try test_f80_floatCast_f64(0x0.a3456789abcdefp+6, 0x4004a3456789abcdf000);
102103
103 try test__extenddfxf2(0x0.edcba987654321fp-8, 0x3ff6edcba98765432000);
104 try test_f80_floatCast_f64(0x0.edcba987654321fp-8, 0x3ff6edcba98765432000);
104105
105 try test__extenddfxf2(0x0.a3456789abcdefp+46, 0x402ca3456789abcdf000);
106 try test_f80_floatCast_f64(0x0.a3456789abcdefp+46, 0x402ca3456789abcdf000);
106107
107 try test__extenddfxf2(0x0.edcba987654321fp-44, 0x3fd2edcba98765432000);
108 try test_f80_floatCast_f64(0x0.edcba987654321fp-44, 0x3fd2edcba98765432000);
108109
109110 // subnormal
110 try test__extenddfxf2(0x1.8000000000001p-1022, 0x3c01c000000000000800);
111 try test__extenddfxf2(0x1.8000000000002p-1023, 0x3c00c000000000001000);
111 try test_f80_floatCast_f64(0x1.8000000000001p-1022, 0x3c01c000000000000800);
112 try test_f80_floatCast_f64(0x1.8000000000002p-1023, 0x3c00c000000000001000);
112113}
113114
114test "extenddftf2" {
115 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
116
115test f128_floatCast_f64 {
117116 // qNaN
118 try test__extenddftf2(makeQNaN64(), 0x7fff800000000000, 0x0);
117 try test_f128_floatCast_f64(makeQNaN64(), 0x7fff800000000000, 0x0);
119118
120119 // NaN
121 try test__extenddftf2(makeNaN64(0x7100000000000), 0x7fff710000000000, 0x0);
120 try test_f128_floatCast_f64(makeNaN64(0x7100000000000), 0x7fff710000000000, 0x0);
122121
123122 // inf
124 try test__extenddftf2(makeInf64(), 0x7fff000000000000, 0x0);
123 try test_f128_floatCast_f64(makeInf64(), 0x7fff000000000000, 0x0);
125124
126125 // zero
127 try test__extenddftf2(0.0, 0x0, 0x0);
126 try test_f128_floatCast_f64(0.0, 0x0, 0x0);
128127
129 try test__extenddftf2(0x1.23456789abcdefp+5, 0x400423456789abcd, 0xf000000000000000);
128 try test_f128_floatCast_f64(0x1.23456789abcdefp+5, 0x400423456789abcd, 0xf000000000000000);
130129
131 try test__extenddftf2(0x1.edcba987654321fp-9, 0x3ff6edcba9876543, 0x2000000000000000);
130 try test_f128_floatCast_f64(0x1.edcba987654321fp-9, 0x3ff6edcba9876543, 0x2000000000000000);
132131
133 try test__extenddftf2(0x1.23456789abcdefp+45, 0x402c23456789abcd, 0xf000000000000000);
132 try test_f128_floatCast_f64(0x1.23456789abcdefp+45, 0x402c23456789abcd, 0xf000000000000000);
134133
135 try test__extenddftf2(0x1.edcba987654321fp-45, 0x3fd2edcba9876543, 0x2000000000000000);
134 try test_f128_floatCast_f64(0x1.edcba987654321fp-45, 0x3fd2edcba9876543, 0x2000000000000000);
136135
137136 // subnormal
138 try test__extenddftf2(0x1.8p-1022, 0x3c01800000000000, 0x0);
139 try test__extenddftf2(0x1.8p-1023, 0x3c00800000000000, 0x0);
137 try test_f128_floatCast_f64(0x1.8p-1022, 0x3c01800000000000, 0x0);
138 try test_f128_floatCast_f64(0x1.8p-1023, 0x3c00800000000000, 0x0);
140139}
141140
142test "extendhfsf2" {
143 try test__extendhfsf2(0x7e00, 0x7fc00000); // qNaN
144 try test__extendhfsf2(0x7f00, 0x7fe00000); // sNaN
141test f32_floatCast_f16 {
142 try test_f32_floatCast_f16(0x7e00, 0x7fc00000); // qNaN
143 try test_f32_floatCast_f16(0x7f00, 0x7fe00000); // sNaN
145144 // On x86 the NaN becomes quiet because the return is pushed on the x87
146145 // stack due to ABI requirements
147146 if (builtin.target.cpu.arch != .x86 and builtin.target.os.tag == .windows)
148 try test__extendhfsf2(0x7c01, 0x7f802000); // sNaN
147 try test_f32_floatCast_f16(0x7c01, 0x7f802000); // sNaN
149148
150 try test__extendhfsf2(0, 0); // 0
151 try test__extendhfsf2(0x8000, 0x80000000); // -0
149 try test_f32_floatCast_f16(0, 0); // 0
150 try test_f32_floatCast_f16(0x8000, 0x80000000); // -0
152151
153 try test__extendhfsf2(0x7c00, 0x7f800000); // inf
154 try test__extendhfsf2(0xfc00, 0xff800000); // -inf
152 try test_f32_floatCast_f16(0x7c00, 0x7f800000); // inf
153 try test_f32_floatCast_f16(0xfc00, 0xff800000); // -inf
155154
156 try test__extendhfsf2(0x0001, 0x33800000); // denormal (min), 2**-24
157 try test__extendhfsf2(0x8001, 0xb3800000); // denormal (min), -2**-24
155 try test_f32_floatCast_f16(0x0001, 0x33800000); // denormal (min), 2**-24
156 try test_f32_floatCast_f16(0x8001, 0xb3800000); // denormal (min), -2**-24
158157
159 try test__extendhfsf2(0x03ff, 0x387fc000); // denormal (max), 2**-14 - 2**-24
160 try test__extendhfsf2(0x83ff, 0xb87fc000); // denormal (max), -2**-14 + 2**-24
158 try test_f32_floatCast_f16(0x03ff, 0x387fc000); // denormal (max), 2**-14 - 2**-24
159 try test_f32_floatCast_f16(0x83ff, 0xb87fc000); // denormal (max), -2**-14 + 2**-24
161160
162 try test__extendhfsf2(0x0400, 0x38800000); // normal (min), 2**-14
163 try test__extendhfsf2(0x8400, 0xb8800000); // normal (min), -2**-14
161 try test_f32_floatCast_f16(0x0400, 0x38800000); // normal (min), 2**-14
162 try test_f32_floatCast_f16(0x8400, 0xb8800000); // normal (min), -2**-14
164163
165 try test__extendhfsf2(0x7bff, 0x477fe000); // normal (max), 65504
166 try test__extendhfsf2(0xfbff, 0xc77fe000); // normal (max), -65504
164 try test_f32_floatCast_f16(0x7bff, 0x477fe000); // normal (max), 65504
165 try test_f32_floatCast_f16(0xfbff, 0xc77fe000); // normal (max), -65504
167166
168 try test__extendhfsf2(0x3c01, 0x3f802000); // normal, 1 + 2**-10
169 try test__extendhfsf2(0xbc01, 0xbf802000); // normal, -1 - 2**-10
167 try test_f32_floatCast_f16(0x3c01, 0x3f802000); // normal, 1 + 2**-10
168 try test_f32_floatCast_f16(0xbc01, 0xbf802000); // normal, -1 - 2**-10
170169
171 try test__extendhfsf2(0x3555, 0x3eaaa000); // normal, approx. 1/3
172 try test__extendhfsf2(0xb555, 0xbeaaa000); // normal, approx. -1/3
170 try test_f32_floatCast_f16(0x3555, 0x3eaaa000); // normal, approx. 1/3
171 try test_f32_floatCast_f16(0xb555, 0xbeaaa000); // normal, approx. -1/3
173172}
174173
175test "extendsftf2" {
174test f128_floatCast_f32 {
176175 // qNaN
177 try test__extendsftf2(makeQNaN32(), 0x7fff800000000000, 0x0);
176 try test_f128_floatCast_f32(makeQNaN32(), 0x7fff800000000000, 0x0);
178177 // NaN
179 try test__extendsftf2(makeNaN32(0x410000), 0x7fff820000000000, 0x0);
178 try test_f128_floatCast_f32(makeNaN32(0x410000), 0x7fff820000000000, 0x0);
180179 // inf
181 try test__extendsftf2(makeInf32(), 0x7fff000000000000, 0x0);
180 try test_f128_floatCast_f32(makeInf32(), 0x7fff000000000000, 0x0);
182181 // zero
183 try test__extendsftf2(0.0, 0x0, 0x0);
184 try test__extendsftf2(0x1.23456p+5, 0x4004234560000000, 0x0);
185 try test__extendsftf2(0x1.edcbap-9, 0x3ff6edcba0000000, 0x0);
186 try test__extendsftf2(0x1.23456p+45, 0x402c234560000000, 0x0);
187 try test__extendsftf2(0x1.edcbap-45, 0x3fd2edcba0000000, 0x0);
182 try test_f128_floatCast_f32(0.0, 0x0, 0x0);
183 try test_f128_floatCast_f32(0x1.23456p+5, 0x4004234560000000, 0x0);
184 try test_f128_floatCast_f32(0x1.edcbap-9, 0x3ff6edcba0000000, 0x0);
185 try test_f128_floatCast_f32(0x1.23456p+45, 0x402c234560000000, 0x0);
186 try test_f128_floatCast_f32(0x1.edcbap-45, 0x3fd2edcba0000000, 0x0);
188187}
189188
190189fn makeQNaN64() f64 {
......@@ -211,8 +210,8 @@ fn makeInf32() f32 {
211210 return @bitCast(@as(u32, 0x7f800000));
212211}
213212
214fn test__extendhftf2(a: u16, expected_hi: u64, expected_lo: u64) !void {
215 const x = __extendhftf2(@as(F16T(f128), @bitCast(a)));
213fn test_f128_floatCast_f16(a: u16, expected_hi: u64, expected_lo: u64) !void {
214 const x = f128_floatCast_f16(@bitCast(a));
216215
217216 const rep: u128 = @bitCast(x);
218217 const hi: u64 = @intCast(rep >> 64);
......@@ -233,26 +232,26 @@ fn test__extendhftf2(a: u16, expected_hi: u64, expected_lo: u64) !void {
233232 return error.TestFailure;
234233}
235234
236test "extendhftf2" {
235test f128_floatCast_f16 {
237236 // qNaN
238 try test__extendhftf2(0x7e00, 0x7fff800000000000, 0x0);
237 try test_f128_floatCast_f16(0x7e00, 0x7fff800000000000, 0x0);
239238 // NaN
240 try test__extendhftf2(0x7d00, 0x7fff400000000000, 0x0);
239 try test_f128_floatCast_f16(0x7d00, 0x7fff400000000000, 0x0);
241240 // inf
242 try test__extendhftf2(0x7c00, 0x7fff000000000000, 0x0);
243 try test__extendhftf2(0xfc00, 0xffff000000000000, 0x0);
241 try test_f128_floatCast_f16(0x7c00, 0x7fff000000000000, 0x0);
242 try test_f128_floatCast_f16(0xfc00, 0xffff000000000000, 0x0);
244243 // zero
245 try test__extendhftf2(0x0000, 0x0000000000000000, 0x0);
246 try test__extendhftf2(0x8000, 0x8000000000000000, 0x0);
244 try test_f128_floatCast_f16(0x0000, 0x0000000000000000, 0x0);
245 try test_f128_floatCast_f16(0x8000, 0x8000000000000000, 0x0);
247246 // denormal
248 try test__extendhftf2(0x0010, 0x3feb000000000000, 0x0);
249 try test__extendhftf2(0x0001, 0x3fe7000000000000, 0x0);
250 try test__extendhftf2(0x8001, 0xbfe7000000000000, 0x0);
247 try test_f128_floatCast_f16(0x0010, 0x3feb000000000000, 0x0);
248 try test_f128_floatCast_f16(0x0001, 0x3fe7000000000000, 0x0);
249 try test_f128_floatCast_f16(0x8001, 0xbfe7000000000000, 0x0);
251250
252251 // pi
253 try test__extendhftf2(0x4248, 0x4000920000000000, 0x0);
254 try test__extendhftf2(0xc248, 0xc000920000000000, 0x0);
252 try test_f128_floatCast_f16(0x4248, 0x4000920000000000, 0x0);
253 try test_f128_floatCast_f16(0xc248, 0xc000920000000000, 0x0);
255254
256 try test__extendhftf2(0x508c, 0x4004230000000000, 0x0);
257 try test__extendhftf2(0x1bb7, 0x3ff6edc000000000, 0x0);
255 try test_f128_floatCast_f16(0x508c, 0x4004230000000000, 0x0);
256 try test_f128_floatCast_f16(0x1bb7, 0x3ff6edc000000000, 0x0);
258257}
lib/compiler_rt/extendhfdf2.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const extendf = @import("./extendf.zig").extendf;
4
5comptime {
6 symbol(&__extendhfdf2, "__extendhfdf2");
7}
8
9pub fn __extendhfdf2(a: compiler_rt.F16T(f64)) callconv(.c) f64 {
10 return extendf(f64, f16, @as(u16, @bitCast(a)));
11}
lib/compiler_rt/extendhfsf2.zig deleted-24
......@@ -1,24 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const extendf = @import("./extendf.zig").extendf;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.gnu_f16_abi) {
7 symbol(&__gnu_h2f_ieee, "__gnu_h2f_ieee");
8 } else if (compiler_rt.want_aeabi) {
9 symbol(&__aeabi_h2f, "__aeabi_h2f");
10 }
11 symbol(&__extendhfsf2, "__extendhfsf2");
12}
13
14pub fn __extendhfsf2(a: compiler_rt.F16T(f32)) callconv(.c) f32 {
15 return extendf(f32, f16, @as(u16, @bitCast(a)));
16}
17
18fn __gnu_h2f_ieee(a: compiler_rt.F16T(f32)) callconv(.c) f32 {
19 return extendf(f32, f16, @as(u16, @bitCast(a)));
20}
21
22fn __aeabi_h2f(a: u16) callconv(.{ .arm_aapcs = .{} }) f32 {
23 return extendf(f32, f16, @as(u16, @bitCast(a)));
24}
lib/compiler_rt/extendhftf2.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const extendf = @import("./extendf.zig").extendf;
4
5comptime {
6 symbol(&__extendhftf2, "__extendhftf2");
7}
8
9pub fn __extendhftf2(a: compiler_rt.F16T(f128)) callconv(.c) f128 {
10 return extendf(f128, f16, @as(u16, @bitCast(a)));
11}
lib/compiler_rt/extendhfxf2.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const extend_f80 = @import("./extendf.zig").extend_f80;
4
5comptime {
6 symbol(&__extendhfxf2, "__extendhfxf2");
7}
8
9fn __extendhfxf2(a: compiler_rt.F16T(f80)) callconv(.c) f80 {
10 return extend_f80(f16, @as(u16, @bitCast(a)));
11}
lib/compiler_rt/extendsfdf2.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const extendf = @import("./extendf.zig").extendf;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_f2d, "__aeabi_f2d");
8 } else {
9 symbol(&__extendsfdf2, "__extendsfdf2");
10 }
11}
12
13fn __extendsfdf2(a: f32) callconv(.c) f64 {
14 return extendf(f64, f32, @as(u32, @bitCast(a)));
15}
16
17fn __aeabi_f2d(a: f32) callconv(.{ .arm_aapcs = .{} }) f64 {
18 return extendf(f64, f32, @as(u32, @bitCast(a)));
19}
lib/compiler_rt/extendsftf2.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const extendf = @import("./extendf.zig").extendf;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__extendsftf2, "__extendsfkf2");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_stoq, "_Qp_stoq");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__extendsftf2, "_Q_stoq");
12 }
13 symbol(&__extendsftf2, "__extendsftf2");
14}
15
16pub fn __extendsftf2(a: f32) callconv(.c) f128 {
17 return extendf(f128, f32, @as(u32, @bitCast(a)));
18}
19
20fn _Qp_stoq(c: *f128, a: f32) callconv(.c) void {
21 c.* = extendf(f128, f32, @as(u32, @bitCast(a)));
22}
lib/compiler_rt/extendsfxf2.zig deleted-10
......@@ -1,10 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const extend_f80 = @import("./extendf.zig").extend_f80;
3
4comptime {
5 symbol(&__extendsfxf2, "__extendsfxf2");
6}
7
8fn __extendsfxf2(a: f32) callconv(.c) f80 {
9 return extend_f80(f32, @as(u32, @bitCast(a)));
10}
lib/compiler_rt/extendxftf2.zig deleted-42
......@@ -1,42 +0,0 @@
1const std = @import("std");
2
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 symbol(&__extendxftf2, "__extendxftf2");
7}
8
9fn __extendxftf2(a: f80) callconv(.c) f128 {
10 const src_int_bit: u64 = 0x8000000000000000;
11 const src_sig_mask = ~src_int_bit;
12 const src_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit
13 const dst_sig_bits = std.math.floatMantissaBits(f128);
14
15 const dst_bits = @bitSizeOf(f128);
16
17 // Break a into a sign and representation of the absolute value
18 var a_rep = std.math.F80.fromFloat(a);
19 const sign = a_rep.exp & 0x8000;
20 a_rep.exp &= 0x7FFF;
21 var abs_result: u128 = undefined;
22
23 if (a_rep.exp == 0 and a_rep.fraction == 0) {
24 // zero
25 abs_result = 0;
26 } else if (a_rep.exp == 0x7FFF) {
27 // a is nan or infinite
28 abs_result = @as(u128, a_rep.fraction) << (dst_sig_bits - src_sig_bits);
29 abs_result |= @as(u128, a_rep.exp) << dst_sig_bits;
30 } else if (a_rep.fraction & src_int_bit != 0) {
31 // a is a normal value
32 abs_result = @as(u128, a_rep.fraction & src_sig_mask) << (dst_sig_bits - src_sig_bits);
33 abs_result |= @as(u128, a_rep.exp) << dst_sig_bits;
34 } else {
35 // a is denormal
36 abs_result = @as(u128, a_rep.fraction) << (dst_sig_bits - src_sig_bits);
37 }
38
39 // Apply the signbit to (dst_t)abs(a).
40 const result: u128 align(@alignOf(f128)) = abs_result | @as(u128, sign) << (dst_bits - 16);
41 return @bitCast(result);
42}
lib/compiler_rt/fabs.zig+25-13
......@@ -9,39 +9,51 @@ comptime {
99 symbol(&fabsf, "fabsf");
1010 symbol(&fabs, "fabs");
1111 symbol(&__fabsx, "__fabsx");
12 if (compiler_rt.want_ppc_abi) {
13 symbol(&fabsq, "fabsf128");
14 }
15 symbol(&fabsq, "fabsq");
12 symbol(&fabsq, "fabsf128");
1613 symbol(&fabsl, "fabsl");
1714}
1815
19pub fn __fabsh(a: f16) callconv(.c) f16 {
16fn __fabsh(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
17 return compiler_rt.f16.toAbi(fabs_f16(compiler_rt.f16.fromAbi(a)));
18}
19pub fn fabs_f16(a: f16) f16 {
2020 return generic_fabs(a);
2121}
2222
23pub fn fabsf(a: f32) callconv(.c) f32 {
23fn fabsf(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
24 return compiler_rt.f32.toAbi(fabs_f32(compiler_rt.f32.fromAbi(a)));
25}
26pub fn fabs_f32(a: f32) f32 {
2427 return generic_fabs(a);
2528}
2629
27pub fn fabs(a: f64) callconv(.c) f64 {
30fn fabs(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
31 return compiler_rt.f64.toAbi(fabs_f64(compiler_rt.f64.fromAbi(a)));
32}
33pub fn fabs_f64(a: f64) f64 {
2834 return generic_fabs(a);
2935}
3036
31pub fn __fabsx(a: f80) callconv(.c) f80 {
37fn __fabsx(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
38 return compiler_rt.f80.toAbi(fabs_f80(compiler_rt.f80.fromAbi(a)));
39}
40pub fn fabs_f80(a: f80) f80 {
3241 return generic_fabs(a);
3342}
3443
35pub fn fabsq(a: f128) callconv(.c) f128 {
44fn fabsq(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
45 return compiler_rt.f128.toAbi(fabs_f128(compiler_rt.f128.fromAbi(a)));
46}
47pub fn fabs_f128(a: f128) f128 {
3648 return generic_fabs(a);
3749}
3850
3951pub fn fabsl(x: c_longdouble) callconv(.c) c_longdouble {
4052 switch (@typeInfo(c_longdouble).float.bits) {
41 64 => return fabs(x),
42 80 => return __fabsx(x),
43 128 => return fabsq(x),
44 else => @compileError("unreachable"),
53 64 => return fabs_f64(x),
54 80 => return fabs_f80(x),
55 128 => return fabs_f128(x),
56 else => comptime unreachable,
4557 }
4658}
4759
lib/compiler_rt/fixdfdi.zig deleted-23
......@@ -1,23 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const intFromFloat = @import("./int_from_float.zig").intFromFloat;
5
6comptime {
7 if (compiler_rt.want_aeabi) {
8 symbol(&__aeabi_d2lz, "__aeabi_d2lz");
9 } else {
10 if (compiler_rt.want_windows_arm_abi) {
11 symbol(&__fixdfdi, "__dtoi64");
12 }
13 symbol(&__fixdfdi, "__fixdfdi");
14 }
15}
16
17pub fn __fixdfdi(a: f64) callconv(.c) i64 {
18 return intFromFloat(i64, a);
19}
20
21fn __aeabi_d2lz(a: f64) callconv(.{ .arm_aapcs = .{} }) i64 {
22 return intFromFloat(i64, a);
23}
lib/compiler_rt/fixdfei.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat;
6
7comptime {
8 symbol(&__fixdfei, "__fixdfei");
9}
10
11pub fn __fixdfei(r: [*]u8, bits: usize, a: f64) callconv(.c) void {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return bigIntFromFloat(.signed, @ptrCast(@alignCast(r[0..byte_size])), a);
14}
lib/compiler_rt/fixdfsi.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const intFromFloat = @import("./int_from_float.zig").intFromFloat;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_d2iz, "__aeabi_d2iz");
8 } else {
9 symbol(&__fixdfsi, "__fixdfsi");
10 }
11}
12
13pub fn __fixdfsi(a: f64) callconv(.c) i32 {
14 return intFromFloat(i32, a);
15}
16
17fn __aeabi_d2iz(a: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
18 return intFromFloat(i32, a);
19}
lib/compiler_rt/fixdfti.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const intFromFloat = @import("./int_from_float.zig").intFromFloat;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 symbol(&__fixdfti, "__fixdfti");
7}
8
9pub fn __fixdfti(a: f64) callconv(.c) i128 {
10 return intFromFloat(i128, a);
11}
lib/compiler_rt/fixhfei.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat;
6
7comptime {
8 symbol(&__fixhfei, "__fixhfei");
9}
10
11pub fn __fixhfei(r: [*]u8, bits: usize, a: f16) callconv(.c) void {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return bigIntFromFloat(.signed, @ptrCast(@alignCast(r[0..byte_size])), a);
14}
lib/compiler_rt/fixint_test.zig deleted-149
......@@ -1,149 +0,0 @@
1const std = @import("std");
2const math = std.math;
3const testing = std.testing;
4
5const fixint = @import("fixint.zig").fixint;
6
7fn test__fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t, expected: fixint_t) !void {
8 const x = fixint(fp_t, fixint_t, a);
9 try testing.expect(x == expected);
10}
11
12test "fixint.i1" {
13 try test__fixint(f32, i1, -math.inf(f32), -1);
14 try test__fixint(f32, i1, -math.floatMax(f32), -1);
15 try test__fixint(f32, i1, -2.0, -1);
16 try test__fixint(f32, i1, -1.1, -1);
17 try test__fixint(f32, i1, -1.0, -1);
18 try test__fixint(f32, i1, -0.9, 0);
19 try test__fixint(f32, i1, -0.1, 0);
20 try test__fixint(f32, i1, -math.floatMin(f32), 0);
21 try test__fixint(f32, i1, -0.0, 0);
22 try test__fixint(f32, i1, 0.0, 0);
23 try test__fixint(f32, i1, math.floatMin(f32), 0);
24 try test__fixint(f32, i1, 0.1, 0);
25 try test__fixint(f32, i1, 0.9, 0);
26 try test__fixint(f32, i1, 1.0, 0);
27 try test__fixint(f32, i1, 2.0, 0);
28 try test__fixint(f32, i1, math.floatMax(f32), 0);
29 try test__fixint(f32, i1, math.inf(f32), 0);
30}
31
32test "fixint.i2" {
33 try test__fixint(f32, i2, -math.inf(f32), -2);
34 try test__fixint(f32, i2, -math.floatMax(f32), -2);
35 try test__fixint(f32, i2, -2.0, -2);
36 try test__fixint(f32, i2, -1.9, -1);
37 try test__fixint(f32, i2, -1.1, -1);
38 try test__fixint(f32, i2, -1.0, -1);
39 try test__fixint(f32, i2, -0.9, 0);
40 try test__fixint(f32, i2, -0.1, 0);
41 try test__fixint(f32, i2, -math.floatMin(f32), 0);
42 try test__fixint(f32, i2, -0.0, 0);
43 try test__fixint(f32, i2, 0.0, 0);
44 try test__fixint(f32, i2, math.floatMin(f32), 0);
45 try test__fixint(f32, i2, 0.1, 0);
46 try test__fixint(f32, i2, 0.9, 0);
47 try test__fixint(f32, i2, 1.0, 1);
48 try test__fixint(f32, i2, 2.0, 1);
49 try test__fixint(f32, i2, math.floatMax(f32), 1);
50 try test__fixint(f32, i2, math.inf(f32), 1);
51}
52
53test "fixint.i3" {
54 try test__fixint(f32, i3, -math.inf(f32), -4);
55 try test__fixint(f32, i3, -math.floatMax(f32), -4);
56 try test__fixint(f32, i3, -4.0, -4);
57 try test__fixint(f32, i3, -3.0, -3);
58 try test__fixint(f32, i3, -2.0, -2);
59 try test__fixint(f32, i3, -1.9, -1);
60 try test__fixint(f32, i3, -1.1, -1);
61 try test__fixint(f32, i3, -1.0, -1);
62 try test__fixint(f32, i3, -0.9, 0);
63 try test__fixint(f32, i3, -0.1, 0);
64 try test__fixint(f32, i3, -math.floatMin(f32), 0);
65 try test__fixint(f32, i3, -0.0, 0);
66 try test__fixint(f32, i3, 0.0, 0);
67 try test__fixint(f32, i3, math.floatMin(f32), 0);
68 try test__fixint(f32, i3, 0.1, 0);
69 try test__fixint(f32, i3, 0.9, 0);
70 try test__fixint(f32, i3, 1.0, 1);
71 try test__fixint(f32, i3, 2.0, 2);
72 try test__fixint(f32, i3, 3.0, 3);
73 try test__fixint(f32, i3, 4.0, 3);
74 try test__fixint(f32, i3, math.floatMax(f32), 3);
75 try test__fixint(f32, i3, math.inf(f32), 3);
76}
77
78test "fixint.i32" {
79 try test__fixint(f64, i32, -math.inf(f64), math.minInt(i32));
80 try test__fixint(f64, i32, -math.floatMax(f64), math.minInt(i32));
81 try test__fixint(f64, i32, @as(f64, math.minInt(i32)), math.minInt(i32));
82 try test__fixint(f64, i32, @as(f64, math.minInt(i32)) + 1, math.minInt(i32) + 1);
83 try test__fixint(f64, i32, -2.0, -2);
84 try test__fixint(f64, i32, -1.9, -1);
85 try test__fixint(f64, i32, -1.1, -1);
86 try test__fixint(f64, i32, -1.0, -1);
87 try test__fixint(f64, i32, -0.9, 0);
88 try test__fixint(f64, i32, -0.1, 0);
89 try test__fixint(f64, i32, -@as(f64, math.floatMin(f32)), 0);
90 try test__fixint(f64, i32, -0.0, 0);
91 try test__fixint(f64, i32, 0.0, 0);
92 try test__fixint(f64, i32, @as(f64, math.floatMin(f32)), 0);
93 try test__fixint(f64, i32, 0.1, 0);
94 try test__fixint(f64, i32, 0.9, 0);
95 try test__fixint(f64, i32, 1.0, 1);
96 try test__fixint(f64, i32, @as(f64, math.maxInt(i32)) - 1, math.maxInt(i32) - 1);
97 try test__fixint(f64, i32, @as(f64, math.maxInt(i32)), math.maxInt(i32));
98 try test__fixint(f64, i32, math.floatMax(f64), math.maxInt(i32));
99 try test__fixint(f64, i32, math.inf(f64), math.maxInt(i32));
100}
101
102test "fixint.i64" {
103 try test__fixint(f64, i64, -math.inf(f64), math.minInt(i64));
104 try test__fixint(f64, i64, -math.floatMax(f64), math.minInt(i64));
105 try test__fixint(f64, i64, @as(f64, math.minInt(i64)), math.minInt(i64));
106 try test__fixint(f64, i64, @as(f64, math.minInt(i64)) + 1, math.minInt(i64));
107 try test__fixint(f64, i64, @as(f64, math.minInt(i64) / 2), math.minInt(i64) / 2);
108 try test__fixint(f64, i64, -2.0, -2);
109 try test__fixint(f64, i64, -1.9, -1);
110 try test__fixint(f64, i64, -1.1, -1);
111 try test__fixint(f64, i64, -1.0, -1);
112 try test__fixint(f64, i64, -0.9, 0);
113 try test__fixint(f64, i64, -0.1, 0);
114 try test__fixint(f64, i64, -@as(f64, math.floatMin(f32)), 0);
115 try test__fixint(f64, i64, -0.0, 0);
116 try test__fixint(f64, i64, 0.0, 0);
117 try test__fixint(f64, i64, @as(f64, math.floatMin(f32)), 0);
118 try test__fixint(f64, i64, 0.1, 0);
119 try test__fixint(f64, i64, 0.9, 0);
120 try test__fixint(f64, i64, 1.0, 1);
121 try test__fixint(f64, i64, @as(f64, math.maxInt(i64)) - 1, math.maxInt(i64));
122 try test__fixint(f64, i64, @as(f64, math.maxInt(i64)), math.maxInt(i64));
123 try test__fixint(f64, i64, math.floatMax(f64), math.maxInt(i64));
124 try test__fixint(f64, i64, math.inf(f64), math.maxInt(i64));
125}
126
127test "fixint.i128" {
128 try test__fixint(f64, i128, -math.inf(f64), math.minInt(i128));
129 try test__fixint(f64, i128, -math.floatMax(f64), math.minInt(i128));
130 try test__fixint(f64, i128, @as(f64, math.minInt(i128)), math.minInt(i128));
131 try test__fixint(f64, i128, @as(f64, math.minInt(i128)) + 1, math.minInt(i128));
132 try test__fixint(f64, i128, -2.0, -2);
133 try test__fixint(f64, i128, -1.9, -1);
134 try test__fixint(f64, i128, -1.1, -1);
135 try test__fixint(f64, i128, -1.0, -1);
136 try test__fixint(f64, i128, -0.9, 0);
137 try test__fixint(f64, i128, -0.1, 0);
138 try test__fixint(f64, i128, -@as(f64, math.floatMin(f32)), 0);
139 try test__fixint(f64, i128, -0.0, 0);
140 try test__fixint(f64, i128, 0.0, 0);
141 try test__fixint(f64, i128, @as(f64, math.floatMin(f32)), 0);
142 try test__fixint(f64, i128, 0.1, 0);
143 try test__fixint(f64, i128, 0.9, 0);
144 try test__fixint(f64, i128, 1.0, 1);
145 try test__fixint(f64, i128, @as(f64, math.maxInt(i128)) - 1, math.maxInt(i128));
146 try test__fixint(f64, i128, @as(f64, math.maxInt(i128)), math.maxInt(i128));
147 try test__fixint(f64, i128, math.floatMax(f64), math.maxInt(i128));
148 try test__fixint(f64, i128, math.inf(f64), math.maxInt(i128));
149}
lib/compiler_rt/fixsfdi.zig deleted-23
......@@ -1,23 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4const symbol = @import("../compiler_rt.zig").symbol;
5
6comptime {
7 if (compiler_rt.want_aeabi) {
8 symbol(&__aeabi_f2lz, "__aeabi_f2lz");
9 } else {
10 if (compiler_rt.want_windows_arm_abi) {
11 symbol(&__fixsfdi, "__stoi64");
12 }
13 symbol(&__fixsfdi, "__fixsfdi");
14 }
15}
16
17pub fn __fixsfdi(a: f32) callconv(.c) i64 {
18 return intFromFloat(i64, a);
19}
20
21fn __aeabi_f2lz(a: f32) callconv(.{ .arm_aapcs = .{} }) i64 {
22 return intFromFloat(i64, a);
23}
lib/compiler_rt/fixsfei.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat;
6
7comptime {
8 symbol(&__fixsfei, "__fixsfei");
9}
10
11pub fn __fixsfei(r: [*]u8, bits: usize, a: f32) callconv(.c) void {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return bigIntFromFloat(.signed, @ptrCast(@alignCast(r[0..byte_size])), a);
14}
lib/compiler_rt/fixsfsi.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_f2iz, "__aeabi_f2iz");
8 } else {
9 symbol(&__fixsfsi, "__fixsfsi");
10 }
11}
12
13pub fn __fixsfsi(a: f32) callconv(.c) i32 {
14 return intFromFloat(i32, a);
15}
16
17fn __aeabi_f2iz(a: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
18 return intFromFloat(i32, a);
19}
lib/compiler_rt/fixsfti.zig deleted-12
......@@ -1,12 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const intFromFloat = @import("./int_from_float.zig").intFromFloat;
5
6comptime {
7 symbol(&__fixsfti, "__fixsfti");
8}
9
10pub fn __fixsfti(a: f32) callconv(.c) i128 {
11 return intFromFloat(i128, a);
12}
lib/compiler_rt/fixtfdi.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const intFromFloat = @import("./int_from_float.zig").intFromFloat;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__fixtfdi, "__fixkfdi");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_qtox, "_Qp_qtox");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__fixtfdi, "_Q_qtoll");
12 }
13 symbol(&__fixtfdi, "__fixtfdi");
14}
15
16pub fn __fixtfdi(a: f128) callconv(.c) i64 {
17 return intFromFloat(i64, a);
18}
19
20fn _Qp_qtox(a: *const f128) callconv(.c) i64 {
21 return intFromFloat(i64, a.*);
22}
lib/compiler_rt/fixtfei.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat;
6
7comptime {
8 symbol(&__fixtfei, "__fixtfei");
9}
10
11pub fn __fixtfei(r: [*]u8, bits: usize, a: f128) callconv(.c) void {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return bigIntFromFloat(.signed, @ptrCast(@alignCast(r[0..byte_size])), a);
14}
lib/compiler_rt/fixtfsi.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__fixtfsi, "__fixkfsi");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_qtoi, "_Qp_qtoi");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__fixtfsi, "_Q_qtoi");
12 }
13 symbol(&__fixtfsi, "__fixtfsi");
14}
15
16pub fn __fixtfsi(a: f128) callconv(.c) i32 {
17 return intFromFloat(i32, a);
18}
19
20fn _Qp_qtoi(a: *const f128) callconv(.c) i32 {
21 return intFromFloat(i32, a.*);
22}
lib/compiler_rt/fixtfti.zig deleted-13
......@@ -1,13 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const intFromFloat = @import("./int_from_float.zig").intFromFloat;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_ppc_abi)
7 symbol(&__fixtfti, "__fixkfti");
8 symbol(&__fixtfti, "__fixtfti");
9}
10
11pub fn __fixtfti(a: f128) callconv(.c) i128 {
12 return intFromFloat(i128, a);
13}
lib/compiler_rt/fixunsdfdi.zig deleted-23
......@@ -1,23 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const intFromFloat = @import("./int_from_float.zig").intFromFloat;
5
6comptime {
7 if (compiler_rt.want_aeabi) {
8 symbol(&__aeabi_d2ulz, "__aeabi_d2ulz");
9 } else {
10 if (compiler_rt.want_windows_arm_abi) {
11 symbol(&__fixunsdfdi, "__dtou64");
12 }
13 symbol(&__fixunsdfdi, "__fixunsdfdi");
14 }
15}
16
17pub fn __fixunsdfdi(a: f64) callconv(.c) u64 {
18 return intFromFloat(u64, a);
19}
20
21fn __aeabi_d2ulz(a: f64) callconv(.{ .arm_aapcs = .{} }) u64 {
22 return intFromFloat(u64, a);
23}
lib/compiler_rt/fixunsdfei.zig deleted-15
......@@ -1,15 +0,0 @@
1const builtin = @import("builtin");
2
3const std = @import("std");
4
5const symbol = @import("../compiler_rt.zig").symbol;
6const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat;
7
8comptime {
9 symbol(&__fixunsdfei, "__fixunsdfei");
10}
11
12pub fn __fixunsdfei(r: [*]u8, bits: usize, a: f64) callconv(.c) void {
13 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
14 return bigIntFromFloat(.unsigned, @ptrCast(@alignCast(r[0..byte_size])), a);
15}
lib/compiler_rt/fixunsdfsi.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_d2uiz, "__aeabi_d2uiz");
8 } else {
9 symbol(&__fixunsdfsi, "__fixunsdfsi");
10 }
11}
12
13pub fn __fixunsdfsi(a: f64) callconv(.c) u32 {
14 return intFromFloat(u32, a);
15}
16
17fn __aeabi_d2uiz(a: f64) callconv(.{ .arm_aapcs = .{} }) u32 {
18 return intFromFloat(u32, a);
19}
lib/compiler_rt/fixunsdfti.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4
5comptime {
6 symbol(&__fixunsdfti, "__fixunsdfti");
7}
8
9pub fn __fixunsdfti(a: f64) callconv(.c) u128 {
10 return intFromFloat(u128, a);
11}
lib/compiler_rt/fixunshfdi.zig deleted-10
......@@ -1,10 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const intFromFloat = @import("./int_from_float.zig").intFromFloat;
3
4comptime {
5 symbol(&__fixunshfdi, "__fixunshfdi");
6}
7
8fn __fixunshfdi(a: f16) callconv(.c) u64 {
9 return intFromFloat(u64, a);
10}
lib/compiler_rt/fixunshfei.zig deleted-15
......@@ -1,15 +0,0 @@
1const builtin = @import("builtin");
2
3const std = @import("std");
4
5const symbol = @import("../compiler_rt.zig").symbol;
6const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat;
7
8comptime {
9 symbol(&__fixunshfei, "__fixunshfei");
10}
11
12pub fn __fixunshfei(r: [*]u8, bits: usize, a: f16) callconv(.c) void {
13 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
14 return bigIntFromFloat(.unsigned, @ptrCast(@alignCast(r[0..byte_size])), a);
15}
lib/compiler_rt/fixunshfsi.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4
5comptime {
6 symbol(&__fixunshfsi, "__fixunshfsi");
7}
8
9fn __fixunshfsi(a: f16) callconv(.c) u32 {
10 return intFromFloat(u32, a);
11}
lib/compiler_rt/fixunshfti.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const intFromFloat = @import("./int_from_float.zig").intFromFloat;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 symbol(&__fixunshfti, "__fixunshfti");
7}
8
9pub fn __fixunshfti(a: f16) callconv(.c) u128 {
10 return intFromFloat(u128, a);
11}
lib/compiler_rt/fixunssfdi.zig deleted-23
......@@ -1,23 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const intFromFloat = @import("./int_from_float.zig").intFromFloat;
5
6comptime {
7 if (compiler_rt.want_aeabi) {
8 symbol(&__aeabi_f2ulz, "__aeabi_f2ulz");
9 } else {
10 if (compiler_rt.want_windows_arm_abi) {
11 symbol(&__fixunssfdi, "__stou64");
12 }
13 symbol(&__fixunssfdi, "__fixunssfdi");
14 }
15}
16
17pub fn __fixunssfdi(a: f32) callconv(.c) u64 {
18 return intFromFloat(u64, a);
19}
20
21fn __aeabi_f2ulz(a: f32) callconv(.{ .arm_aapcs = .{} }) u64 {
22 return intFromFloat(u64, a);
23}
lib/compiler_rt/fixunssfei.zig deleted-15
......@@ -1,15 +0,0 @@
1const builtin = @import("builtin");
2
3const std = @import("std");
4
5const symbol = @import("../compiler_rt.zig").symbol;
6const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat;
7
8comptime {
9 symbol(&__fixunssfei, "__fixunssfei");
10}
11
12pub fn __fixunssfei(r: [*]u8, bits: usize, a: f32) callconv(.c) void {
13 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
14 return bigIntFromFloat(.unsigned, @ptrCast(@alignCast(r[0..byte_size])), a);
15}
lib/compiler_rt/fixunssfsi.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_f2uiz, "__aeabi_f2uiz");
8 } else {
9 symbol(&__fixunssfsi, "__fixunssfsi");
10 }
11}
12
13pub fn __fixunssfsi(a: f32) callconv(.c) u32 {
14 return intFromFloat(u32, a);
15}
16
17fn __aeabi_f2uiz(a: f32) callconv(.{ .arm_aapcs = .{} }) u32 {
18 return intFromFloat(u32, a);
19}
lib/compiler_rt/fixunssfti.zig deleted-12
......@@ -1,12 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4const symbol = @import("../compiler_rt.zig").symbol;
5
6comptime {
7 symbol(&__fixunssfti, "__fixunssfti");
8}
9
10pub fn __fixunssfti(a: f32) callconv(.c) u128 {
11 return intFromFloat(u128, a);
12}
lib/compiler_rt/fixunstfdi.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__fixunstfdi, "__fixunskfdi");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_qtoux, "_Qp_qtoux");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__fixunstfdi, "_Q_qtoull");
12 }
13 symbol(&__fixunstfdi, "__fixunstfdi");
14}
15
16pub fn __fixunstfdi(a: f128) callconv(.c) u64 {
17 return intFromFloat(u64, a);
18}
19
20fn _Qp_qtoux(a: *const f128) callconv(.c) u64 {
21 return intFromFloat(u64, a.*);
22}
lib/compiler_rt/fixunstfei.zig deleted-15
......@@ -1,15 +0,0 @@
1const builtin = @import("builtin");
2
3const std = @import("std");
4
5const symbol = @import("../compiler_rt.zig").symbol;
6const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat;
7
8comptime {
9 symbol(&__fixunstfei, "__fixunstfei");
10}
11
12pub fn __fixunstfei(r: [*]u8, bits: usize, a: f128) callconv(.c) void {
13 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
14 return bigIntFromFloat(.unsigned, @ptrCast(@alignCast(r[0..byte_size])), a);
15}
lib/compiler_rt/fixunstfsi.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__fixunstfsi, "__fixunskfsi");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_qtoui, "_Qp_qtoui");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__fixunstfsi, "_Q_qtou");
12 }
13 symbol(&__fixunstfsi, "__fixunstfsi");
14}
15
16pub fn __fixunstfsi(a: f128) callconv(.c) u32 {
17 return intFromFloat(u32, a);
18}
19
20fn _Qp_qtoui(a: *const f128) callconv(.c) u32 {
21 return intFromFloat(u32, a.*);
22}
lib/compiler_rt/fixunstfti.zig deleted-14
......@@ -1,14 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const intFromFloat = @import("./int_from_float.zig").intFromFloat;
5
6comptime {
7 if (compiler_rt.want_ppc_abi)
8 symbol(&__fixunstfti, "__fixunskfti");
9 symbol(&__fixunstfti, "__fixunstfti");
10}
11
12pub fn __fixunstfti(a: f128) callconv(.c) u128 {
13 return intFromFloat(u128, a);
14}
lib/compiler_rt/fixunsxfdi.zig deleted-10
......@@ -1,10 +0,0 @@
1const intFromFloat = @import("./int_from_float.zig").intFromFloat;
2const symbol = @import("../compiler_rt.zig").symbol;
3
4comptime {
5 symbol(&__fixunsxfdi, "__fixunsxfdi");
6}
7
8fn __fixunsxfdi(a: f80) callconv(.c) u64 {
9 return intFromFloat(u64, a);
10}
lib/compiler_rt/fixunsxfei.zig deleted-13
......@@ -1,13 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const symbol = @import("../compiler_rt.zig").symbol;
4const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat;
5
6comptime {
7 symbol(&__fixunsxfei, "__fixunsxfei");
8}
9
10pub fn __fixunsxfei(r: [*]u8, bits: usize, a: f80) callconv(.c) void {
11 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
12 return bigIntFromFloat(.unsigned, @ptrCast(@alignCast(r[0..byte_size])), a);
13}
lib/compiler_rt/fixunsxfsi.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4
5comptime {
6 symbol(&__fixunsxfsi, "__fixunsxfsi");
7}
8
9fn __fixunsxfsi(a: f80) callconv(.c) u32 {
10 return intFromFloat(u32, a);
11}
lib/compiler_rt/fixunsxfti.zig deleted-12
......@@ -1,12 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const intFromFloat = @import("./int_from_float.zig").intFromFloat;
5
6comptime {
7 symbol(&__fixunsxfti, "__fixunsxfti");
8}
9
10pub fn __fixunsxfti(a: f80) callconv(.c) u128 {
11 return intFromFloat(u128, a);
12}
lib/compiler_rt/fixxfdi.zig deleted-10
......@@ -1,10 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const intFromFloat = @import("./int_from_float.zig").intFromFloat;
3
4comptime {
5 symbol(&__fixxfdi, "__fixxfdi");
6}
7
8fn __fixxfdi(a: f80) callconv(.c) i64 {
9 return intFromFloat(i64, a);
10}
lib/compiler_rt/fixxfei.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat;
6
7comptime {
8 symbol(&__fixxfei, "__fixxfei");
9}
10
11pub fn __fixxfei(r: [*]u8, bits: usize, a: f80) callconv(.c) void {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return bigIntFromFloat(.signed, @ptrCast(@alignCast(r[0..byte_size])), a);
14}
lib/compiler_rt/fixxfsi.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4
5comptime {
6 symbol(&__fixxfsi, "__fixxfsi");
7}
8
9fn __fixxfsi(a: f80) callconv(.c) i32 {
10 return intFromFloat(i32, a);
11}
lib/compiler_rt/float_from_int.zig+472-4
......@@ -1,7 +1,475 @@
1const builtin = @import("builtin");
12const std = @import("std");
23const math = std.math;
34
4pub fn floatFromInt(comptime T: type, x: anytype) T {
5const compiler_rt = @import("../compiler_rt.zig");
6const symbol = compiler_rt.symbol;
7
8comptime {
9 symbol(&__floatsihf, "__floatsihf");
10 symbol(&__floatdihf, "__floatdihf");
11 symbol(&__floattihf, "__floattihf");
12 symbol(&__floateihf, "__floateihf");
13
14 if (compiler_rt.want_aeabi) {
15 symbol(&__aeabi_i2f, "__aeabi_i2f");
16 symbol(&__aeabi_l2f, "__aeabi_l2f");
17 } else {
18 symbol(&__floatsisf, "__floatsisf");
19 symbol(&__floatdisf, "__floatdisf");
20 if (compiler_rt.want_windows_arm_abi) symbol(&__floatdisf, "__i64tos");
21 }
22 symbol(&__floattisf, "__floattisf");
23 symbol(&__floateisf, "__floateisf");
24
25 if (compiler_rt.want_aeabi) {
26 symbol(&__aeabi_i2d, "__aeabi_i2d");
27 symbol(&__aeabi_l2d, "__aeabi_l2d");
28 } else {
29 symbol(&__floatsidf, "__floatsidf");
30 symbol(&__floatdidf, "__floatdidf");
31 if (compiler_rt.want_windows_arm_abi) symbol(&__floatdidf, "__i64tod");
32 }
33 symbol(&__floattidf, "__floattidf");
34 symbol(&__floateidf, "__floateidf");
35
36 symbol(&__floatsixf, "__floatsixf");
37 symbol(&__floatdixf, "__floatdixf");
38 symbol(&__floattixf, "__floattixf");
39 symbol(&__floateixf, "__floateixf");
40
41 if (compiler_rt.want_ppc_abi) {
42 symbol(&__floatsitf, "__floatsikf");
43 symbol(&__floatditf, "__floatdikf");
44 } else if (compiler_rt.want_sparc64_abi) {
45 symbol(&_Qp_itoq, "_Qp_itoq");
46 symbol(&_Qp_xtoq, "_Qp_xtoq");
47 } else if (compiler_rt.want_sparc32_abi) {
48 symbol(&__floatsitf, "_Q_itoq");
49 symbol(&__floatditf, "_Q_lltoq");
50 } else {
51 symbol(&__floatsitf, "__floatsitf");
52 symbol(&__floatditf, "__floatditf");
53 }
54 if (compiler_rt.want_ppc_abi) {
55 symbol(&__floattitf, "__floattikf");
56 symbol(&__floateitf, "__floateikf");
57 } else {
58 if (builtin.cpu.arch == .x86) {
59 symbol(&__floattitf_x86, "__floattitf");
60 } else {
61 symbol(&__floattitf, "__floattitf");
62 }
63 symbol(&__floateitf, "__floateitf");
64 }
65}
66
67fn __floatsihf(a: i32) callconv(.c) compiler_rt.f16.Abi {
68 return compiler_rt.f16.toAbi(f16_floatFromInt_i32(a));
69}
70pub fn f16_floatFromInt_i32(a: i32) f16 {
71 return floatFromInt(f16, a);
72}
73
74fn __floatdihf(a: i64) callconv(.c) compiler_rt.f16.Abi {
75 return compiler_rt.f16.toAbi(f16_floatFromInt_i64(a));
76}
77pub fn f16_floatFromInt_i64(a: i64) f16 {
78 return floatFromInt(f16, a);
79}
80
81fn __floattihf(a: i128) callconv(.c) compiler_rt.f16.Abi {
82 return compiler_rt.f16.toAbi(f16_floatFromInt_i128(a));
83}
84pub fn f16_floatFromInt_i128(a: i128) f16 {
85 return floatFromInt(f16, a);
86}
87
88fn __floateihf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f16.Abi {
89 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
90 return compiler_rt.f16.toAbi(f16_floatFromInt_signed(a[0..byte_size]));
91}
92pub fn f16_floatFromInt_signed(a: []const u8) f16 {
93 return floatFromBigInt(f16, .signed, @ptrCast(@alignCast(a)));
94}
95
96fn __floatsisf(a: i32) callconv(.c) compiler_rt.f32.Abi {
97 return compiler_rt.f32.toAbi(f32_floatFromInt_i32(a));
98}
99fn __aeabi_i2f(a: i32) callconv(.{ .arm_aapcs = .{} }) f32 {
100 return f32_floatFromInt_i32(a);
101}
102pub fn f32_floatFromInt_i32(a: i32) f32 {
103 return floatFromInt(f32, a);
104}
105
106fn __floatdisf(a: i64) callconv(.c) compiler_rt.f32.Abi {
107 return compiler_rt.f32.toAbi(f32_floatFromInt_i64(a));
108}
109fn __aeabi_l2f(a: i64) callconv(.{ .arm_aapcs = .{} }) f32 {
110 return f32_floatFromInt_i64(a);
111}
112pub fn f32_floatFromInt_i64(a: i64) f32 {
113 return floatFromInt(f32, a);
114}
115
116fn __floattisf(a: i128) callconv(.c) compiler_rt.f32.Abi {
117 return compiler_rt.f32.toAbi(f32_floatFromInt_i128(a));
118}
119pub fn f32_floatFromInt_i128(a: i128) f32 {
120 return floatFromInt(f32, a);
121}
122
123fn __floateisf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f32.Abi {
124 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
125 return compiler_rt.f32.toAbi(f32_floatFromInt_signed(a[0..byte_size]));
126}
127pub fn f32_floatFromInt_signed(a: []const u8) f32 {
128 return floatFromBigInt(f32, .signed, @ptrCast(@alignCast(a)));
129}
130
131fn __floatsidf(a: i32) callconv(.c) compiler_rt.f64.Abi {
132 return compiler_rt.f64.toAbi(f64_floatFromInt_i32(a));
133}
134fn __aeabi_i2d(a: i32) callconv(.{ .arm_aapcs = .{} }) f64 {
135 return f64_floatFromInt_i32(a);
136}
137pub fn f64_floatFromInt_i32(a: i32) f64 {
138 return floatFromInt(f64, a);
139}
140
141fn __floatdidf(a: i64) callconv(.c) compiler_rt.f64.Abi {
142 return compiler_rt.f64.toAbi(f64_floatFromInt_i64(a));
143}
144fn __aeabi_l2d(a: i64) callconv(.{ .arm_aapcs = .{} }) f64 {
145 return f64_floatFromInt_i64(a);
146}
147pub fn f64_floatFromInt_i64(a: i64) f64 {
148 return floatFromInt(f64, a);
149}
150
151fn __floattidf(a: i128) callconv(.c) compiler_rt.f64.Abi {
152 return compiler_rt.f64.toAbi(f64_floatFromInt_i128(a));
153}
154pub fn f64_floatFromInt_i128(a: i128) f64 {
155 return floatFromInt(f64, a);
156}
157
158fn __floateidf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f64.Abi {
159 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
160 return compiler_rt.f64.toAbi(f64_floatFromInt_signed(a[0..byte_size]));
161}
162pub fn f64_floatFromInt_signed(a: []const u8) f64 {
163 return floatFromBigInt(f64, .signed, @ptrCast(@alignCast(a)));
164}
165
166fn __floatsixf(a: i32) callconv(.c) compiler_rt.f80.Abi {
167 return compiler_rt.f80.toAbi(f80_floatFromInt_i32(a));
168}
169pub fn f80_floatFromInt_i32(a: i32) f80 {
170 return floatFromInt(f80, a);
171}
172
173fn __floatdixf(a: i64) callconv(.c) compiler_rt.f80.Abi {
174 return compiler_rt.f80.toAbi(f80_floatFromInt_i64(a));
175}
176pub fn f80_floatFromInt_i64(a: i64) f80 {
177 return floatFromInt(f80, a);
178}
179
180fn __floattixf(a: i128) callconv(.c) compiler_rt.f80.Abi {
181 return compiler_rt.f80.toAbi(f80_floatFromInt_i128(a));
182}
183pub fn f80_floatFromInt_i128(a: i128) f80 {
184 return floatFromInt(f80, a);
185}
186
187fn __floateixf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f80.Abi {
188 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
189 return compiler_rt.f80.toAbi(f80_floatFromInt_signed(a[0..byte_size]));
190}
191pub fn f80_floatFromInt_signed(a: []const u8) f80 {
192 return floatFromBigInt(f80, .signed, @ptrCast(@alignCast(a)));
193}
194
195fn __floatsitf(a: i32) callconv(.c) compiler_rt.f128.Abi {
196 return compiler_rt.f128.toAbi(f128_floatFromInt_i32(a));
197}
198fn _Qp_itoq(c: *f128, a: i32) callconv(.c) void {
199 c.* = f128_floatFromInt_i32(a);
200}
201pub fn f128_floatFromInt_i32(a: i32) f128 {
202 return floatFromInt(f128, a);
203}
204
205fn __floatditf(a: i64) callconv(.c) compiler_rt.f128.Abi {
206 return compiler_rt.f128.toAbi(f128_floatFromInt_i64(a));
207}
208fn _Qp_xtoq(c: *f128, a: i64) callconv(.c) void {
209 c.* = f128_floatFromInt_i64(a);
210}
211pub fn f128_floatFromInt_i64(a: i64) f128 {
212 return floatFromInt(f128, a);
213}
214
215fn __floattitf(a: i128) callconv(.c) compiler_rt.f128.Abi {
216 return compiler_rt.f128.toAbi(f128_floatFromInt_i128(a));
217}
218fn __floattitf_x86(a: f128) callconv(.c) compiler_rt.f128.Abi {
219 return compiler_rt.f128.toAbi(f128_floatFromInt_i128(@bitCast(a)));
220}
221pub fn f128_floatFromInt_i128(a: i128) f128 {
222 return floatFromInt(f128, a);
223}
224
225fn __floateitf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f128.Abi {
226 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
227 return compiler_rt.f128.toAbi(f128_floatFromInt_signed(a[0..byte_size]));
228}
229pub fn f128_floatFromInt_signed(a: []const u8) f128 {
230 return floatFromBigInt(f128, .signed, @ptrCast(@alignCast(a)));
231}
232
233comptime {
234 symbol(&__floatunsihf, "__floatunsihf");
235 symbol(&__floatundihf, "__floatundihf");
236 symbol(&__floatuntihf, "__floatuntihf");
237 symbol(&__floatuneihf, "__floatuneihf");
238
239 if (compiler_rt.want_aeabi) {
240 symbol(&__aeabi_ui2f, "__aeabi_ui2f");
241 symbol(&__aeabi_ul2f, "__aeabi_ul2f");
242 } else {
243 symbol(&__floatunsisf, "__floatunsisf");
244 symbol(&__floatundisf, "__floatundisf");
245 if (compiler_rt.want_windows_arm_abi) symbol(&__floatundisf, "__u64tos");
246 }
247 symbol(&__floatuntisf, "__floatuntisf");
248 symbol(&__floatuneisf, "__floatuneisf");
249
250 if (compiler_rt.want_aeabi) {
251 symbol(&__aeabi_ui2d, "__aeabi_ui2d");
252 } else {
253 symbol(&__floatunsidf, "__floatunsidf");
254 }
255 if (compiler_rt.want_aeabi) {
256 symbol(&__aeabi_ul2d, "__aeabi_ul2d");
257 } else {
258 if (compiler_rt.want_windows_arm_abi) {
259 symbol(&__floatundidf, "__u64tod");
260 }
261 symbol(&__floatundidf, "__floatundidf");
262 }
263 symbol(&__floatuntidf, "__floatuntidf");
264 symbol(&__floatuneidf, "__floatuneidf");
265
266 symbol(&__floatunsixf, "__floatunsixf");
267 symbol(&__floatundixf, "__floatundixf");
268 symbol(&__floatuntixf, "__floatuntixf");
269 symbol(&__floatuneixf, "__floatuneixf");
270
271 if (compiler_rt.want_ppc_abi) {
272 symbol(&__floatunsitf, "__floatunsikf");
273 symbol(&__floatunditf, "__floatundikf");
274 } else if (compiler_rt.want_sparc64_abi) {
275 symbol(&_Qp_uitoq, "_Qp_uitoq");
276 symbol(&_Qp_uxtoq, "_Qp_uxtoq");
277 } else if (compiler_rt.want_sparc32_abi) {
278 symbol(&__floatunsitf, "_Q_utoq");
279 symbol(&__floatunditf, "_Q_ulltoq");
280 } else {
281 symbol(&__floatunsitf, "__floatunsitf");
282 symbol(&__floatunditf, "__floatunditf");
283 }
284 if (compiler_rt.want_ppc_abi) {
285 symbol(&__floatuntitf, "__floatuntikf");
286 symbol(&__floatuneitf, "__floatuneikf");
287 } else {
288 if (builtin.cpu.arch == .x86) {
289 symbol(&__floatuntitf_x86, "__floatuntitf");
290 } else if (builtin.cpu.arch == .x86_64 and
291 (builtin.os.tag == .windows or builtin.os.tag == .uefi))
292 {
293 symbol(&__floatuntitf_x86_64_windows, "__floatuntitf");
294 } else {
295 symbol(&__floatuntitf, "__floatuntitf");
296 }
297 symbol(&__floatuneitf, "__floatuneitf");
298 }
299}
300
301fn __floatunsihf(a: u32) callconv(.c) compiler_rt.f16.Abi {
302 return compiler_rt.f16.toAbi(f16_floatFromInt_u32(a));
303}
304pub fn f16_floatFromInt_u32(a: u32) f16 {
305 return floatFromInt(f16, a);
306}
307
308fn __floatundihf(a: u64) callconv(.c) compiler_rt.f16.Abi {
309 return compiler_rt.f16.toAbi(f16_floatFromInt_u64(a));
310}
311pub fn f16_floatFromInt_u64(a: u64) f16 {
312 return floatFromInt(f16, a);
313}
314
315fn __floatuntihf(a: u128) callconv(.c) compiler_rt.f16.Abi {
316 return compiler_rt.f16.toAbi(f16_floatFromInt_u128(a));
317}
318pub fn f16_floatFromInt_u128(a: u128) f16 {
319 return floatFromInt(f16, a);
320}
321
322fn __floatuneihf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f16.Abi {
323 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
324 return compiler_rt.f16.toAbi(f16_floatFromInt_unsigned(a[0..byte_size]));
325}
326pub fn f16_floatFromInt_unsigned(a: []const u8) f16 {
327 return floatFromBigInt(f16, .unsigned, @ptrCast(@alignCast(a)));
328}
329
330fn __floatunsisf(a: u32) callconv(.c) compiler_rt.f32.Abi {
331 return compiler_rt.f32.toAbi(f32_floatFromInt_u32(a));
332}
333fn __aeabi_ui2f(a: u32) callconv(.{ .arm_aapcs = .{} }) f32 {
334 return f32_floatFromInt_u32(a);
335}
336pub fn f32_floatFromInt_u32(a: u32) f32 {
337 return floatFromInt(f32, a);
338}
339
340fn __floatundisf(a: u64) callconv(.c) compiler_rt.f32.Abi {
341 return compiler_rt.f32.toAbi(f32_floatFromInt_u64(a));
342}
343fn __aeabi_ul2f(a: u64) callconv(.{ .arm_aapcs = .{} }) f32 {
344 return f32_floatFromInt_u64(a);
345}
346pub fn f32_floatFromInt_u64(a: u64) f32 {
347 return floatFromInt(f32, a);
348}
349
350fn __floatuntisf(a: u128) callconv(.c) compiler_rt.f32.Abi {
351 return compiler_rt.f32.toAbi(f32_floatFromInt_u128(a));
352}
353pub fn f32_floatFromInt_u128(a: u128) f32 {
354 return floatFromInt(f32, a);
355}
356
357fn __floatuneisf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f32.Abi {
358 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
359 return compiler_rt.f32.toAbi(f32_floatFromInt_unsigned(a[0..byte_size]));
360}
361pub fn f32_floatFromInt_unsigned(a: []const u8) f32 {
362 return floatFromBigInt(f32, .unsigned, @ptrCast(@alignCast(a)));
363}
364
365fn __floatunsidf(a: u32) callconv(.c) compiler_rt.f64.Abi {
366 return compiler_rt.f64.toAbi(f64_floatFromInt_u32(a));
367}
368fn __aeabi_ui2d(a: u32) callconv(.{ .arm_aapcs = .{} }) f64 {
369 return f64_floatFromInt_u32(a);
370}
371pub fn f64_floatFromInt_u32(a: u32) f64 {
372 return floatFromInt(f64, a);
373}
374
375fn __floatundidf(a: u64) callconv(.c) compiler_rt.f64.Abi {
376 return compiler_rt.f64.toAbi(f64_floatFromInt_u64(a));
377}
378fn __aeabi_ul2d(a: u64) callconv(.{ .arm_aapcs = .{} }) f64 {
379 return f64_floatFromInt_u64(a);
380}
381pub fn f64_floatFromInt_u64(a: u64) f64 {
382 return floatFromInt(f64, a);
383}
384
385fn __floatuntidf(a: u128) callconv(.c) compiler_rt.f64.Abi {
386 return compiler_rt.f64.toAbi(f64_floatFromInt_u128(a));
387}
388pub fn f64_floatFromInt_u128(a: u128) f64 {
389 return floatFromInt(f64, a);
390}
391
392fn __floatuneidf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f64.Abi {
393 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
394 return compiler_rt.f64.toAbi(f64_floatFromInt_unsigned(a[0..byte_size]));
395}
396pub fn f64_floatFromInt_unsigned(a: []const u8) f64 {
397 return floatFromBigInt(f64, .unsigned, @ptrCast(@alignCast(a)));
398}
399
400fn __floatunsixf(a: u32) callconv(.c) compiler_rt.f80.Abi {
401 return compiler_rt.f80.toAbi(f80_floatFromInt_u32(a));
402}
403pub fn f80_floatFromInt_u32(a: u32) f80 {
404 return floatFromInt(f80, a);
405}
406
407fn __floatundixf(a: u64) callconv(.c) compiler_rt.f80.Abi {
408 return compiler_rt.f80.toAbi(f80_floatFromInt_u64(a));
409}
410pub fn f80_floatFromInt_u64(a: u64) f80 {
411 return floatFromInt(f80, a);
412}
413
414fn __floatuntixf(a: u128) callconv(.c) compiler_rt.f80.Abi {
415 return compiler_rt.f80.toAbi(f80_floatFromInt_u128(a));
416}
417pub fn f80_floatFromInt_u128(a: u128) f80 {
418 return floatFromInt(f80, a);
419}
420
421fn __floatuneixf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f80.Abi {
422 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
423 return compiler_rt.f80.toAbi(f80_floatFromInt_unsigned(a[0..byte_size]));
424}
425pub fn f80_floatFromInt_unsigned(a: []const u8) f80 {
426 return floatFromBigInt(f80, .unsigned, @ptrCast(@alignCast(a)));
427}
428
429fn __floatunsitf(a: u32) callconv(.c) compiler_rt.f128.Abi {
430 return compiler_rt.f128.toAbi(f128_floatFromInt_u32(a));
431}
432fn _Qp_uitoq(c: *f128, a: u32) callconv(.c) void {
433 c.* = f128_floatFromInt_u32(a);
434}
435pub fn f128_floatFromInt_u32(a: u32) f128 {
436 return floatFromInt(f128, a);
437}
438
439fn __floatunditf(a: u64) callconv(.c) compiler_rt.f128.Abi {
440 return compiler_rt.f128.toAbi(f128_floatFromInt_u64(a));
441}
442fn _Qp_uxtoq(c: *f128, a: u64) callconv(.c) void {
443 c.* = f128_floatFromInt_u64(a);
444}
445pub fn f128_floatFromInt_u64(a: u64) f128 {
446 return floatFromInt(f128, a);
447}
448
449fn __floatuntitf(a: u128) callconv(.c) compiler_rt.f128.Abi {
450 return compiler_rt.f128.toAbi(f128_floatFromInt_u128(a));
451}
452fn __floatuntitf_x86(a: f128) callconv(.c) compiler_rt.f128.Abi {
453 return compiler_rt.f128.toAbi(f128_floatFromInt_u128(@bitCast(a)));
454}
455fn __floatuntitf_x86_64_windows(a_lo: u64, a_hi: u64) callconv(.c) compiler_rt.f128.Abi {
456 return compiler_rt.f128.toAbi(f128_floatFromInt_u128(@bitCast(
457 packed struct { lo: u64, hi: u64 }{ .lo = a_lo, .hi = a_hi },
458 )));
459}
460pub fn f128_floatFromInt_u128(a: u128) f128 {
461 return floatFromInt(f128, a);
462}
463
464fn __floatuneitf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f128.Abi {
465 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
466 return compiler_rt.f128.toAbi(f128_floatFromInt_unsigned(a[0..byte_size]));
467}
468pub fn f128_floatFromInt_unsigned(a: []const u8) f128 {
469 return floatFromBigInt(f128, .unsigned, @ptrCast(@alignCast(a)));
470}
471
472inline fn floatFromInt(comptime T: type, x: anytype) T {
5473 if (x == 0) return 0;
6474
7475 // Various constants whose values follow from the type parameters.
......@@ -53,7 +521,7 @@ pub fn floatFromInt(comptime T: type, x: anytype) T {
53521 return @bitCast(sign_bit | result);
54522}
55523
56const endian = @import("builtin").cpu.arch.endian();
524const endian = builtin.cpu.arch.endian();
57525inline fn limb(limbs: []const u32, index: usize) u32 {
58526 return switch (endian) {
59527 .little => limbs[index],
......@@ -61,11 +529,11 @@ inline fn limb(limbs: []const u32, index: usize) u32 {
61529 };
62530}
63531
64pub inline fn floatFromBigInt(comptime T: type, comptime signedness: std.builtin.Signedness, x: []const u32) T {
532inline fn floatFromBigInt(comptime T: type, comptime signedness: std.lang.Signedness, x: []const u32) T {
65533 switch (x.len) {
66534 0 => return 0,
67535 inline 1...4 => |limbs_len| {
68 const low_to_high: [limbs_len]u32 = switch (@import("builtin").cpu.arch.endian()) {
536 const low_to_high: [limbs_len]u32 = switch (endian) {
69537 .little => x[0..limbs_len].*,
70538 .big => switch (limbs_len) {
71539 1 => .{x[0]},
lib/compiler_rt/float_from_int_test.zig+757-733
......@@ -2,571 +2,593 @@ const std = @import("std");
22const testing = std.testing;
33const math = std.math;
44
5const __floatunsihf = @import("floatunsihf.zig").__floatunsihf;
6
7// Conversion to f32
8const __floatsisf = @import("floatsisf.zig").__floatsisf;
9const __floatunsisf = @import("floatunsisf.zig").__floatunsisf;
10const __floatdisf = @import("floatdisf.zig").__floatdisf;
11const __floatundisf = @import("floatundisf.zig").__floatundisf;
12const __floattisf = @import("floattisf.zig").__floattisf;
13const __floatuntisf = @import("floatuntisf.zig").__floatuntisf;
14const __floateisf = @import("floateisf.zig").__floateisf;
15const __floatuneisf = @import("floatuneisf.zig").__floatuneisf;
16
17// Conversion to f64
18const __floatsidf = @import("floatsidf.zig").__floatsidf;
19const __floatunsidf = @import("floatunsidf.zig").__floatunsidf;
20const __floatdidf = @import("floatdidf.zig").__floatdidf;
21const __floatundidf = @import("floatundidf.zig").__floatundidf;
22const __floattidf = @import("floattidf.zig").__floattidf;
23const __floatuntidf = @import("floatuntidf.zig").__floatuntidf;
24
25// Conversion to f128
26const __floatsitf = @import("floatsitf.zig").__floatsitf;
27const __floatunsitf = @import("floatunsitf.zig").__floatunsitf;
28const __floatditf = @import("floatditf.zig").__floatditf;
29const __floatunditf = @import("floatunditf.zig").__floatunditf;
30const __floattitf = @import("floattitf.zig").__floattitf;
31const __floatuntitf = @import("floatuntitf.zig").__floatuntitf;
32
33fn test__floatsisf(a: i32, expected: u32) !void {
34 const r = __floatsisf(a);
5const impl = @import("float_from_int.zig");
6
7const f16_floatFromInt_i32 = impl.f16_floatFromInt_i32;
8const f16_floatFromInt_u32 = impl.f16_floatFromInt_u32;
9const f16_floatFromInt_i64 = impl.f16_floatFromInt_i64;
10const f16_floatFromInt_u64 = impl.f16_floatFromInt_u64;
11const f16_floatFromInt_i128 = impl.f16_floatFromInt_i128;
12const f16_floatFromInt_u128 = impl.f16_floatFromInt_u128;
13const f16_floatFromInt_signed = impl.f16_floatFromInt_signed;
14const f16_floatFromInt_unsigned = impl.f16_floatFromInt_unsigned;
15
16const f32_floatFromInt_i32 = impl.f32_floatFromInt_i32;
17const f32_floatFromInt_u32 = impl.f32_floatFromInt_u32;
18const f32_floatFromInt_i64 = impl.f32_floatFromInt_i64;
19const f32_floatFromInt_u64 = impl.f32_floatFromInt_u64;
20const f32_floatFromInt_i128 = impl.f32_floatFromInt_i128;
21const f32_floatFromInt_u128 = impl.f32_floatFromInt_u128;
22const f32_floatFromInt_signed = impl.f32_floatFromInt_signed;
23const f32_floatFromInt_unsigned = impl.f32_floatFromInt_unsigned;
24
25const f64_floatFromInt_i32 = impl.f64_floatFromInt_i32;
26const f64_floatFromInt_u32 = impl.f64_floatFromInt_u32;
27const f64_floatFromInt_i64 = impl.f64_floatFromInt_i64;
28const f64_floatFromInt_u64 = impl.f64_floatFromInt_u64;
29const f64_floatFromInt_i128 = impl.f64_floatFromInt_i128;
30const f64_floatFromInt_u128 = impl.f64_floatFromInt_u128;
31const f64_floatFromInt_signed = impl.f64_floatFromInt_signed;
32const f64_floatFromInt_unsigned = impl.f64_floatFromInt_unsigned;
33
34const f80_floatFromInt_i32 = impl.f80_floatFromInt_i32;
35const f80_floatFromInt_u32 = impl.f80_floatFromInt_u32;
36const f80_floatFromInt_i64 = impl.f80_floatFromInt_i64;
37const f80_floatFromInt_u64 = impl.f80_floatFromInt_u64;
38const f80_floatFromInt_i128 = impl.f80_floatFromInt_i128;
39const f80_floatFromInt_u128 = impl.f80_floatFromInt_u128;
40const f80_floatFromInt_signed = impl.f80_floatFromInt_signed;
41const f80_floatFromInt_unsigned = impl.f80_floatFromInt_unsigned;
42
43const f128_floatFromInt_i32 = impl.f128_floatFromInt_i32;
44const f128_floatFromInt_u32 = impl.f128_floatFromInt_u32;
45const f128_floatFromInt_i64 = impl.f128_floatFromInt_i64;
46const f128_floatFromInt_u64 = impl.f128_floatFromInt_u64;
47const f128_floatFromInt_i128 = impl.f128_floatFromInt_i128;
48const f128_floatFromInt_u128 = impl.f128_floatFromInt_u128;
49const f128_floatFromInt_signed = impl.f128_floatFromInt_signed;
50const f128_floatFromInt_unsigned = impl.f128_floatFromInt_unsigned;
51
52fn test_f32_floatFromInt_i32(a: i32, expected: u32) !void {
53 const r = f32_floatFromInt_i32(a);
3554 try std.testing.expect(@as(u32, @bitCast(r)) == expected);
3655}
3756
38fn test_one_floatunsisf(a: u32, expected: u32) !void {
39 const r = __floatunsisf(a);
57fn test_f32_floatFromInt_u32(a: u32, expected: u32) !void {
58 const r = f32_floatFromInt_u32(a);
4059 try std.testing.expect(@as(u32, @bitCast(r)) == expected);
4160}
4261
43test "floatsisf" {
44 try test__floatsisf(0, 0x00000000);
45 try test__floatsisf(1, 0x3f800000);
46 try test__floatsisf(-1, 0xbf800000);
47 try test__floatsisf(0x7FFFFFFF, 0x4f000000);
48 try test__floatsisf(@bitCast(@as(u32, @intCast(0x80000000))), 0xcf000000);
62test f32_floatFromInt_i32 {
63 try test_f32_floatFromInt_i32(0, 0x00000000);
64 try test_f32_floatFromInt_i32(1, 0x3f800000);
65 try test_f32_floatFromInt_i32(-1, 0xbf800000);
66 try test_f32_floatFromInt_i32(0x7FFFFFFF, 0x4f000000);
67 try test_f32_floatFromInt_i32(@bitCast(@as(u32, @intCast(0x80000000))), 0xcf000000);
68
69 try testing.expect(f32_floatFromInt_i32(math.minInt(i32)) == math.minInt(i32));
4970}
5071
51test "floatunsisf" {
72test f32_floatFromInt_u32 {
5273 // Test the produced bit pattern
53 try test_one_floatunsisf(0, 0);
54 try test_one_floatunsisf(1, 0x3f800000);
55 try test_one_floatunsisf(0x7FFFFFFF, 0x4f000000);
56 try test_one_floatunsisf(0x80000000, 0x4f000000);
57 try test_one_floatunsisf(0xFFFFFFFF, 0x4f800000);
74 try test_f32_floatFromInt_u32(0, 0);
75 try test_f32_floatFromInt_u32(1, 0x3f800000);
76 try test_f32_floatFromInt_u32(0x7FFFFFFF, 0x4f000000);
77 try test_f32_floatFromInt_u32(0x80000000, 0x4f000000);
78 try test_f32_floatFromInt_u32(0xFFFFFFFF, 0x4f800000);
79
80 try testing.expect(f32_floatFromInt_u32(0) == 0.0);
81 try testing.expect(f32_floatFromInt_u32(math.maxInt(u24)) == math.maxInt(u24));
82 try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 1) == math.maxInt(u24) + 1); // 0x100_0000 - Exact
83 try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 2) == math.maxInt(u24) + 1); // 0x100_0001 - Tie: Rounds down to even
84 try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 3) == math.maxInt(u24) + 3); // 0x100_0002 - Exact
85 try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 4) == math.maxInt(u24) + 5); // 0x100_0003 - Tie: Rounds up to even
86 try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 5) == math.maxInt(u24) + 5); // 0x100_0004 - Exact
87 try testing.expect(f32_floatFromInt_u32(math.maxInt(u32)) == math.maxInt(u32) + 1);
88}
89
90fn test_f32_floatFromInt_i64(a: i64, expected: f32) !void {
91 const x = f32_floatFromInt_i64(a);
92 try testing.expect(x == expected);
5893}
5994
60fn test__floatdisf(a: i64, expected: f32) !void {
61 const x = __floatdisf(a);
95fn test_f32_floatFromInt_u64(a: u64, expected: f32) !void {
96 const x = f32_floatFromInt_u64(a);
6297 try testing.expect(x == expected);
6398}
6499
65fn test__floatundisf(a: u64, expected: f32) !void {
66 try std.testing.expectEqual(expected, __floatundisf(a));
67}
68
69test "floatdisf" {
70 try test__floatdisf(0, 0.0);
71 try test__floatdisf(1, 1.0);
72 try test__floatdisf(2, 2.0);
73 try test__floatdisf(-1, -1.0);
74 try test__floatdisf(-2, -2.0);
75 try test__floatdisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
76 try test__floatdisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
77 try test__floatdisf(@bitCast(@as(u64, 0x8000008000000000)), -0x1.FFFFFEp+62);
78 try test__floatdisf(@bitCast(@as(u64, 0x8000010000000000)), -0x1.FFFFFCp+62);
79 try test__floatdisf(@bitCast(@as(u64, 0x8000000000000000)), -0x1.000000p+63);
80 try test__floatdisf(@bitCast(@as(u64, 0x8000000000000001)), -0x1.000000p+63);
81 try test__floatdisf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
82 try test__floatdisf(0x0007FB72EA000000, 0x1.FEDCBAp+50);
83 try test__floatdisf(0x0007FB72EB000000, 0x1.FEDCBAp+50);
84 try test__floatdisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
85 try test__floatdisf(0x0007FB72EC000000, 0x1.FEDCBCp+50);
86 try test__floatdisf(0x0007FB72E8000001, 0x1.FEDCBAp+50);
87 try test__floatdisf(0x0007FB72E6000000, 0x1.FEDCBAp+50);
88 try test__floatdisf(0x0007FB72E7000000, 0x1.FEDCBAp+50);
89 try test__floatdisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
90 try test__floatdisf(0x0007FB72E4000001, 0x1.FEDCBAp+50);
91 try test__floatdisf(0x0007FB72E4000000, 0x1.FEDCB8p+50);
92}
93
94test "floatundisf" {
95 try test__floatundisf(0, 0.0);
96 try test__floatundisf(1, 1.0);
97 try test__floatundisf(2, 2.0);
98 try test__floatundisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
99 try test__floatundisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
100 try test__floatundisf(0x8000008000000000, 0x1p+63);
101 try test__floatundisf(0x8000010000000000, 0x1.000002p+63);
102 try test__floatundisf(0x8000000000000000, 0x1p+63);
103 try test__floatundisf(0x8000000000000001, 0x1p+63);
104 try test__floatundisf(0xFFFFFFFFFFFFFFFE, 0x1p+64);
105 try test__floatundisf(0xFFFFFFFFFFFFFFFF, 0x1p+64);
106 try test__floatundisf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
107 try test__floatundisf(0x0007FB72EA000000, 0x1.FEDCBAp+50);
108 try test__floatundisf(0x0007FB72EB000000, 0x1.FEDCBAp+50);
109 try test__floatundisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
110 try test__floatundisf(0x0007FB72EC000000, 0x1.FEDCBCp+50);
111 try test__floatundisf(0x0007FB72E8000001, 0x1.FEDCBAp+50);
112 try test__floatundisf(0x0007FB72E6000000, 0x1.FEDCBAp+50);
113 try test__floatundisf(0x0007FB72E7000000, 0x1.FEDCBAp+50);
114 try test__floatundisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
115 try test__floatundisf(0x0007FB72E4000001, 0x1.FEDCBAp+50);
116 try test__floatundisf(0x0007FB72E4000000, 0x1.FEDCB8p+50);
117}
118
119fn test__floattisf(a: i128, expected: f32) !void {
120 const x = __floattisf(a);
100test f32_floatFromInt_i64 {
101 try test_f32_floatFromInt_i64(0, 0.0);
102 try test_f32_floatFromInt_i64(1, 1.0);
103 try test_f32_floatFromInt_i64(2, 2.0);
104 try test_f32_floatFromInt_i64(-1, -1.0);
105 try test_f32_floatFromInt_i64(-2, -2.0);
106 try test_f32_floatFromInt_i64(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
107 try test_f32_floatFromInt_i64(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
108 try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000008000000000)), -0x1.FFFFFEp+62);
109 try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000010000000000)), -0x1.FFFFFCp+62);
110 try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000000000000000)), -0x1.000000p+63);
111 try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000000000000001)), -0x1.000000p+63);
112 try test_f32_floatFromInt_i64(0x0007FB72E8000000, 0x1.FEDCBAp+50);
113 try test_f32_floatFromInt_i64(0x0007FB72EA000000, 0x1.FEDCBAp+50);
114 try test_f32_floatFromInt_i64(0x0007FB72EB000000, 0x1.FEDCBAp+50);
115 try test_f32_floatFromInt_i64(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
116 try test_f32_floatFromInt_i64(0x0007FB72EC000000, 0x1.FEDCBCp+50);
117 try test_f32_floatFromInt_i64(0x0007FB72E8000001, 0x1.FEDCBAp+50);
118 try test_f32_floatFromInt_i64(0x0007FB72E6000000, 0x1.FEDCBAp+50);
119 try test_f32_floatFromInt_i64(0x0007FB72E7000000, 0x1.FEDCBAp+50);
120 try test_f32_floatFromInt_i64(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
121 try test_f32_floatFromInt_i64(0x0007FB72E4000001, 0x1.FEDCBAp+50);
122 try test_f32_floatFromInt_i64(0x0007FB72E4000000, 0x1.FEDCB8p+50);
123}
124
125test f32_floatFromInt_u64 {
126 try test_f32_floatFromInt_u64(0, 0.0);
127 try test_f32_floatFromInt_u64(1, 1.0);
128 try test_f32_floatFromInt_u64(2, 2.0);
129 try test_f32_floatFromInt_u64(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
130 try test_f32_floatFromInt_u64(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
131 try test_f32_floatFromInt_u64(0x8000008000000000, 0x1p+63);
132 try test_f32_floatFromInt_u64(0x8000010000000000, 0x1.000002p+63);
133 try test_f32_floatFromInt_u64(0x8000000000000000, 0x1p+63);
134 try test_f32_floatFromInt_u64(0x8000000000000001, 0x1p+63);
135 try test_f32_floatFromInt_u64(0xFFFFFFFFFFFFFFFE, 0x1p+64);
136 try test_f32_floatFromInt_u64(0xFFFFFFFFFFFFFFFF, 0x1p+64);
137 try test_f32_floatFromInt_u64(0x0007FB72E8000000, 0x1.FEDCBAp+50);
138 try test_f32_floatFromInt_u64(0x0007FB72EA000000, 0x1.FEDCBAp+50);
139 try test_f32_floatFromInt_u64(0x0007FB72EB000000, 0x1.FEDCBAp+50);
140 try test_f32_floatFromInt_u64(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
141 try test_f32_floatFromInt_u64(0x0007FB72EC000000, 0x1.FEDCBCp+50);
142 try test_f32_floatFromInt_u64(0x0007FB72E8000001, 0x1.FEDCBAp+50);
143 try test_f32_floatFromInt_u64(0x0007FB72E6000000, 0x1.FEDCBAp+50);
144 try test_f32_floatFromInt_u64(0x0007FB72E7000000, 0x1.FEDCBAp+50);
145 try test_f32_floatFromInt_u64(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
146 try test_f32_floatFromInt_u64(0x0007FB72E4000001, 0x1.FEDCBAp+50);
147 try test_f32_floatFromInt_u64(0x0007FB72E4000000, 0x1.FEDCB8p+50);
148}
149
150fn test_f32_floatFromInt_i128(a: i128, expected: f32) !void {
151 const x = f32_floatFromInt_i128(a);
121152 try testing.expect(x == expected);
122153}
123154
124fn test__floatuntisf(a: u128, expected: f32) !void {
125 const x = __floatuntisf(a);
155fn test_f32_floatFromInt_u128(a: u128, expected: f32) !void {
156 const x = f32_floatFromInt_u128(a);
126157 try testing.expect(x == expected);
127158}
128159
129test "floattisf" {
130 try test__floattisf(0, 0.0);
160test f32_floatFromInt_i128 {
161 try test_f32_floatFromInt_i128(0, 0.0);
131162
132 try test__floattisf(1, 1.0);
133 try test__floattisf(2, 2.0);
134 try test__floattisf(-1, -1.0);
135 try test__floattisf(-2, -2.0);
163 try test_f32_floatFromInt_i128(1, 1.0);
164 try test_f32_floatFromInt_i128(2, 2.0);
165 try test_f32_floatFromInt_i128(-1, -1.0);
166 try test_f32_floatFromInt_i128(-2, -2.0);
136167
137 try test__floattisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
138 try test__floattisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
168 try test_f32_floatFromInt_i128(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
169 try test_f32_floatFromInt_i128(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
139170
140 try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000008000000000), -0x1.FFFFFEp+62);
141 try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000010000000000), -0x1.FFFFFCp+62);
171 try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000008000000000), -0x1.FFFFFEp+62);
172 try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000010000000000), -0x1.FFFFFCp+62);
142173
143 try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000000), -0x1.000000p+63);
144 try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000001), -0x1.000000p+63);
174 try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000000), -0x1.000000p+63);
175 try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000001), -0x1.000000p+63);
145176
146 try test__floattisf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
177 try test_f32_floatFromInt_i128(0x0007FB72E8000000, 0x1.FEDCBAp+50);
147178
148 try test__floattisf(0x0007FB72EA000000, 0x1.FEDCBAp+50);
149 try test__floattisf(0x0007FB72EB000000, 0x1.FEDCBAp+50);
150 try test__floattisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
151 try test__floattisf(0x0007FB72EC000000, 0x1.FEDCBCp+50);
152 try test__floattisf(0x0007FB72E8000001, 0x1.FEDCBAp+50);
179 try test_f32_floatFromInt_i128(0x0007FB72EA000000, 0x1.FEDCBAp+50);
180 try test_f32_floatFromInt_i128(0x0007FB72EB000000, 0x1.FEDCBAp+50);
181 try test_f32_floatFromInt_i128(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
182 try test_f32_floatFromInt_i128(0x0007FB72EC000000, 0x1.FEDCBCp+50);
183 try test_f32_floatFromInt_i128(0x0007FB72E8000001, 0x1.FEDCBAp+50);
153184
154 try test__floattisf(0x0007FB72E6000000, 0x1.FEDCBAp+50);
155 try test__floattisf(0x0007FB72E7000000, 0x1.FEDCBAp+50);
156 try test__floattisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
157 try test__floattisf(0x0007FB72E4000001, 0x1.FEDCBAp+50);
158 try test__floattisf(0x0007FB72E4000000, 0x1.FEDCB8p+50);
185 try test_f32_floatFromInt_i128(0x0007FB72E6000000, 0x1.FEDCBAp+50);
186 try test_f32_floatFromInt_i128(0x0007FB72E7000000, 0x1.FEDCBAp+50);
187 try test_f32_floatFromInt_i128(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
188 try test_f32_floatFromInt_i128(0x0007FB72E4000001, 0x1.FEDCBAp+50);
189 try test_f32_floatFromInt_i128(0x0007FB72E4000000, 0x1.FEDCB8p+50);
159190
160 try test__floattisf(make_ti(0x0007FB72E8000000, 0), 0x1.FEDCBAp+114);
191 try test_f32_floatFromInt_i128(make_ti(0x0007FB72E8000000, 0), 0x1.FEDCBAp+114);
161192
162 try test__floattisf(make_ti(0x0007FB72EA000000, 0), 0x1.FEDCBAp+114);
163 try test__floattisf(make_ti(0x0007FB72EB000000, 0), 0x1.FEDCBAp+114);
164 try test__floattisf(make_ti(0x0007FB72EBFFFFFF, 0), 0x1.FEDCBAp+114);
165 try test__floattisf(make_ti(0x0007FB72EC000000, 0), 0x1.FEDCBCp+114);
166 try test__floattisf(make_ti(0x0007FB72E8000001, 0), 0x1.FEDCBAp+114);
193 try test_f32_floatFromInt_i128(make_ti(0x0007FB72EA000000, 0), 0x1.FEDCBAp+114);
194 try test_f32_floatFromInt_i128(make_ti(0x0007FB72EB000000, 0), 0x1.FEDCBAp+114);
195 try test_f32_floatFromInt_i128(make_ti(0x0007FB72EBFFFFFF, 0), 0x1.FEDCBAp+114);
196 try test_f32_floatFromInt_i128(make_ti(0x0007FB72EC000000, 0), 0x1.FEDCBCp+114);
197 try test_f32_floatFromInt_i128(make_ti(0x0007FB72E8000001, 0), 0x1.FEDCBAp+114);
167198
168 try test__floattisf(make_ti(0x0007FB72E6000000, 0), 0x1.FEDCBAp+114);
169 try test__floattisf(make_ti(0x0007FB72E7000000, 0), 0x1.FEDCBAp+114);
170 try test__floattisf(make_ti(0x0007FB72E7FFFFFF, 0), 0x1.FEDCBAp+114);
171 try test__floattisf(make_ti(0x0007FB72E4000001, 0), 0x1.FEDCBAp+114);
172 try test__floattisf(make_ti(0x0007FB72E4000000, 0), 0x1.FEDCB8p+114);
199 try test_f32_floatFromInt_i128(make_ti(0x0007FB72E6000000, 0), 0x1.FEDCBAp+114);
200 try test_f32_floatFromInt_i128(make_ti(0x0007FB72E7000000, 0), 0x1.FEDCBAp+114);
201 try test_f32_floatFromInt_i128(make_ti(0x0007FB72E7FFFFFF, 0), 0x1.FEDCBAp+114);
202 try test_f32_floatFromInt_i128(make_ti(0x0007FB72E4000001, 0), 0x1.FEDCBAp+114);
203 try test_f32_floatFromInt_i128(make_ti(0x0007FB72E4000000, 0), 0x1.FEDCB8p+114);
173204}
174205
175test "floatuntisf" {
176 try test__floatuntisf(0, 0.0);
206test f32_floatFromInt_u128 {
207 try test_f32_floatFromInt_u128(0, 0.0);
177208
178 try test__floatuntisf(1, 1.0);
179 try test__floatuntisf(2, 2.0);
180 try test__floatuntisf(20, 20.0);
209 try test_f32_floatFromInt_u128(1, 1.0);
210 try test_f32_floatFromInt_u128(2, 2.0);
211 try test_f32_floatFromInt_u128(20, 20.0);
181212
182 try test__floatuntisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
183 try test__floatuntisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
213 try test_f32_floatFromInt_u128(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
214 try test_f32_floatFromInt_u128(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
184215
185 try test__floatuntisf(make_uti(0x8000008000000000, 0), 0x1.000001p+127);
186 try test__floatuntisf(make_uti(0x8000000000000800, 0), 0x1.0p+127);
187 try test__floatuntisf(make_uti(0x8000010000000000, 0), 0x1.000002p+127);
216 try test_f32_floatFromInt_u128(make_uti(0x8000008000000000, 0), 0x1.000001p+127);
217 try test_f32_floatFromInt_u128(make_uti(0x8000000000000800, 0), 0x1.0p+127);
218 try test_f32_floatFromInt_u128(make_uti(0x8000010000000000, 0), 0x1.000002p+127);
188219
189 try test__floatuntisf(make_uti(0x8000000000000000, 0), 0x1.000000p+127);
220 try test_f32_floatFromInt_u128(make_uti(0x8000000000000000, 0), 0x1.000000p+127);
190221
191 try test__floatuntisf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
222 try test_f32_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50);
192223
193 try test__floatuntisf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
194 try test__floatuntisf(0x0007FB72EB000000, 0x1.FEDCBACp+50);
224 try test_f32_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
225 try test_f32_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBACp+50);
195226
196 try test__floatuntisf(0x0007FB72EC000000, 0x1.FEDCBBp+50);
227 try test_f32_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBBp+50);
197228
198 try test__floatuntisf(0x0007FB72E6000000, 0x1.FEDCB98p+50);
199 try test__floatuntisf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
200 try test__floatuntisf(0x0007FB72E4000000, 0x1.FEDCB9p+50);
229 try test_f32_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCB98p+50);
230 try test_f32_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
231 try test_f32_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB9p+50);
201232
202 try test__floatuntisf(0xFFFFFFFFFFFFFFFE, 0x1p+64);
203 try test__floatuntisf(0xFFFFFFFFFFFFFFFF, 0x1p+64);
233 try test_f32_floatFromInt_u128(0xFFFFFFFFFFFFFFFE, 0x1p+64);
234 try test_f32_floatFromInt_u128(0xFFFFFFFFFFFFFFFF, 0x1p+64);
204235
205 try test__floatuntisf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
236 try test_f32_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50);
206237
207 try test__floatuntisf(0x0007FB72EA000000, 0x1.FEDCBAp+50);
208 try test__floatuntisf(0x0007FB72EB000000, 0x1.FEDCBAp+50);
209 try test__floatuntisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
210 try test__floatuntisf(0x0007FB72EC000000, 0x1.FEDCBCp+50);
211 try test__floatuntisf(0x0007FB72E8000001, 0x1.FEDCBAp+50);
238 try test_f32_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBAp+50);
239 try test_f32_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBAp+50);
240 try test_f32_floatFromInt_u128(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
241 try test_f32_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBCp+50);
242 try test_f32_floatFromInt_u128(0x0007FB72E8000001, 0x1.FEDCBAp+50);
212243
213 try test__floatuntisf(0x0007FB72E6000000, 0x1.FEDCBAp+50);
214 try test__floatuntisf(0x0007FB72E7000000, 0x1.FEDCBAp+50);
215 try test__floatuntisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
216 try test__floatuntisf(0x0007FB72E4000001, 0x1.FEDCBAp+50);
217 try test__floatuntisf(0x0007FB72E4000000, 0x1.FEDCB8p+50);
244 try test_f32_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCBAp+50);
245 try test_f32_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCBAp+50);
246 try test_f32_floatFromInt_u128(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
247 try test_f32_floatFromInt_u128(0x0007FB72E4000001, 0x1.FEDCBAp+50);
248 try test_f32_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB8p+50);
218249
219 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCB90000000000001), 0x1.FEDCBAp+76);
220 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBA0000000000000), 0x1.FEDCBAp+76);
221 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBAFFFFFFFFFFFFF), 0x1.FEDCBAp+76);
222 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBB0000000000000), 0x1.FEDCBCp+76);
223 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBB0000000000001), 0x1.FEDCBCp+76);
224 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBBFFFFFFFFFFFFF), 0x1.FEDCBCp+76);
225 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBC0000000000000), 0x1.FEDCBCp+76);
226 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBC0000000000001), 0x1.FEDCBCp+76);
227 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBD0000000000000), 0x1.FEDCBCp+76);
228 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBD0000000000001), 0x1.FEDCBEp+76);
229 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBDFFFFFFFFFFFFF), 0x1.FEDCBEp+76);
230 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBE0000000000000), 0x1.FEDCBEp+76);
250 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCB90000000000001), 0x1.FEDCBAp+76);
251 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBA0000000000000), 0x1.FEDCBAp+76);
252 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBAFFFFFFFFFFFFF), 0x1.FEDCBAp+76);
253 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBB0000000000000), 0x1.FEDCBCp+76);
254 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBB0000000000001), 0x1.FEDCBCp+76);
255 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBBFFFFFFFFFFFFF), 0x1.FEDCBCp+76);
256 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBC0000000000000), 0x1.FEDCBCp+76);
257 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBC0000000000001), 0x1.FEDCBCp+76);
258 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBD0000000000000), 0x1.FEDCBCp+76);
259 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBD0000000000001), 0x1.FEDCBEp+76);
260 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBDFFFFFFFFFFFFF), 0x1.FEDCBEp+76);
261 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBE0000000000000), 0x1.FEDCBEp+76);
231262
232263 // Test overflow to infinity
233 try test__floatuntisf(math.maxInt(u128), @bitCast(math.inf(f32)));
264 try test_f32_floatFromInt_u128(math.maxInt(u128), @bitCast(math.inf(f32)));
234265}
235266
236fn test_floateisf(expected: u32, comptime T: type, a: T) !void {
267fn test_f32_floatFromInt(expected: u32, comptime T: type, a: T) !void {
237268 const int = @typeInfo(T).int;
238269 const r = switch (int.signedness) {
239 .signed => __floateisf,
240 .unsigned => __floatuneisf,
241 }(@ptrCast(&a), int.bits);
270 .signed => f32_floatFromInt_signed,
271 .unsigned => f32_floatFromInt_unsigned,
272 }(@ptrCast(&a));
242273 try testing.expect(expected == @as(u32, @bitCast(r)));
243274}
244275
245test "floateisf" {
246 try test_floateisf(0xFF000000, i256, -1 << 127);
247 try test_floateisf(0xFF000000, i256, -math.maxInt(u127));
248 try test_floateisf(0xDF012347, i256, -0x8123468100000000);
249 try test_floateisf(0xDF012347, i256, -0x8123468000000001);
250 try test_floateisf(0xDF012346, i256, -0x8123468000000000);
251 try test_floateisf(0xDF012346, i256, -0x8123458100000000);
252 try test_floateisf(0xDF012346, i256, -0x8123458000000001);
253 try test_floateisf(0xDF012346, i256, -0x8123458000000000);
254 try test_floateisf(0xDF012345, i256, -0x8123456789ABCDEF);
255 try test_floateisf(0xBF800000, i256, -1);
256 try test_floateisf(0x00000000, i256, 0);
257 try test_floateisf(0x5F012345, i256, 0x8123456789ABCDEF);
258 try test_floateisf(0x5F012346, i256, 0x8123458000000000);
259 try test_floateisf(0x5F012346, i256, 0x8123458000000001);
260 try test_floateisf(0x5F012346, i256, 0x8123458100000000);
261 try test_floateisf(0x5F012346, i256, 0x8123468000000000);
262 try test_floateisf(0x5F012347, i256, 0x8123468000000001);
263 try test_floateisf(0x5F012347, i256, 0x8123468100000000);
264 try test_floateisf(0x7F000000, i256, math.maxInt(u127));
265 try test_floateisf(0x7F000000, i256, 1 << 127);
266}
267
268test "floatuneisf" {
269 try test_floateisf(0x00000000, u256, 0);
270 try test_floateisf(0x5F012345, u256, 0x8123456789ABCDEF);
271 try test_floateisf(0x5F012346, u256, 0x8123458000000000);
272 try test_floateisf(0x5F012346, u256, 0x8123458000000001);
273 try test_floateisf(0x5F012346, u256, 0x8123458080000000);
274 try test_floateisf(0x5F012346, u256, 0x8123468000000000);
275 try test_floateisf(0x5F012347, u256, 0x8123468000000001);
276 try test_floateisf(0x5F012347, u256, 0x8123468080000000);
277 try test_floateisf(0x7F000000, u256, math.maxInt(u127));
278 try test_floateisf(0x7F000000, u256, 1 << 127);
279 try test_floateisf(0x7F800000, u256, math.maxInt(u256));
280}
281
282fn test_one_floatsidf(a: i32, expected: u64) !void {
283 const r = __floatsidf(a);
276test f32_floatFromInt_signed {
277 try test_f32_floatFromInt(0xFF000000, i256, -1 << 127);
278 try test_f32_floatFromInt(0xFF000000, i256, -math.maxInt(u127));
279 try test_f32_floatFromInt(0xDF012347, i256, -0x8123468100000000);
280 try test_f32_floatFromInt(0xDF012347, i256, -0x8123468000000001);
281 try test_f32_floatFromInt(0xDF012346, i256, -0x8123468000000000);
282 try test_f32_floatFromInt(0xDF012346, i256, -0x8123458100000000);
283 try test_f32_floatFromInt(0xDF012346, i256, -0x8123458000000001);
284 try test_f32_floatFromInt(0xDF012346, i256, -0x8123458000000000);
285 try test_f32_floatFromInt(0xDF012345, i256, -0x8123456789ABCDEF);
286 try test_f32_floatFromInt(0xBF800000, i256, -1);
287 try test_f32_floatFromInt(0x00000000, i256, 0);
288 try test_f32_floatFromInt(0x5F012345, i256, 0x8123456789ABCDEF);
289 try test_f32_floatFromInt(0x5F012346, i256, 0x8123458000000000);
290 try test_f32_floatFromInt(0x5F012346, i256, 0x8123458000000001);
291 try test_f32_floatFromInt(0x5F012346, i256, 0x8123458100000000);
292 try test_f32_floatFromInt(0x5F012346, i256, 0x8123468000000000);
293 try test_f32_floatFromInt(0x5F012347, i256, 0x8123468000000001);
294 try test_f32_floatFromInt(0x5F012347, i256, 0x8123468100000000);
295 try test_f32_floatFromInt(0x7F000000, i256, math.maxInt(u127));
296 try test_f32_floatFromInt(0x7F000000, i256, 1 << 127);
297}
298
299test f32_floatFromInt_unsigned {
300 try test_f32_floatFromInt(0x00000000, u256, 0);
301 try test_f32_floatFromInt(0x5F012345, u256, 0x8123456789ABCDEF);
302 try test_f32_floatFromInt(0x5F012346, u256, 0x8123458000000000);
303 try test_f32_floatFromInt(0x5F012346, u256, 0x8123458000000001);
304 try test_f32_floatFromInt(0x5F012346, u256, 0x8123458080000000);
305 try test_f32_floatFromInt(0x5F012346, u256, 0x8123468000000000);
306 try test_f32_floatFromInt(0x5F012347, u256, 0x8123468000000001);
307 try test_f32_floatFromInt(0x5F012347, u256, 0x8123468080000000);
308 try test_f32_floatFromInt(0x7F000000, u256, math.maxInt(u127));
309 try test_f32_floatFromInt(0x7F000000, u256, 1 << 127);
310 try test_f32_floatFromInt(0x7F800000, u256, math.maxInt(u256));
311}
312
313fn test_f64_floatFromInt_i32(a: i32, expected: u64) !void {
314 const r = f64_floatFromInt_i32(a);
284315 try std.testing.expect(@as(u64, @bitCast(r)) == expected);
285316}
286317
287fn test_one_floatunsidf(a: u32, expected: u64) !void {
288 const r = __floatunsidf(a);
318fn test_f64_floatFromInt_u32(a: u32, expected: u64) !void {
319 const r = f64_floatFromInt_u32(a);
289320 try std.testing.expect(@as(u64, @bitCast(r)) == expected);
290321}
291322
292test "floatsidf" {
293 try test_one_floatsidf(0, 0x0000000000000000);
294 try test_one_floatsidf(1, 0x3ff0000000000000);
295 try test_one_floatsidf(-1, 0xbff0000000000000);
296 try test_one_floatsidf(0x7FFFFFFF, 0x41dfffffffc00000);
297 try test_one_floatsidf(@bitCast(@as(u32, @intCast(0x80000000))), 0xc1e0000000000000);
323test f64_floatFromInt_i32 {
324 try test_f64_floatFromInt_i32(0, 0x0000000000000000);
325 try test_f64_floatFromInt_i32(1, 0x3ff0000000000000);
326 try test_f64_floatFromInt_i32(-1, 0xbff0000000000000);
327 try test_f64_floatFromInt_i32(0x7FFFFFFF, 0x41dfffffffc00000);
328 try test_f64_floatFromInt_i32(@bitCast(@as(u32, @intCast(0x80000000))), 0xc1e0000000000000);
298329}
299330
300test "floatunsidf" {
301 try test_one_floatunsidf(0, 0x0000000000000000);
302 try test_one_floatunsidf(1, 0x3ff0000000000000);
303 try test_one_floatunsidf(0x7FFFFFFF, 0x41dfffffffc00000);
304 try test_one_floatunsidf(@intCast(0x80000000), 0x41e0000000000000);
305 try test_one_floatunsidf(@intCast(0xFFFFFFFF), 0x41efffffffe00000);
331test f64_floatFromInt_u32 {
332 try test_f64_floatFromInt_u32(0, 0x0000000000000000);
333 try test_f64_floatFromInt_u32(1, 0x3ff0000000000000);
334 try test_f64_floatFromInt_u32(0x7FFFFFFF, 0x41dfffffffc00000);
335 try test_f64_floatFromInt_u32(@intCast(0x80000000), 0x41e0000000000000);
336 try test_f64_floatFromInt_u32(@intCast(0xFFFFFFFF), 0x41efffffffe00000);
306337}
307338
308fn test__floatdidf(a: i64, expected: f64) !void {
309 const r = __floatdidf(a);
339fn test_f64_floatFromInt_i64(a: i64, expected: f64) !void {
340 const r = f64_floatFromInt_i64(a);
310341 try testing.expect(r == expected);
311342}
312343
313fn test__floatundidf(a: u64, expected: f64) !void {
314 const r = __floatundidf(a);
344fn test_f64_floatFromInt_u64(a: u64, expected: f64) !void {
345 const r = f64_floatFromInt_u64(a);
315346 try testing.expect(r == expected);
316347}
317348
318test "floatdidf" {
319 try test__floatdidf(0, 0.0);
320 try test__floatdidf(1, 1.0);
321 try test__floatdidf(2, 2.0);
322 try test__floatdidf(20, 20.0);
323 try test__floatdidf(-1, -1.0);
324 try test__floatdidf(-2, -2.0);
325 try test__floatdidf(-20, -20.0);
326 try test__floatdidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
327 try test__floatdidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
328 try test__floatdidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
329 try test__floatdidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
330 try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000008000000000))), -0x1.FFFFFEp+62);
331 try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000000800))), -0x1.FFFFFFFFFFFFEp+62);
332 try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000010000000000))), -0x1.FFFFFCp+62);
333 try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000001000))), -0x1.FFFFFFFFFFFFCp+62);
334 try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000000000))), -0x1.000000p+63);
335 try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000000001))), -0x1.000000p+63); // 0x8000000000000001
336 try test__floatdidf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
337 try test__floatdidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
338 try test__floatdidf(0x0007FB72EB000000, 0x1.FEDCBACp+50);
339 try test__floatdidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
340 try test__floatdidf(0x0007FB72EC000000, 0x1.FEDCBBp+50);
341 try test__floatdidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
342 try test__floatdidf(0x0007FB72E6000000, 0x1.FEDCB98p+50);
343 try test__floatdidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
344 try test__floatdidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
345 try test__floatdidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
346 try test__floatdidf(0x0007FB72E4000000, 0x1.FEDCB9p+50);
347 try test__floatdidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
348 try test__floatdidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
349 try test__floatdidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
350 try test__floatdidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
351 try test__floatdidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
352 try test__floatdidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
353 try test__floatdidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
354 try test__floatdidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
355 try test__floatdidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
356 try test__floatdidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
357 try test__floatdidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
358 try test__floatdidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
359 try test__floatdidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
360 try test__floatdidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
361 try test__floatdidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
362}
363
364test "floatundidf" {
365 try test__floatundidf(0, 0.0);
366 try test__floatundidf(1, 1.0);
367 try test__floatundidf(2, 2.0);
368 try test__floatundidf(20, 20.0);
369 try test__floatundidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
370 try test__floatundidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
371 try test__floatundidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
372 try test__floatundidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
373 try test__floatundidf(0x8000008000000000, 0x1.000001p+63);
374 try test__floatundidf(0x8000000000000800, 0x1.0000000000001p+63);
375 try test__floatundidf(0x8000010000000000, 0x1.000002p+63);
376 try test__floatundidf(0x8000000000001000, 0x1.0000000000002p+63);
377 try test__floatundidf(0x8000000000000000, 0x1p+63);
378 try test__floatundidf(0x8000000000000001, 0x1p+63);
379 try test__floatundidf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
380 try test__floatundidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
381 try test__floatundidf(0x0007FB72EB000000, 0x1.FEDCBACp+50);
382 try test__floatundidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
383 try test__floatundidf(0x0007FB72EC000000, 0x1.FEDCBBp+50);
384 try test__floatundidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
385 try test__floatundidf(0x0007FB72E6000000, 0x1.FEDCB98p+50);
386 try test__floatundidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
387 try test__floatundidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
388 try test__floatundidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
389 try test__floatundidf(0x0007FB72E4000000, 0x1.FEDCB9p+50);
390 try test__floatundidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
391 try test__floatundidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
392 try test__floatundidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
393 try test__floatundidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
394 try test__floatundidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
395 try test__floatundidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
396 try test__floatundidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
397 try test__floatundidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
398 try test__floatundidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
399 try test__floatundidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
400 try test__floatundidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
401 try test__floatundidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
402 try test__floatundidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
403 try test__floatundidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
404 try test__floatundidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
405}
406
407fn test__floattidf(a: i128, expected: f64) !void {
408 const x = __floattidf(a);
349test f64_floatFromInt_i64 {
350 try test_f64_floatFromInt_i64(0, 0.0);
351 try test_f64_floatFromInt_i64(1, 1.0);
352 try test_f64_floatFromInt_i64(2, 2.0);
353 try test_f64_floatFromInt_i64(20, 20.0);
354 try test_f64_floatFromInt_i64(-1, -1.0);
355 try test_f64_floatFromInt_i64(-2, -2.0);
356 try test_f64_floatFromInt_i64(-20, -20.0);
357 try test_f64_floatFromInt_i64(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
358 try test_f64_floatFromInt_i64(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
359 try test_f64_floatFromInt_i64(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
360 try test_f64_floatFromInt_i64(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
361 try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000008000000000))), -0x1.FFFFFEp+62);
362 try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000000800))), -0x1.FFFFFFFFFFFFEp+62);
363 try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000010000000000))), -0x1.FFFFFCp+62);
364 try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000001000))), -0x1.FFFFFFFFFFFFCp+62);
365 try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000000000))), -0x1.000000p+63);
366 try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000000001))), -0x1.000000p+63); // 0x8000000000000001
367 try test_f64_floatFromInt_i64(0x0007FB72E8000000, 0x1.FEDCBAp+50);
368 try test_f64_floatFromInt_i64(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
369 try test_f64_floatFromInt_i64(0x0007FB72EB000000, 0x1.FEDCBACp+50);
370 try test_f64_floatFromInt_i64(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
371 try test_f64_floatFromInt_i64(0x0007FB72EC000000, 0x1.FEDCBBp+50);
372 try test_f64_floatFromInt_i64(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
373 try test_f64_floatFromInt_i64(0x0007FB72E6000000, 0x1.FEDCB98p+50);
374 try test_f64_floatFromInt_i64(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
375 try test_f64_floatFromInt_i64(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
376 try test_f64_floatFromInt_i64(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
377 try test_f64_floatFromInt_i64(0x0007FB72E4000000, 0x1.FEDCB9p+50);
378 try test_f64_floatFromInt_i64(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
379 try test_f64_floatFromInt_i64(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
380 try test_f64_floatFromInt_i64(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
381 try test_f64_floatFromInt_i64(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
382 try test_f64_floatFromInt_i64(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
383 try test_f64_floatFromInt_i64(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
384 try test_f64_floatFromInt_i64(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
385 try test_f64_floatFromInt_i64(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
386 try test_f64_floatFromInt_i64(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
387 try test_f64_floatFromInt_i64(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
388 try test_f64_floatFromInt_i64(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
389 try test_f64_floatFromInt_i64(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
390 try test_f64_floatFromInt_i64(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
391 try test_f64_floatFromInt_i64(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
392 try test_f64_floatFromInt_i64(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
393}
394
395test f64_floatFromInt_u64 {
396 try test_f64_floatFromInt_u64(0, 0.0);
397 try test_f64_floatFromInt_u64(1, 1.0);
398 try test_f64_floatFromInt_u64(2, 2.0);
399 try test_f64_floatFromInt_u64(20, 20.0);
400 try test_f64_floatFromInt_u64(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
401 try test_f64_floatFromInt_u64(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
402 try test_f64_floatFromInt_u64(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
403 try test_f64_floatFromInt_u64(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
404 try test_f64_floatFromInt_u64(0x8000008000000000, 0x1.000001p+63);
405 try test_f64_floatFromInt_u64(0x8000000000000800, 0x1.0000000000001p+63);
406 try test_f64_floatFromInt_u64(0x8000010000000000, 0x1.000002p+63);
407 try test_f64_floatFromInt_u64(0x8000000000001000, 0x1.0000000000002p+63);
408 try test_f64_floatFromInt_u64(0x8000000000000000, 0x1p+63);
409 try test_f64_floatFromInt_u64(0x8000000000000001, 0x1p+63);
410 try test_f64_floatFromInt_u64(0x0007FB72E8000000, 0x1.FEDCBAp+50);
411 try test_f64_floatFromInt_u64(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
412 try test_f64_floatFromInt_u64(0x0007FB72EB000000, 0x1.FEDCBACp+50);
413 try test_f64_floatFromInt_u64(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
414 try test_f64_floatFromInt_u64(0x0007FB72EC000000, 0x1.FEDCBBp+50);
415 try test_f64_floatFromInt_u64(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
416 try test_f64_floatFromInt_u64(0x0007FB72E6000000, 0x1.FEDCB98p+50);
417 try test_f64_floatFromInt_u64(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
418 try test_f64_floatFromInt_u64(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
419 try test_f64_floatFromInt_u64(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
420 try test_f64_floatFromInt_u64(0x0007FB72E4000000, 0x1.FEDCB9p+50);
421 try test_f64_floatFromInt_u64(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
422 try test_f64_floatFromInt_u64(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
423 try test_f64_floatFromInt_u64(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
424 try test_f64_floatFromInt_u64(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
425 try test_f64_floatFromInt_u64(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
426 try test_f64_floatFromInt_u64(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
427 try test_f64_floatFromInt_u64(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
428 try test_f64_floatFromInt_u64(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
429 try test_f64_floatFromInt_u64(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
430 try test_f64_floatFromInt_u64(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
431 try test_f64_floatFromInt_u64(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
432 try test_f64_floatFromInt_u64(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
433 try test_f64_floatFromInt_u64(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
434 try test_f64_floatFromInt_u64(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
435 try test_f64_floatFromInt_u64(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
436}
437
438fn test_f64_floatFromInt_i128(a: i128, expected: f64) !void {
439 const x = f64_floatFromInt_i128(a);
409440 try testing.expect(x == expected);
410441}
411442
412fn test__floatuntidf(a: u128, expected: f64) !void {
413 const x = __floatuntidf(a);
443fn test_f64_floatFromInt_u128(a: u128, expected: f64) !void {
444 const x = f64_floatFromInt_u128(a);
414445 try testing.expect(x == expected);
415446}
416447
417test "floattidf" {
418 try test__floattidf(0, 0.0);
419
420 try test__floattidf(1, 1.0);
421 try test__floattidf(2, 2.0);
422 try test__floattidf(20, 20.0);
423 try test__floattidf(-1, -1.0);
424 try test__floattidf(-2, -2.0);
425 try test__floattidf(-20, -20.0);
426
427 try test__floattidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
428 try test__floattidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
429 try test__floattidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
430 try test__floattidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
431
432 try test__floattidf(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126);
433 try test__floattidf(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126);
434 try test__floattidf(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126);
435 try test__floattidf(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126);
436
437 try test__floattidf(make_ti(0x8000000000000000, 0), -0x1.000000p+127);
438 try test__floattidf(make_ti(0x8000000000000001, 0), -0x1.000000p+127);
439
440 try test__floattidf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
441
442 try test__floattidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
443 try test__floattidf(0x0007FB72EB000000, 0x1.FEDCBACp+50);
444 try test__floattidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
445 try test__floattidf(0x0007FB72EC000000, 0x1.FEDCBBp+50);
446 try test__floattidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
447
448 try test__floattidf(0x0007FB72E6000000, 0x1.FEDCB98p+50);
449 try test__floattidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
450 try test__floattidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
451 try test__floattidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
452 try test__floattidf(0x0007FB72E4000000, 0x1.FEDCB9p+50);
453
454 try test__floattidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
455 try test__floattidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
456 try test__floattidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
457 try test__floattidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
458 try test__floattidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
459 try test__floattidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
460 try test__floattidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
461 try test__floattidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
462 try test__floattidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
463 try test__floattidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
464 try test__floattidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
465 try test__floattidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
466 try test__floattidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
467 try test__floattidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
468 try test__floattidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
469
470 try test__floattidf(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);
471 try test__floattidf(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121);
472 try test__floattidf(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121);
473 try test__floattidf(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121);
474 try test__floattidf(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121);
475 try test__floattidf(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121);
476 try test__floattidf(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121);
477 try test__floattidf(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121);
478 try test__floattidf(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121);
479 try test__floattidf(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121);
480 try test__floattidf(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121);
481 try test__floattidf(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121);
482 try test__floattidf(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121);
483 try test__floattidf(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121);
484 try test__floattidf(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);
485}
486
487test "floatuntidf" {
488 try test__floatuntidf(0, 0.0);
489
490 try test__floatuntidf(1, 1.0);
491 try test__floatuntidf(2, 2.0);
492 try test__floatuntidf(20, 20.0);
493
494 try test__floatuntidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
495 try test__floatuntidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
496 try test__floatuntidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
497 try test__floatuntidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
498
499 try test__floatuntidf(make_uti(0x8000008000000000, 0), 0x1.000001p+127);
500 try test__floatuntidf(make_uti(0x8000000000000800, 0), 0x1.0000000000001p+127);
501 try test__floatuntidf(make_uti(0x8000010000000000, 0), 0x1.000002p+127);
502 try test__floatuntidf(make_uti(0x8000000000001000, 0), 0x1.0000000000002p+127);
503
504 try test__floatuntidf(make_uti(0x8000000000000000, 0), 0x1.000000p+127);
505 try test__floatuntidf(make_uti(0x8000000000000001, 0), 0x1.0000000000000002p+127);
506
507 try test__floatuntidf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
508
509 try test__floatuntidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
510 try test__floatuntidf(0x0007FB72EB000000, 0x1.FEDCBACp+50);
511 try test__floatuntidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
512 try test__floatuntidf(0x0007FB72EC000000, 0x1.FEDCBBp+50);
513 try test__floatuntidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
514
515 try test__floatuntidf(0x0007FB72E6000000, 0x1.FEDCB98p+50);
516 try test__floatuntidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
517 try test__floatuntidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
518 try test__floatuntidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
519 try test__floatuntidf(0x0007FB72E4000000, 0x1.FEDCB9p+50);
520
521 try test__floatuntidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
522 try test__floatuntidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
523 try test__floatuntidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
524 try test__floatuntidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
525 try test__floatuntidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
526 try test__floatuntidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
527 try test__floatuntidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
528 try test__floatuntidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
529 try test__floatuntidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
530 try test__floatuntidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
531 try test__floatuntidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
532 try test__floatuntidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
533 try test__floatuntidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
534 try test__floatuntidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
535 try test__floatuntidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
536
537 try test__floatuntidf(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);
538 try test__floatuntidf(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121);
539 try test__floatuntidf(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121);
540 try test__floatuntidf(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121);
541 try test__floatuntidf(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121);
542 try test__floatuntidf(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121);
543 try test__floatuntidf(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121);
544 try test__floatuntidf(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121);
545 try test__floatuntidf(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121);
546 try test__floatuntidf(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121);
547 try test__floatuntidf(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121);
548 try test__floatuntidf(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121);
549 try test__floatuntidf(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121);
550 try test__floatuntidf(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121);
551 try test__floatuntidf(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);
552}
553
554fn test__floatsitf(a: i32, expected: u128) !void {
555 const r = __floatsitf(a);
448test f64_floatFromInt_i128 {
449 try test_f64_floatFromInt_i128(0, 0.0);
450
451 try test_f64_floatFromInt_i128(1, 1.0);
452 try test_f64_floatFromInt_i128(2, 2.0);
453 try test_f64_floatFromInt_i128(20, 20.0);
454 try test_f64_floatFromInt_i128(-1, -1.0);
455 try test_f64_floatFromInt_i128(-2, -2.0);
456 try test_f64_floatFromInt_i128(-20, -20.0);
457
458 try test_f64_floatFromInt_i128(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
459 try test_f64_floatFromInt_i128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
460 try test_f64_floatFromInt_i128(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
461 try test_f64_floatFromInt_i128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
462
463 try test_f64_floatFromInt_i128(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126);
464 try test_f64_floatFromInt_i128(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126);
465 try test_f64_floatFromInt_i128(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126);
466 try test_f64_floatFromInt_i128(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126);
467
468 try test_f64_floatFromInt_i128(make_ti(0x8000000000000000, 0), -0x1.000000p+127);
469 try test_f64_floatFromInt_i128(make_ti(0x8000000000000001, 0), -0x1.000000p+127);
470
471 try test_f64_floatFromInt_i128(0x0007FB72E8000000, 0x1.FEDCBAp+50);
472
473 try test_f64_floatFromInt_i128(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
474 try test_f64_floatFromInt_i128(0x0007FB72EB000000, 0x1.FEDCBACp+50);
475 try test_f64_floatFromInt_i128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
476 try test_f64_floatFromInt_i128(0x0007FB72EC000000, 0x1.FEDCBBp+50);
477 try test_f64_floatFromInt_i128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
478
479 try test_f64_floatFromInt_i128(0x0007FB72E6000000, 0x1.FEDCB98p+50);
480 try test_f64_floatFromInt_i128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
481 try test_f64_floatFromInt_i128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
482 try test_f64_floatFromInt_i128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
483 try test_f64_floatFromInt_i128(0x0007FB72E4000000, 0x1.FEDCB9p+50);
484
485 try test_f64_floatFromInt_i128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
486 try test_f64_floatFromInt_i128(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
487 try test_f64_floatFromInt_i128(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
488 try test_f64_floatFromInt_i128(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
489 try test_f64_floatFromInt_i128(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
490 try test_f64_floatFromInt_i128(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
491 try test_f64_floatFromInt_i128(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
492 try test_f64_floatFromInt_i128(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
493 try test_f64_floatFromInt_i128(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
494 try test_f64_floatFromInt_i128(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
495 try test_f64_floatFromInt_i128(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
496 try test_f64_floatFromInt_i128(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
497 try test_f64_floatFromInt_i128(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
498 try test_f64_floatFromInt_i128(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
499 try test_f64_floatFromInt_i128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
500
501 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);
502 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121);
503 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121);
504 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121);
505 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121);
506 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121);
507 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121);
508 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121);
509 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121);
510 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121);
511 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121);
512 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121);
513 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121);
514 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121);
515 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);
516}
517
518test f64_floatFromInt_u128 {
519 try test_f64_floatFromInt_u128(0, 0.0);
520
521 try test_f64_floatFromInt_u128(1, 1.0);
522 try test_f64_floatFromInt_u128(2, 2.0);
523 try test_f64_floatFromInt_u128(20, 20.0);
524
525 try test_f64_floatFromInt_u128(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
526 try test_f64_floatFromInt_u128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
527 try test_f64_floatFromInt_u128(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
528 try test_f64_floatFromInt_u128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
529
530 try test_f64_floatFromInt_u128(make_uti(0x8000008000000000, 0), 0x1.000001p+127);
531 try test_f64_floatFromInt_u128(make_uti(0x8000000000000800, 0), 0x1.0000000000001p+127);
532 try test_f64_floatFromInt_u128(make_uti(0x8000010000000000, 0), 0x1.000002p+127);
533 try test_f64_floatFromInt_u128(make_uti(0x8000000000001000, 0), 0x1.0000000000002p+127);
534
535 try test_f64_floatFromInt_u128(make_uti(0x8000000000000000, 0), 0x1.000000p+127);
536 try test_f64_floatFromInt_u128(make_uti(0x8000000000000001, 0), 0x1.0000000000000002p+127);
537
538 try test_f64_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50);
539
540 try test_f64_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
541 try test_f64_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBACp+50);
542 try test_f64_floatFromInt_u128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
543 try test_f64_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBBp+50);
544 try test_f64_floatFromInt_u128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
545
546 try test_f64_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCB98p+50);
547 try test_f64_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
548 try test_f64_floatFromInt_u128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
549 try test_f64_floatFromInt_u128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
550 try test_f64_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB9p+50);
551
552 try test_f64_floatFromInt_u128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
553 try test_f64_floatFromInt_u128(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
554 try test_f64_floatFromInt_u128(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
555 try test_f64_floatFromInt_u128(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
556 try test_f64_floatFromInt_u128(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
557 try test_f64_floatFromInt_u128(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
558 try test_f64_floatFromInt_u128(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
559 try test_f64_floatFromInt_u128(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
560 try test_f64_floatFromInt_u128(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
561 try test_f64_floatFromInt_u128(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
562 try test_f64_floatFromInt_u128(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
563 try test_f64_floatFromInt_u128(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
564 try test_f64_floatFromInt_u128(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
565 try test_f64_floatFromInt_u128(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
566 try test_f64_floatFromInt_u128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
567
568 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);
569 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121);
570 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121);
571 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121);
572 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121);
573 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121);
574 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121);
575 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121);
576 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121);
577 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121);
578 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121);
579 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121);
580 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121);
581 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121);
582 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);
583}
584
585fn test_f128_floatFromInt_i32(a: i32, expected: u128) !void {
586 const r = f128_floatFromInt_i32(a);
556587 try std.testing.expect(@as(u128, @bitCast(r)) == expected);
557588}
558589
559test "floatsitf" {
560 try test__floatsitf(0, 0);
561 try test__floatsitf(0x7FFFFFFF, 0x401dfffffffc00000000000000000000);
562 try test__floatsitf(0x12345678, 0x401b2345678000000000000000000000);
563 try test__floatsitf(-0x12345678, 0xc01b2345678000000000000000000000);
564 try test__floatsitf(@bitCast(@as(u32, @intCast(0xffffffff))), 0xbfff0000000000000000000000000000);
565 try test__floatsitf(@bitCast(@as(u32, @intCast(0x80000000))), 0xc01e0000000000000000000000000000);
566}
567
568fn test__floatunsitf(a: u32, expected_hi: u64, expected_lo: u64) !void {
569 const x = __floatunsitf(a);
590fn test_f128_floatFromInt_u32(a: u32, expected_hi: u64, expected_lo: u64) !void {
591 const x = f128_floatFromInt_u32(a);
570592
571593 const x_repr: u128 = @bitCast(x);
572594 const x_hi: u64 = @intCast(x_repr >> 64);
......@@ -581,24 +603,32 @@ fn test__floatunsitf(a: u32, expected_hi: u64, expected_lo: u64) !void {
581603 return;
582604 }
583605 }
606 return error.TestFailure;
607}
584608
585 @panic("__floatunsitf test failure");
609test f128_floatFromInt_i32 {
610 try test_f128_floatFromInt_i32(0, 0);
611 try test_f128_floatFromInt_i32(0x7FFFFFFF, 0x401dfffffffc00000000000000000000);
612 try test_f128_floatFromInt_i32(0x12345678, 0x401b2345678000000000000000000000);
613 try test_f128_floatFromInt_i32(-0x12345678, 0xc01b2345678000000000000000000000);
614 try test_f128_floatFromInt_i32(@bitCast(@as(u32, @intCast(0xffffffff))), 0xbfff0000000000000000000000000000);
615 try test_f128_floatFromInt_i32(@bitCast(@as(u32, @intCast(0x80000000))), 0xc01e0000000000000000000000000000);
586616}
587617
588test "floatunsitf" {
589 try test__floatunsitf(0x7fffffff, 0x401dfffffffc0000, 0x0);
590 try test__floatunsitf(0, 0x0, 0x0);
591 try test__floatunsitf(0xffffffff, 0x401efffffffe0000, 0x0);
592 try test__floatunsitf(0x12345678, 0x401b234567800000, 0x0);
618test f128_floatFromInt_u32 {
619 try test_f128_floatFromInt_u32(0x7fffffff, 0x401dfffffffc0000, 0x0);
620 try test_f128_floatFromInt_u32(0, 0x0, 0x0);
621 try test_f128_floatFromInt_u32(0xffffffff, 0x401efffffffe0000, 0x0);
622 try test_f128_floatFromInt_u32(0x12345678, 0x401b234567800000, 0x0);
593623}
594624
595fn test__floatditf(a: i64, expected: f128) !void {
596 const x = __floatditf(a);
625fn test_f128_floatFromInt_i64(a: i64, expected: f128) !void {
626 const x = f128_floatFromInt_i64(a);
597627 try testing.expect(x == expected);
598628}
599629
600fn test__floatunditf(a: u64, expected_hi: u64, expected_lo: u64) !void {
601 const x = __floatunditf(a);
630fn test_f128_floatFromInt_u64(a: u64, expected_hi: u64, expected_lo: u64) !void {
631 const x = f128_floatFromInt_u64(a);
602632
603633 const x_repr: u128 = @bitCast(x);
604634 const x_hi: u64 = @intCast(x_repr >> 64);
......@@ -613,208 +643,207 @@ fn test__floatunditf(a: u64, expected_hi: u64, expected_lo: u64) !void {
613643 return;
614644 }
615645 }
616
617 @panic("__floatunditf test failure");
618}
619
620test "floatditf" {
621 try test__floatditf(0x7fffffffffffffff, make_tf(0x403dffffffffffff, 0xfffc000000000000));
622 try test__floatditf(0x123456789abcdef1, make_tf(0x403b23456789abcd, 0xef10000000000000));
623 try test__floatditf(0x2, make_tf(0x4000000000000000, 0x0));
624 try test__floatditf(0x1, make_tf(0x3fff000000000000, 0x0));
625 try test__floatditf(0x0, make_tf(0x0, 0x0));
626 try test__floatditf(@bitCast(@as(u64, 0xffffffffffffffff)), make_tf(0xbfff000000000000, 0x0));
627 try test__floatditf(@bitCast(@as(u64, 0xfffffffffffffffe)), make_tf(0xc000000000000000, 0x0));
628 try test__floatditf(-0x123456789abcdef1, make_tf(0xc03b23456789abcd, 0xef10000000000000));
629 try test__floatditf(@bitCast(@as(u64, 0x8000000000000000)), make_tf(0xc03e000000000000, 0x0));
630}
631
632test "floatunditf" {
633 try test__floatunditf(0xffffffffffffffff, 0x403effffffffffff, 0xfffe000000000000);
634 try test__floatunditf(0xfffffffffffffffe, 0x403effffffffffff, 0xfffc000000000000);
635 try test__floatunditf(0x8000000000000000, 0x403e000000000000, 0x0);
636 try test__floatunditf(0x7fffffffffffffff, 0x403dffffffffffff, 0xfffc000000000000);
637 try test__floatunditf(0x123456789abcdef1, 0x403b23456789abcd, 0xef10000000000000);
638 try test__floatunditf(0x2, 0x4000000000000000, 0x0);
639 try test__floatunditf(0x1, 0x3fff000000000000, 0x0);
640 try test__floatunditf(0x0, 0x0, 0x0);
641}
642
643fn test__floattitf(a: i128, expected: f128) !void {
644 const x = __floattitf(a);
646 return error.TestFailure;
647}
648
649test f128_floatFromInt_i64 {
650 try test_f128_floatFromInt_i64(0x7fffffffffffffff, make_tf(0x403dffffffffffff, 0xfffc000000000000));
651 try test_f128_floatFromInt_i64(0x123456789abcdef1, make_tf(0x403b23456789abcd, 0xef10000000000000));
652 try test_f128_floatFromInt_i64(0x2, make_tf(0x4000000000000000, 0x0));
653 try test_f128_floatFromInt_i64(0x1, make_tf(0x3fff000000000000, 0x0));
654 try test_f128_floatFromInt_i64(0x0, make_tf(0x0, 0x0));
655 try test_f128_floatFromInt_i64(@bitCast(@as(u64, 0xffffffffffffffff)), make_tf(0xbfff000000000000, 0x0));
656 try test_f128_floatFromInt_i64(@bitCast(@as(u64, 0xfffffffffffffffe)), make_tf(0xc000000000000000, 0x0));
657 try test_f128_floatFromInt_i64(-0x123456789abcdef1, make_tf(0xc03b23456789abcd, 0xef10000000000000));
658 try test_f128_floatFromInt_i64(@bitCast(@as(u64, 0x8000000000000000)), make_tf(0xc03e000000000000, 0x0));
659}
660
661test f128_floatFromInt_u64 {
662 try test_f128_floatFromInt_u64(0xffffffffffffffff, 0x403effffffffffff, 0xfffe000000000000);
663 try test_f128_floatFromInt_u64(0xfffffffffffffffe, 0x403effffffffffff, 0xfffc000000000000);
664 try test_f128_floatFromInt_u64(0x8000000000000000, 0x403e000000000000, 0x0);
665 try test_f128_floatFromInt_u64(0x7fffffffffffffff, 0x403dffffffffffff, 0xfffc000000000000);
666 try test_f128_floatFromInt_u64(0x123456789abcdef1, 0x403b23456789abcd, 0xef10000000000000);
667 try test_f128_floatFromInt_u64(0x2, 0x4000000000000000, 0x0);
668 try test_f128_floatFromInt_u64(0x1, 0x3fff000000000000, 0x0);
669 try test_f128_floatFromInt_u64(0x0, 0x0, 0x0);
670}
671
672fn test_f128_floatFromInt_i128(a: i128, expected: f128) !void {
673 const x = f128_floatFromInt_i128(a);
645674 try testing.expect(x == expected);
646675}
647676
648fn test__floatuntitf(a: u128, expected: f128) !void {
649 const x = __floatuntitf(a);
677fn test_f128_floatFromInt_u128(a: u128, expected: f128) !void {
678 const x = f128_floatFromInt_u128(a);
650679 try testing.expect(x == expected);
651680}
652681
653test "floattitf" {
654 try test__floattitf(0, 0.0);
655
656 try test__floattitf(1, 1.0);
657 try test__floattitf(2, 2.0);
658 try test__floattitf(20, 20.0);
659 try test__floattitf(-1, -1.0);
660 try test__floattitf(-2, -2.0);
661 try test__floattitf(-20, -20.0);
662
663 try test__floattitf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
664 try test__floattitf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
665 try test__floattitf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
666 try test__floattitf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
667
668 try test__floattitf(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126);
669 try test__floattitf(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126);
670 try test__floattitf(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126);
671 try test__floattitf(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126);
672
673 try test__floattitf(make_ti(0x8000000000000000, 0), -0x1.000000p+127);
674 try test__floattitf(make_ti(0x8000000000000001, 0), -0x1.FFFFFFFFFFFFFFFCp+126);
675
676 try test__floattitf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
677
678 try test__floattitf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
679 try test__floattitf(0x0007FB72EB000000, 0x1.FEDCBACp+50);
680 try test__floattitf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
681 try test__floattitf(0x0007FB72EC000000, 0x1.FEDCBBp+50);
682 try test__floattitf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
683
684 try test__floattitf(0x0007FB72E6000000, 0x1.FEDCB98p+50);
685 try test__floattitf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
686 try test__floattitf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
687 try test__floattitf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
688 try test__floattitf(0x0007FB72E4000000, 0x1.FEDCB9p+50);
689
690 try test__floattitf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
691 try test__floattitf(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57);
692 try test__floattitf(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57);
693 try test__floattitf(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57);
694 try test__floattitf(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57);
695 try test__floattitf(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57);
696 try test__floattitf(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57);
697 try test__floattitf(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57);
698 try test__floattitf(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57);
699 try test__floattitf(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57);
700 try test__floattitf(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57);
701 try test__floattitf(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57);
702 try test__floattitf(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57);
703 try test__floattitf(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57);
704 try test__floattitf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
705
706 try test__floattitf(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);
707 try test__floattitf(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121);
708 try test__floattitf(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121);
709 try test__floattitf(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121);
710 try test__floattitf(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121);
711 try test__floattitf(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121);
712 try test__floattitf(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121);
713 try test__floattitf(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121);
714 try test__floattitf(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121);
715 try test__floattitf(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121);
716 try test__floattitf(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121);
717 try test__floattitf(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121);
718 try test__floattitf(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121);
719 try test__floattitf(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121);
720 try test__floattitf(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);
721
722 try test__floattitf(make_ti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63);
723
724 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124);
725 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124);
726 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124);
727 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124);
728 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124);
729 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124);
730 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124);
731 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124);
732 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124);
733}
734
735test "floatuntitf" {
736 try test__floatuntitf(0, 0.0);
737
738 try test__floatuntitf(1, 1.0);
739 try test__floatuntitf(2, 2.0);
740 try test__floatuntitf(20, 20.0);
741
742 try test__floatuntitf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
743 try test__floatuntitf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
744 try test__floatuntitf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
745 try test__floatuntitf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
746 try test__floatuntitf(0x7FFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFEp+59);
747 try test__floatuntitf(0xFFFFFFFFFFFFFFFE, 0xF.FFFFFFFFFFFFFFEp+60);
748 try test__floatuntitf(0xFFFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFFp+60);
749
750 try test__floatuntitf(0x8000008000000000, 0x8.000008p+60);
751 try test__floatuntitf(0x8000000000000800, 0x8.0000000000008p+60);
752 try test__floatuntitf(0x8000010000000000, 0x8.00001p+60);
753 try test__floatuntitf(0x8000000000001000, 0x8.000000000001p+60);
754
755 try test__floatuntitf(0x8000000000000000, 0x8p+60);
756 try test__floatuntitf(0x8000000000000001, 0x8.000000000000001p+60);
757
758 try test__floatuntitf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
759
760 try test__floatuntitf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
761 try test__floatuntitf(0x0007FB72EB000000, 0x1.FEDCBACp+50);
762 try test__floatuntitf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
763 try test__floatuntitf(0x0007FB72EC000000, 0x1.FEDCBBp+50);
764 try test__floatuntitf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
765
766 try test__floatuntitf(0x0007FB72E6000000, 0x1.FEDCB98p+50);
767 try test__floatuntitf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
768 try test__floatuntitf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
769 try test__floatuntitf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
770 try test__floatuntitf(0x0007FB72E4000000, 0x1.FEDCB9p+50);
771
772 try test__floatuntitf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
773 try test__floatuntitf(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57);
774 try test__floatuntitf(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57);
775 try test__floatuntitf(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57);
776 try test__floatuntitf(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57);
777 try test__floatuntitf(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57);
778 try test__floatuntitf(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57);
779 try test__floatuntitf(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57);
780 try test__floatuntitf(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57);
781 try test__floatuntitf(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57);
782 try test__floatuntitf(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57);
783 try test__floatuntitf(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57);
784 try test__floatuntitf(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57);
785 try test__floatuntitf(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57);
786 try test__floatuntitf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
787
788 try test__floatuntitf(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);
789 try test__floatuntitf(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121);
790 try test__floatuntitf(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121);
791 try test__floatuntitf(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121);
792 try test__floatuntitf(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121);
793 try test__floatuntitf(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121);
794 try test__floatuntitf(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121);
795 try test__floatuntitf(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121);
796 try test__floatuntitf(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121);
797 try test__floatuntitf(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121);
798 try test__floatuntitf(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121);
799 try test__floatuntitf(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121);
800 try test__floatuntitf(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121);
801 try test__floatuntitf(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121);
802 try test__floatuntitf(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);
803
804 try test__floatuntitf(make_uti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63);
805
806 try test__floatuntitf(make_uti(0xFFFFFFFFFFFFFFFF, 0x0000000000000000), 0x1.FFFFFFFFFFFFFFFEp+127);
807 try test__floatuntitf(make_uti(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF), 0x1.0000000000000000p+128);
808
809 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124);
810 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124);
811 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124);
812 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124);
813 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124);
814 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124);
815 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124);
816 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124);
817 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124);
682test f128_floatFromInt_i128 {
683 try test_f128_floatFromInt_i128(0, 0.0);
684
685 try test_f128_floatFromInt_i128(1, 1.0);
686 try test_f128_floatFromInt_i128(2, 2.0);
687 try test_f128_floatFromInt_i128(20, 20.0);
688 try test_f128_floatFromInt_i128(-1, -1.0);
689 try test_f128_floatFromInt_i128(-2, -2.0);
690 try test_f128_floatFromInt_i128(-20, -20.0);
691
692 try test_f128_floatFromInt_i128(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
693 try test_f128_floatFromInt_i128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
694 try test_f128_floatFromInt_i128(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
695 try test_f128_floatFromInt_i128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
696
697 try test_f128_floatFromInt_i128(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126);
698 try test_f128_floatFromInt_i128(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126);
699 try test_f128_floatFromInt_i128(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126);
700 try test_f128_floatFromInt_i128(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126);
701
702 try test_f128_floatFromInt_i128(make_ti(0x8000000000000000, 0), -0x1.000000p+127);
703 try test_f128_floatFromInt_i128(make_ti(0x8000000000000001, 0), -0x1.FFFFFFFFFFFFFFFCp+126);
704
705 try test_f128_floatFromInt_i128(0x0007FB72E8000000, 0x1.FEDCBAp+50);
706
707 try test_f128_floatFromInt_i128(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
708 try test_f128_floatFromInt_i128(0x0007FB72EB000000, 0x1.FEDCBACp+50);
709 try test_f128_floatFromInt_i128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
710 try test_f128_floatFromInt_i128(0x0007FB72EC000000, 0x1.FEDCBBp+50);
711 try test_f128_floatFromInt_i128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
712
713 try test_f128_floatFromInt_i128(0x0007FB72E6000000, 0x1.FEDCB98p+50);
714 try test_f128_floatFromInt_i128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
715 try test_f128_floatFromInt_i128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
716 try test_f128_floatFromInt_i128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
717 try test_f128_floatFromInt_i128(0x0007FB72E4000000, 0x1.FEDCB9p+50);
718
719 try test_f128_floatFromInt_i128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
720 try test_f128_floatFromInt_i128(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57);
721 try test_f128_floatFromInt_i128(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57);
722 try test_f128_floatFromInt_i128(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57);
723 try test_f128_floatFromInt_i128(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57);
724 try test_f128_floatFromInt_i128(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57);
725 try test_f128_floatFromInt_i128(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57);
726 try test_f128_floatFromInt_i128(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57);
727 try test_f128_floatFromInt_i128(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57);
728 try test_f128_floatFromInt_i128(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57);
729 try test_f128_floatFromInt_i128(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57);
730 try test_f128_floatFromInt_i128(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57);
731 try test_f128_floatFromInt_i128(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57);
732 try test_f128_floatFromInt_i128(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57);
733 try test_f128_floatFromInt_i128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
734
735 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);
736 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121);
737 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121);
738 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121);
739 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121);
740 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121);
741 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121);
742 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121);
743 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121);
744 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121);
745 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121);
746 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121);
747 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121);
748 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121);
749 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);
750
751 try test_f128_floatFromInt_i128(make_ti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63);
752
753 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124);
754 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124);
755 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124);
756 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124);
757 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124);
758 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124);
759 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124);
760 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124);
761 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124);
762}
763
764test f128_floatFromInt_u128 {
765 try test_f128_floatFromInt_u128(0, 0.0);
766
767 try test_f128_floatFromInt_u128(1, 1.0);
768 try test_f128_floatFromInt_u128(2, 2.0);
769 try test_f128_floatFromInt_u128(20, 20.0);
770
771 try test_f128_floatFromInt_u128(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
772 try test_f128_floatFromInt_u128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
773 try test_f128_floatFromInt_u128(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
774 try test_f128_floatFromInt_u128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
775 try test_f128_floatFromInt_u128(0x7FFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFEp+59);
776 try test_f128_floatFromInt_u128(0xFFFFFFFFFFFFFFFE, 0xF.FFFFFFFFFFFFFFEp+60);
777 try test_f128_floatFromInt_u128(0xFFFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFFp+60);
778
779 try test_f128_floatFromInt_u128(0x8000008000000000, 0x8.000008p+60);
780 try test_f128_floatFromInt_u128(0x8000000000000800, 0x8.0000000000008p+60);
781 try test_f128_floatFromInt_u128(0x8000010000000000, 0x8.00001p+60);
782 try test_f128_floatFromInt_u128(0x8000000000001000, 0x8.000000000001p+60);
783
784 try test_f128_floatFromInt_u128(0x8000000000000000, 0x8p+60);
785 try test_f128_floatFromInt_u128(0x8000000000000001, 0x8.000000000000001p+60);
786
787 try test_f128_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50);
788
789 try test_f128_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
790 try test_f128_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBACp+50);
791 try test_f128_floatFromInt_u128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
792 try test_f128_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBBp+50);
793 try test_f128_floatFromInt_u128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
794
795 try test_f128_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCB98p+50);
796 try test_f128_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
797 try test_f128_floatFromInt_u128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
798 try test_f128_floatFromInt_u128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
799 try test_f128_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB9p+50);
800
801 try test_f128_floatFromInt_u128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
802 try test_f128_floatFromInt_u128(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57);
803 try test_f128_floatFromInt_u128(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57);
804 try test_f128_floatFromInt_u128(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57);
805 try test_f128_floatFromInt_u128(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57);
806 try test_f128_floatFromInt_u128(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57);
807 try test_f128_floatFromInt_u128(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57);
808 try test_f128_floatFromInt_u128(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57);
809 try test_f128_floatFromInt_u128(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57);
810 try test_f128_floatFromInt_u128(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57);
811 try test_f128_floatFromInt_u128(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57);
812 try test_f128_floatFromInt_u128(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57);
813 try test_f128_floatFromInt_u128(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57);
814 try test_f128_floatFromInt_u128(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57);
815 try test_f128_floatFromInt_u128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
816
817 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);
818 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121);
819 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121);
820 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121);
821 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121);
822 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121);
823 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121);
824 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121);
825 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121);
826 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121);
827 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121);
828 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121);
829 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121);
830 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121);
831 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);
832
833 try test_f128_floatFromInt_u128(make_uti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63);
834
835 try test_f128_floatFromInt_u128(make_uti(0xFFFFFFFFFFFFFFFF, 0x0000000000000000), 0x1.FFFFFFFFFFFFFFFEp+127);
836 try test_f128_floatFromInt_u128(make_uti(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF), 0x1.0000000000000000p+128);
837
838 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124);
839 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124);
840 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124);
841 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124);
842 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124);
843 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124);
844 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124);
845 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124);
846 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124);
818847}
819848
820849fn make_ti(high: u64, low: u64) i128 {
......@@ -838,45 +867,40 @@ fn make_tf(high: u64, low: u64) f128 {
838867 return @bitCast(result);
839868}
840869
841test "conversion to f16" {
842 try testing.expect(__floatunsihf(@as(u32, 0)) == 0.0);
843 try testing.expect(__floatunsihf(@as(u32, 1)) == 1.0);
844 try testing.expect(__floatunsihf(@as(u32, 65504)) == 65504);
845 try testing.expect(__floatunsihf(@as(u32, 65504 + (1 << 4))) == math.inf(f16));
846}
847
848test "conversion to f32" {
849 try testing.expect(__floatunsisf(@as(u32, 0)) == 0.0);
850 try testing.expect(__floatunsisf(@as(u32, math.maxInt(u32))) != 1.0);
851 try testing.expect(__floatsisf(@as(i32, math.minInt(i32))) != 1.0);
852 try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24))) == math.maxInt(u24));
853 try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 1) == math.maxInt(u24) + 1); // 0x100_0000 - Exact
854 try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 2) == math.maxInt(u24) + 1); // 0x100_0001 - Tie: Rounds down to even
855 try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 3) == math.maxInt(u24) + 3); // 0x100_0002 - Exact
856 try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 4) == math.maxInt(u24) + 5); // 0x100_0003 - Tie: Rounds up to even
857 try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 5) == math.maxInt(u24) + 5); // 0x100_0004 - Exact
858}
859
860test "conversion to f80" {
861 const floatFromInt = @import("./float_from_int.zig").floatFromInt;
862
863 try testing.expect(floatFromInt(f80, @as(i80, -12)) == -12);
864 try testing.expect(@as(u80, @intFromFloat(floatFromInt(f80, @as(u64, math.maxInt(u64)) + 0))) == math.maxInt(u64) + 0);
865 try testing.expect(@as(u80, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 1))) == math.maxInt(u64) + 1);
866
867 try testing.expect(floatFromInt(f80, @as(u32, 0)) == 0.0);
868 try testing.expect(floatFromInt(f80, @as(u32, 1)) == 1.0);
869 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u32, math.maxInt(u24)) + 0))) == math.maxInt(u24));
870 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 0))) == math.maxInt(u64));
871 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 1))) == math.maxInt(u64) + 1); // Exact
872 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 2))) == math.maxInt(u64) + 1); // Rounds down
873 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 3))) == math.maxInt(u64) + 3); // Tie - Exact
874 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 4))) == math.maxInt(u64) + 5); // Rounds up
875
876 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 0))) == math.maxInt(u65) + 1); // Rounds up
877 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 1))) == math.maxInt(u65) + 1); // Exact
878 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 2))) == math.maxInt(u65) + 1); // Rounds down
879 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 3))) == math.maxInt(u65) + 1); // Tie - Rounds down
880 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 4))) == math.maxInt(u65) + 5); // Rounds up
881 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 5))) == math.maxInt(u65) + 5); // Exact
870test f16_floatFromInt_u32 {
871 try testing.expect(f16_floatFromInt_u32(0) == 0.0);
872 try testing.expect(f16_floatFromInt_u32(1) == 1.0);
873 try testing.expect(f16_floatFromInt_u32(65504) == 65504);
874 try testing.expect(f16_floatFromInt_u32(65504 + (1 << 4)) == math.inf(f16));
875}
876
877test f80_floatFromInt_u32 {
878 try testing.expect(f80_floatFromInt_u32(0) == 0.0);
879 try testing.expect(f80_floatFromInt_u32(1) == 1.0);
880 try testing.expect(f80_floatFromInt_u32(math.maxInt(u24) + 0) == math.maxInt(u24));
881}
882
883test f80_floatFromInt_u64 {
884 try testing.expect(f80_floatFromInt_u64(math.maxInt(u64) + 0) == math.maxInt(u64) + 0);
885}
886
887test f80_floatFromInt_i128 {
888 try testing.expect(f80_floatFromInt_i128(-12) == -12);
889}
890
891test f80_floatFromInt_u128 {
892 try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 1) == math.maxInt(u64) + 1);
893
894 try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 0) == math.maxInt(u64));
895 try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 1) == math.maxInt(u64) + 1); // Exact
896 try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 2) == math.maxInt(u64) + 1); // Rounds down
897 try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 3) == math.maxInt(u64) + 3); // Tie - Exact
898 try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 4) == math.maxInt(u64) + 5); // Rounds up
899
900 try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 0) == math.maxInt(u65) + 1); // Rounds up
901 try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 1) == math.maxInt(u65) + 1); // Exact
902 try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 2) == math.maxInt(u65) + 1); // Rounds down
903 try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 3) == math.maxInt(u65) + 1); // Tie - Rounds down
904 try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 4) == math.maxInt(u65) + 5); // Rounds up
905 try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 5) == math.maxInt(u65) + 5); // Exact
882906}
lib/compiler_rt/floatdidf.zig deleted-23
......@@ -1,23 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const floatFromInt = @import("./float_from_int.zig").floatFromInt;
5
6comptime {
7 if (compiler_rt.want_aeabi) {
8 symbol(&__aeabi_l2d, "__aeabi_l2d");
9 } else {
10 if (compiler_rt.want_windows_arm_abi) {
11 symbol(&__floatdidf, "__i64tod");
12 }
13 symbol(&__floatdidf, "__floatdidf");
14 }
15}
16
17pub fn __floatdidf(a: i64) callconv(.c) f64 {
18 return floatFromInt(f64, a);
19}
20
21fn __aeabi_l2d(a: i64) callconv(.{ .arm_aapcs = .{} }) f64 {
22 return floatFromInt(f64, a);
23}
lib/compiler_rt/floatdihf.zig deleted-10
......@@ -1,10 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3
4comptime {
5 symbol(&__floatdihf, "__floatdihf");
6}
7
8fn __floatdihf(a: i64) callconv(.c) f16 {
9 return floatFromInt(f16, a);
10}
lib/compiler_rt/floatdisf.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_l2f, "__aeabi_l2f");
8 } else {
9 if (compiler_rt.want_windows_arm_abi) {
10 symbol(&__floatdisf, "__i64tos");
11 }
12 symbol(&__floatdisf, "__floatdisf");
13 }
14}
15
16pub fn __floatdisf(a: i64) callconv(.c) f32 {
17 return floatFromInt(f32, a);
18}
19
20fn __aeabi_l2f(a: i64) callconv(.{ .arm_aapcs = .{} }) f32 {
21 return floatFromInt(f32, a);
22}
lib/compiler_rt/floatditf.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__floatditf, "__floatdikf");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_xtoq, "_Qp_xtoq");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__floatditf, "_Q_lltoq");
12 }
13 symbol(&__floatditf, "__floatditf");
14}
15
16pub fn __floatditf(a: i64) callconv(.c) f128 {
17 return floatFromInt(f128, a);
18}
19
20fn _Qp_xtoq(c: *f128, a: i64) callconv(.c) void {
21 c.* = floatFromInt(f128, a);
22}
lib/compiler_rt/floatdixf.zig deleted-10
......@@ -1,10 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3
4comptime {
5 symbol(&__floatdixf, "__floatdixf");
6}
7
8fn __floatdixf(a: i64) callconv(.c) f80 {
9 return floatFromInt(f80, a);
10}
lib/compiler_rt/floateidf.zig deleted-15
......@@ -1,15 +0,0 @@
1const builtin = @import("builtin");
2
3const std = @import("std");
4
5const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt;
6const symbol = @import("../compiler_rt.zig").symbol;
7
8comptime {
9 symbol(&__floateidf, "__floateidf");
10}
11
12pub fn __floateidf(a: [*]const u8, bits: usize) callconv(.c) f64 {
13 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
14 return floatFromBigInt(f64, .signed, @ptrCast(@alignCast(a[0..byte_size])));
15}
lib/compiler_rt/floateihf.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt;
6
7comptime {
8 symbol(&__floateihf, "__floateihf");
9}
10
11pub fn __floateihf(a: [*]const u8, bits: usize) callconv(.c) f16 {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return floatFromBigInt(f16, .signed, @ptrCast(@alignCast(a[0..byte_size])));
14}
lib/compiler_rt/floateisf.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt;
6
7comptime {
8 symbol(&__floateisf, "__floateisf");
9}
10
11pub fn __floateisf(a: [*]const u8, bits: usize) callconv(.c) f32 {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return floatFromBigInt(f32, .signed, @ptrCast(@alignCast(a[0..byte_size])));
14}
lib/compiler_rt/floateitf.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt;
6
7comptime {
8 symbol(&__floateitf, "__floateitf");
9}
10
11pub fn __floateitf(a: [*]const u8, bits: usize) callconv(.c) f128 {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return floatFromBigInt(f128, .signed, @ptrCast(@alignCast(a[0..byte_size])));
14}
lib/compiler_rt/floateixf.zig deleted-15
......@@ -1,15 +0,0 @@
1const builtin = @import("builtin");
2
3const std = @import("std");
4
5const symbol = @import("../compiler_rt.zig").symbol;
6const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt;
7
8comptime {
9 symbol(&__floateixf, "__floateixf");
10}
11
12pub fn __floateixf(a: [*]const u8, bits: usize) callconv(.c) f80 {
13 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
14 return floatFromBigInt(f80, .signed, @ptrCast(@alignCast(a[0..byte_size])));
15}
lib/compiler_rt/floatsidf.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_i2d, "__aeabi_i2d");
8 } else {
9 symbol(&__floatsidf, "__floatsidf");
10 }
11}
12
13pub fn __floatsidf(a: i32) callconv(.c) f64 {
14 return floatFromInt(f64, a);
15}
16
17fn __aeabi_i2d(a: i32) callconv(.{ .arm_aapcs = .{} }) f64 {
18 return floatFromInt(f64, a);
19}
lib/compiler_rt/floatsihf.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 symbol(&__floatsihf, "__floatsihf");
7}
8
9fn __floatsihf(a: i32) callconv(.c) f16 {
10 return floatFromInt(f16, a);
11}
lib/compiler_rt/floatsisf.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_i2f, "__aeabi_i2f");
8 } else {
9 symbol(&__floatsisf, "__floatsisf");
10 }
11}
12
13pub fn __floatsisf(a: i32) callconv(.c) f32 {
14 return floatFromInt(f32, a);
15}
16
17fn __aeabi_i2f(a: i32) callconv(.{ .arm_aapcs = .{} }) f32 {
18 return floatFromInt(f32, a);
19}
lib/compiler_rt/floatsitf.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__floatsitf, "__floatsikf");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_itoq, "_Qp_itoq");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__floatsitf, "_Q_itoq");
12 }
13 symbol(&__floatsitf, "__floatsitf");
14}
15
16pub fn __floatsitf(a: i32) callconv(.c) f128 {
17 return floatFromInt(f128, a);
18}
19
20fn _Qp_itoq(c: *f128, a: i32) callconv(.c) void {
21 c.* = floatFromInt(f128, a);
22}
lib/compiler_rt/floatsixf.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 symbol(&__floatsixf, "__floatsixf");
7}
8
9fn __floatsixf(a: i32) callconv(.c) f80 {
10 return floatFromInt(f80, a);
11}
lib/compiler_rt/floattidf.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 symbol(&__floattidf, "__floattidf");
7}
8
9pub fn __floattidf(a: i128) callconv(.c) f64 {
10 return floatFromInt(f64, a);
11}
lib/compiler_rt/floattihf.zig deleted-12
......@@ -1,12 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const floatFromInt = @import("./float_from_int.zig").floatFromInt;
5
6comptime {
7 symbol(&__floattihf, "__floattihf");
8}
9
10pub fn __floattihf(a: i128) callconv(.c) f16 {
11 return floatFromInt(f16, a);
12}
lib/compiler_rt/floattisf.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 symbol(&__floattisf, "__floattisf");
7}
8
9pub fn __floattisf(a: i128) callconv(.c) f32 {
10 return floatFromInt(f32, a);
11}
lib/compiler_rt/floattitf.zig deleted-13
......@@ -1,13 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 if (compiler_rt.want_ppc_abi)
7 symbol(&__floattitf, "__floattikf");
8 symbol(&__floattitf, "__floattitf");
9}
10
11pub fn __floattitf(a: i128) callconv(.c) f128 {
12 return floatFromInt(f128, a);
13}
lib/compiler_rt/floattixf.zig deleted-12
......@@ -1,12 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const floatFromInt = @import("./float_from_int.zig").floatFromInt;
5
6comptime {
7 symbol(&__floattixf, "__floattixf");
8}
9
10pub fn __floattixf(a: i128) callconv(.c) f80 {
11 return floatFromInt(f80, a);
12}
lib/compiler_rt/floatundidf.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_ul2d, "__aeabi_ul2d");
8 } else {
9 if (compiler_rt.want_windows_arm_abi) {
10 symbol(&__floatundidf, "__u64tod");
11 }
12 symbol(&__floatundidf, "__floatundidf");
13 }
14}
15
16pub fn __floatundidf(a: u64) callconv(.c) f64 {
17 return floatFromInt(f64, a);
18}
19
20fn __aeabi_ul2d(a: u64) callconv(.{ .arm_aapcs = .{} }) f64 {
21 return floatFromInt(f64, a);
22}
lib/compiler_rt/floatundihf.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 symbol(&__floatundihf, "__floatundihf");
7}
8
9fn __floatundihf(a: u64) callconv(.c) f16 {
10 return floatFromInt(f16, a);
11}
lib/compiler_rt/floatundisf.zig deleted-23
......@@ -1,23 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const floatFromInt = @import("./float_from_int.zig").floatFromInt;
5
6comptime {
7 if (compiler_rt.want_aeabi) {
8 symbol(&__aeabi_ul2f, "__aeabi_ul2f");
9 } else {
10 if (compiler_rt.want_windows_arm_abi) {
11 symbol(&__floatundisf, "__u64tos");
12 }
13 symbol(&__floatundisf, "__floatundisf");
14 }
15}
16
17pub fn __floatundisf(a: u64) callconv(.c) f32 {
18 return floatFromInt(f32, a);
19}
20
21fn __aeabi_ul2f(a: u64) callconv(.{ .arm_aapcs = .{} }) f32 {
22 return floatFromInt(f32, a);
23}
lib/compiler_rt/floatunditf.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__floatunditf, "__floatundikf");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_uxtoq, "_Qp_uxtoq");
10 } else if (compiler_rt.want_sparc32_abi) {
11 @export(&__floatunditf, "_Q_ulltoq");
12 }
13 symbol(&__floatunditf, "__floatunditf");
14}
15
16pub fn __floatunditf(a: u64) callconv(.c) f128 {
17 return floatFromInt(f128, a);
18}
19
20fn _Qp_uxtoq(c: *f128, a: u64) callconv(.c) void {
21 c.* = floatFromInt(f128, a);
22}
lib/compiler_rt/floatundixf.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 symbol(&__floatundixf, "__floatundixf");
7}
8
9fn __floatundixf(a: u64) callconv(.c) f80 {
10 return floatFromInt(f80, a);
11}
lib/compiler_rt/floatuneidf.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt;
6
7comptime {
8 symbol(&__floatuneidf, "__floatuneidf");
9}
10
11pub fn __floatuneidf(a: [*]const u8, bits: usize) callconv(.c) f64 {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return floatFromBigInt(f64, .unsigned, @ptrCast(@alignCast(a[0..byte_size])));
14}
lib/compiler_rt/floatuneihf.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt;
6
7comptime {
8 symbol(&__floatuneihf, "__floatuneihf");
9}
10
11pub fn __floatuneihf(a: [*]const u8, bits: usize) callconv(.c) f16 {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return floatFromBigInt(f16, .unsigned, @ptrCast(@alignCast(a[0..byte_size])));
14}
lib/compiler_rt/floatuneisf.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt;
6
7comptime {
8 symbol(&__floatuneisf, "__floatuneisf");
9}
10
11pub fn __floatuneisf(a: [*]const u8, bits: usize) callconv(.c) f32 {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return floatFromBigInt(f32, .unsigned, @ptrCast(@alignCast(a[0..byte_size])));
14}
lib/compiler_rt/floatuneitf.zig deleted-15
......@@ -1,15 +0,0 @@
1const builtin = @import("builtin");
2
3const std = @import("std");
4
5const symbol = @import("../compiler_rt.zig").symbol;
6const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt;
7
8comptime {
9 symbol(&__floatuneitf, "__floatuneitf");
10}
11
12pub fn __floatuneitf(a: [*]const u8, bits: usize) callconv(.c) f128 {
13 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
14 return floatFromBigInt(f128, .unsigned, @ptrCast(@alignCast(a[0..byte_size])));
15}
lib/compiler_rt/floatuneixf.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt;
6
7comptime {
8 symbol(&__floatuneixf, "__floatuneixf");
9}
10
11pub fn __floatuneixf(a: [*]const u8, bits: usize) callconv(.c) f80 {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return floatFromBigInt(f80, .unsigned, @ptrCast(@alignCast(a[0..byte_size])));
14}
lib/compiler_rt/floatunsidf.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_ui2d, "__aeabi_ui2d");
8 } else {
9 symbol(&__floatunsidf, "__floatunsidf");
10 }
11}
12
13pub fn __floatunsidf(a: u32) callconv(.c) f64 {
14 return floatFromInt(f64, a);
15}
16
17fn __aeabi_ui2d(a: u32) callconv(.{ .arm_aapcs = .{} }) f64 {
18 return floatFromInt(f64, a);
19}
lib/compiler_rt/floatunsihf.zig deleted-10
......@@ -1,10 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3
4comptime {
5 symbol(&__floatunsihf, "__floatunsihf");
6}
7
8pub fn __floatunsihf(a: u32) callconv(.c) f16 {
9 return floatFromInt(f16, a);
10}
lib/compiler_rt/floatunsisf.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_ui2f, "__aeabi_ui2f");
8 } else {
9 symbol(&__floatunsisf, "__floatunsisf");
10 }
11}
12
13pub fn __floatunsisf(a: u32) callconv(.c) f32 {
14 return floatFromInt(f32, a);
15}
16
17fn __aeabi_ui2f(a: u32) callconv(.{ .arm_aapcs = .{} }) f32 {
18 return floatFromInt(f32, a);
19}
lib/compiler_rt/floatunsitf.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__floatunsitf, "__floatunsikf");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_uitoq, "_Qp_uitoq");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__floatunsitf, "_Q_utoq");
12 }
13 symbol(&__floatunsitf, "__floatunsitf");
14}
15
16pub fn __floatunsitf(a: u32) callconv(.c) f128 {
17 return floatFromInt(f128, a);
18}
19
20fn _Qp_uitoq(c: *f128, a: u32) callconv(.c) void {
21 c.* = floatFromInt(f128, a);
22}
lib/compiler_rt/floatunsixf.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 symbol(&__floatunsixf, "__floatunsixf");
7}
8
9fn __floatunsixf(a: u32) callconv(.c) f80 {
10 return floatFromInt(f80, a);
11}
lib/compiler_rt/floatuntidf.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 symbol(&__floatuntidf, "__floatuntidf");
7}
8
9pub fn __floatuntidf(a: u128) callconv(.c) f64 {
10 return floatFromInt(f64, a);
11}
lib/compiler_rt/floatuntihf.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 symbol(&__floatuntihf, "__floatuntihf");
7}
8
9pub fn __floatuntihf(a: u128) callconv(.c) f16 {
10 return floatFromInt(f16, a);
11}
lib/compiler_rt/floatuntisf.zig deleted-12
......@@ -1,12 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const floatFromInt = @import("./float_from_int.zig").floatFromInt;
5
6comptime {
7 symbol(&__floatuntisf, "__floatuntisf");
8}
9
10pub fn __floatuntisf(a: u128) callconv(.c) f32 {
11 return floatFromInt(f32, a);
12}
lib/compiler_rt/floatuntitf.zig deleted-13
......@@ -1,13 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_ppc_abi)
7 symbol(&__floatuntitf, "__floatuntikf");
8 symbol(&__floatuntitf, "__floatuntitf");
9}
10
11pub fn __floatuntitf(a: u128) callconv(.c) f128 {
12 return floatFromInt(f128, a);
13}
lib/compiler_rt/floatuntixf.zig deleted-12
......@@ -1,12 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const floatFromInt = @import("./float_from_int.zig").floatFromInt;
5
6comptime {
7 symbol(&__floatuntixf, "__floatuntixf");
8}
9
10pub fn __floatuntixf(a: u128) callconv(.c) f80 {
11 return floatFromInt(f80, a);
12}
lib/compiler_rt/floor_ceil.zig+173-159
......@@ -15,7 +15,7 @@ const mem = std.mem;
1515const expect = std.testing.expect;
1616
1717const compiler_rt = @import("../compiler_rt.zig");
18const symbol = @import("../compiler_rt.zig").symbol;
18const symbol = compiler_rt.symbol;
1919
2020comptime {
2121 // floor
......@@ -23,10 +23,7 @@ comptime {
2323 symbol(&floorf, "floorf");
2424 symbol(&floor, "floor");
2525 symbol(&__floorx, "__floorx");
26 if (compiler_rt.want_ppc_abi) {
27 symbol(&floorq, "floorf128");
28 }
29 symbol(&floorq, "floorq");
26 symbol(&floorq, "floorf128");
3027 symbol(&floorl, "floorl");
3128
3229 // ceil
......@@ -34,59 +31,96 @@ comptime {
3431 symbol(&ceilf, "ceilf");
3532 symbol(&ceil, "ceil");
3633 symbol(&__ceilx, "__ceilx");
37 if (compiler_rt.want_ppc_abi) {
38 symbol(&ceilq, "ceilf128");
39 }
40 symbol(&ceilq, "ceilq");
34 symbol(&ceilq, "ceilf128");
4135 symbol(&ceill, "ceill");
4236}
4337
44pub fn __floorh(x: f16) callconv(.c) f16 {
38fn __floorh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
39 return compiler_rt.f16.toAbi(floor_f16(compiler_rt.f16.fromAbi(x)));
40}
41pub fn floor_f16(x: f16) f16 {
4542 return impl(f16, .floor, x);
4643}
4744
48pub fn floorf(x: f32) callconv(.c) f32 {
45fn floorf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
46 return compiler_rt.f32.toAbi(floor_f32(compiler_rt.f32.fromAbi(x)));
47}
48pub fn floor_f32(x: f32) f32 {
4949 return impl(f32, .floor, x);
5050}
5151
52pub fn floor(x: f64) callconv(.c) f64 {
52fn floor(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
53 return compiler_rt.f64.toAbi(floor_f64(compiler_rt.f64.fromAbi(x)));
54}
55pub fn floor_f64(x: f64) f64 {
5356 return impl(f64, .floor, x);
5457}
5558
56pub fn __floorx(x: f80) callconv(.c) f80 {
59fn __floorx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
60 return compiler_rt.f80.toAbi(floor_f80(compiler_rt.f80.fromAbi(x)));
61}
62pub fn floor_f80(x: f80) f80 {
5763 return impl(f80, .floor, x);
5864}
5965
60pub fn floorq(x: f128) callconv(.c) f128 {
66fn floorq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
67 return compiler_rt.f128.toAbi(floor_f128(compiler_rt.f128.fromAbi(x)));
68}
69pub fn floor_f128(x: f128) f128 {
6170 return impl(f128, .floor, x);
6271}
6372
6473pub fn floorl(x: c_longdouble) callconv(.c) c_longdouble {
65 return impl(std.meta.Float(@bitSizeOf(c_longdouble)), .floor, x);
74 switch (@typeInfo(c_longdouble).float.bits) {
75 64 => return floor_f64(x),
76 80 => return floor_f80(x),
77 128 => return floor_f128(x),
78 else => comptime unreachable,
79 }
6680}
6781
68pub fn __ceilh(x: f16) callconv(.c) f16 {
82fn __ceilh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
83 return compiler_rt.f16.toAbi(ceil_f16(compiler_rt.f16.fromAbi(x)));
84}
85pub fn ceil_f16(x: f16) f16 {
6986 return impl(f16, .ceil, x);
7087}
7188
72pub fn ceilf(x: f32) callconv(.c) f32 {
89fn ceilf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
90 return compiler_rt.f32.toAbi(ceil_f32(compiler_rt.f32.fromAbi(x)));
91}
92pub fn ceil_f32(x: f32) f32 {
7393 return impl(f32, .ceil, x);
7494}
7595
76pub fn ceil(x: f64) callconv(.c) f64 {
96fn ceil(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
97 return compiler_rt.f64.toAbi(ceil_f64(compiler_rt.f64.fromAbi(x)));
98}
99pub fn ceil_f64(x: f64) f64 {
77100 return impl(f64, .ceil, x);
78101}
79102
80pub fn __ceilx(x: f80) callconv(.c) f80 {
103fn __ceilx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
104 return compiler_rt.f80.toAbi(ceil_f80(compiler_rt.f80.fromAbi(x)));
105}
106pub fn ceil_f80(x: f80) f80 {
81107 return impl(f80, .ceil, x);
82108}
83109
84pub fn ceilq(x: f128) callconv(.c) f128 {
110fn ceilq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
111 return compiler_rt.f128.toAbi(ceil_f128(compiler_rt.f128.fromAbi(x)));
112}
113pub fn ceil_f128(x: f128) f128 {
85114 return impl(f128, .ceil, x);
86115}
87116
88117pub fn ceill(x: c_longdouble) callconv(.c) c_longdouble {
89 return impl(std.meta.Float(@bitSizeOf(c_longdouble)), .ceil, x);
118 switch (@typeInfo(c_longdouble).float.bits) {
119 64 => return ceil_f64(x),
120 80 => return ceil_f80(x),
121 128 => return ceil_f128(x),
122 else => comptime unreachable,
123 }
90124}
91125
92126inline fn impl(comptime T: type, comptime op: enum { floor, ceil }, x: T) T {
......@@ -144,142 +178,122 @@ inline fn impl(comptime T: type, comptime op: enum { floor, ceil }, x: T) T {
144178 }
145179}
146180
147test "floor16" {
148 try expect(__floorh(1.3) == 1.0);
149 try expect(__floorh(-1.3) == -2.0);
150 try expect(__floorh(0.2) == 0.0);
151}
152
153test "floor32" {
154 try expect(floorf(1.3) == 1.0);
155 try expect(floorf(-1.3) == -2.0);
156 try expect(floorf(0.2) == 0.0);
157}
158
159test "floor64" {
160 try expect(floor(1.3) == 1.0);
161 try expect(floor(-1.3) == -2.0);
162 try expect(floor(0.2) == 0.0);
163}
164
165test "floor80" {
166 try expect(__floorx(1.3) == 1.0);
167 try expect(__floorx(-1.3) == -2.0);
168 try expect(__floorx(0.2) == 0.0);
169}
170
171test "floor128" {
172 try expect(floorq(1.3) == 1.0);
173 try expect(floorq(-1.3) == -2.0);
174 try expect(floorq(0.2) == 0.0);
175}
176
177test "floor16.special" {
178 try expect(__floorh(0.0) == 0.0);
179 try expect(__floorh(-0.0) == -0.0);
180 try expect(math.isPositiveInf(__floorh(math.inf(f16))));
181 try expect(math.isNegativeInf(__floorh(-math.inf(f16))));
182 try expect(math.isNan(__floorh(math.nan(f16))));
183}
184
185test "floor32.special" {
186 try expect(floorf(0.0) == 0.0);
187 try expect(floorf(-0.0) == -0.0);
188 try expect(math.isPositiveInf(floorf(math.inf(f32))));
189 try expect(math.isNegativeInf(floorf(-math.inf(f32))));
190 try expect(math.isNan(floorf(math.nan(f32))));
191}
192
193test "floor64.special" {
194 try expect(floor(0.0) == 0.0);
195 try expect(floor(-0.0) == -0.0);
196 try expect(math.isPositiveInf(floor(math.inf(f64))));
197 try expect(math.isNegativeInf(floor(-math.inf(f64))));
198 try expect(math.isNan(floor(math.nan(f64))));
199}
200
201test "floor80.special" {
202 try expect(__floorx(0.0) == 0.0);
203 try expect(__floorx(-0.0) == -0.0);
204 try expect(math.isPositiveInf(__floorx(math.inf(f80))));
205 try expect(math.isNegativeInf(__floorx(-math.inf(f80))));
206 try expect(math.isNan(__floorx(math.nan(f80))));
207}
208
209test "floor128.special" {
210 try expect(floorq(0.0) == 0.0);
211 try expect(floorq(-0.0) == -0.0);
212 try expect(math.isPositiveInf(floorq(math.inf(f128))));
213 try expect(math.isNegativeInf(floorq(-math.inf(f128))));
214 try expect(math.isNan(floorq(math.nan(f128))));
215}
216
217test "ceil16" {
218 try expect(__ceilh(1.3) == 2.0);
219 try expect(__ceilh(-1.3) == -1.0);
220 try expect(__ceilh(0.2) == 1.0);
221}
222
223test "ceil32" {
224 try expect(ceilf(1.3) == 2.0);
225 try expect(ceilf(-1.3) == -1.0);
226 try expect(ceilf(0.2) == 1.0);
227}
228
229test "ceil64" {
230 try expect(ceil(1.3) == 2.0);
231 try expect(ceil(-1.3) == -1.0);
232 try expect(ceil(0.2) == 1.0);
233}
234
235test "ceil80" {
236 try expect(__ceilx(1.3) == 2.0);
237 try expect(__ceilx(-1.3) == -1.0);
238 try expect(__ceilx(0.2) == 1.0);
239}
240
241test "ceil128" {
242 try expect(ceilq(1.3) == 2.0);
243 try expect(ceilq(-1.3) == -1.0);
244 try expect(ceilq(0.2) == 1.0);
245}
246
247test "ceil16.special" {
248 try expect(__ceilh(0.0) == 0.0);
249 try expect(__ceilh(-0.0) == -0.0);
250 try expect(math.isPositiveInf(__ceilh(math.inf(f16))));
251 try expect(math.isNegativeInf(__ceilh(-math.inf(f16))));
252 try expect(math.isNan(__ceilh(math.nan(f16))));
253}
254
255test "ceil32.special" {
256 try expect(ceilf(0.0) == 0.0);
257 try expect(ceilf(-0.0) == -0.0);
258 try expect(math.isPositiveInf(ceilf(math.inf(f32))));
259 try expect(math.isNegativeInf(ceilf(-math.inf(f32))));
260 try expect(math.isNan(ceilf(math.nan(f32))));
261}
262
263test "ceil64.special" {
264 try expect(ceil(0.0) == 0.0);
265 try expect(ceil(-0.0) == -0.0);
266 try expect(math.isPositiveInf(ceil(math.inf(f64))));
267 try expect(math.isNegativeInf(ceil(-math.inf(f64))));
268 try expect(math.isNan(ceil(math.nan(f64))));
269}
270
271test "ceil80.special" {
272 try expect(__ceilx(0.0) == 0.0);
273 try expect(__ceilx(-0.0) == -0.0);
274 try expect(math.isPositiveInf(__ceilx(math.inf(f80))));
275 try expect(math.isNegativeInf(__ceilx(-math.inf(f80))));
276 try expect(math.isNan(__ceilx(math.nan(f80))));
277}
278
279test "ceil128.special" {
280 try expect(ceilq(0.0) == 0.0);
281 try expect(ceilq(-0.0) == -0.0);
282 try expect(math.isPositiveInf(ceilq(math.inf(f128))));
283 try expect(math.isNegativeInf(ceilq(-math.inf(f128))));
284 try expect(math.isNan(ceilq(math.nan(f128))));
181test floor_f16 {
182 try expect(floor_f16(1.3) == 1.0);
183 try expect(floor_f16(-1.3) == -2.0);
184 try expect(floor_f16(-0.2) == -1.0);
185 try expect(math.isPositiveZero(floor_f16(0.2)));
186 try expect(math.isPositiveZero(floor_f16(0.0)));
187 try expect(math.isNegativeZero(floor_f16(-0.0)));
188 try expect(math.isPositiveInf(floor_f16(math.inf(f16))));
189 try expect(math.isNegativeInf(floor_f16(-math.inf(f16))));
190 try expect(math.isNan(floor_f16(math.nan(f16))));
191}
192
193test floor_f32 {
194 try expect(floor_f32(1.3) == 1.0);
195 try expect(floor_f32(-1.3) == -2.0);
196 try expect(floor_f32(-0.2) == -1.0);
197 try expect(math.isPositiveZero(floor_f32(0.2)));
198 try expect(math.isPositiveZero(floor_f32(0.0)));
199 try expect(math.isNegativeZero(floor_f32(-0.0)));
200 try expect(math.isPositiveInf(floor_f32(math.inf(f32))));
201 try expect(math.isNegativeInf(floor_f32(-math.inf(f32))));
202 try expect(math.isNan(floor_f32(math.nan(f32))));
203}
204
205test floor_f64 {
206 try expect(floor_f64(1.3) == 1.0);
207 try expect(floor_f64(-1.3) == -2.0);
208 try expect(floor_f64(-0.2) == -1.0);
209 try expect(math.isPositiveZero(floor_f64(0.2)));
210 try expect(math.isPositiveZero(floor_f64(0.0)));
211 try expect(math.isNegativeZero(floor_f64(-0.0)));
212 try expect(math.isPositiveInf(floor_f64(math.inf(f64))));
213 try expect(math.isNegativeInf(floor_f64(-math.inf(f64))));
214 try expect(math.isNan(floor_f64(math.nan(f64))));
215}
216
217test floor_f80 {
218 try expect(floor_f80(1.3) == 1.0);
219 try expect(floor_f80(-1.3) == -2.0);
220 try expect(floor_f80(-0.2) == -1.0);
221 try expect(math.isPositiveZero(floor_f80(0.2)));
222 try expect(math.isPositiveZero(floor_f80(0.0)));
223 try expect(math.isNegativeZero(floor_f80(-0.0)));
224 try expect(math.isPositiveInf(floor_f80(math.inf(f80))));
225 try expect(math.isNegativeInf(floor_f80(-math.inf(f80))));
226 try expect(math.isNan(floor_f80(math.nan(f80))));
227}
228
229test floor_f128 {
230 try expect(floor_f128(1.3) == 1.0);
231 try expect(floor_f128(-1.3) == -2.0);
232 try expect(floor_f128(-0.2) == -1.0);
233 try expect(math.isPositiveZero(floor_f128(0.2)));
234 try expect(math.isPositiveZero(floor_f128(0.0)));
235 try expect(math.isNegativeZero(floor_f128(-0.0)));
236 try expect(math.isPositiveInf(floor_f128(math.inf(f128))));
237 try expect(math.isNegativeInf(floor_f128(-math.inf(f128))));
238 try expect(math.isNan(floor_f128(math.nan(f128))));
239}
240
241test ceil_f16 {
242 try expect(ceil_f16(1.3) == 2.0);
243 try expect(ceil_f16(-1.3) == -1.0);
244 try expect(ceil_f16(0.2) == 1.0);
245 try expect(math.isNegativeZero(ceil_f16(-0.2)));
246 try expect(math.isPositiveZero(ceil_f16(0.0)));
247 try expect(math.isNegativeZero(ceil_f16(-0.0)));
248 try expect(math.isPositiveInf(ceil_f16(math.inf(f16))));
249 try expect(math.isNegativeInf(ceil_f16(-math.inf(f16))));
250 try expect(math.isNan(ceil_f16(math.nan(f16))));
251}
252
253test ceil_f32 {
254 try expect(ceil_f32(1.3) == 2.0);
255 try expect(ceil_f32(-1.3) == -1.0);
256 try expect(ceil_f32(0.2) == 1.0);
257 try expect(math.isNegativeZero(ceil_f32(-0.2)));
258 try expect(math.isPositiveZero(ceil_f32(0.0)));
259 try expect(math.isNegativeZero(ceil_f32(-0.0)));
260 try expect(math.isPositiveInf(ceil_f32(math.inf(f32))));
261 try expect(math.isNegativeInf(ceil_f32(-math.inf(f32))));
262 try expect(math.isNan(ceil_f32(math.nan(f32))));
263}
264
265test ceil_f64 {
266 try expect(ceil_f64(1.3) == 2.0);
267 try expect(ceil_f64(-1.3) == -1.0);
268 try expect(ceil_f64(0.2) == 1.0);
269 try expect(math.isNegativeZero(ceil_f64(-0.2)));
270 try expect(math.isPositiveZero(ceil_f64(0.0)));
271 try expect(math.isNegativeZero(ceil_f64(-0.0)));
272 try expect(math.isPositiveInf(ceil_f64(math.inf(f64))));
273 try expect(math.isNegativeInf(ceil_f64(-math.inf(f64))));
274 try expect(math.isNan(ceil_f64(math.nan(f64))));
275}
276
277test ceil_f80 {
278 try expect(ceil_f80(1.3) == 2.0);
279 try expect(ceil_f80(-1.3) == -1.0);
280 try expect(ceil_f80(0.2) == 1.0);
281 try expect(math.isNegativeZero(ceil_f80(-0.2)));
282 try expect(math.isPositiveZero(ceil_f80(0.0)));
283 try expect(math.isNegativeZero(ceil_f80(-0.0)));
284 try expect(math.isPositiveInf(ceil_f80(math.inf(f80))));
285 try expect(math.isNegativeInf(ceil_f80(-math.inf(f80))));
286 try expect(math.isNan(ceil_f80(math.nan(f80))));
287}
288
289test ceil_f128 {
290 try expect(ceil_f128(1.3) == 2.0);
291 try expect(ceil_f128(-1.3) == -1.0);
292 try expect(ceil_f128(0.2) == 1.0);
293 try expect(math.isNegativeZero(ceil_f128(-0.2)));
294 try expect(math.isPositiveZero(ceil_f128(0.0)));
295 try expect(math.isNegativeZero(ceil_f128(-0.0)));
296 try expect(math.isPositiveInf(ceil_f128(math.inf(f128))));
297 try expect(math.isNegativeInf(ceil_f128(-math.inf(f128))));
298 try expect(math.isNan(ceil_f128(math.nan(f128))));
285299}
lib/compiler_rt/fma.zig+48-36
......@@ -16,19 +16,22 @@ comptime {
1616 symbol(&fmaf, "fmaf");
1717 symbol(&fma, "fma");
1818 symbol(&__fmax, "__fmax");
19 if (compiler_rt.want_ppc_abi) {
20 symbol(&fmaq, "fmaf128");
21 }
22 symbol(&fmaq, "fmaq");
19 symbol(&fmaq, "fmaf128");
2320 symbol(&fmal, "fmal");
2421}
2522
26pub fn __fmah(x: f16, y: f16, z: f16) callconv(.c) f16 {
23fn __fmah(x: compiler_rt.f16.Abi, y: compiler_rt.f16.Abi, z: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
24 return compiler_rt.f16.toAbi(fma_f16(compiler_rt.f16.fromAbi(x), compiler_rt.f16.fromAbi(y), compiler_rt.f16.fromAbi(z)));
25}
26pub fn fma_f16(x: f16, y: f16, z: f16) f16 {
2727 // TODO: more efficient implementation
28 return @floatCast(fmaf(x, y, z));
28 return @floatCast(fma_f32(x, y, z));
2929}
3030
31pub fn fmaf(x: f32, y: f32, z: f32) callconv(.c) f32 {
31fn fmaf(x: compiler_rt.f32.Abi, y: compiler_rt.f32.Abi, z: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
32 return compiler_rt.f32.toAbi(fma_f32(compiler_rt.f32.fromAbi(x), compiler_rt.f32.fromAbi(y), compiler_rt.f32.fromAbi(z)));
33}
34pub fn fma_f32(x: f32, y: f32, z: f32) f32 {
3235 const xy = @as(f64, x) * y;
3336 const xy_z = xy + z;
3437 const u = @as(u64, @bitCast(xy_z));
......@@ -42,8 +45,11 @@ pub fn fmaf(x: f32, y: f32, z: f32) callconv(.c) f32 {
4245 }
4346}
4447
48fn fma(x: compiler_rt.f64.Abi, y: compiler_rt.f64.Abi, z: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
49 return compiler_rt.f64.toAbi(fma_f64(compiler_rt.f64.fromAbi(x), compiler_rt.f64.fromAbi(y), compiler_rt.f64.fromAbi(z)));
50}
4551/// NOTE: Upstream fma.c has been rewritten completely to raise fp exceptions more accurately.
46pub fn fma(x: f64, y: f64, z: f64) callconv(.c) f64 {
52pub fn fma_f64(x: f64, y: f64, z: f64) f64 {
4753 if (!math.isFinite(x) or !math.isFinite(y)) {
4854 return x * y + z;
4955 }
......@@ -90,11 +96,17 @@ pub fn fma(x: f64, y: f64, z: f64) callconv(.c) f64 {
9096 }
9197}
9298
93pub fn __fmax(a: f80, b: f80, c: f80) callconv(.c) f80 {
99fn __fmax(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi, c: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
100 return compiler_rt.f80.toAbi(fma_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b), compiler_rt.f80.fromAbi(c)));
101}
102pub fn fma_f80(a: f80, b: f80, c: f80) f80 {
94103 // TODO: more efficient implementation
95 return @floatCast(fmaq(a, b, c));
104 return @floatCast(fma_f128(a, b, c));
96105}
97106
107fn fmaq(x: compiler_rt.f128.Abi, y: compiler_rt.f128.Abi, z: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
108 return compiler_rt.f128.toAbi(fma_f128(compiler_rt.f128.fromAbi(x), compiler_rt.f128.fromAbi(y), compiler_rt.f128.fromAbi(z)));
109}
98110/// Fused multiply-add: Compute x * y + z with a single rounding error.
99111///
100112/// We use scaling to avoid overflow/underflow, along with the
......@@ -102,7 +114,7 @@ pub fn __fmax(a: f80, b: f80, c: f80) callconv(.c) f80 {
102114///
103115/// Dekker, T. A Floating-Point Technique for Extending the
104116/// Available Precision. Numer. Math. 18, 224-242 (1971).
105pub fn fmaq(x: f128, y: f128, z: f128) callconv(.c) f128 {
117pub fn fma_f128(x: f128, y: f128, z: f128) f128 {
106118 if (!math.isFinite(x) or !math.isFinite(y)) {
107119 return x * y + z;
108120 }
......@@ -151,10 +163,10 @@ pub fn fmaq(x: f128, y: f128, z: f128) callconv(.c) f128 {
151163
152164pub fn fmal(x: c_longdouble, y: c_longdouble, z: c_longdouble) callconv(.c) c_longdouble {
153165 switch (@typeInfo(c_longdouble).float.bits) {
154 64 => return fma(x, y, z),
155 80 => return __fmax(x, y, z),
156 128 => return fmaq(x, y, z),
157 else => @compileError("unreachable"),
166 64 => return fma_f64(x, y, z),
167 80 => return fma_f80(x, y, z),
168 128 => return fma_f128(x, y, z),
169 else => comptime unreachable,
158170 }
159171}
160172
......@@ -316,35 +328,35 @@ fn dd_mul128(a: f128, b: f128) dd128 {
316328test "32" {
317329 const epsilon = 0.000001;
318330
319 try expect(math.approxEqAbs(f32, fmaf(0.0, 5.0, 9.124), 9.124, epsilon));
320 try expect(math.approxEqAbs(f32, fmaf(0.2, 5.0, 9.124), 10.124, epsilon));
321 try expect(math.approxEqAbs(f32, fmaf(0.8923, 5.0, 9.124), 13.5855, epsilon));
322 try expect(math.approxEqAbs(f32, fmaf(1.5, 5.0, 9.124), 16.624, epsilon));
323 try expect(math.approxEqAbs(f32, fmaf(37.45, 5.0, 9.124), 196.374004, epsilon));
324 try expect(math.approxEqAbs(f32, fmaf(89.123, 5.0, 9.124), 454.739005, epsilon));
325 try expect(math.approxEqAbs(f32, fmaf(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
331 try expect(math.approxEqAbs(f32, fma_f32(0.0, 5.0, 9.124), 9.124, epsilon));
332 try expect(math.approxEqAbs(f32, fma_f32(0.2, 5.0, 9.124), 10.124, epsilon));
333 try expect(math.approxEqAbs(f32, fma_f32(0.8923, 5.0, 9.124), 13.5855, epsilon));
334 try expect(math.approxEqAbs(f32, fma_f32(1.5, 5.0, 9.124), 16.624, epsilon));
335 try expect(math.approxEqAbs(f32, fma_f32(37.45, 5.0, 9.124), 196.374004, epsilon));
336 try expect(math.approxEqAbs(f32, fma_f32(89.123, 5.0, 9.124), 454.739005, epsilon));
337 try expect(math.approxEqAbs(f32, fma_f32(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
326338}
327339
328340test "64" {
329341 const epsilon = 0.000001;
330342
331 try expect(math.approxEqAbs(f64, fma(0.0, 5.0, 9.124), 9.124, epsilon));
332 try expect(math.approxEqAbs(f64, fma(0.2, 5.0, 9.124), 10.124, epsilon));
333 try expect(math.approxEqAbs(f64, fma(0.8923, 5.0, 9.124), 13.5855, epsilon));
334 try expect(math.approxEqAbs(f64, fma(1.5, 5.0, 9.124), 16.624, epsilon));
335 try expect(math.approxEqAbs(f64, fma(37.45, 5.0, 9.124), 196.374, epsilon));
336 try expect(math.approxEqAbs(f64, fma(89.123, 5.0, 9.124), 454.739, epsilon));
337 try expect(math.approxEqAbs(f64, fma(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
343 try expect(math.approxEqAbs(f64, fma_f64(0.0, 5.0, 9.124), 9.124, epsilon));
344 try expect(math.approxEqAbs(f64, fma_f64(0.2, 5.0, 9.124), 10.124, epsilon));
345 try expect(math.approxEqAbs(f64, fma_f64(0.8923, 5.0, 9.124), 13.5855, epsilon));
346 try expect(math.approxEqAbs(f64, fma_f64(1.5, 5.0, 9.124), 16.624, epsilon));
347 try expect(math.approxEqAbs(f64, fma_f64(37.45, 5.0, 9.124), 196.374, epsilon));
348 try expect(math.approxEqAbs(f64, fma_f64(89.123, 5.0, 9.124), 454.739, epsilon));
349 try expect(math.approxEqAbs(f64, fma_f64(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
338350}
339351
340352test "128" {
341353 const epsilon = 0.000001;
342354
343 try expect(math.approxEqAbs(f128, fmaq(0.0, 5.0, 9.124), 9.124, epsilon));
344 try expect(math.approxEqAbs(f128, fmaq(0.2, 5.0, 9.124), 10.124, epsilon));
345 try expect(math.approxEqAbs(f128, fmaq(0.8923, 5.0, 9.124), 13.5855, epsilon));
346 try expect(math.approxEqAbs(f128, fmaq(1.5, 5.0, 9.124), 16.624, epsilon));
347 try expect(math.approxEqAbs(f128, fmaq(37.45, 5.0, 9.124), 196.374, epsilon));
348 try expect(math.approxEqAbs(f128, fmaq(89.123, 5.0, 9.124), 454.739, epsilon));
349 try expect(math.approxEqAbs(f128, fmaq(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
355 try expect(math.approxEqAbs(f128, fma_f128(0.0, 5.0, 9.124), 9.124, epsilon));
356 try expect(math.approxEqAbs(f128, fma_f128(0.2, 5.0, 9.124), 10.124, epsilon));
357 try expect(math.approxEqAbs(f128, fma_f128(0.8923, 5.0, 9.124), 13.5855, epsilon));
358 try expect(math.approxEqAbs(f128, fma_f128(1.5, 5.0, 9.124), 16.624, epsilon));
359 try expect(math.approxEqAbs(f128, fma_f128(37.45, 5.0, 9.124), 196.374, epsilon));
360 try expect(math.approxEqAbs(f128, fma_f128(89.123, 5.0, 9.124), 454.739, epsilon));
361 try expect(math.approxEqAbs(f128, fma_f128(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
350362}
lib/compiler_rt/fmax.zig+25-13
......@@ -10,39 +10,51 @@ comptime {
1010 symbol(&fmaxf, "fmaxf");
1111 symbol(&fmax, "fmax");
1212 symbol(&__fmaxx, "__fmaxx");
13 if (compiler_rt.want_ppc_abi) {
14 symbol(&fmaxq, "fmaxf128");
15 }
16 symbol(&fmaxq, "fmaxq");
13 symbol(&fmaxq, "fmaxf128");
1714 symbol(&fmaxl, "fmaxl");
1815}
1916
20pub fn __fmaxh(x: f16, y: f16) callconv(.c) f16 {
17fn __fmaxh(x: compiler_rt.f16.Abi, y: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
18 return compiler_rt.f16.toAbi(fmax_f16(compiler_rt.f16.fromAbi(x), compiler_rt.f16.fromAbi(y)));
19}
20pub fn fmax_f16(x: f16, y: f16) f16 {
2121 return generic_fmax(f16, x, y);
2222}
2323
24pub fn fmaxf(x: f32, y: f32) callconv(.c) f32 {
24fn fmaxf(x: compiler_rt.f32.Abi, y: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
25 return compiler_rt.f32.toAbi(fmax_f32(compiler_rt.f32.fromAbi(x), compiler_rt.f32.fromAbi(y)));
26}
27pub fn fmax_f32(x: f32, y: f32) f32 {
2528 return generic_fmax(f32, x, y);
2629}
2730
28pub fn fmax(x: f64, y: f64) callconv(.c) f64 {
31fn fmax(x: compiler_rt.f64.Abi, y: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
32 return compiler_rt.f64.toAbi(fmax_f64(compiler_rt.f64.fromAbi(x), compiler_rt.f64.fromAbi(y)));
33}
34pub fn fmax_f64(x: f64, y: f64) f64 {
2935 return generic_fmax(f64, x, y);
3036}
3137
32pub fn __fmaxx(x: f80, y: f80) callconv(.c) f80 {
38fn __fmaxx(x: compiler_rt.f80.Abi, y: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
39 return compiler_rt.f80.toAbi(fmax_f80(compiler_rt.f80.fromAbi(x), compiler_rt.f80.fromAbi(y)));
40}
41pub fn fmax_f80(x: f80, y: f80) f80 {
3342 return generic_fmax(f80, x, y);
3443}
3544
36pub fn fmaxq(x: f128, y: f128) callconv(.c) f128 {
45fn fmaxq(x: compiler_rt.f128.Abi, y: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
46 return compiler_rt.f128.toAbi(fmax_f128(compiler_rt.f128.fromAbi(x), compiler_rt.f128.fromAbi(y)));
47}
48pub fn fmax_f128(x: f128, y: f128) f128 {
3749 return generic_fmax(f128, x, y);
3850}
3951
4052pub fn fmaxl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble {
4153 switch (@typeInfo(c_longdouble).float.bits) {
42 64 => return fmax(x, y),
43 80 => return __fmaxx(x, y),
44 128 => return fmaxq(x, y),
45 else => @compileError("unreachable"),
54 64 => return fmax_f64(x, y),
55 80 => return fmax_f80(x, y),
56 128 => return fmax_f128(x, y),
57 else => comptime unreachable,
4658 }
4759}
4860
lib/compiler_rt/fmin.zig+25-13
......@@ -10,39 +10,51 @@ comptime {
1010 symbol(&fminf, "fminf");
1111 symbol(&fmin, "fmin");
1212 symbol(&__fminx, "__fminx");
13 if (compiler_rt.want_ppc_abi) {
14 symbol(&fminq, "fminf128");
15 }
16 symbol(&fminq, "fminq");
13 symbol(&fminq, "fminf128");
1714 symbol(&fminl, "fminl");
1815}
1916
20pub fn __fminh(x: f16, y: f16) callconv(.c) f16 {
17fn __fminh(x: compiler_rt.f16.Abi, y: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
18 return compiler_rt.f16.toAbi(fmin_f16(compiler_rt.f16.fromAbi(x), compiler_rt.f16.fromAbi(y)));
19}
20pub fn fmin_f16(x: f16, y: f16) f16 {
2121 return generic_fmin(f16, x, y);
2222}
2323
24pub fn fminf(x: f32, y: f32) callconv(.c) f32 {
24fn fminf(x: compiler_rt.f32.Abi, y: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
25 return compiler_rt.f32.toAbi(fmin_f32(compiler_rt.f32.fromAbi(x), compiler_rt.f32.fromAbi(y)));
26}
27pub fn fmin_f32(x: f32, y: f32) f32 {
2528 return generic_fmin(f32, x, y);
2629}
2730
28pub fn fmin(x: f64, y: f64) callconv(.c) f64 {
31fn fmin(x: compiler_rt.f64.Abi, y: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
32 return compiler_rt.f64.toAbi(fmin_f64(compiler_rt.f64.fromAbi(x), compiler_rt.f64.fromAbi(y)));
33}
34pub fn fmin_f64(x: f64, y: f64) f64 {
2935 return generic_fmin(f64, x, y);
3036}
3137
32pub fn __fminx(x: f80, y: f80) callconv(.c) f80 {
38fn __fminx(x: compiler_rt.f80.Abi, y: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
39 return compiler_rt.f80.toAbi(fmin_f80(compiler_rt.f80.fromAbi(x), compiler_rt.f80.fromAbi(y)));
40}
41pub fn fmin_f80(x: f80, y: f80) f80 {
3342 return generic_fmin(f80, x, y);
3443}
3544
36pub fn fminq(x: f128, y: f128) callconv(.c) f128 {
45fn fminq(x: compiler_rt.f128.Abi, y: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
46 return compiler_rt.f128.toAbi(fmin_f128(compiler_rt.f128.fromAbi(x), compiler_rt.f128.fromAbi(y)));
47}
48pub fn fmin_f128(x: f128, y: f128) f128 {
3749 return generic_fmin(f128, x, y);
3850}
3951
4052pub fn fminl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble {
4153 switch (@typeInfo(c_longdouble).float.bits) {
42 64 => return fmin(x, y),
43 80 => return __fminx(x, y),
44 128 => return fminq(x, y),
45 else => @compileError("unreachable"),
54 64 => return fmin_f64(x, y),
55 80 => return fmin_f80(x, y),
56 128 => return fmin_f128(x, y),
57 else => comptime unreachable,
4658 }
4759}
4860
lib/compiler_rt/fmod.zig+50-38
......@@ -12,29 +12,38 @@ comptime {
1212 symbol(&fmodf, "fmodf");
1313 symbol(&fmod, "fmod");
1414 symbol(&__fmodx, "__fmodx");
15 if (compiler_rt.want_ppc_abi) {
16 symbol(&fmodq, "fmodf128");
17 }
18 symbol(&fmodq, "fmodq");
15 symbol(&fmodq, "fmodf128");
1916 symbol(&fmodl, "fmodl");
2017}
2118
22pub fn __fmodh(x: f16, y: f16) callconv(.c) f16 {
19fn __fmodh(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
20 return compiler_rt.f16.toAbi(fmod_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)));
21}
22pub fn fmod_f16(x: f16, y: f16) f16 {
2323 // TODO: more efficient implementation
24 return @floatCast(fmodf(x, y));
24 return @floatCast(fmod_f32(x, y));
2525}
2626
27pub fn fmodf(x: f32, y: f32) callconv(.c) f32 {
27fn fmodf(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
28 return compiler_rt.f32.toAbi(fmod_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)));
29}
30pub fn fmod_f32(x: f32, y: f32) f32 {
2831 return generic_fmod(f32, x, y);
2932}
3033
31pub fn fmod(x: f64, y: f64) callconv(.c) f64 {
34fn fmod(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
35 return compiler_rt.f64.toAbi(fmod_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)));
36}
37pub fn fmod_f64(x: f64, y: f64) f64 {
3238 return generic_fmod(f64, x, y);
3339}
3440
41fn __fmodx(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
42 return compiler_rt.f80.toAbi(fmod_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b)));
43}
3544/// fmodx - floating modulo large, returns the remainder of division for f80 types
3645/// Logic and flow heavily inspired by MUSL fmodl for 113 mantissa digits
37pub fn __fmodx(a: f80, b: f80) callconv(.c) f80 {
46pub fn fmod_f80(a: f80, b: f80) f80 {
3847 const T = f80;
3948 const Z = @Int(.unsigned, @bitSizeOf(T));
4049
......@@ -130,9 +139,12 @@ pub fn __fmodx(a: f80, b: f80) callconv(.c) f80 {
130139 }
131140}
132141
142fn fmodq(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
143 return compiler_rt.f128.toAbi(fmod_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)));
144}
133145/// fmodq - floating modulo large, returns the remainder of division for f128 types
134146/// Logic and flow heavily inspired by MUSL fmodl for 113 mantissa digits
135pub fn fmodq(a: f128, b: f128) callconv(.c) f128 {
147pub fn fmod_f128(a: f128, b: f128) f128 {
136148 var amod = a;
137149 var bmod = b;
138150 const aPtr_u64: [*]u64 = @ptrCast(&amod);
......@@ -251,10 +263,10 @@ pub fn fmodq(a: f128, b: f128) callconv(.c) f128 {
251263
252264pub fn fmodl(a: c_longdouble, b: c_longdouble) callconv(.c) c_longdouble {
253265 switch (@typeInfo(c_longdouble).float.bits) {
254 64 => return fmod(a, b),
255 80 => return __fmodx(a, b),
256 128 => return fmodq(a, b),
257 else => @compileError("unreachable"),
266 64 => return fmod_f64(a, b),
267 80 => return fmod_f80(a, b),
268 128 => return fmod_f128(a, b),
269 else => comptime unreachable,
258270 }
259271}
260272
......@@ -342,42 +354,42 @@ inline fn generic_fmod(comptime T: type, x: T, y: T) T {
342354 return @bitCast(ux);
343355}
344356
345test "fmodf" {
357test fmod_f32 {
346358 const nan_val = math.nan(f32);
347359 const inf_val = math.inf(f32);
348360
349 try std.testing.expect(math.isNan(fmodf(nan_val, 1.0)));
350 try std.testing.expect(math.isNan(fmodf(1.0, nan_val)));
351 try std.testing.expect(math.isNan(fmodf(inf_val, 1.0)));
352 try std.testing.expect(math.isNan(fmodf(0.0, 0.0)));
353 try std.testing.expect(math.isNan(fmodf(1.0, 0.0)));
361 try std.testing.expect(math.isNan(fmod_f32(nan_val, 1.0)));
362 try std.testing.expect(math.isNan(fmod_f32(1.0, nan_val)));
363 try std.testing.expect(math.isNan(fmod_f32(inf_val, 1.0)));
364 try std.testing.expect(math.isNan(fmod_f32(0.0, 0.0)));
365 try std.testing.expect(math.isNan(fmod_f32(1.0, 0.0)));
354366
355 try std.testing.expectEqual(@as(f32, 0.0), fmodf(0.0, 2.0));
356 try std.testing.expectEqual(@as(f32, -0.0), fmodf(-0.0, 2.0));
367 try std.testing.expectEqual(@as(f32, 0.0), fmod_f32(0.0, 2.0));
368 try std.testing.expectEqual(@as(f32, -0.0), fmod_f32(-0.0, 2.0));
357369
358 try std.testing.expectEqual(@as(f32, -2.0), fmodf(-32.0, 10.0));
359 try std.testing.expectEqual(@as(f32, -2.0), fmodf(-32.0, -10.0));
360 try std.testing.expectEqual(@as(f32, 2.0), fmodf(32.0, 10.0));
361 try std.testing.expectEqual(@as(f32, 2.0), fmodf(32.0, -10.0));
370 try std.testing.expectEqual(@as(f32, -2.0), fmod_f32(-32.0, 10.0));
371 try std.testing.expectEqual(@as(f32, -2.0), fmod_f32(-32.0, -10.0));
372 try std.testing.expectEqual(@as(f32, 2.0), fmod_f32(32.0, 10.0));
373 try std.testing.expectEqual(@as(f32, 2.0), fmod_f32(32.0, -10.0));
362374}
363375
364test "fmod" {
376test fmod_f64 {
365377 const nan_val = math.nan(f64);
366378 const inf_val = math.inf(f64);
367379
368 try std.testing.expect(math.isNan(fmod(nan_val, 1.0)));
369 try std.testing.expect(math.isNan(fmod(1.0, nan_val)));
370 try std.testing.expect(math.isNan(fmod(inf_val, 1.0)));
371 try std.testing.expect(math.isNan(fmod(0.0, 0.0)));
372 try std.testing.expect(math.isNan(fmod(1.0, 0.0)));
380 try std.testing.expect(math.isNan(fmod_f64(nan_val, 1.0)));
381 try std.testing.expect(math.isNan(fmod_f64(1.0, nan_val)));
382 try std.testing.expect(math.isNan(fmod_f64(inf_val, 1.0)));
383 try std.testing.expect(math.isNan(fmod_f64(0.0, 0.0)));
384 try std.testing.expect(math.isNan(fmod_f64(1.0, 0.0)));
373385
374 try std.testing.expectEqual(@as(f64, 0.0), fmod(0.0, 2.0));
375 try std.testing.expectEqual(@as(f64, -0.0), fmod(-0.0, 2.0));
386 try std.testing.expectEqual(@as(f64, 0.0), fmod_f64(0.0, 2.0));
387 try std.testing.expectEqual(@as(f64, -0.0), fmod_f64(-0.0, 2.0));
376388
377 try std.testing.expectEqual(@as(f64, -2.0), fmod(-32.0, 10.0));
378 try std.testing.expectEqual(@as(f64, -2.0), fmod(-32.0, -10.0));
379 try std.testing.expectEqual(@as(f64, 2.0), fmod(32.0, 10.0));
380 try std.testing.expectEqual(@as(f64, 2.0), fmod(32.0, -10.0));
389 try std.testing.expectEqual(@as(f64, -2.0), fmod_f64(-32.0, 10.0));
390 try std.testing.expectEqual(@as(f64, -2.0), fmod_f64(-32.0, -10.0));
391 try std.testing.expectEqual(@as(f64, 2.0), fmod_f64(32.0, 10.0));
392 try std.testing.expectEqual(@as(f64, 2.0), fmod_f64(32.0, -10.0));
381393}
382394
383395test {
lib/compiler_rt/fmodq_test.zig+32-32
......@@ -1,52 +1,52 @@
11const std = @import("std");
2const fmod = @import("fmod.zig");
2const fmod_f128 = @import("fmod.zig").fmod_f128;
33const testing = std.testing;
44
5fn test_fmodq(a: f128, b: f128, exp: f128) !void {
6 const res = fmod.fmodq(a, b);
5fn test_fmod_f128(a: f128, b: f128, exp: f128) !void {
6 const res = fmod_f128(a, b);
77 try testing.expect(exp == res);
88}
99
10fn test_fmodq_nans() !void {
11 try testing.expect(std.math.isNan(fmod.fmodq(1.0, std.math.nan(f128))));
12 try testing.expect(std.math.isNan(fmod.fmodq(1.0, -std.math.nan(f128))));
13 try testing.expect(std.math.isNan(fmod.fmodq(std.math.nan(f128), 1.0)));
14 try testing.expect(std.math.isNan(fmod.fmodq(-std.math.nan(f128), 1.0)));
10fn test_fmod_f128_nans() !void {
11 try testing.expect(std.math.isNan(fmod_f128(1.0, std.math.nan(f128))));
12 try testing.expect(std.math.isNan(fmod_f128(1.0, -std.math.nan(f128))));
13 try testing.expect(std.math.isNan(fmod_f128(std.math.nan(f128), 1.0)));
14 try testing.expect(std.math.isNan(fmod_f128(-std.math.nan(f128), 1.0)));
1515}
1616
17fn test_fmodq_infs() !void {
18 try testing.expect(fmod.fmodq(1.0, std.math.inf(f128)) == 1.0);
19 try testing.expect(fmod.fmodq(1.0, -std.math.inf(f128)) == 1.0);
20 try testing.expect(std.math.isNan(fmod.fmodq(std.math.inf(f128), 1.0)));
21 try testing.expect(std.math.isNan(fmod.fmodq(-std.math.inf(f128), 1.0)));
17fn test_fmod_f128_infs() !void {
18 try testing.expect(fmod_f128(1.0, std.math.inf(f128)) == 1.0);
19 try testing.expect(fmod_f128(1.0, -std.math.inf(f128)) == 1.0);
20 try testing.expect(std.math.isNan(fmod_f128(std.math.inf(f128), 1.0)));
21 try testing.expect(std.math.isNan(fmod_f128(-std.math.inf(f128), 1.0)));
2222}
2323
24test "fmodq" {
25 try test_fmodq(6.8, 4.0, 2.8);
26 try test_fmodq(6.8, -4.0, 2.8);
27 try test_fmodq(-6.8, 4.0, -2.8);
28 try test_fmodq(-6.8, -4.0, -2.8);
29 try test_fmodq(3.0, 2.0, 1.0);
30 try test_fmodq(-5.0, 3.0, -2.0);
31 try test_fmodq(3.0, 2.0, 1.0);
32 try test_fmodq(1.0, 2.0, 1.0);
33 try test_fmodq(0.0, 1.0, 0.0);
34 try test_fmodq(-0.0, 1.0, -0.0);
35 try test_fmodq(7046119.0, 5558362.0, 1487757.0);
36 try test_fmodq(9010357.0, 1957236.0, 1181413.0);
37 try test_fmodq(5192296858534827628530496329220095, 10.0, 5.0);
38 try test_fmodq(5192296858534827628530496329220095, 922337203681230954775807, 220474884073715748246157);
24test fmod_f128 {
25 try test_fmod_f128(6.8, 4.0, 2.8);
26 try test_fmod_f128(6.8, -4.0, 2.8);
27 try test_fmod_f128(-6.8, 4.0, -2.8);
28 try test_fmod_f128(-6.8, -4.0, -2.8);
29 try test_fmod_f128(3.0, 2.0, 1.0);
30 try test_fmod_f128(-5.0, 3.0, -2.0);
31 try test_fmod_f128(3.0, 2.0, 1.0);
32 try test_fmod_f128(1.0, 2.0, 1.0);
33 try test_fmod_f128(0.0, 1.0, 0.0);
34 try test_fmod_f128(-0.0, 1.0, -0.0);
35 try test_fmod_f128(7046119.0, 5558362.0, 1487757.0);
36 try test_fmod_f128(9010357.0, 1957236.0, 1181413.0);
37 try test_fmod_f128(5192296858534827628530496329220095, 10.0, 5.0);
38 try test_fmod_f128(5192296858534827628530496329220095, 922337203681230954775807, 220474884073715748246157);
3939
4040 // Denormals
4141 const a1: f128 = 0xedcb34a235253948765432134674p-16494;
4242 const b1: f128 = 0x5d2e38791cfbc0737402da5a9518p-16494;
4343 const exp1: f128 = 0x336ec3affb2db8618e4e7d5e1c44p-16494;
44 try test_fmodq(a1, b1, exp1);
44 try test_fmod_f128(a1, b1, exp1);
4545 const a2: f128 = 0x0.7654_3210_fdec_ba98_7654_3210_fdecp-16382;
4646 const b2: f128 = 0x0.0012_fdac_bdef_1234_fdec_3222_1111p-16382;
4747 const exp2: f128 = 0x0.0001_aecd_9d66_4a6e_67b7_d7d0_a901p-16382;
48 try test_fmodq(a2, b2, exp2);
48 try test_fmod_f128(a2, b2, exp2);
4949
50 try test_fmodq_nans();
51 try test_fmodq_infs();
50 try test_fmod_f128_nans();
51 try test_fmod_f128_infs();
5252}
lib/compiler_rt/fmodx_test.zig+31-31
......@@ -1,52 +1,52 @@
11const std = @import("std");
22const builtin = @import("builtin");
3const fmod = @import("fmod.zig");
3const fmod_f80 = @import("fmod.zig").fmod_f80;
44const testing = std.testing;
55
6fn test_fmodx(a: f80, b: f80, exp: f80) !void {
7 const res = fmod.__fmodx(a, b);
6fn test_fmod_f80(a: f80, b: f80, exp: f80) !void {
7 const res = fmod_f80(a, b);
88 try testing.expect(exp == res);
99}
1010
11fn test_fmodx_nans() !void {
12 try testing.expect(std.math.isNan(fmod.__fmodx(1.0, std.math.nan(f80))));
13 try testing.expect(std.math.isNan(fmod.__fmodx(1.0, -std.math.nan(f80))));
14 try testing.expect(std.math.isNan(fmod.__fmodx(std.math.nan(f80), 1.0)));
15 try testing.expect(std.math.isNan(fmod.__fmodx(-std.math.nan(f80), 1.0)));
11fn test_fmod_f80_nans() !void {
12 try testing.expect(std.math.isNan(fmod_f80(1.0, std.math.nan(f80))));
13 try testing.expect(std.math.isNan(fmod_f80(1.0, -std.math.nan(f80))));
14 try testing.expect(std.math.isNan(fmod_f80(std.math.nan(f80), 1.0)));
15 try testing.expect(std.math.isNan(fmod_f80(-std.math.nan(f80), 1.0)));
1616}
1717
18fn test_fmodx_infs() !void {
19 try testing.expect(fmod.__fmodx(1.0, std.math.inf(f80)) == 1.0);
20 try testing.expect(fmod.__fmodx(1.0, -std.math.inf(f80)) == 1.0);
21 try testing.expect(std.math.isNan(fmod.__fmodx(std.math.inf(f80), 1.0)));
22 try testing.expect(std.math.isNan(fmod.__fmodx(-std.math.inf(f80), 1.0)));
18fn test_fmod_f80_infs() !void {
19 try testing.expect(fmod_f80(1.0, std.math.inf(f80)) == 1.0);
20 try testing.expect(fmod_f80(1.0, -std.math.inf(f80)) == 1.0);
21 try testing.expect(std.math.isNan(fmod_f80(std.math.inf(f80), 1.0)));
22 try testing.expect(std.math.isNan(fmod_f80(-std.math.inf(f80), 1.0)));
2323}
2424
25test "fmodx" {
26 try test_fmodx(6.4, 4.0, 2.4);
27 try test_fmodx(6.4, -4.0, 2.4);
28 try test_fmodx(-6.4, 4.0, -2.4);
29 try test_fmodx(-6.4, -4.0, -2.4);
30 try test_fmodx(3.0, 2.0, 1.0);
31 try test_fmodx(-5.0, 3.0, -2.0);
32 try test_fmodx(3.0, 2.0, 1.0);
33 try test_fmodx(1.0, 2.0, 1.0);
34 try test_fmodx(0.0, 1.0, 0.0);
35 try test_fmodx(-0.0, 1.0, -0.0);
36 try test_fmodx(7046119.0, 5558362.0, 1487757.0);
37 try test_fmodx(9010357.0, 1957236.0, 1181413.0);
38 try test_fmodx(9223372036854775807, 10.0, 7.0);
25test fmod_f80 {
26 try test_fmod_f80(6.4, 4.0, 2.4);
27 try test_fmod_f80(6.4, -4.0, 2.4);
28 try test_fmod_f80(-6.4, 4.0, -2.4);
29 try test_fmod_f80(-6.4, -4.0, -2.4);
30 try test_fmod_f80(3.0, 2.0, 1.0);
31 try test_fmod_f80(-5.0, 3.0, -2.0);
32 try test_fmod_f80(3.0, 2.0, 1.0);
33 try test_fmod_f80(1.0, 2.0, 1.0);
34 try test_fmod_f80(0.0, 1.0, 0.0);
35 try test_fmod_f80(-0.0, 1.0, -0.0);
36 try test_fmod_f80(7046119.0, 5558362.0, 1487757.0);
37 try test_fmod_f80(9010357.0, 1957236.0, 1181413.0);
38 try test_fmod_f80(9223372036854775807, 10.0, 7.0);
3939
4040 // Denormals
4141 const a1: f80 = 0x0.76e5_9a51_1a92_9ca4p-16381;
4242 const b1: f80 = 0x0.2e97_1c3c_8e7d_e03ap-16381;
4343 const exp1: f80 = 0x0.19b7_61d7_fd96_dc30p-16381;
44 try test_fmodx(a1, b1, exp1);
44 try test_fmod_f80(a1, b1, exp1);
4545 const a2: f80 = 0x0.76e5_9a51_1a92_9ca4p-16381;
4646 const b2: f80 = 0x0.0e97_1c3c_8e7d_e03ap-16381;
4747 const exp2: f80 = 0x0.022c_b86c_a6a3_9ad4p-16381;
48 try test_fmodx(a2, b2, exp2);
48 try test_fmod_f80(a2, b2, exp2);
4949
50 try test_fmodx_nans();
51 try test_fmodx_infs();
50 try test_fmod_f80_nans();
51 try test_fmod_f80_infs();
5252}
lib/compiler_rt/gedf2.zig deleted-35
......@@ -1,35 +0,0 @@
1///! The quoted behavior definitions are from
2///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines
3const compiler_rt = @import("../compiler_rt.zig");
4const comparef = @import("./comparef.zig");
5const symbol = @import("../compiler_rt.zig").symbol;
6
7comptime {
8 if (compiler_rt.want_aeabi) {
9 symbol(&__aeabi_dcmpge, "__aeabi_dcmpge");
10 symbol(&__aeabi_dcmpgt, "__aeabi_dcmpgt");
11 } else {
12 symbol(&__gedf2, "__gedf2");
13 symbol(&__gtdf2, "__gtdf2");
14 }
15}
16
17/// "These functions return a value greater than or equal to zero if neither
18/// argument is NaN, and a is greater than or equal to b."
19pub fn __gedf2(a: f64, b: f64) callconv(.c) i32 {
20 return @backingInt(comparef.cmpf2(f64, comparef.GE, a, b));
21}
22
23/// "These functions return a value greater than zero if neither argument is NaN,
24/// and a is strictly greater than b."
25pub fn __gtdf2(a: f64, b: f64) callconv(.c) i32 {
26 return __gedf2(a, b);
27}
28
29fn __aeabi_dcmpge(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
30 return @intFromBool(comparef.cmpf2(f64, comparef.GE, a, b) != .Less);
31}
32
33fn __aeabi_dcmpgt(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
34 return @intFromBool(comparef.cmpf2(f64, comparef.GE, a, b) == .Greater);
35}
lib/compiler_rt/gehf2.zig deleted-21
......@@ -1,21 +0,0 @@
1///! The quoted behavior definitions are from
2///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines
3const symbol = @import("../compiler_rt.zig").symbol;
4const comparef = @import("./comparef.zig");
5
6comptime {
7 symbol(&__gehf2, "__gehf2");
8 symbol(&__gthf2, "__gthf2");
9}
10
11/// "These functions return a value greater than or equal to zero if neither
12/// argument is NaN, and a is greater than or equal to b."
13pub fn __gehf2(a: f16, b: f16) callconv(.c) i32 {
14 return @backingInt(comparef.cmpf2(f16, comparef.GE, a, b));
15}
16
17/// "These functions return a value greater than zero if neither argument is NaN,
18/// and a is strictly greater than b."
19pub fn __gthf2(a: f16, b: f16) callconv(.c) i32 {
20 return __gehf2(a, b);
21}
lib/compiler_rt/gesf2.zig deleted-35
......@@ -1,35 +0,0 @@
1///! The quoted behavior definitions are from
2///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const comparef = @import("./comparef.zig");
6
7comptime {
8 if (compiler_rt.want_aeabi) {
9 symbol(&__aeabi_fcmpge, "__aeabi_fcmpge");
10 symbol(&__aeabi_fcmpgt, "__aeabi_fcmpgt");
11 } else {
12 symbol(&__gesf2, "__gesf2");
13 symbol(&__gtsf2, "__gtsf2");
14 }
15}
16
17/// "These functions return a value greater than or equal to zero if neither
18/// argument is NaN, and a is greater than or equal to b."
19pub fn __gesf2(a: f32, b: f32) callconv(.c) i32 {
20 return @backingInt(comparef.cmpf2(f32, comparef.GE, a, b));
21}
22
23/// "These functions return a value greater than zero if neither argument is NaN,
24/// and a is strictly greater than b."
25pub fn __gtsf2(a: f32, b: f32) callconv(.c) i32 {
26 return __gesf2(a, b);
27}
28
29fn __aeabi_fcmpge(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
30 return @intFromBool(comparef.cmpf2(f32, comparef.GE, a, b) != .Less);
31}
32
33fn __aeabi_fcmpgt(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
34 return @intFromBool(comparef.cmpf2(f32, comparef.LE, a, b) == .Greater);
35}
lib/compiler_rt/getf2.zig deleted-26
......@@ -1,26 +0,0 @@
1///! The quoted behavior definitions are from
2///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const comparef = @import("./comparef.zig");
6
7comptime {
8 if (compiler_rt.want_ppc_abi) {
9 symbol(&__getf2, "__gekf2");
10 symbol(&__gttf2, "__gtkf2");
11 }
12 symbol(&__getf2, "__getf2");
13 symbol(&__gttf2, "__gttf2");
14}
15
16/// "These functions return a value greater than or equal to zero if neither
17/// argument is NaN, and a is greater than or equal to b."
18fn __getf2(a: f128, b: f128) callconv(.c) i32 {
19 return @backingInt(comparef.cmpf2(f128, comparef.GE, a, b));
20}
21
22/// "These functions return a value greater than zero if neither argument is NaN,
23/// and a is strictly greater than b."
24fn __gttf2(a: f128, b: f128) callconv(.c) i32 {
25 return __getf2(a, b);
26}
lib/compiler_rt/gexf2.zig deleted-15
......@@ -1,15 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const comparef = @import("./comparef.zig");
3
4comptime {
5 symbol(&__gexf2, "__gexf2");
6 symbol(&__gtxf2, "__gtxf2");
7}
8
9fn __gexf2(a: f80, b: f80) callconv(.c) i32 {
10 return @backingInt(comparef.cmp_f80(comparef.GE, a, b));
11}
12
13fn __gtxf2(a: f80, b: f80) callconv(.c) i32 {
14 return __gexf2(a, b);
15}
lib/compiler_rt/int.zig+39-40
......@@ -36,7 +36,7 @@ comptime {
3636
3737pub fn __divmodti4(a: i128, b: i128, rem: *i128) callconv(.c) i128 {
3838 const d = __divti3(a, b);
39 rem.* = a -% (d * b);
39 rem.* = a - d *% b;
4040 return d;
4141}
4242
......@@ -69,7 +69,7 @@ fn test_one_divmodti4(a: i128, b: i128, expected_q: i128, expected_r: i128) !voi
6969
7070pub fn __divmoddi4(a: i64, b: i64, rem: *i64) callconv(.c) i64 {
7171 const d = __divdi3(a, b);
72 rem.* = a -% (d * b);
72 rem.* = a - d *% b;
7373 return d;
7474}
7575
......@@ -79,21 +79,20 @@ fn test_one_divmoddi4(a: i64, b: i64, expected_q: i64, expected_r: i64) !void {
7979 try testing.expect(q == expected_q and r == expected_r);
8080}
8181
82const cases__divmoddi4 =
83 [_][4]i64{
84 [_]i64{ 0, 1, 0, 0 },
85 [_]i64{ 0, -1, 0, 0 },
86 [_]i64{ 2, 1, 2, 0 },
87 [_]i64{ 2, -1, -2, 0 },
88 [_]i64{ -2, 1, -2, 0 },
89 [_]i64{ -2, -1, 2, 0 },
90 [_]i64{ 7, 5, 1, 2 },
91 [_]i64{ -7, 5, -1, -2 },
92 [_]i64{ 19, 5, 3, 4 },
93 [_]i64{ 19, -5, -3, 4 },
94 [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000000))), 0 },
95 [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000007))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000001))), -1 },
96 };
82const cases__divmoddi4 = [_][4]i64{
83 [_]i64{ 0, 1, 0, 0 },
84 [_]i64{ 0, -1, 0, 0 },
85 [_]i64{ 2, 1, 2, 0 },
86 [_]i64{ 2, -1, -2, 0 },
87 [_]i64{ -2, 1, -2, 0 },
88 [_]i64{ -2, -1, 2, 0 },
89 [_]i64{ 7, 5, 1, 2 },
90 [_]i64{ -7, 5, -1, -2 },
91 [_]i64{ 19, 5, 3, 4 },
92 [_]i64{ 19, -5, -3, 4 },
93 [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000000))), 0 },
94 [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000007))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000001))), -1 },
95};
9796
9897test "test_divmoddi4" {
9998 for (cases__divmoddi4) |case| {
......@@ -105,10 +104,6 @@ pub fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?*u64) callconv(.c) u64 {
105104 return udivmod(u64, a, b, maybe_rem);
106105}
107106
108test "test_udivmoddi4" {
109 _ = @import("udivmoddi4_test.zig");
110}
111
112107pub fn __divdi3(a: i64, b: i64) callconv(.c) i64 {
113108 // Set aside the sign of the quotient.
114109 const sign: u64 = @bitCast((a ^ b) >> 63);
......@@ -209,25 +204,24 @@ fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) !void {
209204
210205pub fn __divmodsi4(a: i32, b: i32, rem: *i32) callconv(.c) i32 {
211206 const d = __divsi3(a, b);
212 rem.* = a -% (d * b);
207 rem.* = a - d *% b;
213208 return d;
214209}
215210
216const cases__divmodsi4 =
217 [_][4]i32{
218 [_]i32{ 0, 1, 0, 0 },
219 [_]i32{ 0, -1, 0, 0 },
220 [_]i32{ 2, 1, 2, 0 },
221 [_]i32{ 2, -1, -2, 0 },
222 [_]i32{ -2, 1, -2, 0 },
223 [_]i32{ -2, -1, 2, 0 },
224 [_]i32{ 7, 5, 1, 2 },
225 [_]i32{ -7, 5, -1, -2 },
226 [_]i32{ 19, 5, 3, 4 },
227 [_]i32{ 19, -5, -3, 4 },
228 [_]i32{ @bitCast(@as(u32, 0x80000000)), 8, @bitCast(@as(u32, 0xf0000000)), 0 },
229 [_]i32{ @bitCast(@as(u32, 0x80000007)), 8, @bitCast(@as(u32, 0xf0000001)), -1 },
230 };
211const cases__divmodsi4 = [_][4]i32{
212 [_]i32{ 0, 1, 0, 0 },
213 [_]i32{ 0, -1, 0, 0 },
214 [_]i32{ 2, 1, 2, 0 },
215 [_]i32{ 2, -1, -2, 0 },
216 [_]i32{ -2, 1, -2, 0 },
217 [_]i32{ -2, -1, 2, 0 },
218 [_]i32{ 7, 5, 1, 2 },
219 [_]i32{ -7, 5, -1, -2 },
220 [_]i32{ 19, 5, 3, 4 },
221 [_]i32{ 19, -5, -3, 4 },
222 [_]i32{ @bitCast(@as(u32, 0x80000000)), 8, @bitCast(@as(u32, 0xf0000000)), 0 },
223 [_]i32{ @bitCast(@as(u32, 0x80000007)), 8, @bitCast(@as(u32, 0xf0000001)), -1 },
224};
231225
232226fn test_one_divmodsi4(a: i32, b: i32, expected_q: i32, expected_r: i32) !void {
233227 var r: i32 = undefined;
......@@ -243,7 +237,7 @@ test "test_divmodsi4" {
243237
244238pub fn __udivmodsi4(a: u32, b: u32, rem: *u32) callconv(.c) u32 {
245239 const d = __udivsi3(a, b);
246 rem.* = @bitCast(@as(i32, @bitCast(a)) -% (@as(i32, @bitCast(d)) * @as(i32, @bitCast(b))));
240 rem.* = a - d * b;
247241 return d;
248242}
249243
......@@ -486,7 +480,7 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) !void {
486480}
487481
488482pub fn __modsi3(n: i32, d: i32) callconv(.c) i32 {
489 return n -% __divsi3(n, d) * d;
483 return n - __divsi3(n, d) *% d;
490484}
491485
492486test "test_modsi3" {
......@@ -515,7 +509,7 @@ fn test_one_modsi3(a: i32, b: i32, expected_r: i32) !void {
515509}
516510
517511pub fn __umodsi3(n: u32, d: u32) callconv(.c) u32 {
518 return n -% __udivsi3(n, d) * d;
512 return n - __udivsi3(n, d) * d;
519513}
520514
521515test "test_umodsi3" {
......@@ -663,3 +657,8 @@ fn test_one_umodsi3(a: u32, b: u32, expected_r: u32) !void {
663657 const r: u32 = __umodsi3(a, b);
664658 try testing.expect(r == expected_r);
665659}
660
661test {
662 _ = @import("udivmodsi4_test.zig");
663 _ = @import("udivmoddi4_test.zig");
664}
lib/compiler_rt/int_from_float.zig+513-9
......@@ -1,3 +1,4 @@
1const builtin = @import("builtin");
12const std = @import("std");
23const math = std.math;
34const Log2Int = std.math.Log2Int;
......@@ -6,29 +7,532 @@ const compiler_rt = @import("../compiler_rt.zig");
67const symbol = compiler_rt.symbol;
78
89comptime {
9 symbol(&__fixxfti, "__fixxfti");
1010 symbol(&__fixhfsi, "__fixhfsi");
1111 symbol(&__fixhfdi, "__fixhfdi");
1212 symbol(&__fixhfti, "__fixhfti");
13 symbol(&__fixhfei, "__fixhfei");
14
15 if (compiler_rt.want_aeabi) {
16 symbol(&__aeabi_f2iz, "__aeabi_f2iz");
17 symbol(&__aeabi_f2lz, "__aeabi_f2lz");
18 symbol(&__aeabi_fixsfti, "__fixsfti");
19 } else {
20 symbol(&__fixsfsi, "__fixsfsi");
21 symbol(&__fixsfdi, "__fixsfdi");
22 if (compiler_rt.want_windows_arm_abi) symbol(&__fixsfdi, "__stoi64");
23 symbol(&__fixsfti, "__fixsfti");
24 }
25 symbol(&__fixsfei, "__fixsfei");
26
27 if (compiler_rt.want_aeabi) {
28 symbol(&__aeabi_d2iz, "__aeabi_d2iz");
29 symbol(&__aeabi_d2lz, "__aeabi_d2lz");
30 symbol(&__aeabi_fixdfti, "__fixdfti");
31 } else {
32 symbol(&__fixdfsi, "__fixdfsi");
33 symbol(&__fixdfdi, "__fixdfdi");
34 if (compiler_rt.want_windows_arm_abi) symbol(&__fixdfdi, "__dtoi64");
35 symbol(&__fixdfti, "__fixdfti");
36 }
37 symbol(&__fixdfei, "__fixdfei");
38
39 symbol(&__fixxfsi, "__fixxfsi");
40 symbol(&__fixxfdi, "__fixxfdi");
41 symbol(&__fixxfti, "__fixxfti");
42 symbol(&__fixxfei, "__fixxfei");
43
44 if (compiler_rt.want_ppc_abi) {
45 symbol(&__fixtfsi, "__fixkfsi");
46 symbol(&__fixtfdi, "__fixkfdi");
47 } else if (compiler_rt.want_sparc64_abi) {
48 symbol(&_Qp_qtoi, "_Qp_qtoi");
49 symbol(&_Qp_qtox, "_Qp_qtox");
50 } else if (compiler_rt.want_sparc32_abi) {
51 symbol(&__fixtfsi, "_Q_qtoi");
52 symbol(&__fixtfdi, "_Q_qtoll");
53 } else {
54 symbol(&__fixtfsi, "__fixtfsi");
55 symbol(&__fixtfdi, "__fixtfdi");
56 }
57 if (compiler_rt.want_ppc_abi) {
58 symbol(&__fixtfti, "__fixkfti");
59 symbol(&__fixtfei, "__fixkfei");
60 } else {
61 symbol(&__fixtfti, "__fixtfti");
62 symbol(&__fixtfei, "__fixtfei");
63 }
64}
65
66fn __fixhfsi(a: compiler_rt.f16.Abi) callconv(.c) i32 {
67 return i32_intFromFloat_f16(compiler_rt.f16.fromAbi(a));
68}
69pub fn i32_intFromFloat_f16(a: f16) i32 {
70 return intFromFloat(i32, a);
71}
72
73fn __fixhfdi(a: compiler_rt.f16.Abi) callconv(.c) i64 {
74 return i64_intFromFloat_f16(compiler_rt.f16.fromAbi(a));
75}
76pub fn i64_intFromFloat_f16(a: f16) i64 {
77 return intFromFloat(i64, a);
78}
79
80fn __fixhfti(a: compiler_rt.f16.Abi) callconv(.c) i128 {
81 return i128_intFromFloat_f16(compiler_rt.f16.fromAbi(a));
82}
83pub fn i128_intFromFloat_f16(a: f16) i128 {
84 return intFromFloat(i128, a);
85}
86
87fn __fixhfei(r: [*]u8, bits: usize, a: compiler_rt.f16.Abi) callconv(.c) void {
88 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
89 return signed_intFromFloat_f16(r[0..byte_size], compiler_rt.f16.fromAbi(a));
90}
91pub fn signed_intFromFloat_f16(result: []u8, a: f16) void {
92 bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a);
93}
94
95fn __fixsfsi(a: compiler_rt.f32.Abi) callconv(.c) i32 {
96 return i32_intFromFloat_f32(compiler_rt.f32.fromAbi(a));
97}
98fn __aeabi_f2iz(a: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
99 return i32_intFromFloat_f32(a);
100}
101pub fn i32_intFromFloat_f32(a: f32) i32 {
102 return intFromFloat(i32, a);
103}
104
105fn __fixsfdi(a: compiler_rt.f32.Abi) callconv(.c) i64 {
106 return i64_intFromFloat_f32(compiler_rt.f32.fromAbi(a));
107}
108fn __aeabi_f2lz(a: f32) callconv(.{ .arm_aapcs = .{} }) i64 {
109 return i64_intFromFloat_f32(a);
110}
111pub fn i64_intFromFloat_f32(a: f32) i64 {
112 return intFromFloat(i64, a);
113}
114
115fn __fixsfti(a: compiler_rt.f32.Abi) callconv(.c) i128 {
116 return i128_intFromFloat_f32(compiler_rt.f32.fromAbi(a));
117}
118fn __aeabi_fixsfti(_: compiler_rt.f32.Abi) callconv(.naked) i128 {
119 switch (builtin.abi.float()) {
120 .soft => asm volatile (
121 \\ push {r0-r4, lr}
122 \\ movs r1, r0
123 \\ mov r0, sp
124 \\ bl %[__fixsfti]
125 \\ pop {r0-r4, pc}
126 :
127 : [__fixsfti] "X" (&__fixsfti),
128 ),
129 .hard => asm volatile (
130 \\ push {r0-r4, lr}
131 \\ mov r0, sp
132 \\ bl %[__fixsfti]
133 \\ pop {r0-r4, pc}
134 :
135 : [__fixsfti] "X" (&__fixsfti),
136 ),
137 }
138}
139pub fn i128_intFromFloat_f32(a: f32) i128 {
140 return intFromFloat(i128, a);
141}
142
143fn __fixsfei(r: [*]u8, bits: usize, a: compiler_rt.f32.Abi) callconv(.c) void {
144 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
145 return signed_intFromFloat_f32(r[0..byte_size], compiler_rt.f32.fromAbi(a));
146}
147pub fn signed_intFromFloat_f32(result: []u8, a: f32) void {
148 bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a);
149}
150
151fn __fixdfsi(a: compiler_rt.f64.Abi) callconv(.c) i32 {
152 return i32_intFromFloat_f64(compiler_rt.f64.fromAbi(a));
153}
154fn __aeabi_d2iz(a: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
155 return i32_intFromFloat_f64(a);
156}
157pub fn i32_intFromFloat_f64(a: f64) i32 {
158 return intFromFloat(i32, a);
159}
160
161fn __fixdfdi(a: compiler_rt.f64.Abi) callconv(.c) i64 {
162 return i64_intFromFloat_f64(compiler_rt.f64.fromAbi(a));
163}
164fn __aeabi_d2lz(a: f64) callconv(.{ .arm_aapcs = .{} }) i64 {
165 return i64_intFromFloat_f64(a);
166}
167pub fn i64_intFromFloat_f64(a: f64) i64 {
168 return intFromFloat(i64, a);
13169}
14170
15pub fn __fixhfti(a: f16) callconv(.c) i128 {
171fn __fixdfti(a: compiler_rt.f64.Abi) callconv(.c) i128 {
172 return i128_intFromFloat_f64(compiler_rt.f64.fromAbi(a));
173}
174fn __aeabi_fixdfti(_: compiler_rt.f64.Abi) callconv(.naked) i128 {
175 switch (builtin.abi.float()) {
176 .soft => asm volatile (
177 \\ push {r0-r4, lr}
178 \\ movs r3, r1
179 \\ movs r2, r0
180 \\ mov r0, sp
181 \\ bl %[__fixdfti]
182 \\ pop {r0-r4, pc}
183 :
184 : [__fixdfti] "X" (&__fixdfti),
185 ),
186 .hard => asm volatile (
187 \\ push {r0-r4, lr}
188 \\ mov r0, sp
189 \\ bl %[__fixdfti]
190 \\ pop {r0-r4, pc}
191 :
192 : [__fixdfti] "X" (&__fixdfti),
193 ),
194 }
195}
196pub fn i128_intFromFloat_f64(a: f64) i128 {
16197 return intFromFloat(i128, a);
17198}
18199
19fn __fixhfdi(a: f16) callconv(.c) i64 {
200fn __fixdfei(r: [*]u8, bits: usize, a: compiler_rt.f64.Abi) callconv(.c) void {
201 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
202 return signed_intFromFloat_f64(r[0..byte_size], compiler_rt.f64.fromAbi(a));
203}
204pub fn signed_intFromFloat_f64(result: []u8, a: f64) void {
205 bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a);
206}
207
208fn __fixxfsi(a: compiler_rt.f80.Abi) callconv(.c) i32 {
209 return i32_intFromFloat_f80(compiler_rt.f80.fromAbi(a));
210}
211pub fn i32_intFromFloat_f80(a: f80) i32 {
212 return intFromFloat(i32, a);
213}
214
215fn __fixxfdi(a: compiler_rt.f80.Abi) callconv(.c) i64 {
216 return i64_intFromFloat_f80(compiler_rt.f80.fromAbi(a));
217}
218pub fn i64_intFromFloat_f80(a: f80) i64 {
20219 return intFromFloat(i64, a);
21220}
22221
23fn __fixhfsi(a: f16) callconv(.c) i32 {
222fn __fixxfti(a: compiler_rt.f80.Abi) callconv(.c) i128 {
223 return i128_intFromFloat_f80(compiler_rt.f80.fromAbi(a));
224}
225pub fn i128_intFromFloat_f80(a: f80) i128 {
226 return intFromFloat(i128, a);
227}
228
229fn __fixxfei(r: [*]u8, bits: usize, a: compiler_rt.f80.Abi) callconv(.c) void {
230 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
231 return signed_intFromFloat_f80(r[0..byte_size], compiler_rt.f80.fromAbi(a));
232}
233pub fn signed_intFromFloat_f80(result: []u8, a: f80) void {
234 bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a);
235}
236
237fn __fixtfsi(a: compiler_rt.f128.Abi) callconv(.c) i32 {
238 return i32_intFromFloat_f128(compiler_rt.f128.fromAbi(a));
239}
240fn _Qp_qtoi(a: *const f128) callconv(.c) i32 {
241 return i32_intFromFloat_f128(a.*);
242}
243pub fn i32_intFromFloat_f128(a: f128) i32 {
24244 return intFromFloat(i32, a);
25245}
26246
27pub fn __fixxfti(a: f80) callconv(.c) i128 {
247fn __fixtfdi(a: compiler_rt.f128.Abi) callconv(.c) i64 {
248 return i64_intFromFloat_f128(compiler_rt.f128.fromAbi(a));
249}
250fn _Qp_qtox(a: *const f128) callconv(.c) i64 {
251 return i64_intFromFloat_f128(a.*);
252}
253pub fn i64_intFromFloat_f128(a: f128) i64 {
254 return intFromFloat(i64, a);
255}
256
257fn __fixtfti(a: compiler_rt.f128.Abi) callconv(.c) i128 {
258 return i128_intFromFloat_f128(compiler_rt.f128.fromAbi(a));
259}
260pub fn i128_intFromFloat_f128(a: f128) i128 {
28261 return intFromFloat(i128, a);
29262}
30263
31pub inline fn intFromFloat(comptime I: type, a: anytype) I {
264fn __fixtfei(r: [*]u8, bits: usize, a: compiler_rt.f128.Abi) callconv(.c) void {
265 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
266 return signed_intFromFloat_f128(r[0..byte_size], compiler_rt.f128.fromAbi(a));
267}
268pub fn signed_intFromFloat_f128(result: []u8, a: f128) void {
269 bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a);
270}
271
272comptime {
273 symbol(&__fixunshfsi, "__fixunshfsi");
274 symbol(&__fixunshfdi, "__fixunshfdi");
275 symbol(&__fixunshfti, "__fixunshfti");
276 symbol(&__fixunshfei, "__fixunshfei");
277
278 if (compiler_rt.want_aeabi) {
279 symbol(&__aeabi_f2uiz, "__aeabi_f2uiz");
280 symbol(&__aeabi_f2ulz, "__aeabi_f2ulz");
281 symbol(&__aeabi_fixunssfti, "__fixunssfti");
282 } else {
283 symbol(&__fixunssfsi, "__fixunssfsi");
284 symbol(&__fixunssfdi, "__fixunssfdi");
285 if (compiler_rt.want_windows_arm_abi) symbol(&__fixunssfdi, "__stou64");
286 symbol(&__fixunssfti, "__fixunssfti");
287 }
288 symbol(&__fixunssfei, "__fixunssfei");
289
290 if (compiler_rt.want_aeabi) {
291 symbol(&__aeabi_d2uiz, "__aeabi_d2uiz");
292 symbol(&__aeabi_d2ulz, "__aeabi_d2ulz");
293 symbol(&__aeabi_fixunsdfti, "__fixunsdfti");
294 } else {
295 symbol(&__fixunsdfsi, "__fixunsdfsi");
296 symbol(&__fixunsdfdi, "__fixunsdfdi");
297 if (compiler_rt.want_windows_arm_abi) symbol(&__fixunsdfdi, "__dtou64");
298 symbol(&__fixunsdfti, "__fixunsdfti");
299 }
300 symbol(&__fixunsdfei, "__fixunsdfei");
301
302 symbol(&__fixunsxfsi, "__fixunsxfsi");
303 symbol(&__fixunsxfdi, "__fixunsxfdi");
304 symbol(&__fixunsxfti, "__fixunsxfti");
305 symbol(&__fixunsxfei, "__fixunsxfei");
306
307 if (compiler_rt.want_ppc_abi) {
308 symbol(&__fixunstfsi, "__fixunskfsi");
309 symbol(&__fixunstfdi, "__fixunskfdi");
310 } else if (compiler_rt.want_sparc64_abi) {
311 symbol(&_Qp_qtoui, "_Qp_qtoui");
312 symbol(&_Qp_qtoux, "_Qp_qtoux");
313 } else if (compiler_rt.want_sparc32_abi) {
314 symbol(&__fixunstfsi, "_Q_qtou");
315 symbol(&__fixunstfdi, "_Q_qtoull");
316 } else {
317 symbol(&__fixunstfsi, "__fixunstfsi");
318 symbol(&__fixunstfdi, "__fixunstfdi");
319 }
320 if (compiler_rt.want_ppc_abi) {
321 symbol(&__fixunstfti, "__fixunskfti");
322 symbol(&__fixunstfei, "__fixunskfei");
323 } else {
324 symbol(&__fixunstfti, "__fixunstfti");
325 symbol(&__fixunstfei, "__fixunstfei");
326 }
327}
328
329fn __fixunshfsi(a: compiler_rt.f16.Abi) callconv(.c) u32 {
330 return u32_intFromFloat_f16(compiler_rt.f16.fromAbi(a));
331}
332pub fn u32_intFromFloat_f16(a: f16) u32 {
333 return intFromFloat(u32, a);
334}
335
336fn __fixunshfdi(a: compiler_rt.f16.Abi) callconv(.c) u64 {
337 return u64_intFromFloat_f16(compiler_rt.f16.fromAbi(a));
338}
339pub fn u64_intFromFloat_f16(a: f16) u64 {
340 return intFromFloat(u64, a);
341}
342
343fn __fixunshfti(a: compiler_rt.f16.Abi) callconv(.c) u128 {
344 return u128_intFromFloat_f16(compiler_rt.f16.fromAbi(a));
345}
346pub fn u128_intFromFloat_f16(a: f16) u128 {
347 return intFromFloat(u128, a);
348}
349
350fn __fixunshfei(r: [*]u8, bits: usize, a: compiler_rt.f16.Abi) callconv(.c) void {
351 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
352 return unsigned_intFromFloat_f16(r[0..byte_size], compiler_rt.f16.fromAbi(a));
353}
354pub fn unsigned_intFromFloat_f16(result: []u8, a: f16) void {
355 bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a);
356}
357
358fn __fixunssfsi(a: compiler_rt.f32.Abi) callconv(.c) u32 {
359 return u32_intFromFloat_f32(compiler_rt.f32.fromAbi(a));
360}
361fn __aeabi_f2uiz(a: f32) callconv(.{ .arm_aapcs = .{} }) u32 {
362 return u32_intFromFloat_f32(a);
363}
364pub fn u32_intFromFloat_f32(a: f32) u32 {
365 return intFromFloat(u32, a);
366}
367
368fn __fixunssfdi(a: compiler_rt.f32.Abi) callconv(.c) u64 {
369 return u64_intFromFloat_f32(compiler_rt.f32.fromAbi(a));
370}
371fn __aeabi_f2ulz(a: f32) callconv(.{ .arm_aapcs = .{} }) u64 {
372 return u64_intFromFloat_f32(a);
373}
374pub fn u64_intFromFloat_f32(a: f32) u64 {
375 return intFromFloat(u64, a);
376}
377
378fn __fixunssfti(a: compiler_rt.f32.Abi) callconv(.c) u128 {
379 return u128_intFromFloat_f32(compiler_rt.f32.fromAbi(a));
380}
381fn __aeabi_fixunssfti(_: compiler_rt.f32.Abi) callconv(.naked) u128 {
382 switch (builtin.abi.float()) {
383 .soft => asm volatile (
384 \\ push {r0-r4, lr}
385 \\ movs r1, r0
386 \\ mov r0, sp
387 \\ bl %[__fixunssfti]
388 \\ pop {r0-r4, pc}
389 :
390 : [__fixunssfti] "X" (&__fixunssfti),
391 ),
392 .hard => asm volatile (
393 \\ push {r0-r4, lr}
394 \\ mov r0, sp
395 \\ bl %[__fixunssfti]
396 \\ pop {r0-r4, pc}
397 :
398 : [__fixunssfti] "X" (&__fixunssfti),
399 ),
400 }
401}
402pub fn u128_intFromFloat_f32(a: f32) u128 {
403 return intFromFloat(u128, a);
404}
405
406fn __fixunssfei(r: [*]u8, bits: usize, a: compiler_rt.f32.Abi) callconv(.c) void {
407 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
408 return unsigned_intFromFloat_f32(r[0..byte_size], compiler_rt.f32.fromAbi(a));
409}
410pub fn unsigned_intFromFloat_f32(result: []u8, a: f32) void {
411 bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a);
412}
413
414fn __fixunsdfsi(a: compiler_rt.f64.Abi) callconv(.c) u32 {
415 return u32_intFromFloat_f64(compiler_rt.f64.fromAbi(a));
416}
417fn __aeabi_d2uiz(a: f64) callconv(.{ .arm_aapcs = .{} }) u32 {
418 return u32_intFromFloat_f64(a);
419}
420pub fn u32_intFromFloat_f64(a: f64) u32 {
421 return intFromFloat(u32, a);
422}
423
424fn __fixunsdfdi(a: compiler_rt.f64.Abi) callconv(.c) u64 {
425 return u64_intFromFloat_f64(compiler_rt.f64.fromAbi(a));
426}
427fn __aeabi_d2ulz(a: f64) callconv(.{ .arm_aapcs = .{} }) u64 {
428 return u64_intFromFloat_f64(a);
429}
430pub fn u64_intFromFloat_f64(a: f64) u64 {
431 return intFromFloat(u64, a);
432}
433
434fn __fixunsdfti(a: compiler_rt.f64.Abi) callconv(.c) u128 {
435 return u128_intFromFloat_f64(compiler_rt.f64.fromAbi(a));
436}
437fn __aeabi_fixunsdfti(_: compiler_rt.f64.Abi) callconv(.naked) u128 {
438 switch (builtin.abi.float()) {
439 .soft => asm volatile (
440 \\ push {r0-r4, lr}
441 \\ movs r3, r1
442 \\ movs r2, r0
443 \\ mov r0, sp
444 \\ bl %[__fixunsdfti]
445 \\ pop {r0-r4, pc}
446 :
447 : [__fixunsdfti] "X" (&__fixunsdfti),
448 ),
449 .hard => asm volatile (
450 \\ push {r0-r4, lr}
451 \\ mov r0, sp
452 \\ bl %[__fixunsdfti]
453 \\ pop {r0-r4, pc}
454 :
455 : [__fixunsdfti] "X" (&__fixunsdfti),
456 ),
457 }
458}
459pub fn u128_intFromFloat_f64(a: f64) u128 {
460 return intFromFloat(u128, a);
461}
462
463fn __fixunsdfei(r: [*]u8, bits: usize, a: compiler_rt.f64.Abi) callconv(.c) void {
464 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
465 return unsigned_intFromFloat_f64(r[0..byte_size], compiler_rt.f64.fromAbi(a));
466}
467pub fn unsigned_intFromFloat_f64(result: []u8, a: f64) void {
468 bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a);
469}
470
471fn __fixunsxfsi(a: compiler_rt.f80.Abi) callconv(.c) u32 {
472 return u32_intFromFloat_f80(compiler_rt.f80.fromAbi(a));
473}
474pub fn u32_intFromFloat_f80(a: f80) u32 {
475 return intFromFloat(u32, a);
476}
477
478fn __fixunsxfdi(a: compiler_rt.f80.Abi) callconv(.c) u64 {
479 return u64_intFromFloat_f80(compiler_rt.f80.fromAbi(a));
480}
481pub fn u64_intFromFloat_f80(a: f80) u64 {
482 return intFromFloat(u64, a);
483}
484
485fn __fixunsxfti(a: compiler_rt.f80.Abi) callconv(.c) u128 {
486 return u128_intFromFloat_f80(compiler_rt.f80.fromAbi(a));
487}
488pub fn u128_intFromFloat_f80(a: f80) u128 {
489 return intFromFloat(u128, a);
490}
491
492fn __fixunsxfei(r: [*]u8, bits: usize, a: compiler_rt.f80.Abi) callconv(.c) void {
493 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
494 return unsigned_intFromFloat_f80(r[0..byte_size], compiler_rt.f80.fromAbi(a));
495}
496pub fn unsigned_intFromFloat_f80(result: []u8, a: f80) void {
497 bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a);
498}
499
500fn __fixunstfsi(a: compiler_rt.f128.Abi) callconv(.c) u32 {
501 return u32_intFromFloat_f128(compiler_rt.f128.fromAbi(a));
502}
503fn _Qp_qtoui(a: *const f128) callconv(.c) u32 {
504 return u32_intFromFloat_f128(a.*);
505}
506pub fn u32_intFromFloat_f128(a: f128) u32 {
507 return intFromFloat(u32, a);
508}
509
510fn __fixunstfdi(a: compiler_rt.f128.Abi) callconv(.c) u64 {
511 return u64_intFromFloat_f128(compiler_rt.f128.fromAbi(a));
512}
513fn _Qp_qtoux(a: *const f128) callconv(.c) u64 {
514 return u64_intFromFloat_f128(a.*);
515}
516pub fn u64_intFromFloat_f128(a: f128) u64 {
517 return intFromFloat(u64, a);
518}
519
520fn __fixunstfti(a: compiler_rt.f128.Abi) callconv(.c) u128 {
521 return u128_intFromFloat_f128(compiler_rt.f128.fromAbi(a));
522}
523pub fn u128_intFromFloat_f128(a: f128) u128 {
524 return intFromFloat(u128, a);
525}
526
527fn __fixunstfei(r: [*]u8, bits: usize, a: compiler_rt.f128.Abi) callconv(.c) void {
528 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
529 return unsigned_intFromFloat_f128(r[0..byte_size], compiler_rt.f128.fromAbi(a));
530}
531pub fn unsigned_intFromFloat_f128(result: []u8, a: f128) void {
532 bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a);
533}
534
535inline fn intFromFloat(comptime I: type, a: anytype) I {
32536 const F = @TypeOf(a);
33537 const float_bits = @typeInfo(F).float.bits;
34538 const int_bits = @typeInfo(I).int.bits;
......@@ -76,13 +580,14 @@ pub inline fn intFromFloat(comptime I: type, a: anytype) I {
76580 return result;
77581}
78582
79pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, result: []u32, a: anytype) void {
583inline fn bigIntFromFloat(comptime signedness: std.lang.Signedness, result: []u32, a: anytype) void {
584 const endian = builtin.cpu.arch.endian();
80585 switch (result.len) {
81586 0 => return,
82587 inline 1...4 => |limbs_len| {
83588 const I = @Int(signedness, 32 * limbs_len);
84589 const low_to_high: [limbs_len]u32 = @bitCast(@as(I, @intFromFloat(a)));
85 result[0..limbs_len].* = switch (@import("builtin").cpu.arch.endian()) {
590 result[0..limbs_len].* = switch (endian) {
86591 .little => low_to_high,
87592 .big => switch (limbs_len) {
88593 1 => .{low_to_high[0]},
......@@ -111,7 +616,6 @@ pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, resul
111616 });
112617 switch (signedness) {
113618 .signed => {
114 const endian = @import("builtin").cpu.arch.endian();
115619 const exponent_limb = switch (endian) {
116620 .little => exponent / 32,
117621 .big => result.len - 1 - exponent / 32,
lib/compiler_rt/int_from_float_test.zig+913-897
......@@ -2,1023 +2,1039 @@ const std = @import("std");
22const testing = std.testing;
33const math = std.math;
44
5const __fixunshfti = @import("fixunshfti.zig").__fixunshfti;
6const __fixunsxfti = @import("fixunsxfti.zig").__fixunsxfti;
7
8// Conversion from f32
9const __fixsfsi = @import("fixsfsi.zig").__fixsfsi;
10const __fixunssfsi = @import("fixunssfsi.zig").__fixunssfsi;
11const __fixsfdi = @import("fixsfdi.zig").__fixsfdi;
12const __fixunssfdi = @import("fixunssfdi.zig").__fixunssfdi;
13const __fixsfti = @import("fixsfti.zig").__fixsfti;
14const __fixunssfti = @import("fixunssfti.zig").__fixunssfti;
15const __fixsfei = @import("fixsfei.zig").__fixsfei;
16const __fixunssfei = @import("fixunssfei.zig").__fixunssfei;
17
18// Conversion from f64
19const __fixdfsi = @import("fixdfsi.zig").__fixdfsi;
20const __fixunsdfsi = @import("fixunsdfsi.zig").__fixunsdfsi;
21const __fixdfdi = @import("fixdfdi.zig").__fixdfdi;
22const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi;
23const __fixdfti = @import("fixdfti.zig").__fixdfti;
24const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti;
25const __fixdfei = @import("fixdfei.zig").__fixdfei;
26const __fixunsdfei = @import("fixunsdfei.zig").__fixunsdfei;
27
28// Conversion from f128
29const __fixtfsi = @import("fixtfsi.zig").__fixtfsi;
30const __fixunstfsi = @import("fixunstfsi.zig").__fixunstfsi;
31const __fixtfdi = @import("fixtfdi.zig").__fixtfdi;
32const __fixunstfdi = @import("fixunstfdi.zig").__fixunstfdi;
33const __fixtfti = @import("fixtfti.zig").__fixtfti;
34const __fixunstfti = @import("fixunstfti.zig").__fixunstfti;
35
36fn test__fixsfsi(a: f32, expected: i32) !void {
37 const x = __fixsfsi(a);
5const impl = @import("int_from_float.zig");
6
7const i32_intFromFloat_f16 = impl.i32_intFromFloat_f16;
8const u32_intFromFloat_f16 = impl.u32_intFromFloat_f16;
9const i64_intFromFloat_f16 = impl.i64_intFromFloat_f16;
10const u64_intFromFloat_f16 = impl.u64_intFromFloat_f16;
11const i128_intFromFloat_f16 = impl.i128_intFromFloat_f16;
12const u128_intFromFloat_f16 = impl.u128_intFromFloat_f16;
13const signed_intFromFloat_f16 = impl.signed_intFromFloat_f16;
14const unsigned_intFromFloat_f16 = impl.unsigned_intFromFloat_f16;
15
16const i32_intFromFloat_f32 = impl.i32_intFromFloat_f32;
17const u32_intFromFloat_f32 = impl.u32_intFromFloat_f32;
18const i64_intFromFloat_f32 = impl.i64_intFromFloat_f32;
19const u64_intFromFloat_f32 = impl.u64_intFromFloat_f32;
20const i128_intFromFloat_f32 = impl.i128_intFromFloat_f32;
21const u128_intFromFloat_f32 = impl.u128_intFromFloat_f32;
22const signed_intFromFloat_f32 = impl.signed_intFromFloat_f32;
23const unsigned_intFromFloat_f32 = impl.unsigned_intFromFloat_f32;
24
25const i32_intFromFloat_f64 = impl.i32_intFromFloat_f64;
26const u32_intFromFloat_f64 = impl.u32_intFromFloat_f64;
27const i64_intFromFloat_f64 = impl.i64_intFromFloat_f64;
28const u64_intFromFloat_f64 = impl.u64_intFromFloat_f64;
29const i128_intFromFloat_f64 = impl.i128_intFromFloat_f64;
30const u128_intFromFloat_f64 = impl.u128_intFromFloat_f64;
31const signed_intFromFloat_f64 = impl.signed_intFromFloat_f64;
32const unsigned_intFromFloat_f64 = impl.unsigned_intFromFloat_f64;
33
34const i32_intFromFloat_f80 = impl.i32_intFromFloat_f80;
35const u32_intFromFloat_f80 = impl.u32_intFromFloat_f80;
36const i64_intFromFloat_f80 = impl.i64_intFromFloat_f80;
37const u64_intFromFloat_f80 = impl.u64_intFromFloat_f80;
38const i128_intFromFloat_f80 = impl.i128_intFromFloat_f80;
39const u128_intFromFloat_f80 = impl.u128_intFromFloat_f80;
40const signed_intFromFloat_f80 = impl.signed_intFromFloat_f80;
41const unsigned_intFromFloat_f80 = impl.unsigned_intFromFloat_f80;
42
43const i32_intFromFloat_f128 = impl.i32_intFromFloat_f128;
44const u32_intFromFloat_f128 = impl.u32_intFromFloat_f128;
45const i64_intFromFloat_f128 = impl.i64_intFromFloat_f128;
46const u64_intFromFloat_f128 = impl.u64_intFromFloat_f128;
47const i128_intFromFloat_f128 = impl.i128_intFromFloat_f128;
48const u128_intFromFloat_f128 = impl.u128_intFromFloat_f128;
49const signed_intFromFloat_f128 = impl.signed_intFromFloat_f128;
50const unsigned_intFromFloat_f128 = impl.unsigned_intFromFloat_f128;
51
52fn test_i32_intFromFloat_f32(a: f32, expected: i32) !void {
53 const x = i32_intFromFloat_f32(a);
3854 try testing.expect(x == expected);
3955}
4056
41fn test__fixunssfsi(a: f32, expected: u32) !void {
42 const x = __fixunssfsi(a);
57fn test_u32_intFromFloat_f32(a: f32, expected: u32) !void {
58 const x = u32_intFromFloat_f32(a);
4359 try testing.expect(x == expected);
4460}
4561
46test "fixsfsi" {
47 try test__fixsfsi(-math.floatMax(f32), math.minInt(i32));
48
49 try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
50 try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
51
52 try test__fixsfsi(-0x1.0000000000000p+127, -0x80000000);
53 try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
54 try test__fixsfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
55
56 try test__fixsfsi(-0x1.0000000000001p+63, -0x80000000);
57 try test__fixsfsi(-0x1.0000000000000p+63, -0x80000000);
58 try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
59 try test__fixsfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
60
61 try test__fixsfsi(-0x1.FFFFFEp+62, -0x80000000);
62 try test__fixsfsi(-0x1.FFFFFCp+62, -0x80000000);
63
64 try test__fixsfsi(-0x1.000000p+31, -0x80000000);
65 try test__fixsfsi(-0x1.FFFFFFp+30, -0x80000000);
66 try test__fixsfsi(-0x1.FFFFFEp+30, -0x7FFFFF80);
67 try test__fixsfsi(-0x1.FFFFFCp+30, -0x7FFFFF00);
68
69 try test__fixsfsi(-2.01, -2);
70 try test__fixsfsi(-2.0, -2);
71 try test__fixsfsi(-1.99, -1);
72 try test__fixsfsi(-1.0, -1);
73 try test__fixsfsi(-0.99, 0);
74 try test__fixsfsi(-0.5, 0);
75
76 try test__fixsfsi(-math.floatMin(f32), 0);
77 try test__fixsfsi(0.0, 0);
78 try test__fixsfsi(math.floatMin(f32), 0);
79 try test__fixsfsi(0.5, 0);
80 try test__fixsfsi(0.99, 0);
81 try test__fixsfsi(1.0, 1);
82 try test__fixsfsi(1.5, 1);
83 try test__fixsfsi(1.99, 1);
84 try test__fixsfsi(2.0, 2);
85 try test__fixsfsi(2.01, 2);
86
87 try test__fixsfsi(0x1.FFFFFCp+30, 0x7FFFFF00);
88 try test__fixsfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
89 try test__fixsfsi(0x1.FFFFFFp+30, 0x7FFFFFFF);
90 try test__fixsfsi(0x1.000000p+31, 0x7FFFFFFF);
91
92 try test__fixsfsi(0x1.FFFFFCp+62, 0x7FFFFFFF);
93 try test__fixsfsi(0x1.FFFFFEp+62, 0x7FFFFFFF);
94
95 try test__fixsfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
96 try test__fixsfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
97 try test__fixsfsi(0x1.0000000000000p+63, 0x7FFFFFFF);
98 try test__fixsfsi(0x1.0000000000001p+63, 0x7FFFFFFF);
99
100 try test__fixsfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
101 try test__fixsfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
102 try test__fixsfsi(0x1.0000000000000p+127, 0x7FFFFFFF);
103
104 try test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
105 try test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
106
107 try test__fixsfsi(math.floatMax(f32), math.maxInt(i32));
62test i32_intFromFloat_f32 {
63 try test_i32_intFromFloat_f32(-math.floatMax(f32), math.minInt(i32));
64
65 try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
66 try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
67
68 try test_i32_intFromFloat_f32(-0x1.0000000000000p+127, -0x80000000);
69 try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
70 try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
71
72 try test_i32_intFromFloat_f32(-0x1.0000000000001p+63, -0x80000000);
73 try test_i32_intFromFloat_f32(-0x1.0000000000000p+63, -0x80000000);
74 try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
75 try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
76
77 try test_i32_intFromFloat_f32(-0x1.FFFFFEp+62, -0x80000000);
78 try test_i32_intFromFloat_f32(-0x1.FFFFFCp+62, -0x80000000);
79
80 try test_i32_intFromFloat_f32(-0x1.000000p+31, -0x80000000);
81 try test_i32_intFromFloat_f32(-0x1.FFFFFFp+30, -0x80000000);
82 try test_i32_intFromFloat_f32(-0x1.FFFFFEp+30, -0x7FFFFF80);
83 try test_i32_intFromFloat_f32(-0x1.FFFFFCp+30, -0x7FFFFF00);
84
85 try test_i32_intFromFloat_f32(-2.01, -2);
86 try test_i32_intFromFloat_f32(-2.0, -2);
87 try test_i32_intFromFloat_f32(-1.99, -1);
88 try test_i32_intFromFloat_f32(-1.0, -1);
89 try test_i32_intFromFloat_f32(-0.99, 0);
90 try test_i32_intFromFloat_f32(-0.5, 0);
91
92 try test_i32_intFromFloat_f32(-math.floatMin(f32), 0);
93 try test_i32_intFromFloat_f32(0.0, 0);
94 try test_i32_intFromFloat_f32(math.floatMin(f32), 0);
95 try test_i32_intFromFloat_f32(0.5, 0);
96 try test_i32_intFromFloat_f32(0.99, 0);
97 try test_i32_intFromFloat_f32(1.0, 1);
98 try test_i32_intFromFloat_f32(1.5, 1);
99 try test_i32_intFromFloat_f32(1.99, 1);
100 try test_i32_intFromFloat_f32(2.0, 2);
101 try test_i32_intFromFloat_f32(2.01, 2);
102
103 try test_i32_intFromFloat_f32(0x1.FFFFFCp+30, 0x7FFFFF00);
104 try test_i32_intFromFloat_f32(0x1.FFFFFEp+30, 0x7FFFFF80);
105 try test_i32_intFromFloat_f32(0x1.FFFFFFp+30, 0x7FFFFFFF);
106 try test_i32_intFromFloat_f32(0x1.000000p+31, 0x7FFFFFFF);
107
108 try test_i32_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFFFF);
109 try test_i32_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFFFF);
110
111 try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
112 try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
113 try test_i32_intFromFloat_f32(0x1.0000000000000p+63, 0x7FFFFFFF);
114 try test_i32_intFromFloat_f32(0x1.0000000000001p+63, 0x7FFFFFFF);
115
116 try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
117 try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
118 try test_i32_intFromFloat_f32(0x1.0000000000000p+127, 0x7FFFFFFF);
119
120 try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
121 try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
122
123 try test_i32_intFromFloat_f32(math.floatMax(f32), math.maxInt(i32));
108124}
109125
110test "fixunssfsi" {
111 try test__fixunssfsi(0.0, 0);
112
113 try test__fixunssfsi(0.5, 0);
114 try test__fixunssfsi(0.99, 0);
115 try test__fixunssfsi(1.0, 1);
116 try test__fixunssfsi(1.5, 1);
117 try test__fixunssfsi(1.99, 1);
118 try test__fixunssfsi(2.0, 2);
119 try test__fixunssfsi(2.01, 2);
120 try test__fixunssfsi(-0.5, 0);
121 try test__fixunssfsi(-0.99, 0);
122
123 try test__fixunssfsi(-1.0, 0);
124 try test__fixunssfsi(-1.5, 0);
125 try test__fixunssfsi(-1.99, 0);
126 try test__fixunssfsi(-2.0, 0);
127 try test__fixunssfsi(-2.01, 0);
128
129 try test__fixunssfsi(0x1.000000p+31, 0x80000000);
130 try test__fixunssfsi(0x1.000000p+32, 0xFFFFFFFF);
131 try test__fixunssfsi(0x1.FFFFFEp+31, 0xFFFFFF00);
132 try test__fixunssfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
133 try test__fixunssfsi(0x1.FFFFFCp+30, 0x7FFFFF00);
134
135 try test__fixunssfsi(-0x1.FFFFFEp+30, 0);
136 try test__fixunssfsi(-0x1.FFFFFCp+30, 0);
126test u32_intFromFloat_f32 {
127 try test_u32_intFromFloat_f32(0.0, 0);
128
129 try test_u32_intFromFloat_f32(0.5, 0);
130 try test_u32_intFromFloat_f32(0.99, 0);
131 try test_u32_intFromFloat_f32(1.0, 1);
132 try test_u32_intFromFloat_f32(1.5, 1);
133 try test_u32_intFromFloat_f32(1.99, 1);
134 try test_u32_intFromFloat_f32(2.0, 2);
135 try test_u32_intFromFloat_f32(2.01, 2);
136 try test_u32_intFromFloat_f32(-0.5, 0);
137 try test_u32_intFromFloat_f32(-0.99, 0);
138
139 try test_u32_intFromFloat_f32(-1.0, 0);
140 try test_u32_intFromFloat_f32(-1.5, 0);
141 try test_u32_intFromFloat_f32(-1.99, 0);
142 try test_u32_intFromFloat_f32(-2.0, 0);
143 try test_u32_intFromFloat_f32(-2.01, 0);
144
145 try test_u32_intFromFloat_f32(0x1.000000p+31, 0x80000000);
146 try test_u32_intFromFloat_f32(0x1.000000p+32, 0xFFFFFFFF);
147 try test_u32_intFromFloat_f32(0x1.FFFFFEp+31, 0xFFFFFF00);
148 try test_u32_intFromFloat_f32(0x1.FFFFFEp+30, 0x7FFFFF80);
149 try test_u32_intFromFloat_f32(0x1.FFFFFCp+30, 0x7FFFFF00);
150
151 try test_u32_intFromFloat_f32(-0x1.FFFFFEp+30, 0);
152 try test_u32_intFromFloat_f32(-0x1.FFFFFCp+30, 0);
137153}
138154
139fn test__fixsfdi(a: f32, expected: i64) !void {
140 const x = __fixsfdi(a);
155fn test_i64_intFromFloat_f32(a: f32, expected: i64) !void {
156 const x = i64_intFromFloat_f32(a);
141157 try testing.expect(x == expected);
142158}
143159
144fn test__fixunssfdi(a: f32, expected: u64) !void {
145 const x = __fixunssfdi(a);
160fn test_u64_intFromFloat_f32(a: f32, expected: u64) !void {
161 const x = u64_intFromFloat_f32(a);
146162 try testing.expect(x == expected);
147163}
148164
149test "fixsfdi" {
150 try test__fixsfdi(-math.floatMax(f32), math.minInt(i64));
151
152 try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
153 try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
154
155 try test__fixsfdi(-0x1.0000000000000p+127, -0x8000000000000000);
156 try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
157 try test__fixsfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
158
159 try test__fixsfdi(-0x1.0000000000001p+63, -0x8000000000000000);
160 try test__fixsfdi(-0x1.0000000000000p+63, -0x8000000000000000);
161 try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000);
162 try test__fixsfdi(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000);
163
164 try test__fixsfdi(-0x1.FFFFFFp+62, -0x8000000000000000);
165 try test__fixsfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000);
166 try test__fixsfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000);
167
168 try test__fixsfdi(-2.01, -2);
169 try test__fixsfdi(-2.0, -2);
170 try test__fixsfdi(-1.99, -1);
171 try test__fixsfdi(-1.0, -1);
172 try test__fixsfdi(-0.99, 0);
173 try test__fixsfdi(-0.5, 0);
174 try test__fixsfdi(-math.floatMin(f32), 0);
175 try test__fixsfdi(0.0, 0);
176 try test__fixsfdi(math.floatMin(f32), 0);
177 try test__fixsfdi(0.5, 0);
178 try test__fixsfdi(0.99, 0);
179 try test__fixsfdi(1.0, 1);
180 try test__fixsfdi(1.5, 1);
181 try test__fixsfdi(1.99, 1);
182 try test__fixsfdi(2.0, 2);
183 try test__fixsfdi(2.01, 2);
184
185 try test__fixsfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
186 try test__fixsfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
187 try test__fixsfdi(0x1.FFFFFFp+62, 0x7FFFFFFFFFFFFFFF);
188
189 try test__fixsfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFFFFF);
190 try test__fixsfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFFFF);
191 try test__fixsfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
192 try test__fixsfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
193
194 try test__fixsfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
195 try test__fixsfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
196 try test__fixsfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
197
198 try test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
199 try test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
200
201 try test__fixsfdi(math.floatMax(f32), math.maxInt(i64));
165test i64_intFromFloat_f32 {
166 try test_i64_intFromFloat_f32(-math.floatMax(f32), math.minInt(i64));
167
168 try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
169 try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
170
171 try test_i64_intFromFloat_f32(-0x1.0000000000000p+127, -0x8000000000000000);
172 try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
173 try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
174
175 try test_i64_intFromFloat_f32(-0x1.0000000000001p+63, -0x8000000000000000);
176 try test_i64_intFromFloat_f32(-0x1.0000000000000p+63, -0x8000000000000000);
177 try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000);
178 try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000);
179
180 try test_i64_intFromFloat_f32(-0x1.FFFFFFp+62, -0x8000000000000000);
181 try test_i64_intFromFloat_f32(-0x1.FFFFFEp+62, -0x7fffff8000000000);
182 try test_i64_intFromFloat_f32(-0x1.FFFFFCp+62, -0x7fffff0000000000);
183
184 try test_i64_intFromFloat_f32(-2.01, -2);
185 try test_i64_intFromFloat_f32(-2.0, -2);
186 try test_i64_intFromFloat_f32(-1.99, -1);
187 try test_i64_intFromFloat_f32(-1.0, -1);
188 try test_i64_intFromFloat_f32(-0.99, 0);
189 try test_i64_intFromFloat_f32(-0.5, 0);
190 try test_i64_intFromFloat_f32(-math.floatMin(f32), 0);
191 try test_i64_intFromFloat_f32(0.0, 0);
192 try test_i64_intFromFloat_f32(math.floatMin(f32), 0);
193 try test_i64_intFromFloat_f32(0.5, 0);
194 try test_i64_intFromFloat_f32(0.99, 0);
195 try test_i64_intFromFloat_f32(1.0, 1);
196 try test_i64_intFromFloat_f32(1.5, 1);
197 try test_i64_intFromFloat_f32(1.99, 1);
198 try test_i64_intFromFloat_f32(2.0, 2);
199 try test_i64_intFromFloat_f32(2.01, 2);
200
201 try test_i64_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
202 try test_i64_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
203 try test_i64_intFromFloat_f32(0x1.FFFFFFp+62, 0x7FFFFFFFFFFFFFFF);
204
205 try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFFFFF);
206 try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFFFF);
207 try test_i64_intFromFloat_f32(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
208 try test_i64_intFromFloat_f32(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
209
210 try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
211 try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
212 try test_i64_intFromFloat_f32(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
213
214 try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
215 try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
216
217 try test_i64_intFromFloat_f32(math.floatMax(f32), math.maxInt(i64));
202218}
203219
204test "fixunssfdi" {
205 try test__fixunssfdi(0.0, 0);
206
207 try test__fixunssfdi(0.5, 0);
208 try test__fixunssfdi(0.99, 0);
209 try test__fixunssfdi(1.0, 1);
210 try test__fixunssfdi(1.5, 1);
211 try test__fixunssfdi(1.99, 1);
212 try test__fixunssfdi(2.0, 2);
213 try test__fixunssfdi(2.01, 2);
214 try test__fixunssfdi(-0.5, 0);
215 try test__fixunssfdi(-0.99, 0);
216
217 try test__fixunssfdi(-1.0, 0);
218 try test__fixunssfdi(-1.5, 0);
219 try test__fixunssfdi(-1.99, 0);
220 try test__fixunssfdi(-2.0, 0);
221 try test__fixunssfdi(-2.01, 0);
222
223 try test__fixunssfdi(0x1.FFFFFEp+63, 0xFFFFFF0000000000);
224 try test__fixunssfdi(0x1.000000p+63, 0x8000000000000000);
225 try test__fixunssfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
226 try test__fixunssfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
227
228 try test__fixunssfdi(-0x1.FFFFFEp+62, 0x0000000000000000);
229 try test__fixunssfdi(-0x1.FFFFFCp+62, 0x0000000000000000);
220test u64_intFromFloat_f32 {
221 try test_u64_intFromFloat_f32(0.0, 0);
222
223 try test_u64_intFromFloat_f32(0.5, 0);
224 try test_u64_intFromFloat_f32(0.99, 0);
225 try test_u64_intFromFloat_f32(1.0, 1);
226 try test_u64_intFromFloat_f32(1.5, 1);
227 try test_u64_intFromFloat_f32(1.99, 1);
228 try test_u64_intFromFloat_f32(2.0, 2);
229 try test_u64_intFromFloat_f32(2.01, 2);
230 try test_u64_intFromFloat_f32(-0.5, 0);
231 try test_u64_intFromFloat_f32(-0.99, 0);
232
233 try test_u64_intFromFloat_f32(-1.0, 0);
234 try test_u64_intFromFloat_f32(-1.5, 0);
235 try test_u64_intFromFloat_f32(-1.99, 0);
236 try test_u64_intFromFloat_f32(-2.0, 0);
237 try test_u64_intFromFloat_f32(-2.01, 0);
238
239 try test_u64_intFromFloat_f32(0x1.FFFFFEp+63, 0xFFFFFF0000000000);
240 try test_u64_intFromFloat_f32(0x1.000000p+63, 0x8000000000000000);
241 try test_u64_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
242 try test_u64_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
243
244 try test_u64_intFromFloat_f32(-0x1.FFFFFEp+62, 0x0000000000000000);
245 try test_u64_intFromFloat_f32(-0x1.FFFFFCp+62, 0x0000000000000000);
230246}
231247
232fn test__fixsfti(a: f32, expected: i128) !void {
233 const x = __fixsfti(a);
248fn test_i128_intFromFloat_f32(a: f32, expected: i128) !void {
249 const x = i128_intFromFloat_f32(a);
234250 try testing.expect(x == expected);
235251}
236252
237fn test__fixunssfti(a: f32, expected: u128) !void {
238 const x = __fixunssfti(a);
253fn test_u128_intFromFloat_f32(a: f32, expected: u128) !void {
254 const x = u128_intFromFloat_f32(a);
239255 try testing.expect(x == expected);
240256}
241257
242test "fixsfti" {
243 try test__fixsfti(-math.floatMax(f32), math.minInt(i128));
244
245 try test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
246 try test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
247
248 try test__fixsfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
249 try test__fixsfti(-0x1.FFFFFFFFFFFFFp+126, -0x80000000000000000000000000000000);
250 try test__fixsfti(-0x1.FFFFFFFFFFFFEp+126, -0x80000000000000000000000000000000);
251 try test__fixsfti(-0x1.FFFFFF0000000p+126, -0x80000000000000000000000000000000);
252 try test__fixsfti(-0x1.FFFFFE0000000p+126, -0x7FFFFF80000000000000000000000000);
253 try test__fixsfti(-0x1.FFFFFC0000000p+126, -0x7FFFFF00000000000000000000000000);
254
255 try test__fixsfti(-0x1.0000000000001p+63, -0x8000000000000000);
256 try test__fixsfti(-0x1.0000000000000p+63, -0x8000000000000000);
257 try test__fixsfti(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000);
258 try test__fixsfti(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000);
259
260 try test__fixsfti(-0x1.FFFFFFp+62, -0x8000000000000000);
261 try test__fixsfti(-0x1.FFFFFEp+62, -0x7fffff8000000000);
262 try test__fixsfti(-0x1.FFFFFCp+62, -0x7fffff0000000000);
263
264 try test__fixsfti(-0x1.000000p+31, -0x80000000);
265 try test__fixsfti(-0x1.FFFFFFp+30, -0x80000000);
266 try test__fixsfti(-0x1.FFFFFEp+30, -0x7FFFFF80);
267 try test__fixsfti(-0x1.FFFFFCp+30, -0x7FFFFF00);
268
269 try test__fixsfti(-2.01, -2);
270 try test__fixsfti(-2.0, -2);
271 try test__fixsfti(-1.99, -1);
272 try test__fixsfti(-1.0, -1);
273 try test__fixsfti(-0.99, 0);
274 try test__fixsfti(-0.5, 0);
275 try test__fixsfti(-math.floatMin(f32), 0);
276 try test__fixsfti(0.0, 0);
277 try test__fixsfti(math.floatMin(f32), 0);
278 try test__fixsfti(0.5, 0);
279 try test__fixsfti(0.99, 0);
280 try test__fixsfti(1.0, 1);
281 try test__fixsfti(1.5, 1);
282 try test__fixsfti(1.99, 1);
283 try test__fixsfti(2.0, 2);
284 try test__fixsfti(2.01, 2);
285
286 try test__fixsfti(0x1.FFFFFCp+30, 0x7FFFFF00);
287 try test__fixsfti(0x1.FFFFFEp+30, 0x7FFFFF80);
288 try test__fixsfti(0x1.FFFFFFp+30, 0x80000000);
289 try test__fixsfti(0x1.000000p+31, 0x80000000);
290
291 try test__fixsfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
292 try test__fixsfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
293 try test__fixsfti(0x1.FFFFFFp+62, 0x8000000000000000);
294
295 try test__fixsfti(0x1.FFFFFFFFFFFFEp+62, 0x8000000000000000);
296 try test__fixsfti(0x1.FFFFFFFFFFFFFp+62, 0x8000000000000000);
297 try test__fixsfti(0x1.0000000000000p+63, 0x8000000000000000);
298 try test__fixsfti(0x1.0000000000001p+63, 0x8000000000000000);
299
300 try test__fixsfti(0x1.FFFFFC0000000p+126, 0x7FFFFF00000000000000000000000000);
301 try test__fixsfti(0x1.FFFFFE0000000p+126, 0x7FFFFF80000000000000000000000000);
302 try test__fixsfti(0x1.FFFFFF0000000p+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
303 try test__fixsfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
304 try test__fixsfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
305 try test__fixsfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
306
307 try test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
308 try test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
309
310 try test__fixsfti(math.floatMax(f32), math.maxInt(i128));
258test i128_intFromFloat_f32 {
259 try test_i128_intFromFloat_f32(-math.floatMax(f32), math.minInt(i128));
260
261 try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
262 try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
263
264 try test_i128_intFromFloat_f32(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
265 try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+126, -0x80000000000000000000000000000000);
266 try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+126, -0x80000000000000000000000000000000);
267 try test_i128_intFromFloat_f32(-0x1.FFFFFF0000000p+126, -0x80000000000000000000000000000000);
268 try test_i128_intFromFloat_f32(-0x1.FFFFFE0000000p+126, -0x7FFFFF80000000000000000000000000);
269 try test_i128_intFromFloat_f32(-0x1.FFFFFC0000000p+126, -0x7FFFFF00000000000000000000000000);
270
271 try test_i128_intFromFloat_f32(-0x1.0000000000001p+63, -0x8000000000000000);
272 try test_i128_intFromFloat_f32(-0x1.0000000000000p+63, -0x8000000000000000);
273 try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000);
274 try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000);
275
276 try test_i128_intFromFloat_f32(-0x1.FFFFFFp+62, -0x8000000000000000);
277 try test_i128_intFromFloat_f32(-0x1.FFFFFEp+62, -0x7fffff8000000000);
278 try test_i128_intFromFloat_f32(-0x1.FFFFFCp+62, -0x7fffff0000000000);
279
280 try test_i128_intFromFloat_f32(-0x1.000000p+31, -0x80000000);
281 try test_i128_intFromFloat_f32(-0x1.FFFFFFp+30, -0x80000000);
282 try test_i128_intFromFloat_f32(-0x1.FFFFFEp+30, -0x7FFFFF80);
283 try test_i128_intFromFloat_f32(-0x1.FFFFFCp+30, -0x7FFFFF00);
284
285 try test_i128_intFromFloat_f32(-2.01, -2);
286 try test_i128_intFromFloat_f32(-2.0, -2);
287 try test_i128_intFromFloat_f32(-1.99, -1);
288 try test_i128_intFromFloat_f32(-1.0, -1);
289 try test_i128_intFromFloat_f32(-0.99, 0);
290 try test_i128_intFromFloat_f32(-0.5, 0);
291 try test_i128_intFromFloat_f32(-math.floatMin(f32), 0);
292 try test_i128_intFromFloat_f32(0.0, 0);
293 try test_i128_intFromFloat_f32(math.floatMin(f32), 0);
294 try test_i128_intFromFloat_f32(0.5, 0);
295 try test_i128_intFromFloat_f32(0.99, 0);
296 try test_i128_intFromFloat_f32(1.0, 1);
297 try test_i128_intFromFloat_f32(1.5, 1);
298 try test_i128_intFromFloat_f32(1.99, 1);
299 try test_i128_intFromFloat_f32(2.0, 2);
300 try test_i128_intFromFloat_f32(2.01, 2);
301
302 try test_i128_intFromFloat_f32(0x1.FFFFFCp+30, 0x7FFFFF00);
303 try test_i128_intFromFloat_f32(0x1.FFFFFEp+30, 0x7FFFFF80);
304 try test_i128_intFromFloat_f32(0x1.FFFFFFp+30, 0x80000000);
305 try test_i128_intFromFloat_f32(0x1.000000p+31, 0x80000000);
306
307 try test_i128_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
308 try test_i128_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
309 try test_i128_intFromFloat_f32(0x1.FFFFFFp+62, 0x8000000000000000);
310
311 try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+62, 0x8000000000000000);
312 try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+62, 0x8000000000000000);
313 try test_i128_intFromFloat_f32(0x1.0000000000000p+63, 0x8000000000000000);
314 try test_i128_intFromFloat_f32(0x1.0000000000001p+63, 0x8000000000000000);
315
316 try test_i128_intFromFloat_f32(0x1.FFFFFC0000000p+126, 0x7FFFFF00000000000000000000000000);
317 try test_i128_intFromFloat_f32(0x1.FFFFFE0000000p+126, 0x7FFFFF80000000000000000000000000);
318 try test_i128_intFromFloat_f32(0x1.FFFFFF0000000p+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
319 try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
320 try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
321 try test_i128_intFromFloat_f32(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
322
323 try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
324 try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
325
326 try test_i128_intFromFloat_f32(math.floatMax(f32), math.maxInt(i128));
311327}
312328
313test "fixunssfti" {
314 try test__fixunssfti(0.0, 0);
315
316 try test__fixunssfti(0.5, 0);
317 try test__fixunssfti(0.99, 0);
318 try test__fixunssfti(1.0, 1);
319 try test__fixunssfti(1.5, 1);
320 try test__fixunssfti(1.99, 1);
321 try test__fixunssfti(2.0, 2);
322 try test__fixunssfti(2.01, 2);
323 try test__fixunssfti(-0.5, 0);
324 try test__fixunssfti(-0.99, 0);
325
326 try test__fixunssfti(-1.0, 0);
327 try test__fixunssfti(-1.5, 0);
328 try test__fixunssfti(-1.99, 0);
329 try test__fixunssfti(-2.0, 0);
330 try test__fixunssfti(-2.01, 0);
331
332 try test__fixunssfti(0x1.FFFFFEp+63, 0xFFFFFF0000000000);
333 try test__fixunssfti(0x1.000000p+63, 0x8000000000000000);
334 try test__fixunssfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
335 try test__fixunssfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
336 try test__fixunssfti(0x1.FFFFFEp+127, 0xFFFFFF00000000000000000000000000);
337 try test__fixunssfti(0x1.000000p+127, 0x80000000000000000000000000000000);
338 try test__fixunssfti(0x1.FFFFFEp+126, 0x7FFFFF80000000000000000000000000);
339 try test__fixunssfti(0x1.FFFFFCp+126, 0x7FFFFF00000000000000000000000000);
340
341 try test__fixunssfti(-0x1.FFFFFEp+62, 0x0000000000000000);
342 try test__fixunssfti(-0x1.FFFFFCp+62, 0x0000000000000000);
343 try test__fixunssfti(-0x1.FFFFFEp+126, 0x0000000000000000);
344 try test__fixunssfti(-0x1.FFFFFCp+126, 0x0000000000000000);
345 try test__fixunssfti(math.floatMax(f32), 0xffffff00000000000000000000000000);
346 try test__fixunssfti(math.inf(f32), math.maxInt(u128));
329test u128_intFromFloat_f32 {
330 try test_u128_intFromFloat_f32(0.0, 0);
331
332 try test_u128_intFromFloat_f32(0.5, 0);
333 try test_u128_intFromFloat_f32(0.99, 0);
334 try test_u128_intFromFloat_f32(1.0, 1);
335 try test_u128_intFromFloat_f32(1.5, 1);
336 try test_u128_intFromFloat_f32(1.99, 1);
337 try test_u128_intFromFloat_f32(2.0, 2);
338 try test_u128_intFromFloat_f32(2.01, 2);
339 try test_u128_intFromFloat_f32(-0.5, 0);
340 try test_u128_intFromFloat_f32(-0.99, 0);
341
342 try test_u128_intFromFloat_f32(-1.0, 0);
343 try test_u128_intFromFloat_f32(-1.5, 0);
344 try test_u128_intFromFloat_f32(-1.99, 0);
345 try test_u128_intFromFloat_f32(-2.0, 0);
346 try test_u128_intFromFloat_f32(-2.01, 0);
347
348 try test_u128_intFromFloat_f32(0x1.FFFFFEp+63, 0xFFFFFF0000000000);
349 try test_u128_intFromFloat_f32(0x1.000000p+63, 0x8000000000000000);
350 try test_u128_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
351 try test_u128_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
352 try test_u128_intFromFloat_f32(0x1.FFFFFEp+127, 0xFFFFFF00000000000000000000000000);
353 try test_u128_intFromFloat_f32(0x1.000000p+127, 0x80000000000000000000000000000000);
354 try test_u128_intFromFloat_f32(0x1.FFFFFEp+126, 0x7FFFFF80000000000000000000000000);
355 try test_u128_intFromFloat_f32(0x1.FFFFFCp+126, 0x7FFFFF00000000000000000000000000);
356
357 try test_u128_intFromFloat_f32(-0x1.FFFFFEp+62, 0x0000000000000000);
358 try test_u128_intFromFloat_f32(-0x1.FFFFFCp+62, 0x0000000000000000);
359 try test_u128_intFromFloat_f32(-0x1.FFFFFEp+126, 0x0000000000000000);
360 try test_u128_intFromFloat_f32(-0x1.FFFFFCp+126, 0x0000000000000000);
361 try test_u128_intFromFloat_f32(math.floatMax(f32), 0xffffff00000000000000000000000000);
362 try test_u128_intFromFloat_f32(math.inf(f32), math.maxInt(u128));
347363}
348364
349fn test_fixsfei(comptime T: type, expected: T, a: f32) !void {
365fn test_intFromFloat_f32(comptime T: type, expected: T, a: f32) !void {
350366 const int = @typeInfo(T).int;
351367 var actual: T = undefined;
352368 _ = switch (int.signedness) {
353 .signed => __fixsfei,
354 .unsigned => __fixunssfei,
355 }(@ptrCast(&actual), int.bits, a);
369 .signed => signed_intFromFloat_f32,
370 .unsigned => unsigned_intFromFloat_f32,
371 }(@ptrCast(&actual), a);
356372 try testing.expect(expected == actual);
357373}
358374
359test "fixsfei" {
360 try test_fixsfei(i256, -1 << 127, -0x1p127);
361 try test_fixsfei(i256, -1 << 100, -0x1p100);
362 try test_fixsfei(i256, -1 << 50, -0x1p50);
363 try test_fixsfei(i256, -1 << 1, -0x1p1);
364 try test_fixsfei(i256, -1 << 0, -0x1p0);
365 try test_fixsfei(i256, 0, 0);
366 try test_fixsfei(i256, 1 << 0, 0x1p0);
367 try test_fixsfei(i256, 1 << 1, 0x1p1);
368 try test_fixsfei(i256, 1 << 50, 0x1p50);
369 try test_fixsfei(i256, 1 << 100, 0x1p100);
370 try test_fixsfei(i256, 1 << 127, 0x1p127);
375test signed_intFromFloat_f32 {
376 try test_intFromFloat_f32(i256, -1 << 127, -0x1p127);
377 try test_intFromFloat_f32(i256, -1 << 100, -0x1p100);
378 try test_intFromFloat_f32(i256, -1 << 50, -0x1p50);
379 try test_intFromFloat_f32(i256, -1 << 1, -0x1p1);
380 try test_intFromFloat_f32(i256, -1 << 0, -0x1p0);
381 try test_intFromFloat_f32(i256, 0, 0);
382 try test_intFromFloat_f32(i256, 1 << 0, 0x1p0);
383 try test_intFromFloat_f32(i256, 1 << 1, 0x1p1);
384 try test_intFromFloat_f32(i256, 1 << 50, 0x1p50);
385 try test_intFromFloat_f32(i256, 1 << 100, 0x1p100);
386 try test_intFromFloat_f32(i256, 1 << 127, 0x1p127);
371387}
372388
373test "fixunsfei" {
374 try test_fixsfei(u256, 0, 0);
375 try test_fixsfei(u256, 1 << 0, 0x1p0);
376 try test_fixsfei(u256, 1 << 1, 0x1p1);
377 try test_fixsfei(u256, 1 << 50, 0x1p50);
378 try test_fixsfei(u256, 1 << 100, 0x1p100);
379 try test_fixsfei(u256, 1 << 127, 0x1p127);
389test unsigned_intFromFloat_f32 {
390 try test_intFromFloat_f32(u256, 0, 0);
391 try test_intFromFloat_f32(u256, 1 << 0, 0x1p0);
392 try test_intFromFloat_f32(u256, 1 << 1, 0x1p1);
393 try test_intFromFloat_f32(u256, 1 << 50, 0x1p50);
394 try test_intFromFloat_f32(u256, 1 << 100, 0x1p100);
395 try test_intFromFloat_f32(u256, 1 << 127, 0x1p127);
380396}
381397
382fn test__fixdfsi(a: f64, expected: i32) !void {
383 const x = __fixdfsi(a);
398fn test_i32_intFromFloat_f64(a: f64, expected: i32) !void {
399 const x = i32_intFromFloat_f64(a);
384400 try testing.expect(x == expected);
385401}
386402
387fn test__fixunsdfsi(a: f64, expected: u32) !void {
388 const x = __fixunsdfsi(a);
403fn test_u32_intFromFloat_f64(a: f64, expected: u32) !void {
404 const x = u32_intFromFloat_f64(a);
389405 try testing.expect(x == expected);
390406}
391407
392test "fixdfsi" {
393 try test__fixdfsi(-math.floatMax(f64), math.minInt(i32));
394
395 try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
396 try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
397
398 try test__fixdfsi(-0x1.0000000000000p+127, -0x80000000);
399 try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
400 try test__fixdfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
401
402 try test__fixdfsi(-0x1.0000000000001p+63, -0x80000000);
403 try test__fixdfsi(-0x1.0000000000000p+63, -0x80000000);
404 try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
405 try test__fixdfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
406
407 try test__fixdfsi(-0x1.FFFFFEp+62, -0x80000000);
408 try test__fixdfsi(-0x1.FFFFFCp+62, -0x80000000);
409
410 try test__fixdfsi(-0x1.000000p+31, -0x80000000);
411 try test__fixdfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0);
412 try test__fixdfsi(-0x1.FFFFFEp+30, -0x7FFFFF80);
413
414 try test__fixdfsi(-2.01, -2);
415 try test__fixdfsi(-2.0, -2);
416 try test__fixdfsi(-1.99, -1);
417 try test__fixdfsi(-1.0, -1);
418 try test__fixdfsi(-0.99, 0);
419 try test__fixdfsi(-0.5, 0);
420 try test__fixdfsi(-math.floatMin(f64), 0);
421 try test__fixdfsi(0.0, 0);
422 try test__fixdfsi(math.floatMin(f64), 0);
423 try test__fixdfsi(0.5, 0);
424 try test__fixdfsi(0.99, 0);
425 try test__fixdfsi(1.0, 1);
426 try test__fixdfsi(1.5, 1);
427 try test__fixdfsi(1.99, 1);
428 try test__fixdfsi(2.0, 2);
429 try test__fixdfsi(2.01, 2);
430
431 try test__fixdfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
432 try test__fixdfsi(0x1.FFFFFFp+30, 0x7FFFFFC0);
433 try test__fixdfsi(0x1.000000p+31, 0x7FFFFFFF);
434
435 try test__fixdfsi(0x1.FFFFFCp+62, 0x7FFFFFFF);
436 try test__fixdfsi(0x1.FFFFFEp+62, 0x7FFFFFFF);
437
438 try test__fixdfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
439 try test__fixdfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
440 try test__fixdfsi(0x1.0000000000000p+63, 0x7FFFFFFF);
441 try test__fixdfsi(0x1.0000000000001p+63, 0x7FFFFFFF);
442
443 try test__fixdfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
444 try test__fixdfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
445 try test__fixdfsi(0x1.0000000000000p+127, 0x7FFFFFFF);
446
447 try test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
448 try test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
449
450 try test__fixdfsi(math.floatMax(f64), math.maxInt(i32));
408test i32_intFromFloat_f64 {
409 try test_i32_intFromFloat_f64(-math.floatMax(f64), math.minInt(i32));
410
411 try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
412 try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
413
414 try test_i32_intFromFloat_f64(-0x1.0000000000000p+127, -0x80000000);
415 try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
416 try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
417
418 try test_i32_intFromFloat_f64(-0x1.0000000000001p+63, -0x80000000);
419 try test_i32_intFromFloat_f64(-0x1.0000000000000p+63, -0x80000000);
420 try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
421 try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
422
423 try test_i32_intFromFloat_f64(-0x1.FFFFFEp+62, -0x80000000);
424 try test_i32_intFromFloat_f64(-0x1.FFFFFCp+62, -0x80000000);
425
426 try test_i32_intFromFloat_f64(-0x1.000000p+31, -0x80000000);
427 try test_i32_intFromFloat_f64(-0x1.FFFFFFp+30, -0x7FFFFFC0);
428 try test_i32_intFromFloat_f64(-0x1.FFFFFEp+30, -0x7FFFFF80);
429
430 try test_i32_intFromFloat_f64(-2.01, -2);
431 try test_i32_intFromFloat_f64(-2.0, -2);
432 try test_i32_intFromFloat_f64(-1.99, -1);
433 try test_i32_intFromFloat_f64(-1.0, -1);
434 try test_i32_intFromFloat_f64(-0.99, 0);
435 try test_i32_intFromFloat_f64(-0.5, 0);
436 try test_i32_intFromFloat_f64(-math.floatMin(f64), 0);
437 try test_i32_intFromFloat_f64(0.0, 0);
438 try test_i32_intFromFloat_f64(math.floatMin(f64), 0);
439 try test_i32_intFromFloat_f64(0.5, 0);
440 try test_i32_intFromFloat_f64(0.99, 0);
441 try test_i32_intFromFloat_f64(1.0, 1);
442 try test_i32_intFromFloat_f64(1.5, 1);
443 try test_i32_intFromFloat_f64(1.99, 1);
444 try test_i32_intFromFloat_f64(2.0, 2);
445 try test_i32_intFromFloat_f64(2.01, 2);
446
447 try test_i32_intFromFloat_f64(0x1.FFFFFEp+30, 0x7FFFFF80);
448 try test_i32_intFromFloat_f64(0x1.FFFFFFp+30, 0x7FFFFFC0);
449 try test_i32_intFromFloat_f64(0x1.000000p+31, 0x7FFFFFFF);
450
451 try test_i32_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFFFF);
452 try test_i32_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFFFF);
453
454 try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
455 try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
456 try test_i32_intFromFloat_f64(0x1.0000000000000p+63, 0x7FFFFFFF);
457 try test_i32_intFromFloat_f64(0x1.0000000000001p+63, 0x7FFFFFFF);
458
459 try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
460 try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
461 try test_i32_intFromFloat_f64(0x1.0000000000000p+127, 0x7FFFFFFF);
462
463 try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
464 try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
465
466 try test_i32_intFromFloat_f64(math.floatMax(f64), math.maxInt(i32));
451467}
452468
453test "fixunsdfsi" {
454 try test__fixunsdfsi(0.0, 0);
455
456 try test__fixunsdfsi(0.5, 0);
457 try test__fixunsdfsi(0.99, 0);
458 try test__fixunsdfsi(1.0, 1);
459 try test__fixunsdfsi(1.5, 1);
460 try test__fixunsdfsi(1.99, 1);
461 try test__fixunsdfsi(2.0, 2);
462 try test__fixunsdfsi(2.01, 2);
463 try test__fixunsdfsi(-0.5, 0);
464 try test__fixunsdfsi(-0.99, 0);
465 try test__fixunsdfsi(-1.0, 0);
466 try test__fixunsdfsi(-1.5, 0);
467 try test__fixunsdfsi(-1.99, 0);
468 try test__fixunsdfsi(-2.0, 0);
469 try test__fixunsdfsi(-2.01, 0);
470
471 try test__fixunsdfsi(0x1.000000p+31, 0x80000000);
472 try test__fixunsdfsi(0x1.000000p+32, 0xFFFFFFFF);
473 try test__fixunsdfsi(0x1.FFFFFEp+31, 0xFFFFFF00);
474 try test__fixunsdfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
475 try test__fixunsdfsi(0x1.FFFFFCp+30, 0x7FFFFF00);
476
477 try test__fixunsdfsi(-0x1.FFFFFEp+30, 0);
478 try test__fixunsdfsi(-0x1.FFFFFCp+30, 0);
479
480 try test__fixunsdfsi(0x1.FFFFFFFEp+31, 0xFFFFFFFF);
481 try test__fixunsdfsi(0x1.FFFFFFFC00000p+30, 0x7FFFFFFF);
482 try test__fixunsdfsi(0x1.FFFFFFF800000p+30, 0x7FFFFFFE);
469test u32_intFromFloat_f64 {
470 try test_u32_intFromFloat_f64(0.0, 0);
471
472 try test_u32_intFromFloat_f64(0.5, 0);
473 try test_u32_intFromFloat_f64(0.99, 0);
474 try test_u32_intFromFloat_f64(1.0, 1);
475 try test_u32_intFromFloat_f64(1.5, 1);
476 try test_u32_intFromFloat_f64(1.99, 1);
477 try test_u32_intFromFloat_f64(2.0, 2);
478 try test_u32_intFromFloat_f64(2.01, 2);
479 try test_u32_intFromFloat_f64(-0.5, 0);
480 try test_u32_intFromFloat_f64(-0.99, 0);
481 try test_u32_intFromFloat_f64(-1.0, 0);
482 try test_u32_intFromFloat_f64(-1.5, 0);
483 try test_u32_intFromFloat_f64(-1.99, 0);
484 try test_u32_intFromFloat_f64(-2.0, 0);
485 try test_u32_intFromFloat_f64(-2.01, 0);
486
487 try test_u32_intFromFloat_f64(0x1.000000p+31, 0x80000000);
488 try test_u32_intFromFloat_f64(0x1.000000p+32, 0xFFFFFFFF);
489 try test_u32_intFromFloat_f64(0x1.FFFFFEp+31, 0xFFFFFF00);
490 try test_u32_intFromFloat_f64(0x1.FFFFFEp+30, 0x7FFFFF80);
491 try test_u32_intFromFloat_f64(0x1.FFFFFCp+30, 0x7FFFFF00);
492
493 try test_u32_intFromFloat_f64(-0x1.FFFFFEp+30, 0);
494 try test_u32_intFromFloat_f64(-0x1.FFFFFCp+30, 0);
495
496 try test_u32_intFromFloat_f64(0x1.FFFFFFFEp+31, 0xFFFFFFFF);
497 try test_u32_intFromFloat_f64(0x1.FFFFFFFC00000p+30, 0x7FFFFFFF);
498 try test_u32_intFromFloat_f64(0x1.FFFFFFF800000p+30, 0x7FFFFFFE);
483499}
484500
485fn test__fixdfdi(a: f64, expected: i64) !void {
486 const x = __fixdfdi(a);
501fn test_i64_intFromFloat_f64(a: f64, expected: i64) !void {
502 const x = i64_intFromFloat_f64(a);
487503 try testing.expect(x == expected);
488504}
489505
490fn test__fixunsdfdi(a: f64, expected: u64) !void {
491 const x = __fixunsdfdi(a);
506fn test_u64_intFromFloat_f64(a: f64, expected: u64) !void {
507 const x = u64_intFromFloat_f64(a);
492508 try testing.expect(x == expected);
493509}
494510
495test "fixdfdi" {
496 try test__fixdfdi(-math.floatMax(f64), math.minInt(i64));
497
498 try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
499 try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
500
501 try test__fixdfdi(-0x1.0000000000000p+127, -0x8000000000000000);
502 try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
503 try test__fixdfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
504
505 try test__fixdfdi(-0x1.0000000000001p+63, -0x8000000000000000);
506 try test__fixdfdi(-0x1.0000000000000p+63, -0x8000000000000000);
507 try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
508 try test__fixdfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
509
510 try test__fixdfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000);
511 try test__fixdfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000);
512
513 try test__fixdfdi(-2.01, -2);
514 try test__fixdfdi(-2.0, -2);
515 try test__fixdfdi(-1.99, -1);
516 try test__fixdfdi(-1.0, -1);
517 try test__fixdfdi(-0.99, 0);
518 try test__fixdfdi(-0.5, 0);
519 try test__fixdfdi(-math.floatMin(f64), 0);
520 try test__fixdfdi(0.0, 0);
521 try test__fixdfdi(math.floatMin(f64), 0);
522 try test__fixdfdi(0.5, 0);
523 try test__fixdfdi(0.99, 0);
524 try test__fixdfdi(1.0, 1);
525 try test__fixdfdi(1.5, 1);
526 try test__fixdfdi(1.99, 1);
527 try test__fixdfdi(2.0, 2);
528 try test__fixdfdi(2.01, 2);
529
530 try test__fixdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
531 try test__fixdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
532
533 try test__fixdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
534 try test__fixdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
535 try test__fixdfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
536 try test__fixdfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
537
538 try test__fixdfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
539 try test__fixdfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
540 try test__fixdfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
541
542 try test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
543 try test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
544
545 try test__fixdfdi(math.floatMax(f64), math.maxInt(i64));
511test i64_intFromFloat_f64 {
512 try test_i64_intFromFloat_f64(-math.floatMax(f64), math.minInt(i64));
513
514 try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
515 try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
516
517 try test_i64_intFromFloat_f64(-0x1.0000000000000p+127, -0x8000000000000000);
518 try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
519 try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
520
521 try test_i64_intFromFloat_f64(-0x1.0000000000001p+63, -0x8000000000000000);
522 try test_i64_intFromFloat_f64(-0x1.0000000000000p+63, -0x8000000000000000);
523 try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
524 try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
525
526 try test_i64_intFromFloat_f64(-0x1.FFFFFEp+62, -0x7fffff8000000000);
527 try test_i64_intFromFloat_f64(-0x1.FFFFFCp+62, -0x7fffff0000000000);
528
529 try test_i64_intFromFloat_f64(-2.01, -2);
530 try test_i64_intFromFloat_f64(-2.0, -2);
531 try test_i64_intFromFloat_f64(-1.99, -1);
532 try test_i64_intFromFloat_f64(-1.0, -1);
533 try test_i64_intFromFloat_f64(-0.99, 0);
534 try test_i64_intFromFloat_f64(-0.5, 0);
535 try test_i64_intFromFloat_f64(-math.floatMin(f64), 0);
536 try test_i64_intFromFloat_f64(0.0, 0);
537 try test_i64_intFromFloat_f64(math.floatMin(f64), 0);
538 try test_i64_intFromFloat_f64(0.5, 0);
539 try test_i64_intFromFloat_f64(0.99, 0);
540 try test_i64_intFromFloat_f64(1.0, 1);
541 try test_i64_intFromFloat_f64(1.5, 1);
542 try test_i64_intFromFloat_f64(1.99, 1);
543 try test_i64_intFromFloat_f64(2.0, 2);
544 try test_i64_intFromFloat_f64(2.01, 2);
545
546 try test_i64_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
547 try test_i64_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
548
549 try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
550 try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
551 try test_i64_intFromFloat_f64(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
552 try test_i64_intFromFloat_f64(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
553
554 try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
555 try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
556 try test_i64_intFromFloat_f64(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
557
558 try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
559 try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
560
561 try test_i64_intFromFloat_f64(math.floatMax(f64), math.maxInt(i64));
546562}
547563
548test "fixunsdfdi" {
549 try test__fixunsdfdi(0.0, 0);
550 try test__fixunsdfdi(0.5, 0);
551 try test__fixunsdfdi(0.99, 0);
552 try test__fixunsdfdi(1.0, 1);
553 try test__fixunsdfdi(1.5, 1);
554 try test__fixunsdfdi(1.99, 1);
555 try test__fixunsdfdi(2.0, 2);
556 try test__fixunsdfdi(2.01, 2);
557 try test__fixunsdfdi(-0.5, 0);
558 try test__fixunsdfdi(-0.99, 0);
559 try test__fixunsdfdi(-1.0, 0);
560 try test__fixunsdfdi(-1.5, 0);
561 try test__fixunsdfdi(-1.99, 0);
562 try test__fixunsdfdi(-2.0, 0);
563 try test__fixunsdfdi(-2.01, 0);
564
565 try test__fixunsdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
566 try test__fixunsdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
567
568 try test__fixunsdfdi(-0x1.FFFFFEp+62, 0);
569 try test__fixunsdfdi(-0x1.FFFFFCp+62, 0);
570
571 try test__fixunsdfdi(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800);
572 try test__fixunsdfdi(0x1.0000000000000p+63, 0x8000000000000000);
573 try test__fixunsdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
574 try test__fixunsdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
575
576 try test__fixunsdfdi(-0x1.FFFFFFFFFFFFFp+62, 0);
577 try test__fixunsdfdi(-0x1.FFFFFFFFFFFFEp+62, 0);
564test u64_intFromFloat_f64 {
565 try test_u64_intFromFloat_f64(0.0, 0);
566 try test_u64_intFromFloat_f64(0.5, 0);
567 try test_u64_intFromFloat_f64(0.99, 0);
568 try test_u64_intFromFloat_f64(1.0, 1);
569 try test_u64_intFromFloat_f64(1.5, 1);
570 try test_u64_intFromFloat_f64(1.99, 1);
571 try test_u64_intFromFloat_f64(2.0, 2);
572 try test_u64_intFromFloat_f64(2.01, 2);
573 try test_u64_intFromFloat_f64(-0.5, 0);
574 try test_u64_intFromFloat_f64(-0.99, 0);
575 try test_u64_intFromFloat_f64(-1.0, 0);
576 try test_u64_intFromFloat_f64(-1.5, 0);
577 try test_u64_intFromFloat_f64(-1.99, 0);
578 try test_u64_intFromFloat_f64(-2.0, 0);
579 try test_u64_intFromFloat_f64(-2.01, 0);
580
581 try test_u64_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
582 try test_u64_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
583
584 try test_u64_intFromFloat_f64(-0x1.FFFFFEp+62, 0);
585 try test_u64_intFromFloat_f64(-0x1.FFFFFCp+62, 0);
586
587 try test_u64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800);
588 try test_u64_intFromFloat_f64(0x1.0000000000000p+63, 0x8000000000000000);
589 try test_u64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
590 try test_u64_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
591
592 try test_u64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, 0);
593 try test_u64_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, 0);
578594}
579595
580fn test__fixdfti(a: f64, expected: i128) !void {
581 const x = __fixdfti(a);
596fn test_i128_intFromFloat_f64(a: f64, expected: i128) !void {
597 const x = i128_intFromFloat_f64(a);
582598 try testing.expect(x == expected);
583599}
584600
585fn test__fixunsdfti(a: f64, expected: u128) !void {
586 const x = __fixunsdfti(a);
601fn test_u128_intFromFloat_f64(a: f64, expected: u128) !void {
602 const x = u128_intFromFloat_f64(a);
587603 try testing.expect(x == expected);
588604}
589605
590test "fixdfti" {
591 try test__fixdfti(-math.floatMax(f64), math.minInt(i128));
592
593 try test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
594 try test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
595
596 try test__fixdfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
597 try test__fixdfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000);
598 try test__fixdfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000);
599
600 try test__fixdfti(-0x1.0000000000001p+63, -0x8000000000000800);
601 try test__fixdfti(-0x1.0000000000000p+63, -0x8000000000000000);
602 try test__fixdfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
603 try test__fixdfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
604
605 try test__fixdfti(-0x1.FFFFFEp+62, -0x7fffff8000000000);
606 try test__fixdfti(-0x1.FFFFFCp+62, -0x7fffff0000000000);
607
608 try test__fixdfti(-2.01, -2);
609 try test__fixdfti(-2.0, -2);
610 try test__fixdfti(-1.99, -1);
611 try test__fixdfti(-1.0, -1);
612 try test__fixdfti(-0.99, 0);
613 try test__fixdfti(-0.5, 0);
614 try test__fixdfti(-math.floatMin(f64), 0);
615 try test__fixdfti(0.0, 0);
616 try test__fixdfti(math.floatMin(f64), 0);
617 try test__fixdfti(0.5, 0);
618 try test__fixdfti(0.99, 0);
619 try test__fixdfti(1.0, 1);
620 try test__fixdfti(1.5, 1);
621 try test__fixdfti(1.99, 1);
622 try test__fixdfti(2.0, 2);
623 try test__fixdfti(2.01, 2);
624
625 try test__fixdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
626 try test__fixdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
627
628 try test__fixdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
629 try test__fixdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
630 try test__fixdfti(0x1.0000000000000p+63, 0x8000000000000000);
631 try test__fixdfti(0x1.0000000000001p+63, 0x8000000000000800);
632
633 try test__fixdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
634 try test__fixdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
635 try test__fixdfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
636
637 try test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
638 try test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
639
640 try test__fixdfti(math.floatMax(f64), math.maxInt(i128));
606test i128_intFromFloat_f64 {
607 try test_i128_intFromFloat_f64(-math.floatMax(f64), math.minInt(i128));
608
609 try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
610 try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
611
612 try test_i128_intFromFloat_f64(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
613 try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000);
614 try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000);
615
616 try test_i128_intFromFloat_f64(-0x1.0000000000001p+63, -0x8000000000000800);
617 try test_i128_intFromFloat_f64(-0x1.0000000000000p+63, -0x8000000000000000);
618 try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
619 try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
620
621 try test_i128_intFromFloat_f64(-0x1.FFFFFEp+62, -0x7fffff8000000000);
622 try test_i128_intFromFloat_f64(-0x1.FFFFFCp+62, -0x7fffff0000000000);
623
624 try test_i128_intFromFloat_f64(-2.01, -2);
625 try test_i128_intFromFloat_f64(-2.0, -2);
626 try test_i128_intFromFloat_f64(-1.99, -1);
627 try test_i128_intFromFloat_f64(-1.0, -1);
628 try test_i128_intFromFloat_f64(-0.99, 0);
629 try test_i128_intFromFloat_f64(-0.5, 0);
630 try test_i128_intFromFloat_f64(-math.floatMin(f64), 0);
631 try test_i128_intFromFloat_f64(0.0, 0);
632 try test_i128_intFromFloat_f64(math.floatMin(f64), 0);
633 try test_i128_intFromFloat_f64(0.5, 0);
634 try test_i128_intFromFloat_f64(0.99, 0);
635 try test_i128_intFromFloat_f64(1.0, 1);
636 try test_i128_intFromFloat_f64(1.5, 1);
637 try test_i128_intFromFloat_f64(1.99, 1);
638 try test_i128_intFromFloat_f64(2.0, 2);
639 try test_i128_intFromFloat_f64(2.01, 2);
640
641 try test_i128_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
642 try test_i128_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
643
644 try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
645 try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
646 try test_i128_intFromFloat_f64(0x1.0000000000000p+63, 0x8000000000000000);
647 try test_i128_intFromFloat_f64(0x1.0000000000001p+63, 0x8000000000000800);
648
649 try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
650 try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
651 try test_i128_intFromFloat_f64(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
652
653 try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
654 try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
655
656 try test_i128_intFromFloat_f64(math.floatMax(f64), math.maxInt(i128));
641657}
642658
643test "fixunsdfti" {
644 try test__fixunsdfti(0.0, 0);
645
646 try test__fixunsdfti(0.5, 0);
647 try test__fixunsdfti(0.99, 0);
648 try test__fixunsdfti(1.0, 1);
649 try test__fixunsdfti(1.5, 1);
650 try test__fixunsdfti(1.99, 1);
651 try test__fixunsdfti(2.0, 2);
652 try test__fixunsdfti(2.01, 2);
653 try test__fixunsdfti(-0.5, 0);
654 try test__fixunsdfti(-0.99, 0);
655 try test__fixunsdfti(-1.0, 0);
656 try test__fixunsdfti(-1.5, 0);
657 try test__fixunsdfti(-1.99, 0);
658 try test__fixunsdfti(-2.0, 0);
659 try test__fixunsdfti(-2.01, 0);
660
661 try test__fixunsdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
662 try test__fixunsdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
663
664 try test__fixunsdfti(-0x1.FFFFFEp+62, 0);
665 try test__fixunsdfti(-0x1.FFFFFCp+62, 0);
666
667 try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800);
668 try test__fixunsdfti(0x1.0000000000000p+63, 0x8000000000000000);
669 try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
670 try test__fixunsdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
671
672 try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+127, 0xFFFFFFFFFFFFF8000000000000000000);
673 try test__fixunsdfti(0x1.0000000000000p+127, 0x80000000000000000000000000000000);
674 try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
675 try test__fixunsdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
676 try test__fixunsdfti(0x1.0000000000000p+128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
677
678 try test__fixunsdfti(-0x1.FFFFFFFFFFFFFp+62, 0);
679 try test__fixunsdfti(-0x1.FFFFFFFFFFFFEp+62, 0);
659test u128_intFromFloat_f64 {
660 try test_u128_intFromFloat_f64(0.0, 0);
661
662 try test_u128_intFromFloat_f64(0.5, 0);
663 try test_u128_intFromFloat_f64(0.99, 0);
664 try test_u128_intFromFloat_f64(1.0, 1);
665 try test_u128_intFromFloat_f64(1.5, 1);
666 try test_u128_intFromFloat_f64(1.99, 1);
667 try test_u128_intFromFloat_f64(2.0, 2);
668 try test_u128_intFromFloat_f64(2.01, 2);
669 try test_u128_intFromFloat_f64(-0.5, 0);
670 try test_u128_intFromFloat_f64(-0.99, 0);
671 try test_u128_intFromFloat_f64(-1.0, 0);
672 try test_u128_intFromFloat_f64(-1.5, 0);
673 try test_u128_intFromFloat_f64(-1.99, 0);
674 try test_u128_intFromFloat_f64(-2.0, 0);
675 try test_u128_intFromFloat_f64(-2.01, 0);
676
677 try test_u128_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
678 try test_u128_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
679
680 try test_u128_intFromFloat_f64(-0x1.FFFFFEp+62, 0);
681 try test_u128_intFromFloat_f64(-0x1.FFFFFCp+62, 0);
682
683 try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800);
684 try test_u128_intFromFloat_f64(0x1.0000000000000p+63, 0x8000000000000000);
685 try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
686 try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
687
688 try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+127, 0xFFFFFFFFFFFFF8000000000000000000);
689 try test_u128_intFromFloat_f64(0x1.0000000000000p+127, 0x80000000000000000000000000000000);
690 try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
691 try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
692 try test_u128_intFromFloat_f64(0x1.0000000000000p+128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
693
694 try test_u128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, 0);
695 try test_u128_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, 0);
680696}
681697
682fn test_fixdfei(comptime T: type, expected: T, a: f64) !void {
698fn test_intFromFloat_f64(comptime T: type, expected: T, a: f64) !void {
683699 const int = @typeInfo(T).int;
684700 var actual: T = undefined;
685701 _ = switch (int.signedness) {
686 .signed => __fixdfei,
687 .unsigned => __fixunsdfei,
688 }(@ptrCast(&actual), int.bits, a);
702 .signed => signed_intFromFloat_f64,
703 .unsigned => unsigned_intFromFloat_f64,
704 }(@ptrCast(&actual), a);
689705 try testing.expect(expected == actual);
690706}
691707
692test "fixdfei" {
693 try test_fixdfei(i256, -1 << 255, -0x1p255);
694 try test_fixdfei(i256, -1 << 127, -0x1p127);
695 try test_fixdfei(i256, -1 << 100, -0x1p100);
696 try test_fixdfei(i256, -1 << 50, -0x1p50);
697 try test_fixdfei(i256, -1 << 1, -0x1p1);
698 try test_fixdfei(i256, -1 << 0, -0x1p0);
699 try test_fixdfei(i256, 0, 0);
700 try test_fixdfei(i256, 1 << 0, 0x1p0);
701 try test_fixdfei(i256, 1 << 1, 0x1p1);
702 try test_fixdfei(i256, 1 << 50, 0x1p50);
703 try test_fixdfei(i256, 1 << 100, 0x1p100);
704 try test_fixdfei(i256, 1 << 127, 0x1p127);
705 try test_fixdfei(i256, 1 << 254, 0x1p254);
708test signed_intFromFloat_f64 {
709 try test_intFromFloat_f64(i256, -1 << 255, -0x1p255);
710 try test_intFromFloat_f64(i256, -1 << 127, -0x1p127);
711 try test_intFromFloat_f64(i256, -1 << 100, -0x1p100);
712 try test_intFromFloat_f64(i256, -1 << 50, -0x1p50);
713 try test_intFromFloat_f64(i256, -1 << 1, -0x1p1);
714 try test_intFromFloat_f64(i256, -1 << 0, -0x1p0);
715 try test_intFromFloat_f64(i256, 0, 0);
716 try test_intFromFloat_f64(i256, 1 << 0, 0x1p0);
717 try test_intFromFloat_f64(i256, 1 << 1, 0x1p1);
718 try test_intFromFloat_f64(i256, 1 << 50, 0x1p50);
719 try test_intFromFloat_f64(i256, 1 << 100, 0x1p100);
720 try test_intFromFloat_f64(i256, 1 << 127, 0x1p127);
721 try test_intFromFloat_f64(i256, 1 << 254, 0x1p254);
706722}
707723
708test "fixundfei" {
709 try test_fixdfei(u256, 0, 0);
710 try test_fixdfei(u256, 1 << 0, 0x1p0);
711 try test_fixdfei(u256, 1 << 1, 0x1p1);
712 try test_fixdfei(u256, 1 << 50, 0x1p50);
713 try test_fixdfei(u256, 1 << 100, 0x1p100);
714 try test_fixdfei(u256, 1 << 127, 0x1p127);
715 try test_fixdfei(u256, 1 << 255, 0x1p255);
724test unsigned_intFromFloat_f64 {
725 try test_intFromFloat_f64(u256, 0, 0);
726 try test_intFromFloat_f64(u256, 1 << 0, 0x1p0);
727 try test_intFromFloat_f64(u256, 1 << 1, 0x1p1);
728 try test_intFromFloat_f64(u256, 1 << 50, 0x1p50);
729 try test_intFromFloat_f64(u256, 1 << 100, 0x1p100);
730 try test_intFromFloat_f64(u256, 1 << 127, 0x1p127);
731 try test_intFromFloat_f64(u256, 1 << 255, 0x1p255);
716732}
717733
718fn test__fixtfsi(a: f128, expected: i32) !void {
719 const x = __fixtfsi(a);
734fn test_i32_intFromFloat_f128(a: f128, expected: i32) !void {
735 const x = i32_intFromFloat_f128(a);
720736 try testing.expect(x == expected);
721737}
722738
723fn test__fixunstfsi(a: f128, expected: u32) !void {
724 const x = __fixunstfsi(a);
739fn test_u32_intFromFloat_f128(a: f128, expected: u32) !void {
740 const x = u32_intFromFloat_f128(a);
725741 try testing.expect(x == expected);
726742}
727743
728test "fixtfsi" {
729 try test__fixtfsi(-math.floatMax(f128), math.minInt(i32));
730
731 try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
732 try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
733
734 try test__fixtfsi(-0x1.0000000000000p+127, -0x80000000);
735 try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
736 try test__fixtfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
737
738 try test__fixtfsi(-0x1.0000000000001p+63, -0x80000000);
739 try test__fixtfsi(-0x1.0000000000000p+63, -0x80000000);
740 try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
741 try test__fixtfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
742
743 try test__fixtfsi(-0x1.FFFFFEp+62, -0x80000000);
744 try test__fixtfsi(-0x1.FFFFFCp+62, -0x80000000);
745
746 try test__fixtfsi(-0x1.000000p+31, -0x80000000);
747 try test__fixtfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0);
748 try test__fixtfsi(-0x1.FFFFFEp+30, -0x7FFFFF80);
749 try test__fixtfsi(-0x1.FFFFFCp+30, -0x7FFFFF00);
750
751 try test__fixtfsi(-2.01, -2);
752 try test__fixtfsi(-2.0, -2);
753 try test__fixtfsi(-1.99, -1);
754 try test__fixtfsi(-1.0, -1);
755 try test__fixtfsi(-0.99, 0);
756 try test__fixtfsi(-0.5, 0);
757 try test__fixtfsi(-math.floatMin(f32), 0);
758 try test__fixtfsi(0.0, 0);
759 try test__fixtfsi(math.floatMin(f32), 0);
760 try test__fixtfsi(0.5, 0);
761 try test__fixtfsi(0.99, 0);
762 try test__fixtfsi(1.0, 1);
763 try test__fixtfsi(1.5, 1);
764 try test__fixtfsi(1.99, 1);
765 try test__fixtfsi(2.0, 2);
766 try test__fixtfsi(2.01, 2);
767
768 try test__fixtfsi(0x1.FFFFFCp+30, 0x7FFFFF00);
769 try test__fixtfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
770 try test__fixtfsi(0x1.FFFFFFp+30, 0x7FFFFFC0);
771 try test__fixtfsi(0x1.000000p+31, 0x7FFFFFFF);
772
773 try test__fixtfsi(0x1.FFFFFCp+62, 0x7FFFFFFF);
774 try test__fixtfsi(0x1.FFFFFEp+62, 0x7FFFFFFF);
775
776 try test__fixtfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
777 try test__fixtfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
778 try test__fixtfsi(0x1.0000000000000p+63, 0x7FFFFFFF);
779 try test__fixtfsi(0x1.0000000000001p+63, 0x7FFFFFFF);
780
781 try test__fixtfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
782 try test__fixtfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
783 try test__fixtfsi(0x1.0000000000000p+127, 0x7FFFFFFF);
784
785 try test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
786 try test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
787
788 try test__fixtfsi(math.floatMax(f128), math.maxInt(i32));
744test i32_intFromFloat_f128 {
745 try test_i32_intFromFloat_f128(-math.floatMax(f128), math.minInt(i32));
746
747 try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
748 try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
749
750 try test_i32_intFromFloat_f128(-0x1.0000000000000p+127, -0x80000000);
751 try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
752 try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
753
754 try test_i32_intFromFloat_f128(-0x1.0000000000001p+63, -0x80000000);
755 try test_i32_intFromFloat_f128(-0x1.0000000000000p+63, -0x80000000);
756 try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
757 try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
758
759 try test_i32_intFromFloat_f128(-0x1.FFFFFEp+62, -0x80000000);
760 try test_i32_intFromFloat_f128(-0x1.FFFFFCp+62, -0x80000000);
761
762 try test_i32_intFromFloat_f128(-0x1.000000p+31, -0x80000000);
763 try test_i32_intFromFloat_f128(-0x1.FFFFFFp+30, -0x7FFFFFC0);
764 try test_i32_intFromFloat_f128(-0x1.FFFFFEp+30, -0x7FFFFF80);
765 try test_i32_intFromFloat_f128(-0x1.FFFFFCp+30, -0x7FFFFF00);
766
767 try test_i32_intFromFloat_f128(-2.01, -2);
768 try test_i32_intFromFloat_f128(-2.0, -2);
769 try test_i32_intFromFloat_f128(-1.99, -1);
770 try test_i32_intFromFloat_f128(-1.0, -1);
771 try test_i32_intFromFloat_f128(-0.99, 0);
772 try test_i32_intFromFloat_f128(-0.5, 0);
773 try test_i32_intFromFloat_f128(-math.floatMin(f32), 0);
774 try test_i32_intFromFloat_f128(0.0, 0);
775 try test_i32_intFromFloat_f128(math.floatMin(f32), 0);
776 try test_i32_intFromFloat_f128(0.5, 0);
777 try test_i32_intFromFloat_f128(0.99, 0);
778 try test_i32_intFromFloat_f128(1.0, 1);
779 try test_i32_intFromFloat_f128(1.5, 1);
780 try test_i32_intFromFloat_f128(1.99, 1);
781 try test_i32_intFromFloat_f128(2.0, 2);
782 try test_i32_intFromFloat_f128(2.01, 2);
783
784 try test_i32_intFromFloat_f128(0x1.FFFFFCp+30, 0x7FFFFF00);
785 try test_i32_intFromFloat_f128(0x1.FFFFFEp+30, 0x7FFFFF80);
786 try test_i32_intFromFloat_f128(0x1.FFFFFFp+30, 0x7FFFFFC0);
787 try test_i32_intFromFloat_f128(0x1.000000p+31, 0x7FFFFFFF);
788
789 try test_i32_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFFFF);
790 try test_i32_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFFFF);
791
792 try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
793 try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
794 try test_i32_intFromFloat_f128(0x1.0000000000000p+63, 0x7FFFFFFF);
795 try test_i32_intFromFloat_f128(0x1.0000000000001p+63, 0x7FFFFFFF);
796
797 try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
798 try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
799 try test_i32_intFromFloat_f128(0x1.0000000000000p+127, 0x7FFFFFFF);
800
801 try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
802 try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
803
804 try test_i32_intFromFloat_f128(math.floatMax(f128), math.maxInt(i32));
789805}
790806
791test "fixunstfsi" {
792 try test__fixunstfsi(math.inf(f128), 0xffffffff);
793 try test__fixunstfsi(0, 0x0);
794 try test__fixunstfsi(0x1.23456789abcdefp+5, 0x24);
795 try test__fixunstfsi(0x1.23456789abcdefp-3, 0x0);
796 try test__fixunstfsi(0x1.23456789abcdefp+20, 0x123456);
797 try test__fixunstfsi(0x1.23456789abcdefp+40, 0xffffffff);
798 try test__fixunstfsi(0x1.23456789abcdefp+256, 0xffffffff);
799 try test__fixunstfsi(-0x1.23456789abcdefp+3, 0x0);
800
801 try test__fixunstfsi(0x1p+32, 0xFFFFFFFF);
807test u32_intFromFloat_f128 {
808 try test_u32_intFromFloat_f128(math.inf(f128), 0xffffffff);
809 try test_u32_intFromFloat_f128(0, 0x0);
810 try test_u32_intFromFloat_f128(0x1.23456789abcdefp+5, 0x24);
811 try test_u32_intFromFloat_f128(0x1.23456789abcdefp-3, 0x0);
812 try test_u32_intFromFloat_f128(0x1.23456789abcdefp+20, 0x123456);
813 try test_u32_intFromFloat_f128(0x1.23456789abcdefp+40, 0xffffffff);
814 try test_u32_intFromFloat_f128(0x1.23456789abcdefp+256, 0xffffffff);
815 try test_u32_intFromFloat_f128(-0x1.23456789abcdefp+3, 0x0);
816
817 try test_u32_intFromFloat_f128(0x1p+32, 0xFFFFFFFF);
802818}
803819
804fn test__fixtfdi(a: f128, expected: i64) !void {
805 const x = __fixtfdi(a);
820fn test_i64_intFromFloat_f128(a: f128, expected: i64) !void {
821 const x = i64_intFromFloat_f128(a);
806822 try testing.expect(x == expected);
807823}
808824
809fn test__fixunstfdi(a: f128, expected: u64) !void {
810 const x = __fixunstfdi(a);
825fn test_u64_intFromFloat_f128(a: f128, expected: u64) !void {
826 const x = u64_intFromFloat_f128(a);
811827 try testing.expect(x == expected);
812828}
813829
814test "fixtfdi" {
815 try test__fixtfdi(-math.floatMax(f128), math.minInt(i64));
816
817 try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
818 try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
819
820 try test__fixtfdi(-0x1.0000000000000p+127, -0x8000000000000000);
821 try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
822 try test__fixtfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
823
824 try test__fixtfdi(-0x1.0000000000001p+63, -0x8000000000000000);
825 try test__fixtfdi(-0x1.0000000000000p+63, -0x8000000000000000);
826 try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
827 try test__fixtfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
828
829 try test__fixtfdi(-0x1.FFFFFEp+62, -0x7FFFFF8000000000);
830 try test__fixtfdi(-0x1.FFFFFCp+62, -0x7FFFFF0000000000);
831
832 try test__fixtfdi(-0x1.000000p+31, -0x80000000);
833 try test__fixtfdi(-0x1.FFFFFFp+30, -0x7FFFFFC0);
834 try test__fixtfdi(-0x1.FFFFFEp+30, -0x7FFFFF80);
835 try test__fixtfdi(-0x1.FFFFFCp+30, -0x7FFFFF00);
836
837 try test__fixtfdi(-2.01, -2);
838 try test__fixtfdi(-2.0, -2);
839 try test__fixtfdi(-1.99, -1);
840 try test__fixtfdi(-1.0, -1);
841 try test__fixtfdi(-0.99, 0);
842 try test__fixtfdi(-0.5, 0);
843 try test__fixtfdi(-math.floatMin(f64), 0);
844 try test__fixtfdi(0.0, 0);
845 try test__fixtfdi(math.floatMin(f64), 0);
846 try test__fixtfdi(0.5, 0);
847 try test__fixtfdi(0.99, 0);
848 try test__fixtfdi(1.0, 1);
849 try test__fixtfdi(1.5, 1);
850 try test__fixtfdi(1.99, 1);
851 try test__fixtfdi(2.0, 2);
852 try test__fixtfdi(2.01, 2);
853
854 try test__fixtfdi(0x1.FFFFFCp+30, 0x7FFFFF00);
855 try test__fixtfdi(0x1.FFFFFEp+30, 0x7FFFFF80);
856 try test__fixtfdi(0x1.FFFFFFp+30, 0x7FFFFFC0);
857 try test__fixtfdi(0x1.000000p+31, 0x80000000);
858
859 try test__fixtfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
860 try test__fixtfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
861
862 try test__fixtfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
863 try test__fixtfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
864 try test__fixtfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
865 try test__fixtfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
866
867 try test__fixtfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
868 try test__fixtfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
869 try test__fixtfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
870
871 try test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
872 try test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
873
874 try test__fixtfdi(math.floatMax(f128), math.maxInt(i64));
830test i64_intFromFloat_f128 {
831 try test_i64_intFromFloat_f128(-math.floatMax(f128), math.minInt(i64));
832
833 try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
834 try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
835
836 try test_i64_intFromFloat_f128(-0x1.0000000000000p+127, -0x8000000000000000);
837 try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
838 try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
839
840 try test_i64_intFromFloat_f128(-0x1.0000000000001p+63, -0x8000000000000000);
841 try test_i64_intFromFloat_f128(-0x1.0000000000000p+63, -0x8000000000000000);
842 try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
843 try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
844
845 try test_i64_intFromFloat_f128(-0x1.FFFFFEp+62, -0x7FFFFF8000000000);
846 try test_i64_intFromFloat_f128(-0x1.FFFFFCp+62, -0x7FFFFF0000000000);
847
848 try test_i64_intFromFloat_f128(-0x1.000000p+31, -0x80000000);
849 try test_i64_intFromFloat_f128(-0x1.FFFFFFp+30, -0x7FFFFFC0);
850 try test_i64_intFromFloat_f128(-0x1.FFFFFEp+30, -0x7FFFFF80);
851 try test_i64_intFromFloat_f128(-0x1.FFFFFCp+30, -0x7FFFFF00);
852
853 try test_i64_intFromFloat_f128(-2.01, -2);
854 try test_i64_intFromFloat_f128(-2.0, -2);
855 try test_i64_intFromFloat_f128(-1.99, -1);
856 try test_i64_intFromFloat_f128(-1.0, -1);
857 try test_i64_intFromFloat_f128(-0.99, 0);
858 try test_i64_intFromFloat_f128(-0.5, 0);
859 try test_i64_intFromFloat_f128(-math.floatMin(f64), 0);
860 try test_i64_intFromFloat_f128(0.0, 0);
861 try test_i64_intFromFloat_f128(math.floatMin(f64), 0);
862 try test_i64_intFromFloat_f128(0.5, 0);
863 try test_i64_intFromFloat_f128(0.99, 0);
864 try test_i64_intFromFloat_f128(1.0, 1);
865 try test_i64_intFromFloat_f128(1.5, 1);
866 try test_i64_intFromFloat_f128(1.99, 1);
867 try test_i64_intFromFloat_f128(2.0, 2);
868 try test_i64_intFromFloat_f128(2.01, 2);
869
870 try test_i64_intFromFloat_f128(0x1.FFFFFCp+30, 0x7FFFFF00);
871 try test_i64_intFromFloat_f128(0x1.FFFFFEp+30, 0x7FFFFF80);
872 try test_i64_intFromFloat_f128(0x1.FFFFFFp+30, 0x7FFFFFC0);
873 try test_i64_intFromFloat_f128(0x1.000000p+31, 0x80000000);
874
875 try test_i64_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
876 try test_i64_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
877
878 try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
879 try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
880 try test_i64_intFromFloat_f128(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
881 try test_i64_intFromFloat_f128(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
882
883 try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
884 try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
885 try test_i64_intFromFloat_f128(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
886
887 try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
888 try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
889
890 try test_i64_intFromFloat_f128(math.floatMax(f128), math.maxInt(i64));
875891}
876892
877test "fixunstfdi" {
878 try test__fixunstfdi(0.0, 0);
879
880 try test__fixunstfdi(0.5, 0);
881 try test__fixunstfdi(0.99, 0);
882 try test__fixunstfdi(1.0, 1);
883 try test__fixunstfdi(1.5, 1);
884 try test__fixunstfdi(1.99, 1);
885 try test__fixunstfdi(2.0, 2);
886 try test__fixunstfdi(2.01, 2);
887 try test__fixunstfdi(-0.5, 0);
888 try test__fixunstfdi(-0.99, 0);
889 try test__fixunstfdi(-1.0, 0);
890 try test__fixunstfdi(-1.5, 0);
891 try test__fixunstfdi(-1.99, 0);
892 try test__fixunstfdi(-2.0, 0);
893 try test__fixunstfdi(-2.01, 0);
894
895 try test__fixunstfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
896 try test__fixunstfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
897
898 try test__fixunstfdi(-0x1.FFFFFEp+62, 0);
899 try test__fixunstfdi(-0x1.FFFFFCp+62, 0);
900
901 try test__fixunstfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
902 try test__fixunstfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
903
904 try test__fixunstfdi(-0x1.FFFFFFFFFFFFFp+62, 0);
905 try test__fixunstfdi(-0x1.FFFFFFFFFFFFEp+62, 0);
906
907 try test__fixunstfdi(0x1.FFFFFFFFFFFFFFFEp+63, 0xFFFFFFFFFFFFFFFF);
908 try test__fixunstfdi(0x1.0000000000000002p+63, 0x8000000000000001);
909 try test__fixunstfdi(0x1.0000000000000000p+63, 0x8000000000000000);
910 try test__fixunstfdi(0x1.FFFFFFFFFFFFFFFCp+62, 0x7FFFFFFFFFFFFFFF);
911 try test__fixunstfdi(0x1.FFFFFFFFFFFFFFF8p+62, 0x7FFFFFFFFFFFFFFE);
912 try test__fixunstfdi(0x1p+64, 0xFFFFFFFFFFFFFFFF);
913
914 try test__fixunstfdi(-0x1.0000000000000000p+63, 0);
915 try test__fixunstfdi(-0x1.FFFFFFFFFFFFFFFCp+62, 0);
916 try test__fixunstfdi(-0x1.FFFFFFFFFFFFFFF8p+62, 0);
893test u64_intFromFloat_f128 {
894 try test_u64_intFromFloat_f128(0.0, 0);
895
896 try test_u64_intFromFloat_f128(0.5, 0);
897 try test_u64_intFromFloat_f128(0.99, 0);
898 try test_u64_intFromFloat_f128(1.0, 1);
899 try test_u64_intFromFloat_f128(1.5, 1);
900 try test_u64_intFromFloat_f128(1.99, 1);
901 try test_u64_intFromFloat_f128(2.0, 2);
902 try test_u64_intFromFloat_f128(2.01, 2);
903 try test_u64_intFromFloat_f128(-0.5, 0);
904 try test_u64_intFromFloat_f128(-0.99, 0);
905 try test_u64_intFromFloat_f128(-1.0, 0);
906 try test_u64_intFromFloat_f128(-1.5, 0);
907 try test_u64_intFromFloat_f128(-1.99, 0);
908 try test_u64_intFromFloat_f128(-2.0, 0);
909 try test_u64_intFromFloat_f128(-2.01, 0);
910
911 try test_u64_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
912 try test_u64_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
913
914 try test_u64_intFromFloat_f128(-0x1.FFFFFEp+62, 0);
915 try test_u64_intFromFloat_f128(-0x1.FFFFFCp+62, 0);
916
917 try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
918 try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
919
920 try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, 0);
921 try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, 0);
922
923 try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFFFEp+63, 0xFFFFFFFFFFFFFFFF);
924 try test_u64_intFromFloat_f128(0x1.0000000000000002p+63, 0x8000000000000001);
925 try test_u64_intFromFloat_f128(0x1.0000000000000000p+63, 0x8000000000000000);
926 try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFFFCp+62, 0x7FFFFFFFFFFFFFFF);
927 try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFFF8p+62, 0x7FFFFFFFFFFFFFFE);
928 try test_u64_intFromFloat_f128(0x1p+64, 0xFFFFFFFFFFFFFFFF);
929
930 try test_u64_intFromFloat_f128(-0x1.0000000000000000p+63, 0);
931 try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFFFCp+62, 0);
932 try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFFF8p+62, 0);
917933}
918934
919fn test__fixtfti(a: f128, expected: i128) !void {
920 const x = __fixtfti(a);
935fn test_i128_intFromFloat_f128(a: f128, expected: i128) !void {
936 const x = i128_intFromFloat_f128(a);
921937 try testing.expect(x == expected);
922938}
923939
924fn test__fixunstfti(a: f128, expected: u128) !void {
925 const x = __fixunstfti(a);
940fn test_u128_intFromFloat_f128(a: f128, expected: u128) !void {
941 const x = u128_intFromFloat_f128(a);
926942 try testing.expect(x == expected);
927943}
928944
929test "fixtfti" {
930 try test__fixtfti(-math.floatMax(f128), math.minInt(i128));
931
932 try test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
933 try test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
934
935 try test__fixtfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
936 try test__fixtfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000);
937 try test__fixtfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000);
938
939 try test__fixtfti(-0x1.0000000000001p+63, -0x8000000000000800);
940 try test__fixtfti(-0x1.0000000000000p+63, -0x8000000000000000);
941 try test__fixtfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
942 try test__fixtfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
943
944 try test__fixtfti(-0x1.FFFFFEp+62, -0x7fffff8000000000);
945 try test__fixtfti(-0x1.FFFFFCp+62, -0x7fffff0000000000);
946
947 try test__fixtfti(-2.01, -2);
948 try test__fixtfti(-2.0, -2);
949 try test__fixtfti(-1.99, -1);
950 try test__fixtfti(-1.0, -1);
951 try test__fixtfti(-0.99, 0);
952 try test__fixtfti(-0.5, 0);
953 try test__fixtfti(-math.floatMin(f128), 0);
954 try test__fixtfti(0.0, 0);
955 try test__fixtfti(math.floatMin(f128), 0);
956 try test__fixtfti(0.5, 0);
957 try test__fixtfti(0.99, 0);
958 try test__fixtfti(1.0, 1);
959 try test__fixtfti(1.5, 1);
960 try test__fixtfti(1.99, 1);
961 try test__fixtfti(2.0, 2);
962 try test__fixtfti(2.01, 2);
963
964 try test__fixtfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
965 try test__fixtfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
966
967 try test__fixtfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
968 try test__fixtfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
969 try test__fixtfti(0x1.0000000000000p+63, 0x8000000000000000);
970 try test__fixtfti(0x1.0000000000001p+63, 0x8000000000000800);
971
972 try test__fixtfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
973 try test__fixtfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
974 try test__fixtfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
975
976 try test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
977 try test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
978
979 try test__fixtfti(math.floatMax(f128), math.maxInt(i128));
945test i128_intFromFloat_f128 {
946 try test_i128_intFromFloat_f128(-math.floatMax(f128), math.minInt(i128));
947
948 try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
949 try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
950
951 try test_i128_intFromFloat_f128(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
952 try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000);
953 try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000);
954
955 try test_i128_intFromFloat_f128(-0x1.0000000000001p+63, -0x8000000000000800);
956 try test_i128_intFromFloat_f128(-0x1.0000000000000p+63, -0x8000000000000000);
957 try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
958 try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
959
960 try test_i128_intFromFloat_f128(-0x1.FFFFFEp+62, -0x7fffff8000000000);
961 try test_i128_intFromFloat_f128(-0x1.FFFFFCp+62, -0x7fffff0000000000);
962
963 try test_i128_intFromFloat_f128(-2.01, -2);
964 try test_i128_intFromFloat_f128(-2.0, -2);
965 try test_i128_intFromFloat_f128(-1.99, -1);
966 try test_i128_intFromFloat_f128(-1.0, -1);
967 try test_i128_intFromFloat_f128(-0.99, 0);
968 try test_i128_intFromFloat_f128(-0.5, 0);
969 try test_i128_intFromFloat_f128(-math.floatMin(f128), 0);
970 try test_i128_intFromFloat_f128(0.0, 0);
971 try test_i128_intFromFloat_f128(math.floatMin(f128), 0);
972 try test_i128_intFromFloat_f128(0.5, 0);
973 try test_i128_intFromFloat_f128(0.99, 0);
974 try test_i128_intFromFloat_f128(1.0, 1);
975 try test_i128_intFromFloat_f128(1.5, 1);
976 try test_i128_intFromFloat_f128(1.99, 1);
977 try test_i128_intFromFloat_f128(2.0, 2);
978 try test_i128_intFromFloat_f128(2.01, 2);
979
980 try test_i128_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
981 try test_i128_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
982
983 try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
984 try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
985 try test_i128_intFromFloat_f128(0x1.0000000000000p+63, 0x8000000000000000);
986 try test_i128_intFromFloat_f128(0x1.0000000000001p+63, 0x8000000000000800);
987
988 try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
989 try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
990 try test_i128_intFromFloat_f128(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
991
992 try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
993 try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
994
995 try test_i128_intFromFloat_f128(math.floatMax(f128), math.maxInt(i128));
980996}
981997
982test "fixunstfti" {
983 try test__fixunstfti(math.inf(f128), 0xffffffffffffffffffffffffffffffff);
998test u128_intFromFloat_f128 {
999 try test_u128_intFromFloat_f128(math.inf(f128), 0xffffffffffffffffffffffffffffffff);
9841000
985 try test__fixunstfti(0.0, 0);
1001 try test_u128_intFromFloat_f128(0.0, 0);
9861002
987 try test__fixunstfti(0.5, 0);
988 try test__fixunstfti(0.99, 0);
989 try test__fixunstfti(1.0, 1);
990 try test__fixunstfti(1.5, 1);
991 try test__fixunstfti(1.99, 1);
992 try test__fixunstfti(2.0, 2);
993 try test__fixunstfti(2.01, 2);
994 try test__fixunstfti(-0.01, 0);
995 try test__fixunstfti(-0.99, 0);
1003 try test_u128_intFromFloat_f128(0.5, 0);
1004 try test_u128_intFromFloat_f128(0.99, 0);
1005 try test_u128_intFromFloat_f128(1.0, 1);
1006 try test_u128_intFromFloat_f128(1.5, 1);
1007 try test_u128_intFromFloat_f128(1.99, 1);
1008 try test_u128_intFromFloat_f128(2.0, 2);
1009 try test_u128_intFromFloat_f128(2.01, 2);
1010 try test_u128_intFromFloat_f128(-0.01, 0);
1011 try test_u128_intFromFloat_f128(-0.99, 0);
9961012
997 try test__fixunstfti(0x1p+128, 0xffffffffffffffffffffffffffffffff);
1013 try test_u128_intFromFloat_f128(0x1p+128, 0xffffffffffffffffffffffffffffffff);
9981014
999 try test__fixunstfti(0x1.FFFFFEp+126, 0x7fffff80000000000000000000000000);
1000 try test__fixunstfti(0x1.FFFFFEp+127, 0xffffff00000000000000000000000000);
1001 try test__fixunstfti(0x1.FFFFFEp+128, 0xffffffffffffffffffffffffffffffff);
1002 try test__fixunstfti(0x1.FFFFFEp+129, 0xffffffffffffffffffffffffffffffff);
1015 try test_u128_intFromFloat_f128(0x1.FFFFFEp+126, 0x7fffff80000000000000000000000000);
1016 try test_u128_intFromFloat_f128(0x1.FFFFFEp+127, 0xffffff00000000000000000000000000);
1017 try test_u128_intFromFloat_f128(0x1.FFFFFEp+128, 0xffffffffffffffffffffffffffffffff);
1018 try test_u128_intFromFloat_f128(0x1.FFFFFEp+129, 0xffffffffffffffffffffffffffffffff);
10031019}
10041020
1005fn test__fixunshfti(a: f16, expected: u128) !void {
1006 const x = __fixunshfti(a);
1021fn test_u128_intFromFloat_f16(a: f16, expected: u128) !void {
1022 const x = impl.u128_intFromFloat_f16(a);
10071023 try testing.expect(x == expected);
10081024}
10091025
1010test "fixunshfti for f16" {
1011 try test__fixunshfti(math.inf(f16), math.maxInt(u128));
1012 try test__fixunshfti(math.floatMax(f16), 65504);
1026test u128_intFromFloat_f16 {
1027 try test_u128_intFromFloat_f16(math.inf(f16), math.maxInt(u128));
1028 try test_u128_intFromFloat_f16(math.floatMax(f16), 65504);
10131029}
10141030
1015fn test__fixunsxfti(a: f80, expected: u128) !void {
1016 const x = __fixunsxfti(a);
1031fn test_u128_intFromFloat_f80(a: f80, expected: u128) !void {
1032 const x = impl.u128_intFromFloat_f80(a);
10171033 try testing.expect(x == expected);
10181034}
10191035
1020test "fixunsxfti for f80" {
1021 try test__fixunsxfti(math.inf(f80), math.maxInt(u128));
1022 try test__fixunsxfti(math.floatMax(f80), math.maxInt(u128));
1023 try test__fixunsxfti(math.maxInt(u64), math.maxInt(u64));
1036test u128_intFromFloat_f80 {
1037 try test_u128_intFromFloat_f80(math.inf(f80), math.maxInt(u128));
1038 try test_u128_intFromFloat_f80(math.floatMax(f80), math.maxInt(u128));
1039 try test_u128_intFromFloat_f80(math.maxInt(u64), math.maxInt(u64));
10241040}
lib/compiler_rt/limb64.zig+1-1
......@@ -6,7 +6,7 @@ const minInt = std.math.minInt;
66
77const builtin = @import("builtin");
88const compiler_rt = @import("../compiler_rt.zig");
9const symbol = @import("../compiler_rt.zig").symbol;
9const symbol = compiler_rt.symbol;
1010
1111const endian = builtin.cpu.arch.endian();
1212
lib/compiler_rt/log.zig+113-101
......@@ -11,26 +11,29 @@ const expectEqual = std.testing.expectEqual;
1111const expectApproxEqRel = std.testing.expectApproxEqRel;
1212
1313const compiler_rt = @import("../compiler_rt.zig");
14const symbol = @import("../compiler_rt.zig").symbol;
14const symbol = compiler_rt.symbol;
1515
1616comptime {
1717 symbol(&__logh, "__logh");
1818 symbol(&logf, "logf");
1919 symbol(&log, "log");
2020 symbol(&__logx, "__logx");
21 if (compiler_rt.want_ppc_abi) {
22 symbol(&logq, "logf128");
23 }
24 symbol(&logq, "logq");
21 symbol(&logq, "logf128");
2522 symbol(&logl, "logl");
2623}
2724
28pub fn __logh(a: f16) callconv(.c) f16 {
25fn __logh(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
26 return compiler_rt.f16.toAbi(log_f16(compiler_rt.f16.fromAbi(a)));
27}
28pub fn log_f16(a: f16) f16 {
2929 // TODO: more efficient implementation
30 return @floatCast(logf(a));
30 return @floatCast(log_f32(a));
3131}
3232
33pub fn logf(x_: f32) callconv(.c) f32 {
33fn logf(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
34 return compiler_rt.f32.toAbi(log_f32(compiler_rt.f32.fromAbi(a)));
35}
36pub fn log_f32(x_: f32) f32 {
3437 const ln2_hi: f32 = 6.9313812256e-01;
3538 const ln2_lo: f32 = 9.0580006145e-06;
3639 const Lg1: f32 = 0xaaaaaa.0p-24;
......@@ -82,7 +85,10 @@ pub fn logf(x_: f32) callconv(.c) f32 {
8285 return s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi;
8386}
8487
85pub fn log(x: f64) callconv(.c) f64 {
88fn log(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
89 return compiler_rt.f64.toAbi(log_f64(compiler_rt.f64.fromAbi(a)));
90}
91pub fn log_f64(x: f64) f64 {
8692 const poly1 = [_]f64{
8793 -0x1p-1,
8894 0x1.5555555555577p-2,
......@@ -432,11 +438,17 @@ pub fn log(x: f64) callconv(.c) f64 {
432438 return @bitCast(y);
433439}
434440
435pub fn __logx(a: f80) callconv(.c) f80 {
441fn __logx(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
442 return compiler_rt.f80.toAbi(log_f80(compiler_rt.f80.fromAbi(a)));
443}
444pub fn log_f80(a: f80) f80 {
436445 // TODO: more efficient implementation
437 return @floatCast(logq(a));
446 return @floatCast(log_f128(a));
438447}
439448
449fn logq(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
450 return compiler_rt.f128.toAbi(log_f128(compiler_rt.f128.fromAbi(a)));
451}
440452/// Implementation of "Table-driven implementation of the logarithm function in IEEE floating-point arithmetic"
441453/// by PTP Tang in ACM Transactions on Mathematical Software (TOMS), 1990
442454///
......@@ -449,7 +461,7 @@ pub fn __logx(a: f80) callconv(.c) f80 {
449461///
450462/// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case):
451463/// <= 0.5 ulp: 99.96%, worst case <= 0.528 ulp
452pub fn logq(x: f128) callconv(.c) f128 {
464pub fn log_f128(x: f128) f128 {
453465 const impl = @import("log_f128.zig");
454466
455467 if (impl.specialCases(x)) |y|
......@@ -626,123 +638,123 @@ pub fn logq(x: f128) callconv(.c) f128 {
626638
627639pub fn logl(x: c_longdouble) callconv(.c) c_longdouble {
628640 switch (@typeInfo(c_longdouble).float.bits) {
629 64 => return log(x),
630 80 => return __logx(x),
631 128 => return logq(x),
632 else => @compileError("unreachable"),
641 64 => return log_f64(x),
642 80 => return log_f80(x),
643 128 => return log_f128(x),
644 else => comptime unreachable,
633645 }
634646}
635647
636648test "logf() special" {
637 try expectEqual(logf(0.0), -math.inf(f32));
638 try expectEqual(logf(-0.0), -math.inf(f32));
639 try expect(math.isPositiveZero(logf(1.0)));
640 try expectEqual(logf(math.e), 1.0);
641 try expectEqual(logf(math.inf(f32)), math.inf(f32));
642 try expect(math.isNan(logf(-1.0)));
643 try expect(math.isNan(logf(-math.inf(f32))));
644 try expect(math.isNan(logf(math.nan(f32))));
645 try expect(math.isNan(logf(math.snan(f32))));
649 try expectEqual(log_f32(0.0), -math.inf(f32));
650 try expectEqual(log_f32(-0.0), -math.inf(f32));
651 try expect(math.isPositiveZero(log_f32(1.0)));
652 try expectEqual(log_f32(math.e), 1.0);
653 try expectEqual(log_f32(math.inf(f32)), math.inf(f32));
654 try expect(math.isNan(log_f32(-1.0)));
655 try expect(math.isNan(log_f32(-math.inf(f32))));
656 try expect(math.isNan(log_f32(math.nan(f32))));
657 try expect(math.isNan(log_f32(math.snan(f32))));
646658}
647659
648660test "logf() sanity" {
649 try expect(math.isNan(logf(-0x1.0223a0p+3)));
650 try expectEqual(logf(0x1.161868p+2), 0x1.7815b0p+0);
651 try expect(math.isNan(logf(-0x1.0c34b4p+3)));
652 try expect(math.isNan(logf(-0x1.a206f0p+2)));
653 try expectEqual(logf(0x1.288bbcp+3), 0x1.1cfcd6p+1);
654 try expectEqual(logf(0x1.52efd0p-1), -0x1.a6694cp-2);
655 try expect(math.isNan(logf(-0x1.a05cc8p-2)));
656 try expectEqual(logf(0x1.1f9efap-1), -0x1.2742bap-1);
657 try expectEqual(logf(0x1.8c5db0p-1), -0x1.062160p-2);
658 try expect(math.isNan(logf(-0x1.5b86eap-1)));
661 try expect(math.isNan(log_f32(-0x1.0223a0p+3)));
662 try expectEqual(log_f32(0x1.161868p+2), 0x1.7815b0p+0);
663 try expect(math.isNan(log_f32(-0x1.0c34b4p+3)));
664 try expect(math.isNan(log_f32(-0x1.a206f0p+2)));
665 try expectEqual(log_f32(0x1.288bbcp+3), 0x1.1cfcd6p+1);
666 try expectEqual(log_f32(0x1.52efd0p-1), -0x1.a6694cp-2);
667 try expect(math.isNan(log_f32(-0x1.a05cc8p-2)));
668 try expectEqual(log_f32(0x1.1f9efap-1), -0x1.2742bap-1);
669 try expectEqual(log_f32(0x1.8c5db0p-1), -0x1.062160p-2);
670 try expect(math.isNan(log_f32(-0x1.5b86eap-1)));
659671}
660672
661673test "logf() boundary" {
662 try expectEqual(logf(0x1.fffffep+127), 0x1.62e430p+6); // Max input value
663 try expectEqual(logf(0x1p-149), -0x1.9d1da0p+6); // Min positive input value
664 try expect(math.isNan(logf(-0x1p-149))); // Min negative input value
665 try expectEqual(logf(0x1.000002p+0), 0x1.fffffep-24); // Last value before result reaches +0
666 try expectEqual(logf(0x1.fffffep-1), -0x1p-24); // Last value before result reaches -0
667 try expectEqual(logf(0x1p-126), -0x1.5d58a0p+6); // First subnormal
668 try expect(math.isNan(logf(-0x1p-126))); // First negative subnormal
674 try expectEqual(log_f32(0x1.fffffep+127), 0x1.62e430p+6); // Max input value
675 try expectEqual(log_f32(0x1p-149), -0x1.9d1da0p+6); // Min positive input value
676 try expect(math.isNan(log_f32(-0x1p-149))); // Min negative input value
677 try expectEqual(log_f32(0x1.000002p+0), 0x1.fffffep-24); // Last value before result reaches +0
678 try expectEqual(log_f32(0x1.fffffep-1), -0x1p-24); // Last value before result reaches -0
679 try expectEqual(log_f32(0x1p-126), -0x1.5d58a0p+6); // First subnormal
680 try expect(math.isNan(log_f32(-0x1p-126))); // First negative subnormal
669681}
670682
671683test "log() special" {
672 try expectEqual(log(0.0), -math.inf(f64));
673 try expectEqual(log(-0.0), -math.inf(f64));
674 try expect(math.isPositiveZero(log(1.0)));
675 try expectEqual(log(math.e), 1.0);
676 try expectEqual(log(math.inf(f64)), math.inf(f64));
677 try expect(math.isNan(log(-1.0)));
678 try expect(math.isNan(log(-math.inf(f64))));
679 try expect(math.isNan(log(math.nan(f64))));
680 try expect(math.isNan(log(math.snan(f64))));
684 try expectEqual(log_f64(0.0), -math.inf(f64));
685 try expectEqual(log_f64(-0.0), -math.inf(f64));
686 try expect(math.isPositiveZero(log_f64(1.0)));
687 try expectEqual(log_f64(math.e), 1.0);
688 try expectEqual(log_f64(math.inf(f64)), math.inf(f64));
689 try expect(math.isNan(log_f64(-1.0)));
690 try expect(math.isNan(log_f64(-math.inf(f64))));
691 try expect(math.isNan(log_f64(math.nan(f64))));
692 try expect(math.isNan(log_f64(math.snan(f64))));
681693}
682694
683695test "log() sanity" {
684 try expect(math.isNan(log(-0x1.02239f3c6a8f1p+3)));
685 try expectEqual(log(0x1.161868e18bc67p+2), 0x1.7815b08f99c65p+0);
686 try expect(math.isNan(log(-0x1.0c34b3e01e6e7p+3)));
687 try expect(math.isNan(log(-0x1.a206f0a19dcc4p+2)));
688 try expectEqual(log(0x1.288bbb0d6a1e6p+3), 0x1.1cfcd53d72604p+1);
689 try expectEqual(log(0x1.52efd0cd80497p-1), -0x1.a6694a4a85621p-2);
690 try expect(math.isNan(log(-0x1.a05cc754481d1p-2)));
691 try expectEqual(log(0x1.1f9ef934745cbp-1), -0x1.2742bc03d02ddp-1);
692 try expectEqual(log(0x1.8c5db097f7442p-1), -0x1.06215de4a3f92p-2);
693 try expect(math.isNan(log(-0x1.5b86ea8118a0ep-1)));
696 try expect(math.isNan(log_f64(-0x1.02239f3c6a8f1p+3)));
697 try expectEqual(log_f64(0x1.161868e18bc67p+2), 0x1.7815b08f99c65p+0);
698 try expect(math.isNan(log_f64(-0x1.0c34b3e01e6e7p+3)));
699 try expect(math.isNan(log_f64(-0x1.a206f0a19dcc4p+2)));
700 try expectEqual(log_f64(0x1.288bbb0d6a1e6p+3), 0x1.1cfcd53d72604p+1);
701 try expectEqual(log_f64(0x1.52efd0cd80497p-1), -0x1.a6694a4a85621p-2);
702 try expect(math.isNan(log_f64(-0x1.a05cc754481d1p-2)));
703 try expectEqual(log_f64(0x1.1f9ef934745cbp-1), -0x1.2742bc03d02ddp-1);
704 try expectEqual(log_f64(0x1.8c5db097f7442p-1), -0x1.06215de4a3f92p-2);
705 try expect(math.isNan(log_f64(-0x1.5b86ea8118a0ep-1)));
694706}
695707
696708test "log() boundary" {
697 try expectEqual(log(0x1.fffffffffffffp+1023), 0x1.62e42fefa39efp+9); // Max input value
698 try expectEqual(log(0x1p-1074), -0x1.74385446d71c3p+9); // Min positive input value
699 try expect(math.isNan(log(-0x1p-1074))); // Min negative input value
700 try expectEqual(log(0x1.0000000000001p+0), 0x1.fffffffffffffp-53); // Last value before result reaches +0
701 try expectEqual(log(0x1.fffffffffffffp-1), -0x1p-53); // Last value before result reaches -0
702 try expectEqual(log(0x1p-1022), -0x1.6232bdd7abcd2p+9); // First subnormal
703 try expect(math.isNan(log(-0x1p-1022))); // First negative subnormal
709 try expectEqual(log_f64(0x1.fffffffffffffp+1023), 0x1.62e42fefa39efp+9); // Max input value
710 try expectEqual(log_f64(0x1p-1074), -0x1.74385446d71c3p+9); // Min positive input value
711 try expect(math.isNan(log_f64(-0x1p-1074))); // Min negative input value
712 try expectEqual(log_f64(0x1.0000000000001p+0), 0x1.fffffffffffffp-53); // Last value before result reaches +0
713 try expectEqual(log_f64(0x1.fffffffffffffp-1), -0x1p-53); // Last value before result reaches -0
714 try expectEqual(log_f64(0x1p-1022), -0x1.6232bdd7abcd2p+9); // First subnormal
715 try expect(math.isNan(log_f64(-0x1p-1022))); // First negative subnormal
704716}
705717
706718test "logq() special" {
707 try expectEqual(logq(0.0), -math.inf(f128));
708 try expectEqual(logq(-0.0), -math.inf(f128));
709 try expect(math.isPositiveZero(logq(1.0)));
719 try expectEqual(log_f128(0.0), -math.inf(f128));
720 try expectEqual(log_f128(-0.0), -math.inf(f128));
721 try expect(math.isPositiveZero(log_f128(1.0)));
710722 // Sadly, the rounding gods decided that 0.9999999999999999999999999999999999
711 // is the correctly rounded value of logq(math.e)
712 try expectApproxEqRel(logq(math.e), 1.0, math.floatEpsAt(f128, 1.0));
713 try expectEqual(logq(math.inf(f128)), math.inf(f128));
714 try expect(math.isNan(logq(-1.0)));
715 try expect(math.isNan(logq(-math.inf(f128))));
716 try expect(math.isNan(logq(math.nan(f128))));
717 try expect(math.isNan(logq(math.snan(f128))));
723 // is the correctly rounded value of log_f128(math.e)
724 try expectApproxEqRel(log_f128(math.e), 1.0, math.floatEpsAt(f128, 1.0));
725 try expectEqual(log_f128(math.inf(f128)), math.inf(f128));
726 try expect(math.isNan(log_f128(-1.0)));
727 try expect(math.isNan(log_f128(-math.inf(f128))));
728 try expect(math.isNan(log_f128(math.nan(f128))));
729 try expect(math.isNan(log_f128(math.snan(f128))));
718730}
719731
720732test "logq() boundary" {
721 try expectEqual(logq(0x1.ffffffffffffffffffffffffffffp16383), 0x1.62e42fefa39ef35793c7673007e6p13); // Max input value
722 try expectEqual(logq(0x1p-16494), -0x1.6546282207802c89d24d65e96274p13); // Min positive input value
723 try expect(math.isNan(logq(-0x1p-16494))); // Min negative input value
724 try expectEqual(logq(0x1.0000000000000000000000000001p0), 0x1.ffffffffffffffffffffffffffffp-113); // Last value before result reaches +0
725 try expectEqual(logq(0x1.ffffffffffffffffffffffffffffp-1), -0x1p-113); // Last value before result reaches -0
726 try expectEqual(logq(0x1p-16382), -0x1.62d918ce2421d65ff90ac8f4ce66p13); // First subnormal
727 try expect(math.isNan(logq(-0x1p-16382))); // First negative subnormal
733 try expectEqual(log_f128(0x1.ffffffffffffffffffffffffffffp16383), 0x1.62e42fefa39ef35793c7673007e6p13); // Max input value
734 try expectEqual(log_f128(0x1p-16494), -0x1.6546282207802c89d24d65e96274p13); // Min positive input value
735 try expect(math.isNan(log_f128(-0x1p-16494))); // Min negative input value
736 try expectEqual(log_f128(0x1.0000000000000000000000000001p0), 0x1.ffffffffffffffffffffffffffffp-113); // Last value before result reaches +0
737 try expectEqual(log_f128(0x1.ffffffffffffffffffffffffffffp-1), -0x1p-113); // Last value before result reaches -0
738 try expectEqual(log_f128(0x1p-16382), -0x1.62d918ce2421d65ff90ac8f4ce66p13); // First subnormal
739 try expect(math.isNan(log_f128(-0x1p-16382))); // First negative subnormal
728740}
729741
730742test "logq() sanity" {
731 try expectEqual(logq(4.151135979023751199079583784623537e-4), -7.7869583453055243113993340258295346e0);
732 try expectEqual(logq(9.614234245933828353176667689130293e-14), -2.9972946567656004014786271559909435e1);
733 try expectEqual(logq(1.012889803704721484375e13), 2.9946413646144315985379677542014356e1);
734 try expectEqual(logq(2.397741857206453154086912e24), 5.613656963346284538829358703465392e1);
735 try expectEqual(logq(3.442377567808290806386655232e27), 6.3405959896920645453203836625419693e1);
736 try expectEqual(logq(1.0689155158234028407981544637594257e-8), -1.835403614606774451014272772421113e1);
737 try expectEqual(logq(1.4813913545768791536741499811327596e-10), -2.263286917934202003739900705050399e1);
738 try expectEqual(logq(4.518948965781299591064453125e10), 2.453413036705097282892685629562292e1);
739 try expectEqual(logq(1.200355637363589375e14), 3.2418809179272977400408325788186897e1);
740 try expectEqual(logq(6.6145398293682003021240234375e9), 2.261253606737223221601998075023261e1);
741 try expectEqual(logq(5.16179116383965741056e20), 4.7692985503915646405875629300054525e1);
743 try expectEqual(log_f128(4.151135979023751199079583784623537e-4), -7.7869583453055243113993340258295346e0);
744 try expectEqual(log_f128(9.614234245933828353176667689130293e-14), -2.9972946567656004014786271559909435e1);
745 try expectEqual(log_f128(1.012889803704721484375e13), 2.9946413646144315985379677542014356e1);
746 try expectEqual(log_f128(2.397741857206453154086912e24), 5.613656963346284538829358703465392e1);
747 try expectEqual(log_f128(3.442377567808290806386655232e27), 6.3405959896920645453203836625419693e1);
748 try expectEqual(log_f128(1.0689155158234028407981544637594257e-8), -1.835403614606774451014272772421113e1);
749 try expectEqual(log_f128(1.4813913545768791536741499811327596e-10), -2.263286917934202003739900705050399e1);
750 try expectEqual(log_f128(4.518948965781299591064453125e10), 2.453413036705097282892685629562292e1);
751 try expectEqual(log_f128(1.200355637363589375e14), 3.2418809179272977400408325788186897e1);
752 try expectEqual(log_f128(6.6145398293682003021240234375e9), 2.261253606737223221601998075023261e1);
753 try expectEqual(log_f128(5.16179116383965741056e20), 4.7692985503915646405875629300054525e1);
742754 // testing near 1
743 try expectEqual(logq(1.026586845186097528392910049888087e0), 2.6239557099466251374193777672800004e-2);
744 try expectEqual(logq(9.878220373715243107115568932385941e-1), -1.2252721576456821219120474521538944e-2);
745 try expectEqual(logq(9.417921077517196685541245315675951e-1), -5.997072116986790367958922503195352e-2);
746 try expectEqual(logq(1.043095786320424537962914257605007e0), 4.219300911769055080390811808602425e-2);
747 try expectEqual(logq(1.019043049323190694932517175175235e0), 1.8863999985309781522599012445793722e-2);
755 try expectEqual(log_f128(1.026586845186097528392910049888087e0), 2.6239557099466251374193777672800004e-2);
756 try expectEqual(log_f128(9.878220373715243107115568932385941e-1), -1.2252721576456821219120474521538944e-2);
757 try expectEqual(log_f128(9.417921077517196685541245315675951e-1), -5.997072116986790367958922503195352e-2);
758 try expectEqual(log_f128(1.043095786320424537962914257605007e0), 4.219300911769055080390811808602425e-2);
759 try expectEqual(log_f128(1.019043049323190694932517175175235e0), 1.8863999985309781522599012445793722e-2);
748760}
lib/compiler_rt/log10.zig+114-102
......@@ -18,19 +18,22 @@ comptime {
1818 symbol(&log10f, "log10f");
1919 symbol(&log10, "log10");
2020 symbol(&__log10x, "__log10x");
21 if (compiler_rt.want_ppc_abi) {
22 symbol(&log10q, "log10f128");
23 }
24 symbol(&log10q, "log10q");
21 symbol(&log10q, "log10f128");
2522 symbol(&log10l, "log10l");
2623}
2724
28pub fn __log10h(a: f16) callconv(.c) f16 {
25fn __log10h(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
26 return compiler_rt.f16.toAbi(log10_f16(compiler_rt.f16.fromAbi(a)));
27}
28pub fn log10_f16(a: f16) f16 {
2929 // TODO: more efficient implementation
30 return @floatCast(log10f(a));
30 return @floatCast(log10_f32(a));
3131}
3232
33pub fn log10f(x_: f32) callconv(.c) f32 {
33fn log10f(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
34 return compiler_rt.f32.toAbi(log10_f32(compiler_rt.f32.fromAbi(a)));
35}
36pub fn log10_f32(x_: f32) f32 {
3437 const ivln10hi: f32 = 4.3432617188e-01;
3538 const ivln10lo: f32 = -3.1689971365e-05;
3639 const log10_2hi: f32 = 3.0102920532e-01;
......@@ -90,7 +93,10 @@ pub fn log10f(x_: f32) callconv(.c) f32 {
9093 return dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi + hi * ivln10hi + dk * log10_2hi;
9194}
9295
93pub fn log10(x_: f64) callconv(.c) f64 {
96fn log10(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
97 return compiler_rt.f64.toAbi(log10_f64(compiler_rt.f64.fromAbi(a)));
98}
99pub fn log10_f64(x_: f64) f64 {
94100 const ivln10hi: f64 = 4.34294481878168880939e-01;
95101 const ivln10lo: f64 = 2.50829467116452752298e-11;
96102 const log10_2hi: f64 = 3.01029995663611771306e-01;
......@@ -165,11 +171,17 @@ pub fn log10(x_: f64) callconv(.c) f64 {
165171 return val_lo + val_hi;
166172}
167173
168pub fn __log10x(a: f80) callconv(.c) f80 {
174fn __log10x(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
175 return compiler_rt.f80.toAbi(log10_f80(compiler_rt.f80.fromAbi(a)));
176}
177pub fn log10_f80(a: f80) f80 {
169178 // TODO: more efficient implementation
170 return @floatCast(log10q(a));
179 return @floatCast(log10_f128(a));
171180}
172181
182fn log10q(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
183 return compiler_rt.f128.toAbi(log10_f128(compiler_rt.f128.fromAbi(a)));
184}
173185/// Implementation of "Table-driven implementation of the logarithm function in IEEE floating-point arithmetic"
174186/// by PTP Tang in ACM Transactions on Mathematical Software (TOMS), 1990
175187///
......@@ -182,7 +194,7 @@ pub fn __log10x(a: f80) callconv(.c) f80 {
182194///
183195/// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case):
184196/// <= 0.5 ulp: 99.96%, worst case <= 0.565 ulp
185pub fn log10q(x: f128) callconv(.c) f128 {
197pub fn log10_f128(x: f128) f128 {
186198 const impl = @import("log_f128.zig");
187199
188200 if (impl.specialCases(x)) |y|
......@@ -359,124 +371,124 @@ pub fn log10q(x: f128) callconv(.c) f128 {
359371
360372pub fn log10l(x: c_longdouble) callconv(.c) c_longdouble {
361373 switch (@typeInfo(c_longdouble).float.bits) {
362 64 => return log10(x),
363 80 => return __log10x(x),
364 128 => return log10q(x),
365 else => @compileError("unreachable"),
374 64 => return log10_f64(x),
375 80 => return log10_f80(x),
376 128 => return log10_f128(x),
377 else => comptime unreachable,
366378 }
367379}
368380
369381test "log10f() special" {
370 try expectEqual(log10f(0.0), -math.inf(f32));
371 try expectEqual(log10f(-0.0), -math.inf(f32));
372 try expect(math.isPositiveZero(log10f(1.0)));
373 try expectEqual(log10f(10.0), 1.0);
374 try expectEqual(log10f(0.1), -1.0);
375 try expectEqual(log10f(math.inf(f32)), math.inf(f32));
376 try expect(math.isNan(log10f(-1.0)));
377 try expect(math.isNan(log10f(-math.inf(f32))));
378 try expect(math.isNan(log10f(math.nan(f32))));
379 try expect(math.isNan(log10f(math.snan(f32))));
382 try expectEqual(log10_f32(0.0), -math.inf(f32));
383 try expectEqual(log10_f32(-0.0), -math.inf(f32));
384 try expect(math.isPositiveZero(log10_f32(1.0)));
385 try expectEqual(log10_f32(10.0), 1.0);
386 try expectEqual(log10_f32(0.1), -1.0);
387 try expectEqual(log10_f32(math.inf(f32)), math.inf(f32));
388 try expect(math.isNan(log10_f32(-1.0)));
389 try expect(math.isNan(log10_f32(-math.inf(f32))));
390 try expect(math.isNan(log10_f32(math.nan(f32))));
391 try expect(math.isNan(log10_f32(math.snan(f32))));
380392}
381393
382394test "log10f() sanity" {
383 try expect(math.isNan(log10f(-0x1.0223a0p+3)));
384 try expectEqual(log10f(0x1.161868p+2), 0x1.46a9bcp-1);
385 try expect(math.isNan(log10f(-0x1.0c34b4p+3)));
386 try expect(math.isNan(log10f(-0x1.a206f0p+2)));
387 try expectEqual(log10f(0x1.288bbcp+3), 0x1.ef1300p-1);
388 try expectEqual(log10f(0x1.52efd0p-1), -0x1.6ee6dcp-3); // Disagrees with GCC in last bit
389 try expect(math.isNan(log10f(-0x1.a05cc8p-2)));
390 try expectEqual(log10f(0x1.1f9efap-1), -0x1.0075ccp-2);
391 try expectEqual(log10f(0x1.8c5db0p-1), -0x1.c75df8p-4);
392 try expect(math.isNan(log10f(-0x1.5b86eap-1)));
395 try expect(math.isNan(log10_f32(-0x1.0223a0p+3)));
396 try expectEqual(log10_f32(0x1.161868p+2), 0x1.46a9bcp-1);
397 try expect(math.isNan(log10_f32(-0x1.0c34b4p+3)));
398 try expect(math.isNan(log10_f32(-0x1.a206f0p+2)));
399 try expectEqual(log10_f32(0x1.288bbcp+3), 0x1.ef1300p-1);
400 try expectEqual(log10_f32(0x1.52efd0p-1), -0x1.6ee6dcp-3); // Disagrees with GCC in last bit
401 try expect(math.isNan(log10_f32(-0x1.a05cc8p-2)));
402 try expectEqual(log10_f32(0x1.1f9efap-1), -0x1.0075ccp-2);
403 try expectEqual(log10_f32(0x1.8c5db0p-1), -0x1.c75df8p-4);
404 try expect(math.isNan(log10_f32(-0x1.5b86eap-1)));
393405}
394406
395407test "log10f() boundary" {
396 try expectEqual(log10f(0x1.fffffep+127), 0x1.344136p+5); // Max input value
397 try expectEqual(log10f(0x1p-149), -0x1.66d3e8p+5); // Min positive input value
398 try expect(math.isNan(log10f(-0x1p-149))); // Min negative input value
399 try expectEqual(log10f(0x1.000002p+0), 0x1.bcb7b0p-25); // Last value before result reaches +0
400 try expectEqual(log10f(0x1.fffffep-1), -0x1.bcb7b2p-26); // Last value before result reaches -0
401 try expectEqual(log10f(0x1p-126), -0x1.2f7030p+5); // First subnormal
402 try expect(math.isNan(log10f(-0x1p-126))); // First negative subnormal
408 try expectEqual(log10_f32(0x1.fffffep+127), 0x1.344136p+5); // Max input value
409 try expectEqual(log10_f32(0x1p-149), -0x1.66d3e8p+5); // Min positive input value
410 try expect(math.isNan(log10_f32(-0x1p-149))); // Min negative input value
411 try expectEqual(log10_f32(0x1.000002p+0), 0x1.bcb7b0p-25); // Last value before result reaches +0
412 try expectEqual(log10_f32(0x1.fffffep-1), -0x1.bcb7b2p-26); // Last value before result reaches -0
413 try expectEqual(log10_f32(0x1p-126), -0x1.2f7030p+5); // First subnormal
414 try expect(math.isNan(log10_f32(-0x1p-126))); // First negative subnormal
403415}
404416
405417test "log10() special" {
406 try expectEqual(log10(0.0), -math.inf(f64));
407 try expectEqual(log10(-0.0), -math.inf(f64));
408 try expect(math.isPositiveZero(log10(1.0)));
409 try expectEqual(log10(10.0), 1.0);
410 try expectEqual(log10(0.1), -1.0);
411 try expectEqual(log10(math.inf(f64)), math.inf(f64));
412 try expect(math.isNan(log10(-1.0)));
413 try expect(math.isNan(log10(-math.inf(f64))));
414 try expect(math.isNan(log10(math.nan(f64))));
415 try expect(math.isNan(log10(math.snan(f64))));
418 try expectEqual(log10_f64(0.0), -math.inf(f64));
419 try expectEqual(log10_f64(-0.0), -math.inf(f64));
420 try expect(math.isPositiveZero(log10_f64(1.0)));
421 try expectEqual(log10_f64(10.0), 1.0);
422 try expectEqual(log10_f64(0.1), -1.0);
423 try expectEqual(log10_f64(math.inf(f64)), math.inf(f64));
424 try expect(math.isNan(log10_f64(-1.0)));
425 try expect(math.isNan(log10_f64(-math.inf(f64))));
426 try expect(math.isNan(log10_f64(math.nan(f64))));
427 try expect(math.isNan(log10_f64(math.snan(f64))));
416428}
417429
418430test "log10() sanity" {
419 try expect(math.isNan(log10(-0x1.02239f3c6a8f1p+3)));
420 try expectEqual(log10(0x1.161868e18bc67p+2), 0x1.46a9bd1d2eb87p-1);
421 try expect(math.isNan(log10(-0x1.0c34b3e01e6e7p+3)));
422 try expect(math.isNan(log10(-0x1.a206f0a19dcc4p+2)));
423 try expectEqual(log10(0x1.288bbb0d6a1e6p+3), 0x1.ef12fff994862p-1);
424 try expectEqual(log10(0x1.52efd0cd80497p-1), -0x1.6ee6db5a155cbp-3);
425 try expect(math.isNan(log10(-0x1.a05cc754481d1p-2)));
426 try expectEqual(log10(0x1.1f9ef934745cbp-1), -0x1.0075cda79d321p-2);
427 try expectEqual(log10(0x1.8c5db097f7442p-1), -0x1.c75df6442465ap-4);
428 try expect(math.isNan(log10(-0x1.5b86ea8118a0ep-1)));
431 try expect(math.isNan(log10_f64(-0x1.02239f3c6a8f1p+3)));
432 try expectEqual(log10_f64(0x1.161868e18bc67p+2), 0x1.46a9bd1d2eb87p-1);
433 try expect(math.isNan(log10_f64(-0x1.0c34b3e01e6e7p+3)));
434 try expect(math.isNan(log10_f64(-0x1.a206f0a19dcc4p+2)));
435 try expectEqual(log10_f64(0x1.288bbb0d6a1e6p+3), 0x1.ef12fff994862p-1);
436 try expectEqual(log10_f64(0x1.52efd0cd80497p-1), -0x1.6ee6db5a155cbp-3);
437 try expect(math.isNan(log10_f64(-0x1.a05cc754481d1p-2)));
438 try expectEqual(log10_f64(0x1.1f9ef934745cbp-1), -0x1.0075cda79d321p-2);
439 try expectEqual(log10_f64(0x1.8c5db097f7442p-1), -0x1.c75df6442465ap-4);
440 try expect(math.isNan(log10_f64(-0x1.5b86ea8118a0ep-1)));
429441}
430442
431443test "log10() boundary" {
432 try expectEqual(log10(0x1.fffffffffffffp+1023), 0x1.34413509f79ffp+8); // Max input value
433 try expectEqual(log10(0x1p-1074), -0x1.434e6420f4374p+8); // Min positive input value
434 try expect(math.isNan(log10(-0x1p-1074))); // Min negative input value
435 try expectEqual(log10(0x1.0000000000001p+0), 0x1.bcb7b1526e50dp-54); // Last value before result reaches +0
436 try expectEqual(log10(0x1.fffffffffffffp-1), -0x1.bcb7b1526e50fp-55); // Last value before result reaches -0
437 try expectEqual(log10(0x1p-1022), -0x1.33a7146f72a42p+8); // First subnormal
438 try expect(math.isNan(log10(-0x1p-1022))); // First negative subnormal
444 try expectEqual(log10_f64(0x1.fffffffffffffp+1023), 0x1.34413509f79ffp+8); // Max input value
445 try expectEqual(log10_f64(0x1p-1074), -0x1.434e6420f4374p+8); // Min positive input value
446 try expect(math.isNan(log10_f64(-0x1p-1074))); // Min negative input value
447 try expectEqual(log10_f64(0x1.0000000000001p+0), 0x1.bcb7b1526e50dp-54); // Last value before result reaches +0
448 try expectEqual(log10_f64(0x1.fffffffffffffp-1), -0x1.bcb7b1526e50fp-55); // Last value before result reaches -0
449 try expectEqual(log10_f64(0x1p-1022), -0x1.33a7146f72a42p+8); // First subnormal
450 try expect(math.isNan(log10_f64(-0x1p-1022))); // First negative subnormal
439451}
440452
441453test "log10q() special" {
442 try expectEqual(log10q(0.0), -math.inf(f128));
443 try expectEqual(log10q(-0.0), -math.inf(f128));
444 try expect(math.isPositiveZero(log10q(1.0)));
445 try expectEqual(log10q(10.0), 1.0);
446 try expectEqual(log10q(0.1), -1.0);
447 try expectEqual(log10q(math.inf(f128)), math.inf(f128));
448 try expect(math.isNan(log10q(-1.0)));
449 try expect(math.isNan(log10q(-math.inf(f128))));
450 try expect(math.isNan(log10q(math.nan(f128))));
451 try expect(math.isNan(log10q(math.snan(f128))));
454 try expectEqual(log10_f128(0.0), -math.inf(f128));
455 try expectEqual(log10_f128(-0.0), -math.inf(f128));
456 try expect(math.isPositiveZero(log10_f128(1.0)));
457 try expectEqual(log10_f128(10.0), 1.0);
458 try expectEqual(log10_f128(0.1), -1.0);
459 try expectEqual(log10_f128(math.inf(f128)), math.inf(f128));
460 try expect(math.isNan(log10_f128(-1.0)));
461 try expect(math.isNan(log10_f128(-math.inf(f128))));
462 try expect(math.isNan(log10_f128(math.nan(f128))));
463 try expect(math.isNan(log10_f128(math.snan(f128))));
452464}
453465
454466test "log10q() sanity" {
455 try expectEqual(log10q(2.1744503117482705706605762784484114e1949), 1.949337349488073972035715318447419e3);
456 try expectEqual(log10q(2.3695331993665660983204066767386505e2150), 2.1503746627979481420243846411400265e3);
457 try expectEqual(log10q(1.8071775728314983136779370752110857e612), 6.122570008283284411311428111991705e2);
458 try expectEqual(log10q(2.612170297226630737309271722008693e-2629), -2.628582998513179919647069989114319e3);
459 try expectEqual(log10q(8.485091636263895897993044621224502e-3748), -3.7470713434630800881474518447042895e3);
460 try expectEqual(log10q(4.3668077579803801413736022136116655e-4051), -4.0503598359268068567757367259544416e3);
461 try expectEqual(log10q(2.9321353260885285826237030859036923e4830), 4.830467184010313310864606285356782e3);
462 try expectEqual(log10q(6.6119754254652455408442826553161645e-1417), -1.416179668769227128601620567685071e3);
463 try expectEqual(log10q(5.2459104673488555418645321788108695e4178), 4.178719820874155944446586083585479e3);
464 try expectEqual(log10q(7.809812890804996586377267218360886e-418), -4.1710735937091966815220294599598215e2);
467 try expectEqual(log10_f128(2.1744503117482705706605762784484114e1949), 1.949337349488073972035715318447419e3);
468 try expectEqual(log10_f128(2.3695331993665660983204066767386505e2150), 2.1503746627979481420243846411400265e3);
469 try expectEqual(log10_f128(1.8071775728314983136779370752110857e612), 6.122570008283284411311428111991705e2);
470 try expectEqual(log10_f128(2.612170297226630737309271722008693e-2629), -2.628582998513179919647069989114319e3);
471 try expectEqual(log10_f128(8.485091636263895897993044621224502e-3748), -3.7470713434630800881474518447042895e3);
472 try expectEqual(log10_f128(4.3668077579803801413736022136116655e-4051), -4.0503598359268068567757367259544416e3);
473 try expectEqual(log10_f128(2.9321353260885285826237030859036923e4830), 4.830467184010313310864606285356782e3);
474 try expectEqual(log10_f128(6.6119754254652455408442826553161645e-1417), -1.416179668769227128601620567685071e3);
475 try expectEqual(log10_f128(5.2459104673488555418645321788108695e4178), 4.178719820874155944446586083585479e3);
476 try expectEqual(log10_f128(7.809812890804996586377267218360886e-418), -4.1710735937091966815220294599598215e2);
465477 // testing near 1
466 try expectEqual(log10q(1.0291437165967803055610652052109798e0), 1.2476026819466393459130418401605807e-2);
467 try expectEqual(log10q(1.043095786320424537962914257605007e0), 1.8324191034706598279642145362763252e-2);
468 try expectEqual(log10q(9.900264873754467234601150948947179e-1), -4.3531860417287584780652055666513634e-3);
469 try expectEqual(log10q(1.038295346547007736348611217636062e0), 1.6320907588397540309035279023485962e-2);
470 try expectEqual(log10q(9.821701941230028324703038578036285e-1), -7.813249520562034832371814409278784e-3);
471 try expectEqual(log10q(9.593555263530179895381522214847791e-1), -1.8020418356217558657107271163588764e-2);
478 try expectEqual(log10_f128(1.0291437165967803055610652052109798e0), 1.2476026819466393459130418401605807e-2);
479 try expectEqual(log10_f128(1.043095786320424537962914257605007e0), 1.8324191034706598279642145362763252e-2);
480 try expectEqual(log10_f128(9.900264873754467234601150948947179e-1), -4.3531860417287584780652055666513634e-3);
481 try expectEqual(log10_f128(1.038295346547007736348611217636062e0), 1.6320907588397540309035279023485962e-2);
482 try expectEqual(log10_f128(9.821701941230028324703038578036285e-1), -7.813249520562034832371814409278784e-3);
483 try expectEqual(log10_f128(9.593555263530179895381522214847791e-1), -1.8020418356217558657107271163588764e-2);
472484}
473485
474486test "log10q() boundary" {
475 try expectEqual(log10q(0x1.ffffffffffffffffffffffffffffp16383), 0x1.34413509f79fef311f12b35816f9p12); // Max input value
476 try expectEqual(log10q(0x1p-16494), -0x1.3653051d20c18a143b801b7c5661p12); // Min positive input value
477 try expect(math.isNan(log10q(-0x1p-16494))); // Min negative input value
478 try expectEqual(log10q(0x1.0000000000000000000000000001p0), 0x1.bcb7b1526e50e32a6ab7555f5a67p-114); // Last value before result reaches +0
479 try expectEqual(log10q(0x1.ffffffffffffffffffffffffffffp-1), -0x1.bcb7b1526e50e32a6ab7555f5a68p-115); // Last value before result reaches -0
480 try expectEqual(log10q(0x1p-16382), -0x1.343793004f503231a589bac27c38p12); // First subnormal
481 try expect(math.isNan(log10q(-0x1p-16382))); // First negative subnormal
487 try expectEqual(log10_f128(0x1.ffffffffffffffffffffffffffffp16383), 0x1.34413509f79fef311f12b35816f9p12); // Max input value
488 try expectEqual(log10_f128(0x1p-16494), -0x1.3653051d20c18a143b801b7c5661p12); // Min positive input value
489 try expect(math.isNan(log10_f128(-0x1p-16494))); // Min negative input value
490 try expectEqual(log10_f128(0x1.0000000000000000000000000001p0), 0x1.bcb7b1526e50e32a6ab7555f5a67p-114); // Last value before result reaches +0
491 try expectEqual(log10_f128(0x1.ffffffffffffffffffffffffffffp-1), -0x1.bcb7b1526e50e32a6ab7555f5a68p-115); // Last value before result reaches -0
492 try expectEqual(log10_f128(0x1p-16382), -0x1.343793004f503231a589bac27c38p12); // First subnormal
493 try expect(math.isNan(log10_f128(-0x1p-16382))); // First negative subnormal
482494}
lib/compiler_rt/log2.zig+106-94
......@@ -19,19 +19,22 @@ comptime {
1919 symbol(&log2f, "log2f");
2020 symbol(&log2, "log2");
2121 symbol(&__log2x, "__log2x");
22 if (compiler_rt.want_ppc_abi) {
23 symbol(&log2q, "log2f128");
24 }
25 symbol(&log2q, "log2q");
22 symbol(&log2q, "log2f128");
2623 symbol(&log2l, "log2l");
2724}
2825
29pub fn __log2h(a: f16) callconv(.c) f16 {
26fn __log2h(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
27 return compiler_rt.f16.toAbi(log2_f16(compiler_rt.f16.fromAbi(a)));
28}
29pub fn log2_f16(a: f16) f16 {
3030 // TODO: more efficient implementation
31 return @floatCast(log2f(a));
31 return @floatCast(log2_f32(a));
3232}
3333
34pub fn log2f(x_: f32) callconv(.c) f32 {
34fn log2f(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
35 return compiler_rt.f32.toAbi(log2_f32(compiler_rt.f32.fromAbi(a)));
36}
37pub fn log2_f32(x_: f32) f32 {
3538 const ivln2hi: f32 = 1.4428710938e+00;
3639 const ivln2lo: f32 = -1.7605285393e-04;
3740 const Lg1: f32 = 0xaaaaaa.0p-24;
......@@ -87,7 +90,10 @@ pub fn log2f(x_: f32) callconv(.c) f32 {
8790 return (lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + @as(f32, @floatFromInt(k));
8891}
8992
90pub fn log2(x_: f64) callconv(.c) f64 {
93fn log2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
94 return compiler_rt.f64.toAbi(log2_f64(compiler_rt.f64.fromAbi(a)));
95}
96pub fn log2_f64(x_: f64) f64 {
9197 const ivln2hi: f64 = 1.44269504072144627571e+00;
9298 const ivln2lo: f64 = 1.67517131648865118353e-10;
9399 const Lg1: f64 = 6.666666666666735130e-01;
......@@ -158,11 +164,17 @@ pub fn log2(x_: f64) callconv(.c) f64 {
158164 return val_lo + val_hi;
159165}
160166
161pub fn __log2x(a: f80) callconv(.c) f80 {
167fn __log2x(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
168 return compiler_rt.f80.toAbi(log2_f80(compiler_rt.f80.fromAbi(a)));
169}
170pub fn log2_f80(a: f80) f80 {
162171 // TODO: more efficient implementation
163 return @floatCast(log2q(a));
172 return @floatCast(log2_f128(a));
164173}
165174
175fn log2q(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
176 return compiler_rt.f128.toAbi(log2_f128(compiler_rt.f128.fromAbi(a)));
177}
166178/// Implementation of "Table-driven implementation of the logarithm function in IEEE floating-point arithmetic"
167179/// by PTP Tang in ACM Transactions on Mathematical Software (TOMS), 1990
168180///
......@@ -175,7 +187,7 @@ pub fn __log2x(a: f80) callconv(.c) f80 {
175187///
176188/// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case):
177189/// <= 0.5 ulp: 99.86%, worst case <= 0.546 ulp
178pub fn log2q(x: f128) callconv(.c) f128 {
190pub fn log2_f128(x: f128) f128 {
179191 const impl = @import("log_f128.zig");
180192
181193 if (impl.specialCases(x)) |y|
......@@ -351,117 +363,117 @@ pub fn log2q(x: f128) callconv(.c) f128 {
351363
352364pub fn log2l(x: c_longdouble) callconv(.c) c_longdouble {
353365 switch (@typeInfo(c_longdouble).float.bits) {
354 64 => return log2(x),
355 80 => return __log2x(x),
356 128 => return log2q(x),
357 else => @compileError("unreachable"),
366 64 => return log2_f64(x),
367 80 => return log2_f80(x),
368 128 => return log2_f128(x),
369 else => comptime unreachable,
358370 }
359371}
360372
361373test "log2f() special" {
362 try expectEqual(log2f(0.0), -math.inf(f32));
363 try expectEqual(log2f(-0.0), -math.inf(f32));
364 try expect(math.isPositiveZero(log2f(1.0)));
365 try expectEqual(log2f(2.0), 1.0);
366 try expectEqual(log2f(math.inf(f32)), math.inf(f32));
367 try expect(math.isNan(log2f(-1.0)));
368 try expect(math.isNan(log2f(-math.inf(f32))));
369 try expect(math.isNan(log2f(math.nan(f32))));
370 try expect(math.isNan(log2f(math.snan(f32))));
374 try expectEqual(log2_f32(0.0), -math.inf(f32));
375 try expectEqual(log2_f32(-0.0), -math.inf(f32));
376 try expect(math.isPositiveZero(log2_f32(1.0)));
377 try expectEqual(log2_f32(2.0), 1.0);
378 try expectEqual(log2_f32(math.inf(f32)), math.inf(f32));
379 try expect(math.isNan(log2_f32(-1.0)));
380 try expect(math.isNan(log2_f32(-math.inf(f32))));
381 try expect(math.isNan(log2_f32(math.nan(f32))));
382 try expect(math.isNan(log2_f32(math.snan(f32))));
371383}
372384
373385test "log2f() sanity" {
374 try expect(math.isNan(log2f(-0x1.0223a0p+3)));
375 try expectEqual(log2f(0x1.161868p+2), 0x1.0f49acp+1);
376 try expect(math.isNan(log2f(-0x1.0c34b4p+3)));
377 try expect(math.isNan(log2f(-0x1.a206f0p+2)));
378 try expectEqual(log2f(0x1.288bbcp+3), 0x1.9b2676p+1);
379 try expectEqual(log2f(0x1.52efd0p-1), -0x1.30b494p-1); // Disagrees with GCC in last bit
380 try expect(math.isNan(log2f(-0x1.a05cc8p-2)));
381 try expectEqual(log2f(0x1.1f9efap-1), -0x1.a9f89ap-1);
382 try expectEqual(log2f(0x1.8c5db0p-1), -0x1.7a2c96p-2);
383 try expect(math.isNan(log2f(-0x1.5b86eap-1)));
386 try expect(math.isNan(log2_f32(-0x1.0223a0p+3)));
387 try expectEqual(log2_f32(0x1.161868p+2), 0x1.0f49acp+1);
388 try expect(math.isNan(log2_f32(-0x1.0c34b4p+3)));
389 try expect(math.isNan(log2_f32(-0x1.a206f0p+2)));
390 try expectEqual(log2_f32(0x1.288bbcp+3), 0x1.9b2676p+1);
391 try expectEqual(log2_f32(0x1.52efd0p-1), -0x1.30b494p-1); // Disagrees with GCC in last bit
392 try expect(math.isNan(log2_f32(-0x1.a05cc8p-2)));
393 try expectEqual(log2_f32(0x1.1f9efap-1), -0x1.a9f89ap-1);
394 try expectEqual(log2_f32(0x1.8c5db0p-1), -0x1.7a2c96p-2);
395 try expect(math.isNan(log2_f32(-0x1.5b86eap-1)));
384396}
385397
386398test "log2f() boundary" {
387 try expectEqual(log2f(0x1.fffffep+127), 0x1p+7); // Max input value
388 try expectEqual(log2f(0x1p-149), -0x1.2ap+7); // Min positive input value
389 try expect(math.isNan(log2f(-0x1p-149))); // Min negative input value
390 try expectEqual(log2f(0x1.000002p+0), 0x1.715474p-23); // Last value before result reaches +0
391 try expectEqual(log2f(0x1.fffffep-1), -0x1.715478p-24); // Last value before result reaches -0
392 try expectEqual(log2f(0x1p-126), -0x1.f8p+6); // First subnormal
393 try expect(math.isNan(log2f(-0x1p-126))); // First negative subnormal
399 try expectEqual(log2_f32(0x1.fffffep+127), 0x1p+7); // Max input value
400 try expectEqual(log2_f32(0x1p-149), -0x1.2ap+7); // Min positive input value
401 try expect(math.isNan(log2_f32(-0x1p-149))); // Min negative input value
402 try expectEqual(log2_f32(0x1.000002p+0), 0x1.715474p-23); // Last value before result reaches +0
403 try expectEqual(log2_f32(0x1.fffffep-1), -0x1.715478p-24); // Last value before result reaches -0
404 try expectEqual(log2_f32(0x1p-126), -0x1.f8p+6); // First subnormal
405 try expect(math.isNan(log2_f32(-0x1p-126))); // First negative subnormal
394406
395407}
396408
397409test "log2() special" {
398 try expectEqual(log2(0.0), -math.inf(f64));
399 try expectEqual(log2(-0.0), -math.inf(f64));
400 try expect(math.isPositiveZero(log2(1.0)));
401 try expectEqual(log2(2.0), 1.0);
402 try expectEqual(log2(math.inf(f64)), math.inf(f64));
403 try expect(math.isNan(log2(-1.0)));
404 try expect(math.isNan(log2(-math.inf(f64))));
405 try expect(math.isNan(log2(math.nan(f64))));
406 try expect(math.isNan(log2(math.snan(f64))));
410 try expectEqual(log2_f64(0.0), -math.inf(f64));
411 try expectEqual(log2_f64(-0.0), -math.inf(f64));
412 try expect(math.isPositiveZero(log2_f64(1.0)));
413 try expectEqual(log2_f64(2.0), 1.0);
414 try expectEqual(log2_f64(math.inf(f64)), math.inf(f64));
415 try expect(math.isNan(log2_f64(-1.0)));
416 try expect(math.isNan(log2_f64(-math.inf(f64))));
417 try expect(math.isNan(log2_f64(math.nan(f64))));
418 try expect(math.isNan(log2_f64(math.snan(f64))));
407419}
408420
409421test "log2() sanity" {
410 try expect(math.isNan(log2(-0x1.02239f3c6a8f1p+3)));
411 try expectEqual(log2(0x1.161868e18bc67p+2), 0x1.0f49ac3838580p+1);
412 try expect(math.isNan(log2(-0x1.0c34b3e01e6e7p+3)));
413 try expect(math.isNan(log2(-0x1.a206f0a19dcc4p+2)));
414 try expectEqual(log2(0x1.288bbb0d6a1e6p+3), 0x1.9b26760c2a57ep+1);
415 try expectEqual(log2(0x1.52efd0cd80497p-1), -0x1.30b490ef684c7p-1);
416 try expect(math.isNan(log2(-0x1.a05cc754481d1p-2)));
417 try expectEqual(log2(0x1.1f9ef934745cbp-1), -0x1.a9f89b5f5acb8p-1);
418 try expectEqual(log2(0x1.8c5db097f7442p-1), -0x1.7a2c947173f06p-2);
419 try expect(math.isNan(log2(-0x1.5b86ea8118a0ep-1)));
422 try expect(math.isNan(log2_f64(-0x1.02239f3c6a8f1p+3)));
423 try expectEqual(log2_f64(0x1.161868e18bc67p+2), 0x1.0f49ac3838580p+1);
424 try expect(math.isNan(log2_f64(-0x1.0c34b3e01e6e7p+3)));
425 try expect(math.isNan(log2_f64(-0x1.a206f0a19dcc4p+2)));
426 try expectEqual(log2_f64(0x1.288bbb0d6a1e6p+3), 0x1.9b26760c2a57ep+1);
427 try expectEqual(log2_f64(0x1.52efd0cd80497p-1), -0x1.30b490ef684c7p-1);
428 try expect(math.isNan(log2_f64(-0x1.a05cc754481d1p-2)));
429 try expectEqual(log2_f64(0x1.1f9ef934745cbp-1), -0x1.a9f89b5f5acb8p-1);
430 try expectEqual(log2_f64(0x1.8c5db097f7442p-1), -0x1.7a2c947173f06p-2);
431 try expect(math.isNan(log2_f64(-0x1.5b86ea8118a0ep-1)));
420432}
421433
422434test "log2() boundary" {
423 try expectEqual(log2(0x1.fffffffffffffp+1023), 0x1p+10); // Max input value
424 try expectEqual(log2(0x1p-1074), -0x1.0c8p+10); // Min positive input value
425 try expect(math.isNan(log2(-0x1p-1074))); // Min negative input value
426 try expectEqual(log2(0x1.0000000000001p+0), 0x1.71547652b82fdp-52); // Last value before result reaches +0
427 try expectEqual(log2(0x1.fffffffffffffp-1), -0x1.71547652b82fep-53); // Last value before result reaches -0
428 try expectEqual(log2(0x1p-1022), -0x1.ffp+9); // First subnormal
429 try expect(math.isNan(log2(-0x1p-1022))); // First negative subnormal
435 try expectEqual(log2_f64(0x1.fffffffffffffp+1023), 0x1p+10); // Max input value
436 try expectEqual(log2_f64(0x1p-1074), -0x1.0c8p+10); // Min positive input value
437 try expect(math.isNan(log2_f64(-0x1p-1074))); // Min negative input value
438 try expectEqual(log2_f64(0x1.0000000000001p+0), 0x1.71547652b82fdp-52); // Last value before result reaches +0
439 try expectEqual(log2_f64(0x1.fffffffffffffp-1), -0x1.71547652b82fep-53); // Last value before result reaches -0
440 try expectEqual(log2_f64(0x1p-1022), -0x1.ffp+9); // First subnormal
441 try expect(math.isNan(log2_f64(-0x1p-1022))); // First negative subnormal
430442}
431443
432444test "log2q() special" {
433 try expectEqual(log2q(0.0), -math.inf(f128));
434 try expectEqual(log2q(-0.0), -math.inf(f128));
435 try expect(math.isPositiveZero(log2q(1.0)));
436 try expectEqual(log2q(2.0), 1.0);
437 try expectEqual(log2q(math.inf(f128)), math.inf(f128));
438 try expect(math.isNan(log2q(-1.0)));
439 try expect(math.isNan(log2q(-math.inf(f128))));
440 try expect(math.isNan(log2q(math.nan(f128))));
441 try expect(math.isNan(log2q(math.snan(f128))));
445 try expectEqual(log2_f128(0.0), -math.inf(f128));
446 try expectEqual(log2_f128(-0.0), -math.inf(f128));
447 try expect(math.isPositiveZero(log2_f128(1.0)));
448 try expectEqual(log2_f128(2.0), 1.0);
449 try expectEqual(log2_f128(math.inf(f128)), math.inf(f128));
450 try expect(math.isNan(log2_f128(-1.0)));
451 try expect(math.isNan(log2_f128(-math.inf(f128))));
452 try expect(math.isNan(log2_f128(math.nan(f128))));
453 try expect(math.isNan(log2_f128(math.snan(f128))));
442454}
443455
444456test "log2q() boundary" {
445 try expectEqual(log2q(0x1.ffffffffffffffffffffffffffffp16383), 0x1p14); // Max input value
446 try expectEqual(log2q(0x1p-16494), -0x1.01b8p14); // Min positive input value
447 try expect(math.isNan(log2q(-0x1p-16494))); // Min negative input value
448 try expectEqual(log2q(0x1.0000000000000000000000000001p0), 0x1.71547652b82fe1777d0ffda0d23ap-112); // Last value before result reaches +0
449 try expectEqual(log2q(0x1.ffffffffffffffffffffffffffffp-1), -0x1.71547652b82fe1777d0ffda0d23bp-113); // Last value before result reaches -0
450 try expectEqual(log2q(0x1p-16382), -0x1.fffp13); // First subnormal
451 try expect(math.isNan(log2q(-0x1p-16382))); // First negative subnormal
457 try expectEqual(log2_f128(0x1.ffffffffffffffffffffffffffffp16383), 0x1p14); // Max input value
458 try expectEqual(log2_f128(0x1p-16494), -0x1.01b8p14); // Min positive input value
459 try expect(math.isNan(log2_f128(-0x1p-16494))); // Min negative input value
460 try expectEqual(log2_f128(0x1.0000000000000000000000000001p0), 0x1.71547652b82fe1777d0ffda0d23ap-112); // Last value before result reaches +0
461 try expectEqual(log2_f128(0x1.ffffffffffffffffffffffffffffp-1), -0x1.71547652b82fe1777d0ffda0d23bp-113); // Last value before result reaches -0
462 try expectEqual(log2_f128(0x1p-16382), -0x1.fffp13); // First subnormal
463 try expect(math.isNan(log2_f128(-0x1p-16382))); // First negative subnormal
452464}
453465
454466test "log2q() sanity" {
455 try expectEqual(log2q(8.0965013884643408203125e11), 3.955850767769801288865582596068254e1);
456 try expectEqual(log2q(8.346531942223744e15), 5.28900982928636641107356163006646e1);
457 try expectEqual(log2q(9.707809913413123613777865431464565e-20), -6.315941603809020445822192336703809e1);
458 try expectEqual(log2q(1.9179565888043380306021427656243352e-24), -7.878670421065570557450089031998522e1);
459 try expectEqual(log2q(2.5260048200126556877075044745936796e-25), -8.17113449801679676275805009400338e1);
460 try expectEqual(log2q(3.1170134002568967640399932861328125e7), 2.489366102143423848582774267206741e1);
467 try expectEqual(log2_f128(8.0965013884643408203125e11), 3.955850767769801288865582596068254e1);
468 try expectEqual(log2_f128(8.346531942223744e15), 5.28900982928636641107356163006646e1);
469 try expectEqual(log2_f128(9.707809913413123613777865431464565e-20), -6.315941603809020445822192336703809e1);
470 try expectEqual(log2_f128(1.9179565888043380306021427656243352e-24), -7.878670421065570557450089031998522e1);
471 try expectEqual(log2_f128(2.5260048200126556877075044745936796e-25), -8.17113449801679676275805009400338e1);
472 try expectEqual(log2_f128(3.1170134002568967640399932861328125e7), 2.489366102143423848582774267206741e1);
461473 // test near 1
462 try expectEqual(log2q(1.026586845186097528392910049888087e0), 3.7855678902522753591699367969189364e-2);
463 try expectEqual(log2q(1.0005582850578053877743656130405725e0), 8.052103367568488432896147152682078e-4);
464 try expectEqual(log2q(1.0370174103591254835765589348284266e0), 5.244011558596899945639244281954306e-2);
465 try expectEqual(log2q(1.0429996503525671713075162472250667e0), 6.073867421942172944687194557176633e-2);
466 try expectEqual(log2q(1.0383384027961064621892184334228659e0), 5.4276706191956281784022630732940314e-2);
474 try expectEqual(log2_f128(1.026586845186097528392910049888087e0), 3.7855678902522753591699367969189364e-2);
475 try expectEqual(log2_f128(1.0005582850578053877743656130405725e0), 8.052103367568488432896147152682078e-4);
476 try expectEqual(log2_f128(1.0370174103591254835765589348284266e0), 5.244011558596899945639244281954306e-2);
477 try expectEqual(log2_f128(1.0429996503525671713075162472250667e0), 6.073867421942172944687194557176633e-2);
478 try expectEqual(log2_f128(1.0383384027961064621892184334228659e0), 5.4276706191956281784022630732940314e-2);
467479}
lib/compiler_rt/memcpy.zig+1-1
......@@ -11,7 +11,7 @@ comptime {
1111 .visibility = compiler_rt.visibility,
1212 };
1313
14 if (builtin.mode == .ReleaseSmall or builtin.zig_backend == .stage2_aarch64)
14 if (builtin.mode == .small or builtin.zig_backend == .stage2_aarch64)
1515 @export(&memcpySmall, export_options)
1616 else
1717 @export(&memcpyFast, export_options);
lib/compiler_rt/memmove.zig+1-1
......@@ -14,7 +14,7 @@ comptime {
1414 .visibility = compiler_rt.visibility,
1515 };
1616
17 if (builtin.mode == .ReleaseSmall or builtin.zig_backend == .stage2_aarch64)
17 if (builtin.mode == .small or builtin.zig_backend == .stage2_aarch64)
1818 @export(&memmoveSmall, export_options)
1919 else
2020 @export(&memmoveFast, export_options);
lib/compiler_rt/mulc3.zig+75-10
......@@ -3,19 +3,80 @@ const isNan = std.math.isNan;
33const isInf = std.math.isInf;
44const copysign = std.math.copysign;
55
6pub fn Complex(comptime T: type) type {
7 return extern struct {
8 real: T,
9 imag: T,
10 };
6const compiler_rt = @import("../compiler_rt.zig");
7const symbol = compiler_rt.symbol;
8const Complex = compiler_rt.Complex;
9
10comptime {
11 if (@import("builtin").zig_backend != .stage2_c) {
12 symbol(&__mulhc3, "__mulhc3");
13 symbol(&__mulsc3, "__mulsc3");
14 symbol(&__muldc3, "__muldc3");
15 symbol(&__mulxc3, "__mulxc3");
16 if (compiler_rt.want_ppc_abi) {
17 symbol(&__multc3, "__mulkc3");
18 } else {
19 symbol(&__multc3, "__multc3");
20 }
21 }
22}
23
24fn __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 {
25 return compiler_rt.f16.complex.toAbi(mul_cf16(
26 compiler_rt.f16.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }),
27 compiler_rt.f16.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }),
28 ));
29}
30pub fn mul_cf16(a: Complex(f16), b: Complex(f16)) Complex(f16) {
31 return mulc3(f16, a, b);
32}
33
34fn __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 {
35 return compiler_rt.f32.complex.toAbi(mul_cf32(
36 compiler_rt.f32.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }),
37 compiler_rt.f32.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }),
38 ));
39}
40pub fn mul_cf32(a: Complex(f32), b: Complex(f32)) Complex(f32) {
41 return mulc3(f32, a, b);
42}
43
44fn __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 {
45 return compiler_rt.f64.complex.toAbi(mul_cf64(
46 compiler_rt.f64.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }),
47 compiler_rt.f64.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }),
48 ));
49}
50pub fn mul_cf64(a: Complex(f64), b: Complex(f64)) Complex(f64) {
51 return mulc3(f64, a, b);
52}
53
54fn __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 {
55 return compiler_rt.f80.complex.toAbi(mul_cf80(
56 compiler_rt.f80.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }),
57 compiler_rt.f80.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }),
58 ));
59}
60pub fn mul_cf80(a: Complex(f80), b: Complex(f80)) Complex(f80) {
61 return mulc3(f80, a, b);
62}
63
64fn __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 {
65 return compiler_rt.f128.complex.toAbi(mul_cf128(
66 compiler_rt.f128.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }),
67 compiler_rt.f128.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }),
68 ));
69}
70pub fn mul_cf128(a: Complex(f128), b: Complex(f128)) Complex(f128) {
71 return mulc3(f128, a, b);
1172}
1273
1374/// Implementation based on Annex G of C17 Standard (N2176)
14pub inline fn mulc3(comptime T: type, a_in: T, b_in: T, c_in: T, d_in: T) Complex(T) {
15 var a = a_in;
16 var b = b_in;
17 var c = c_in;
18 var d = d_in;
75inline fn mulc3(comptime T: type, lhs: Complex(T), rhs: Complex(T)) Complex(T) {
76 var a = lhs.real;
77 var b = lhs.imag;
78 var c = rhs.real;
79 var d = rhs.imag;
1980
2081 const ac = a * c;
2182 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
77138 }
78139 return z;
79140}
141
142test {
143 _ = @import("mulc3_test.zig");
144}
lib/compiler_rt/mulc3_test.zig+23-42
......@@ -2,64 +2,45 @@ const std = @import("std");
22const math = std.math;
33const expect = std.testing.expect;
44
5const Complex = @import("./mulc3.zig").Complex;
6const __mulhc3 = @import("./mulhc3.zig").__mulhc3;
7const __mulsc3 = @import("./mulsc3.zig").__mulsc3;
8const __muldc3 = @import("./muldc3.zig").__muldc3;
9const __mulxc3 = @import("./mulxc3.zig").__mulxc3;
10const __multc3 = @import("./multc3.zig").__multc3;
5const Complex = @import("../compiler_rt.zig").Complex;
6const impl = @import("mulc3.zig");
7const mul_cf16 = impl.mul_cf16;
8const mul_cf32 = impl.mul_cf32;
9const mul_cf64 = impl.mul_cf64;
10const mul_cf80 = impl.mul_cf80;
11const mul_cf128 = impl.mul_cf128;
1112
1213test "mulc3" {
13 try testMul(f16, __mulhc3);
14 try testMul(f32, __mulsc3);
15 try testMul(f64, __muldc3);
16 try testMul(f80, __mulxc3);
17 try testMul(f128, __multc3);
14 try testMul(f16, mul_cf16);
15 try testMul(f32, mul_cf32);
16 try testMul(f64, mul_cf64);
17 try testMul(f80, mul_cf80);
18 try testMul(f128, mul_cf128);
1819}
1920
20fn testMul(comptime T: type, comptime f: fn (T, T, T, T) callconv(.c) Complex(T)) !void {
21fn testMul(comptime T: type, comptime f: fn (Complex(T), Complex(T)) Complex(T)) !void {
2122 {
22 const a: T = 1.0;
23 const b: T = 0.0;
24 const c: T = -1.0;
25 const d: T = 0.0;
26
27 const result = f(a, b, c, d);
23 const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -1.0, .imag = 0.0 });
2824 try expect(result.real == -1.0);
29 try expect(result.imag == 0.0);
25 try expect(math.isPositiveZero(result.imag));
3026 }
3127 {
32 const a: T = 1.0;
33 const b: T = 0.0;
34 const c: T = -4.0;
35 const d: T = 0.0;
36
37 const result = f(a, b, c, d);
28 const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -4.0, .imag = 0.0 });
3829 try expect(result.real == -4.0);
39 try expect(result.imag == 0.0);
30 try expect(math.isPositiveZero(result.imag));
4031 }
4132 {
4233 // if one operand is an infinity and the other operand is a nonzero finite number or an infinity,
4334 // then the result of the * operator is an infinity;
44 const a: T = math.inf(T);
45 const b: T = -math.inf(T);
46 const c: T = 1.0;
47 const d: T = 0.0;
48
49 const result = f(a, b, c, d);
50 try expect(result.real == math.inf(T));
51 try expect(result.imag == -math.inf(T));
35 const result = f(.{ .real = math.inf(T), .imag = -math.inf(T) }, .{ .real = 1.0, .imag = 0.0 });
36 try expect(math.isPositiveInf(result.real));
37 try expect(math.isNegativeInf(result.imag));
5238 }
5339 {
5440 // if one operand is an infinity and the other operand is a nonzero finite number or an infinity,
5541 // then the result of the * operator is an infinity;
56 const a: T = math.inf(T);
57 const b: T = -1.0;
58 const c: T = 1.0;
59 const d: T = math.inf(T);
60
61 const result = f(a, b, c, d);
62 try expect(result.real == math.inf(T));
63 try expect(result.imag == math.inf(T));
42 const result = f(.{ .real = math.inf(T), .imag = -1.0 }, .{ .real = 1.0, .imag = math.inf(T) });
43 try expect(math.isPositiveInf(result.real));
44 try expect(math.isPositiveInf(result.imag));
6445 }
6546}
lib/compiler_rt/muldc3.zig deleted-12
......@@ -1,12 +0,0 @@
1const mulc3 = @import("./mulc3.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3
4comptime {
5 if (@import("builtin").zig_backend != .stage2_c) {
6 symbol(&__muldc3, "__muldc3");
7 }
8}
9
10pub fn __muldc3(a: f64, b: f64, c: f64, d: f64) callconv(.c) mulc3.Complex(f64) {
11 return mulc3.mulc3(f64, a, b, c, d);
12}
lib/compiler_rt/muldf3.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const mulf3 = @import("./mulf3.zig").mulf3;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_dmul, "__aeabi_dmul");
8 } else {
9 symbol(&__muldf3, "__muldf3");
10 }
11}
12
13pub fn __muldf3(a: f64, b: f64) callconv(.c) f64 {
14 return mulf3(f64, a, b);
15}
16
17fn __aeabi_dmul(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 {
18 return mulf3(f64, a, b);
19}
lib/compiler_rt/mulf3.zig+67-1
......@@ -2,10 +2,76 @@ const std = @import("std");
22const math = std.math;
33const builtin = @import("builtin");
44const compiler_rt = @import("../compiler_rt.zig");
5const symbol = compiler_rt.symbol;
6
7comptime {
8 symbol(&__mulhf3, "__mulhf3");
9 if (compiler_rt.want_aeabi) {
10 symbol(&__aeabi_fmul, "__aeabi_fmul");
11 symbol(&__aeabi_dmul, "__aeabi_dmul");
12 } else {
13 symbol(&__mulsf3, "__mulsf3");
14 symbol(&__muldf3, "__muldf3");
15 }
16 symbol(&__mulxf3, "__mulxf3");
17 if (compiler_rt.want_ppc_abi) {
18 symbol(&__multf3, "__mulkf3");
19 } else if (compiler_rt.want_sparc64_abi) {
20 symbol(&_Qp_mul, "_Qp_mul");
21 } else if (compiler_rt.want_sparc32_abi) {
22 symbol(&__multf3, "_Q_mul");
23 } else {
24 symbol(&__multf3, "__multf3");
25 }
26}
27
28fn __mulhf3(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
29 return compiler_rt.f16.toAbi(mul_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)));
30}
31pub fn mul_f16(a: f16, b: f16) f16 {
32 return mulf3(f16, a, b);
33}
34
35fn __mulsf3(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
36 return compiler_rt.f32.toAbi(mul_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)));
37}
38fn __aeabi_fmul(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 {
39 return mul_f32(a, b);
40}
41pub fn mul_f32(a: f32, b: f32) f32 {
42 return mulf3(f32, a, b);
43}
44
45fn __muldf3(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
46 return compiler_rt.f64.toAbi(mul_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)));
47}
48fn __aeabi_dmul(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 {
49 return mul_f64(a, b);
50}
51pub fn mul_f64(a: f64, b: f64) f64 {
52 return mulf3(f64, a, b);
53}
54
55fn __mulxf3(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
56 return compiler_rt.f80.toAbi(mul_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b)));
57}
58pub fn mul_f80(a: f80, b: f80) f80 {
59 return mulf3(f80, a, b);
60}
61
62fn __multf3(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
63 return compiler_rt.f128.toAbi(mul_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)));
64}
65fn _Qp_mul(c: *f128, a: *const f128, b: *const f128) callconv(.c) void {
66 c.* = mul_f128(a.*, b.*);
67}
68pub fn mul_f128(a: f128, b: f128) f128 {
69 return mulf3(f128, a, b);
70}
571
672/// Ported from:
773/// https://github.com/llvm/llvm-project/blob/2ffb1b0413efa9a24eb3c49e710e36f92e2cb50b/compiler-rt/lib/builtins/fp_mul_impl.inc
8pub inline fn mulf3(comptime T: type, a: T, b: T) T {
74inline fn mulf3(comptime T: type, a: T, b: T) T {
975 @setRuntimeSafety(compiler_rt.test_safety);
1076 const typeWidth = @typeInfo(T).float.bits;
1177 const significandBits = math.floatMantissaBits(T);
lib/compiler_rt/mulf3_test.zig+48-46
......@@ -7,10 +7,12 @@ const math = std.math;
77const qnan128: f128 = @bitCast(@as(u128, 0x7fff800000000000) << 64);
88const inf128: f128 = @bitCast(@as(u128, 0x7fff000000000000) << 64);
99
10const __multf3 = @import("multf3.zig").__multf3;
11const __mulxf3 = @import("mulxf3.zig").__mulxf3;
12const __muldf3 = @import("muldf3.zig").__muldf3;
13const __mulsf3 = @import("mulsf3.zig").__mulsf3;
10const impl = @import("mulf3.zig");
11const mul_f16 = impl.mul_f16;
12const mul_f32 = impl.mul_f32;
13const mul_f64 = impl.mul_f64;
14const mul_f80 = impl.mul_f80;
15const mul_f128 = impl.mul_f128;
1416
1517// return true if equal
1618// use two 64-bit integers instead of one 128-bit integer
......@@ -34,8 +36,8 @@ fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool {
3436 return false;
3537}
3638
37fn test__multf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void {
38 const x = __multf3(a, b);
39fn test_mul_f128(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void {
40 const x = mul_f128(a, b);
3941
4042 if (compareResultLD(x, expected_hi, expected_lo))
4143 return;
......@@ -49,68 +51,68 @@ fn makeNaN128(rand: u64) f128 {
4951}
5052test "multf3" {
5153 // qNaN * any = qNaN
52 try test__multf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
54 try test_mul_f128(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
5355
5456 // NaN * any = NaN
5557 const a = makeNaN128(0x800030000000);
56 try test__multf3(a, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
58 try test_mul_f128(a, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
5759 // inf * any = inf
58 try test__multf3(inf128, 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0);
60 try test_mul_f128(inf128, 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0);
5961
6062 // any * any
61 try test__multf3(
63 try test_mul_f128(
6264 @as(f128, @bitCast(@as(u128, 0x40042eab345678439abcdefea5678234))),
6365 @as(f128, @bitCast(@as(u128, 0x3ffeedcb34a235253948765432134675))),
6466 0x400423e7f9e3c9fc,
6567 0xd906c2c2a85777c4,
6668 );
6769
68 try test__multf3(
70 try test_mul_f128(
6971 @as(f128, @bitCast(@as(u128, 0x3fcd353e45674d89abacc3a2ebf3ff50))),
7072 @as(f128, @bitCast(@as(u128, 0x3ff6ed8764648369535adf4be3214568))),
7173 0x3fc52a163c6223fc,
7274 0xc94c4bf0430768b4,
7375 );
7476
75 try test__multf3(
77 try test_mul_f128(
7678 0x1.234425696abcad34a35eeffefdcbap+456,
7779 0x451.ed98d76e5d46e5f24323dff21ffp+600,
7880 0x44293a91de5e0e94,
7981 0xe8ed17cc2cdf64ac,
8082 );
8183
82 try test__multf3(
84 try test_mul_f128(
8385 @as(f128, @bitCast(@as(u128, 0x3f154356473c82a9fabf2d22ace345df))),
8486 @as(f128, @bitCast(@as(u128, 0x3e38eda98765476743ab21da23d45679))),
8587 0x3d4f37c1a3137cae,
8688 0xfc6807048bc2836a,
8789 );
8890
89 try test__multf3(0x1.23456734245345p-10000, 0x1.edcba524498724p-6497, 0x0, 0x0);
91 try test_mul_f128(0x1.23456734245345p-10000, 0x1.edcba524498724p-6497, 0x0, 0x0);
9092
9193 // Denormal operands.
92 try test__multf3(
94 try test_mul_f128(
9395 0x0.0000000000000000000000000001p-16382,
9496 0x1p16383,
9597 0x3f90000000000000,
9698 0x0,
9799 );
98 try test__multf3(
100 try test_mul_f128(
99101 0x1p16383,
100102 0x0.0000000000000000000000000001p-16382,
101103 0x3f90000000000000,
102104 0x0,
103105 );
104106
105 try test__multf3(0x1.0000_0000_0000_0000_0000_0000_0001p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0002);
106 try test__multf3(0x1.0000_0000_0000_0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0003);
107 try test__multf3(2.0, math.floatTrueMin(f128), 0x0000_0000_0000_0000, 0x0000_0000_0000_0002);
107 try test_mul_f128(0x1.0000_0000_0000_0000_0000_0000_0001p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0002);
108 try test_mul_f128(0x1.0000_0000_0000_0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0003);
109 try test_mul_f128(2.0, math.floatTrueMin(f128), 0x0000_0000_0000_0000, 0x0000_0000_0000_0002);
108110}
109111
110112const qnan80: f80 = @bitCast(@as(u80, @bitCast(math.nan(f80))) | (1 << (math.floatFractionalBits(f80) - 1)));
111113
112fn test__mulxf3(a: f80, b: f80, expected: u80) !void {
113 const x = __mulxf3(a, b);
114fn test_mul_f80(a: f80, b: f80, expected: u80) !void {
115 const x = mul_f80(a, b);
114116 const rep: u80 = @bitCast(x);
115117
116118 if (rep == expected)
......@@ -124,47 +126,47 @@ fn test__mulxf3(a: f80, b: f80, expected: u80) !void {
124126
125127test "mulxf3" {
126128 // NaN * any = NaN
127 try test__mulxf3(qnan80, 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80)));
128 try test__mulxf3(@as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80)));
129 try test_mul_f80(qnan80, 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80)));
130 try test_mul_f80(@as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80)));
129131
130132 // any * NaN = NaN
131 try test__mulxf3(0x1.23456789abcdefp+5, qnan80, @as(u80, @bitCast(qnan80)));
132 try test__mulxf3(0x1.23456789abcdefp+5, @as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), @as(u80, @bitCast(qnan80)));
133 try test_mul_f80(0x1.23456789abcdefp+5, qnan80, @as(u80, @bitCast(qnan80)));
134 try test_mul_f80(0x1.23456789abcdefp+5, @as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), @as(u80, @bitCast(qnan80)));
133135
134136 // NaN * inf = NaN
135 try test__mulxf3(qnan80, math.inf(f80), @as(u80, @bitCast(qnan80)));
137 try test_mul_f80(qnan80, math.inf(f80), @as(u80, @bitCast(qnan80)));
136138
137139 // inf * NaN = NaN
138 try test__mulxf3(math.inf(f80), qnan80, @as(u80, @bitCast(qnan80)));
140 try test_mul_f80(math.inf(f80), qnan80, @as(u80, @bitCast(qnan80)));
139141
140142 // inf * inf = inf
141 try test__mulxf3(math.inf(f80), math.inf(f80), @as(u80, @bitCast(math.inf(f80))));
143 try test_mul_f80(math.inf(f80), math.inf(f80), @as(u80, @bitCast(math.inf(f80))));
142144
143145 // inf * -inf = -inf
144 try test__mulxf3(math.inf(f80), -math.inf(f80), @as(u80, @bitCast(-math.inf(f80))));
146 try test_mul_f80(math.inf(f80), -math.inf(f80), @as(u80, @bitCast(-math.inf(f80))));
145147
146148 // -inf + inf = -inf
147 try test__mulxf3(-math.inf(f80), math.inf(f80), @as(u80, @bitCast(-math.inf(f80))));
149 try test_mul_f80(-math.inf(f80), math.inf(f80), @as(u80, @bitCast(-math.inf(f80))));
148150
149151 // inf * any = inf
150 try test__mulxf3(math.inf(f80), 0x1.2335653452436234723489432abcdefp+5, @as(u80, @bitCast(math.inf(f80))));
152 try test_mul_f80(math.inf(f80), 0x1.2335653452436234723489432abcdefp+5, @as(u80, @bitCast(math.inf(f80))));
151153
152154 // any * inf = inf
153 try test__mulxf3(0x1.2335653452436234723489432abcdefp+5, math.inf(f80), @as(u80, @bitCast(math.inf(f80))));
155 try test_mul_f80(0x1.2335653452436234723489432abcdefp+5, math.inf(f80), @as(u80, @bitCast(math.inf(f80))));
154156
155157 // any * any
156 try test__mulxf3(0x1.0p+0, 0x1.dcba987654321p+5, 0x4004_ee5d_4c3b_2a19_0800);
157 try test__mulxf3(0x1.0000_0000_0000_0004p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0003); // exact
158
159 try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.0p+5, 0x4004_8000_0000_0000_0001); // exact
160 try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.7ffep+5, 0x4004_BFFF_0000_0000_0001); // round down
161 try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0002); // round up to even
162 try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.8002p+5, 0x4004_C001_0000_0000_0002); // round up
163 try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.0p+6, 0x4005_8000_0000_0000_0001); // exact
164
165 try test__mulxf3(0x1.0000_0001p+0, 0x1.0000_0001p+0, 0x3FFF_8000_0001_0000_0000); // round down to even
166 try test__mulxf3(0x1.0000_0001p+0, 0x1.0000_0001_0002p+0, 0x3FFF_8000_0001_0001_0001); // round up
167 try test__mulxf3(0x0.8000_0000_0000_0000p-16382, 2.0, 0x0001_8000_0000_0000_0000); // denormal -> normal
168 try test__mulxf3(0x0.7fff_ffff_ffff_fffep-16382, 0x2.0000_0000_0000_0008p0, 0x0001_8000_0000_0000_0000); // denormal -> normal
169 try test__mulxf3(0x0.7fff_ffff_ffff_fffep-16382, 0x1.0000_0000_0000_0000p0, 0x0000_3FFF_FFFF_FFFF_FFFF); // denormal -> denormal
158 try test_mul_f80(0x1.0p+0, 0x1.dcba987654321p+5, 0x4004_ee5d_4c3b_2a19_0800);
159 try test_mul_f80(0x1.0000_0000_0000_0004p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0003); // exact
160
161 try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.0p+5, 0x4004_8000_0000_0000_0001); // exact
162 try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.7ffep+5, 0x4004_BFFF_0000_0000_0001); // round down
163 try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0002); // round up to even
164 try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.8002p+5, 0x4004_C001_0000_0000_0002); // round up
165 try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.0p+6, 0x4005_8000_0000_0000_0001); // exact
166
167 try test_mul_f80(0x1.0000_0001p+0, 0x1.0000_0001p+0, 0x3FFF_8000_0001_0000_0000); // round down to even
168 try test_mul_f80(0x1.0000_0001p+0, 0x1.0000_0001_0002p+0, 0x3FFF_8000_0001_0001_0001); // round up
169 try test_mul_f80(0x0.8000_0000_0000_0000p-16382, 2.0, 0x0001_8000_0000_0000_0000); // denormal -> normal
170 try test_mul_f80(0x0.7fff_ffff_ffff_fffep-16382, 0x2.0000_0000_0000_0008p0, 0x0001_8000_0000_0000_0000); // denormal -> normal
171 try test_mul_f80(0x0.7fff_ffff_ffff_fffep-16382, 0x1.0000_0000_0000_0000p0, 0x0000_3FFF_FFFF_FFFF_FFFF); // denormal -> denormal
170172}
lib/compiler_rt/mulhc3.zig deleted-13
......@@ -1,13 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const mulc3 = @import("./mulc3.zig");
4
5comptime {
6 if (@import("builtin").zig_backend != .stage2_c) {
7 symbol(&__mulhc3, "__mulhc3");
8 }
9}
10
11pub fn __mulhc3(a: f16, b: f16, c: f16, d: f16) callconv(.c) mulc3.Complex(f16) {
12 return mulc3.mulc3(f16, a, b, c, d);
13}
lib/compiler_rt/mulhf3.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const mulf3 = @import("./mulf3.zig").mulf3;
4
5comptime {
6 symbol(&__mulhf3, "__mulhf3");
7}
8
9pub fn __mulhf3(a: f16, b: f16) callconv(.c) f16 {
10 return mulf3(f16, a, b);
11}
lib/compiler_rt/mulsc3.zig deleted-12
......@@ -1,12 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const mulc3 = @import("./mulc3.zig");
3
4comptime {
5 if (@import("builtin").zig_backend != .stage2_c) {
6 symbol(&__mulsc3, "__mulsc3");
7 }
8}
9
10pub fn __mulsc3(a: f32, b: f32, c: f32, d: f32) callconv(.c) mulc3.Complex(f32) {
11 return mulc3.mulc3(f32, a, b, c, d);
12}
lib/compiler_rt/mulsf3.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const mulf3 = @import("./mulf3.zig").mulf3;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_fmul, "__aeabi_fmul");
8 } else {
9 symbol(&__mulsf3, "__mulsf3");
10 }
11}
12
13pub fn __mulsf3(a: f32, b: f32) callconv(.c) f32 {
14 return mulf3(f32, a, b);
15}
16
17fn __aeabi_fmul(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 {
18 return mulf3(f32, a, b);
19}
lib/compiler_rt/multc3.zig deleted-15
......@@ -1,15 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const mulc3 = @import("./mulc3.zig");
4
5comptime {
6 if (@import("builtin").zig_backend != .stage2_c) {
7 if (compiler_rt.want_ppc_abi)
8 symbol(&__multc3, "__mulkc3");
9 symbol(&__multc3, "__multc3");
10 }
11}
12
13pub fn __multc3(a: f128, b: f128, c: f128, d: f128) callconv(.c) mulc3.Complex(f128) {
14 return mulc3.mulc3(f128, a, b, c, d);
15}
lib/compiler_rt/multf3.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const mulf3 = @import("./mulf3.zig").mulf3;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__multf3, "__mulkf3");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_mul, "_Qp_mul");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__multf3, "_Q_mul");
12 }
13 symbol(&__multf3, "__multf3");
14}
15
16pub fn __multf3(a: f128, b: f128) callconv(.c) f128 {
17 return mulf3(f128, a, b);
18}
19
20fn _Qp_mul(c: *f128, a: *const f128, b: *const f128) callconv(.c) void {
21 c.* = mulf3(f128, a.*, b.*);
22}
lib/compiler_rt/mulvsi3.zig+3-2
......@@ -1,7 +1,8 @@
11const testing = @import("std").testing;
22
33const mulv = @import("mulo.zig");
4const symbol = @import("../compiler_rt.zig").symbol;
4const compiler_rt = @import("../compiler_rt.zig");
5const symbol = compiler_rt.symbol;
56
67comptime {
78 symbol(&__mulvsi3, "__mulvsi3");
......@@ -10,7 +11,7 @@ comptime {
1011pub fn __mulvsi3(a: i32, b: i32) callconv(.c) i32 {
1112 var overflow: c_int = 0;
1213 const sum = mulv.__mulosi4(a, b, &overflow);
13 if (overflow != 0) @panic("compiler-rt: integer overflow");
14 if (overflow != 0) @panic("integer overflow");
1415 return sum;
1516}
1617
lib/compiler_rt/mulxc3.zig deleted-13
......@@ -1,13 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const mulc3 = @import("./mulc3.zig");
4
5comptime {
6 if (@import("builtin").zig_backend != .stage2_c) {
7 symbol(&__mulxc3, "__mulxc3");
8 }
9}
10
11pub fn __mulxc3(a: f80, b: f80, c: f80, d: f80) callconv(.c) mulc3.Complex(f80) {
12 return mulc3.mulc3(f80, a, b, c, d);
13}
lib/compiler_rt/mulxf3.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const mulf3 = @import("./mulf3.zig").mulf3;
4
5comptime {
6 symbol(&__mulxf3, "__mulxf3");
7}
8
9pub fn __mulxf3(a: f80, b: f80) callconv(.c) f80 {
10 return mulf3(f80, a, b);
11}
lib/compiler_rt/negv.zig+1-2
......@@ -33,8 +33,7 @@ inline fn negvXi(comptime ST: type, a: ST) ST {
3333 };
3434 const N: UT = @bitSizeOf(ST);
3535 const min: ST = @as(ST, @bitCast((@as(UT, 1) << (N - 1))));
36 if (a == min)
37 @panic("compiler_rt negv: overflow");
36 if (a == min) @panic("integer overflow");
3837 return -a;
3938}
4039
lib/compiler_rt/os_version_check.zig-1
......@@ -3,7 +3,6 @@ const testing = std.testing;
33const builtin = @import("builtin");
44const compiler_rt = @import("../compiler_rt.zig");
55const symbol = compiler_rt.symbol;
6const panic = @import("../compiler_rt.zig").panic;
76
87const have_availability_version_check = builtin.os.tag.isDarwin() and
98 builtin.os.version_range.semver.min.order(.{ .major = 10, .minor = 15, .patch = 0 }).compare(.gte);
lib/compiler_rt/parity.zig+2-1
......@@ -1,6 +1,7 @@
11//! parity - if number of bits set is even => 0, else => 1
22//! - pariytXi2_generic for big and little endian
3const symbol = @import("../compiler_rt.zig").symbol;
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
45
56comptime {
67 symbol(&__paritysi2, "__paritysi2");
lib/compiler_rt/popcount.zig+2-1
......@@ -6,7 +6,8 @@
66//! TAOCP: Combinational Algorithms, Bitwise Tricks And Techniques,
77//! subsubsection "Working with the rightmost bits" and "Sideways addition".
88
9const symbol = @import("../compiler_rt.zig").symbol;
9const compiler_rt = @import("../compiler_rt.zig");
10const symbol = compiler_rt.symbol;
1011
1112comptime {
1213 symbol(&__popcountsi2, "__popcountsi2");
lib/compiler_rt/powiXf2.zig+28-11
......@@ -4,16 +4,18 @@
44//! error propagation and this method is optimized for performance, not accuracy.
55
66const compiler_rt = @import("../compiler_rt.zig");
7const symbol = @import("../compiler_rt.zig").symbol;
7const symbol = compiler_rt.symbol;
88
99comptime {
1010 symbol(&__powihf2, "__powihf2");
1111 symbol(&__powisf2, "__powisf2");
1212 symbol(&__powidf2, "__powidf2");
13 if (compiler_rt.want_ppc_abi)
14 symbol(&__powitf2, "__powikf2");
15 symbol(&__powitf2, "__powitf2");
1613 symbol(&__powixf2, "__powixf2");
14 if (compiler_rt.want_ppc_abi) {
15 symbol(&__powitf2, "__powikf2");
16 } else {
17 symbol(&__powitf2, "__powitf2");
18 }
1719}
1820
1921inline 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 {
3234 return if (is_recip) 1 / r else r;
3335}
3436
35pub fn __powihf2(a: f16, b: i32) callconv(.c) f16 {
37fn __powihf2(a: compiler_rt.f16.Abi, b: i32) callconv(.c) compiler_rt.f16.Abi {
38 return compiler_rt.f16.toAbi(powi_f16(compiler_rt.f16.fromAbi(a), b));
39}
40pub fn powi_f16(a: f16, b: i32) f16 {
3641 return powiXf2(f16, a, b);
3742}
3843
39pub fn __powisf2(a: f32, b: i32) callconv(.c) f32 {
44fn __powisf2(a: compiler_rt.f32.Abi, b: i32) callconv(.c) compiler_rt.f32.Abi {
45 return compiler_rt.f32.toAbi(powi_f32(compiler_rt.f32.fromAbi(a), b));
46}
47pub fn powi_f32(a: f32, b: i32) f32 {
4048 return powiXf2(f32, a, b);
4149}
4250
43pub fn __powidf2(a: f64, b: i32) callconv(.c) f64 {
51fn __powidf2(a: compiler_rt.f64.Abi, b: i32) callconv(.c) compiler_rt.f64.Abi {
52 return compiler_rt.f64.toAbi(powi_f64(compiler_rt.f64.fromAbi(a), b));
53}
54pub fn powi_f64(a: f64, b: i32) f64 {
4455 return powiXf2(f64, a, b);
4556}
4657
47pub fn __powitf2(a: f128, b: i32) callconv(.c) f128 {
48 return powiXf2(f128, a, b);
58fn __powixf2(a: compiler_rt.f80.Abi, b: i32) callconv(.c) compiler_rt.f80.Abi {
59 return compiler_rt.f80.toAbi(powi_f80(compiler_rt.f80.fromAbi(a), b));
4960}
50
51pub fn __powixf2(a: f80, b: i32) callconv(.c) f80 {
61pub fn powi_f80(a: f80, b: i32) f80 {
5262 return powiXf2(f80, a, b);
5363}
5464
65fn __powitf2(a: compiler_rt.f128.Abi, b: i32) callconv(.c) compiler_rt.f128.Abi {
66 return compiler_rt.f128.toAbi(powi_f128(compiler_rt.f128.fromAbi(a), b));
67}
68pub fn powi_f128(a: f128, b: i32) f128 {
69 return powiXf2(f128, a, b);
70}
71
5572test {
5673 _ = @import("powiXf2_test.zig");
5774}
lib/compiler_rt/powiXf2_test.zig+531-525
......@@ -2,562 +2,568 @@
22// powisf2_test.c, powidf2_test.c, powitf2_test.c, powixf2_test.c
33// powihf2 adapted from powisf2 tests
44
5const powiXf2 = @import("powiXf2.zig");
65const std = @import("std");
7const builtin = @import("builtin");
86const testing = std.testing;
97const math = std.math;
108
11fn test__powihf2(a: f16, b: i32, expected: f16) !void {
12 const result = powiXf2.__powihf2(a, b);
9const impl = @import("powiXf2.zig");
10
11const powi_f16 = impl.powi_f16;
12const powi_f32 = impl.powi_f32;
13const powi_f64 = impl.powi_f64;
14const powi_f80 = impl.powi_f80;
15const powi_f128 = impl.powi_f128;
16
17fn test_powi_f16(a: f16, b: i32, expected: f16) !void {
18 const result = powi_f16(a, b);
1319 try testing.expectEqual(expected, result);
1420}
1521
16fn test__powisf2(a: f32, b: i32, expected: f32) !void {
17 const result = powiXf2.__powisf2(a, b);
22fn test_powi_f32(a: f32, b: i32, expected: f32) !void {
23 const result = powi_f32(a, b);
1824 try testing.expectEqual(expected, result);
1925}
2026
21fn test__powidf2(a: f64, b: i32, expected: f64) !void {
22 const result = powiXf2.__powidf2(a, b);
27fn test_powi_f64(a: f64, b: i32, expected: f64) !void {
28 const result = powi_f64(a, b);
2329 try testing.expectEqual(expected, result);
2430}
2531
26fn test__powitf2(a: f128, b: i32, expected: f128) !void {
27 const result = powiXf2.__powitf2(a, b);
32fn test_powi_f80(a: f80, b: i32, expected: f80) !void {
33 const result = powi_f80(a, b);
2834 try testing.expectEqual(expected, result);
2935}
3036
31fn test__powixf2(a: f80, b: i32, expected: f80) !void {
32 const result = powiXf2.__powixf2(a, b);
37fn test_powi_f128(a: f128, b: i32, expected: f128) !void {
38 const result = powi_f128(a, b);
3339 try testing.expectEqual(expected, result);
3440}
3541
36test "powihf2" {
42test powi_f16 {
3743 const inf_f16 = math.inf(f16);
38 try test__powisf2(0, 0, 1);
39 try test__powihf2(1, 0, 1);
40 try test__powihf2(1.5, 0, 1);
41 try test__powihf2(2, 0, 1);
42 try test__powihf2(inf_f16, 0, 1);
43
44 try test__powihf2(-0.0, 0, 1);
45 try test__powihf2(-1, 0, 1);
46 try test__powihf2(-1.5, 0, 1);
47 try test__powihf2(-2, 0, 1);
48 try test__powihf2(-inf_f16, 0, 1);
49
50 try test__powihf2(0, 1, 0);
51 try test__powihf2(0, 2, 0);
52 try test__powihf2(0, 3, 0);
53 try test__powihf2(0, 4, 0);
54 try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
55 try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
56
57 try test__powihf2(-0.0, 1, -0.0);
58 try test__powihf2(-0.0, 2, 0);
59 try test__powihf2(-0.0, 3, -0.0);
60 try test__powihf2(-0.0, 4, 0);
61 try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
62 try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
63
64 try test__powihf2(1, 1, 1);
65 try test__powihf2(1, 2, 1);
66 try test__powihf2(1, 3, 1);
67 try test__powihf2(1, 4, 1);
68 try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
69 try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
70
71 try test__powihf2(inf_f16, 1, inf_f16);
72 try test__powihf2(inf_f16, 2, inf_f16);
73 try test__powihf2(inf_f16, 3, inf_f16);
74 try test__powihf2(inf_f16, 4, inf_f16);
75 try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16);
76 try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f16);
77
78 try test__powihf2(-inf_f16, 1, -inf_f16);
79 try test__powihf2(-inf_f16, 2, inf_f16);
80 try test__powihf2(-inf_f16, 3, -inf_f16);
81 try test__powihf2(-inf_f16, 4, inf_f16);
82 try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16);
83 try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f16);
44 try test_powi_f16(0, 0, 1);
45 try test_powi_f16(1, 0, 1);
46 try test_powi_f16(1.5, 0, 1);
47 try test_powi_f16(2, 0, 1);
48 try test_powi_f16(inf_f16, 0, 1);
49
50 try test_powi_f16(-0.0, 0, 1);
51 try test_powi_f16(-1, 0, 1);
52 try test_powi_f16(-1.5, 0, 1);
53 try test_powi_f16(-2, 0, 1);
54 try test_powi_f16(-inf_f16, 0, 1);
55
56 try test_powi_f16(0, 1, 0);
57 try test_powi_f16(0, 2, 0);
58 try test_powi_f16(0, 3, 0);
59 try test_powi_f16(0, 4, 0);
60 try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
61 try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
62
63 try test_powi_f16(-0.0, 1, -0.0);
64 try test_powi_f16(-0.0, 2, 0);
65 try test_powi_f16(-0.0, 3, -0.0);
66 try test_powi_f16(-0.0, 4, 0);
67 try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
68 try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
69
70 try test_powi_f16(1, 1, 1);
71 try test_powi_f16(1, 2, 1);
72 try test_powi_f16(1, 3, 1);
73 try test_powi_f16(1, 4, 1);
74 try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
75 try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
76
77 try test_powi_f16(inf_f16, 1, inf_f16);
78 try test_powi_f16(inf_f16, 2, inf_f16);
79 try test_powi_f16(inf_f16, 3, inf_f16);
80 try test_powi_f16(inf_f16, 4, inf_f16);
81 try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16);
82 try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f16);
83
84 try test_powi_f16(-inf_f16, 1, -inf_f16);
85 try test_powi_f16(-inf_f16, 2, inf_f16);
86 try test_powi_f16(-inf_f16, 3, -inf_f16);
87 try test_powi_f16(-inf_f16, 4, inf_f16);
88 try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16);
89 try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f16);
8490 //
85 try test__powihf2(0, -1, inf_f16);
86 try test__powihf2(0, -2, inf_f16);
87 try test__powihf2(0, -3, inf_f16);
88 try test__powihf2(0, -4, inf_f16);
89 try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // 0 ^ anything = +inf
90 try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f16);
91 try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16);
92
93 try test__powihf2(-0.0, -1, -inf_f16);
94 try test__powihf2(-0.0, -2, inf_f16);
95 try test__powihf2(-0.0, -3, -inf_f16);
96 try test__powihf2(-0.0, -4, inf_f16);
97 try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // -0 ^ anything even = +inf
98 try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f16); // -0 ^ anything odd = -inf
99 try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16);
100
101 try test__powihf2(1, -1, 1);
102 try test__powihf2(1, -2, 1);
103 try test__powihf2(1, -3, 1);
104 try test__powihf2(1, -4, 1);
105 try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); // 1.0 ^ anything = 1
106 try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
107 try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
108
109 try test__powihf2(inf_f16, -1, 0);
110 try test__powihf2(inf_f16, -2, 0);
111 try test__powihf2(inf_f16, -3, 0);
112 try test__powihf2(inf_f16, -4, 0);
113 try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
114 try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
115 try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
91 try test_powi_f16(0, -1, inf_f16);
92 try test_powi_f16(0, -2, inf_f16);
93 try test_powi_f16(0, -3, inf_f16);
94 try test_powi_f16(0, -4, inf_f16);
95 try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // 0 ^ anything = +inf
96 try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f16);
97 try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16);
98
99 try test_powi_f16(-0.0, -1, -inf_f16);
100 try test_powi_f16(-0.0, -2, inf_f16);
101 try test_powi_f16(-0.0, -3, -inf_f16);
102 try test_powi_f16(-0.0, -4, inf_f16);
103 try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // -0 ^ anything even = +inf
104 try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f16); // -0 ^ anything odd = -inf
105 try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16);
106
107 try test_powi_f16(1, -1, 1);
108 try test_powi_f16(1, -2, 1);
109 try test_powi_f16(1, -3, 1);
110 try test_powi_f16(1, -4, 1);
111 try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); // 1.0 ^ anything = 1
112 try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
113 try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
114
115 try test_powi_f16(inf_f16, -1, 0);
116 try test_powi_f16(inf_f16, -2, 0);
117 try test_powi_f16(inf_f16, -3, 0);
118 try test_powi_f16(inf_f16, -4, 0);
119 try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
120 try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
121 try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
116122 //
117 try test__powihf2(-inf_f16, -1, -0.0);
118 try test__powihf2(-inf_f16, -2, 0);
119 try test__powihf2(-inf_f16, -3, -0.0);
120 try test__powihf2(-inf_f16, -4, 0);
121 try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
122 try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
123 try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
124
125 try test__powihf2(2, 10, 1024.0);
126 try test__powihf2(-2, 10, 1024.0);
127 try test__powihf2(2, -10, 1.0 / 1024.0);
128 try test__powihf2(-2, -10, 1.0 / 1024.0);
129
130 try test__powihf2(2, 14, 16384.0);
131 try test__powihf2(-2, 14, 16384.0);
132 try test__powihf2(2, 15, 32768.0);
133 try test__powihf2(-2, 15, -32768.0);
134 try test__powihf2(2, 16, inf_f16);
135 try test__powihf2(-2, 16, inf_f16);
136
137 try test__powihf2(2, -13, 1.0 / 8192.0);
138 try test__powihf2(-2, -13, -1.0 / 8192.0);
139 try test__powihf2(2, -15, 1.0 / 32768.0);
140 try test__powihf2(-2, -15, -1.0 / 32768.0);
141 try test__powihf2(2, -16, 0.0); // expected = 0.0 = 1/(-2**16)
142 try test__powihf2(-2, -16, 0.0); // expected = 0.0 = 1/(2**16)
123 try test_powi_f16(-inf_f16, -1, -0.0);
124 try test_powi_f16(-inf_f16, -2, 0);
125 try test_powi_f16(-inf_f16, -3, -0.0);
126 try test_powi_f16(-inf_f16, -4, 0);
127 try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
128 try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
129 try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
130
131 try test_powi_f16(2, 10, 1024.0);
132 try test_powi_f16(-2, 10, 1024.0);
133 try test_powi_f16(2, -10, 1.0 / 1024.0);
134 try test_powi_f16(-2, -10, 1.0 / 1024.0);
135
136 try test_powi_f16(2, 14, 16384.0);
137 try test_powi_f16(-2, 14, 16384.0);
138 try test_powi_f16(2, 15, 32768.0);
139 try test_powi_f16(-2, 15, -32768.0);
140 try test_powi_f16(2, 16, inf_f16);
141 try test_powi_f16(-2, 16, inf_f16);
142
143 try test_powi_f16(2, -13, 1.0 / 8192.0);
144 try test_powi_f16(-2, -13, -1.0 / 8192.0);
145 try test_powi_f16(2, -15, 1.0 / 32768.0);
146 try test_powi_f16(-2, -15, -1.0 / 32768.0);
147 try test_powi_f16(2, -16, 0.0); // expected = 0.0 = 1/(-2**16)
148 try test_powi_f16(-2, -16, 0.0); // expected = 0.0 = 1/(2**16)
143149}
144150
145test "powisf2" {
151test powi_f32 {
146152 const inf_f32 = math.inf(f32);
147 try test__powisf2(0, 0, 1);
148 try test__powisf2(1, 0, 1);
149 try test__powisf2(1.5, 0, 1);
150 try test__powisf2(2, 0, 1);
151 try test__powisf2(inf_f32, 0, 1);
152
153 try test__powisf2(-0.0, 0, 1);
154 try test__powisf2(-1, 0, 1);
155 try test__powisf2(-1.5, 0, 1);
156 try test__powisf2(-2, 0, 1);
157 try test__powisf2(-inf_f32, 0, 1);
158
159 try test__powisf2(0, 1, 0);
160 try test__powisf2(0, 2, 0);
161 try test__powisf2(0, 3, 0);
162 try test__powisf2(0, 4, 0);
163 try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
164 try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
165
166 try test__powisf2(-0.0, 1, -0.0);
167 try test__powisf2(-0.0, 2, 0);
168 try test__powisf2(-0.0, 3, -0.0);
169 try test__powisf2(-0.0, 4, 0);
170 try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
171 try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
172
173 try test__powisf2(1, 1, 1);
174 try test__powisf2(1, 2, 1);
175 try test__powisf2(1, 3, 1);
176 try test__powisf2(1, 4, 1);
177 try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
178 try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
179
180 try test__powisf2(inf_f32, 1, inf_f32);
181 try test__powisf2(inf_f32, 2, inf_f32);
182 try test__powisf2(inf_f32, 3, inf_f32);
183 try test__powisf2(inf_f32, 4, inf_f32);
184 try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32);
185 try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f32);
186
187 try test__powisf2(-inf_f32, 1, -inf_f32);
188 try test__powisf2(-inf_f32, 2, inf_f32);
189 try test__powisf2(-inf_f32, 3, -inf_f32);
190 try test__powisf2(-inf_f32, 4, inf_f32);
191 try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32);
192 try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f32);
193
194 try test__powisf2(0, -1, inf_f32);
195 try test__powisf2(0, -2, inf_f32);
196 try test__powisf2(0, -3, inf_f32);
197 try test__powisf2(0, -4, inf_f32);
198 try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32);
199 try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f32);
200 try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32);
201
202 try test__powisf2(-0.0, -1, -inf_f32);
203 try test__powisf2(-0.0, -2, inf_f32);
204 try test__powisf2(-0.0, -3, -inf_f32);
205 try test__powisf2(-0.0, -4, inf_f32);
206 try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32);
207 try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f32);
208 try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32);
209
210 try test__powisf2(1, -1, 1);
211 try test__powisf2(1, -2, 1);
212 try test__powisf2(1, -3, 1);
213 try test__powisf2(1, -4, 1);
214 try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
215 try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
216 try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
217
218 try test__powisf2(inf_f32, -1, 0);
219 try test__powisf2(inf_f32, -2, 0);
220 try test__powisf2(inf_f32, -3, 0);
221 try test__powisf2(inf_f32, -4, 0);
222 try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
223 try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
224 try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
225
226 try test__powisf2(-inf_f32, -1, -0.0);
227 try test__powisf2(-inf_f32, -2, 0);
228 try test__powisf2(-inf_f32, -3, -0.0);
229 try test__powisf2(-inf_f32, -4, 0);
230 try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
231 try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
232 try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
233
234 try test__powisf2(2.0, 10, 1024.0);
235 try test__powisf2(-2, 10, 1024.0);
236 try test__powisf2(2, -10, 1.0 / 1024.0);
237 try test__powisf2(-2, -10, 1.0 / 1024.0);
153 try test_powi_f32(0, 0, 1);
154 try test_powi_f32(1, 0, 1);
155 try test_powi_f32(1.5, 0, 1);
156 try test_powi_f32(2, 0, 1);
157 try test_powi_f32(inf_f32, 0, 1);
158
159 try test_powi_f32(-0.0, 0, 1);
160 try test_powi_f32(-1, 0, 1);
161 try test_powi_f32(-1.5, 0, 1);
162 try test_powi_f32(-2, 0, 1);
163 try test_powi_f32(-inf_f32, 0, 1);
164
165 try test_powi_f32(0, 1, 0);
166 try test_powi_f32(0, 2, 0);
167 try test_powi_f32(0, 3, 0);
168 try test_powi_f32(0, 4, 0);
169 try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
170 try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
171
172 try test_powi_f32(-0.0, 1, -0.0);
173 try test_powi_f32(-0.0, 2, 0);
174 try test_powi_f32(-0.0, 3, -0.0);
175 try test_powi_f32(-0.0, 4, 0);
176 try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
177 try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
178
179 try test_powi_f32(1, 1, 1);
180 try test_powi_f32(1, 2, 1);
181 try test_powi_f32(1, 3, 1);
182 try test_powi_f32(1, 4, 1);
183 try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
184 try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
185
186 try test_powi_f32(inf_f32, 1, inf_f32);
187 try test_powi_f32(inf_f32, 2, inf_f32);
188 try test_powi_f32(inf_f32, 3, inf_f32);
189 try test_powi_f32(inf_f32, 4, inf_f32);
190 try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32);
191 try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f32);
192
193 try test_powi_f32(-inf_f32, 1, -inf_f32);
194 try test_powi_f32(-inf_f32, 2, inf_f32);
195 try test_powi_f32(-inf_f32, 3, -inf_f32);
196 try test_powi_f32(-inf_f32, 4, inf_f32);
197 try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32);
198 try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f32);
199
200 try test_powi_f32(0, -1, inf_f32);
201 try test_powi_f32(0, -2, inf_f32);
202 try test_powi_f32(0, -3, inf_f32);
203 try test_powi_f32(0, -4, inf_f32);
204 try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32);
205 try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f32);
206 try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32);
207
208 try test_powi_f32(-0.0, -1, -inf_f32);
209 try test_powi_f32(-0.0, -2, inf_f32);
210 try test_powi_f32(-0.0, -3, -inf_f32);
211 try test_powi_f32(-0.0, -4, inf_f32);
212 try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32);
213 try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f32);
214 try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32);
215
216 try test_powi_f32(1, -1, 1);
217 try test_powi_f32(1, -2, 1);
218 try test_powi_f32(1, -3, 1);
219 try test_powi_f32(1, -4, 1);
220 try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
221 try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
222 try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
223
224 try test_powi_f32(inf_f32, -1, 0);
225 try test_powi_f32(inf_f32, -2, 0);
226 try test_powi_f32(inf_f32, -3, 0);
227 try test_powi_f32(inf_f32, -4, 0);
228 try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
229 try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
230 try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
231
232 try test_powi_f32(-inf_f32, -1, -0.0);
233 try test_powi_f32(-inf_f32, -2, 0);
234 try test_powi_f32(-inf_f32, -3, -0.0);
235 try test_powi_f32(-inf_f32, -4, 0);
236 try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
237 try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
238 try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
239
240 try test_powi_f32(2.0, 10, 1024.0);
241 try test_powi_f32(-2, 10, 1024.0);
242 try test_powi_f32(2, -10, 1.0 / 1024.0);
243 try test_powi_f32(-2, -10, 1.0 / 1024.0);
238244 //
239 try test__powisf2(2, 19, 524288.0);
240 try test__powisf2(-2, 19, -524288.0);
241 try test__powisf2(2, -19, 1.0 / 524288.0);
242 try test__powisf2(-2, -19, -1.0 / 524288.0);
243
244 try test__powisf2(2, 31, 2147483648.0);
245 try test__powisf2(-2, 31, -2147483648.0);
246 try test__powisf2(2, -31, 1.0 / 2147483648.0);
247 try test__powisf2(-2, -31, -1.0 / 2147483648.0);
245 try test_powi_f32(2, 19, 524288.0);
246 try test_powi_f32(-2, 19, -524288.0);
247 try test_powi_f32(2, -19, 1.0 / 524288.0);
248 try test_powi_f32(-2, -19, -1.0 / 524288.0);
249
250 try test_powi_f32(2, 31, 2147483648.0);
251 try test_powi_f32(-2, 31, -2147483648.0);
252 try test_powi_f32(2, -31, 1.0 / 2147483648.0);
253 try test_powi_f32(-2, -31, -1.0 / 2147483648.0);
248254}
249255
250test "powidf2" {
256test powi_f64 {
251257 const inf_f64 = math.inf(f64);
252 try test__powidf2(0, 0, 1);
253 try test__powidf2(1, 0, 1);
254 try test__powidf2(1.5, 0, 1);
255 try test__powidf2(2, 0, 1);
256 try test__powidf2(inf_f64, 0, 1);
257
258 try test__powidf2(-0.0, 0, 1);
259 try test__powidf2(-1, 0, 1);
260 try test__powidf2(-1.5, 0, 1);
261 try test__powidf2(-2, 0, 1);
262 try test__powidf2(-inf_f64, 0, 1);
263
264 try test__powidf2(0, 1, 0);
265 try test__powidf2(0, 2, 0);
266 try test__powidf2(0, 3, 0);
267 try test__powidf2(0, 4, 0);
268 try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
269 try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
270
271 try test__powidf2(-0.0, 1, -0.0);
272 try test__powidf2(-0.0, 2, 0);
273 try test__powidf2(-0.0, 3, -0.0);
274 try test__powidf2(-0.0, 4, 0);
275 try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
276 try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
277
278 try test__powidf2(1, 1, 1);
279 try test__powidf2(1, 2, 1);
280 try test__powidf2(1, 3, 1);
281 try test__powidf2(1, 4, 1);
282 try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
283 try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
284
285 try test__powidf2(inf_f64, 1, inf_f64);
286 try test__powidf2(inf_f64, 2, inf_f64);
287 try test__powidf2(inf_f64, 3, inf_f64);
288 try test__powidf2(inf_f64, 4, inf_f64);
289 try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64);
290 try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f64);
291
292 try test__powidf2(-inf_f64, 1, -inf_f64);
293 try test__powidf2(-inf_f64, 2, inf_f64);
294 try test__powidf2(-inf_f64, 3, -inf_f64);
295 try test__powidf2(-inf_f64, 4, inf_f64);
296 try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64);
297 try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f64);
298
299 try test__powidf2(0, -1, inf_f64);
300 try test__powidf2(0, -2, inf_f64);
301 try test__powidf2(0, -3, inf_f64);
302 try test__powidf2(0, -4, inf_f64);
303 try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64);
304 try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f64);
305 try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64);
306
307 try test__powidf2(-0.0, -1, -inf_f64);
308 try test__powidf2(-0.0, -2, inf_f64);
309 try test__powidf2(-0.0, -3, -inf_f64);
310 try test__powidf2(-0.0, -4, inf_f64);
311 try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64);
312 try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f64);
313 try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64);
314
315 try test__powidf2(1, -1, 1);
316 try test__powidf2(1, -2, 1);
317 try test__powidf2(1, -3, 1);
318 try test__powidf2(1, -4, 1);
319 try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
320 try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
321 try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
322
323 try test__powidf2(inf_f64, -1, 0);
324 try test__powidf2(inf_f64, -2, 0);
325 try test__powidf2(inf_f64, -3, 0);
326 try test__powidf2(inf_f64, -4, 0);
327 try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
328 try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
329 try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
330
331 try test__powidf2(-inf_f64, -1, -0.0);
332 try test__powidf2(-inf_f64, -2, 0);
333 try test__powidf2(-inf_f64, -3, -0.0);
334 try test__powidf2(-inf_f64, -4, 0);
335 try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
336 try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
337 try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
338
339 try test__powidf2(2, 10, 1024.0);
340 try test__powidf2(-2, 10, 1024.0);
341 try test__powidf2(2, -10, 1.0 / 1024.0);
342 try test__powidf2(-2, -10, 1.0 / 1024.0);
343
344 try test__powidf2(2, 19, 524288.0);
345 try test__powidf2(-2, 19, -524288.0);
346 try test__powidf2(2, -19, 1.0 / 524288.0);
347 try test__powidf2(-2, -19, -1.0 / 524288.0);
348
349 try test__powidf2(2, 31, 2147483648.0);
350 try test__powidf2(-2, 31, -2147483648.0);
351 try test__powidf2(2, -31, 1.0 / 2147483648.0);
352 try test__powidf2(-2, -31, -1.0 / 2147483648.0);
258 try test_powi_f64(0, 0, 1);
259 try test_powi_f64(1, 0, 1);
260 try test_powi_f64(1.5, 0, 1);
261 try test_powi_f64(2, 0, 1);
262 try test_powi_f64(inf_f64, 0, 1);
263
264 try test_powi_f64(-0.0, 0, 1);
265 try test_powi_f64(-1, 0, 1);
266 try test_powi_f64(-1.5, 0, 1);
267 try test_powi_f64(-2, 0, 1);
268 try test_powi_f64(-inf_f64, 0, 1);
269
270 try test_powi_f64(0, 1, 0);
271 try test_powi_f64(0, 2, 0);
272 try test_powi_f64(0, 3, 0);
273 try test_powi_f64(0, 4, 0);
274 try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
275 try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
276
277 try test_powi_f64(-0.0, 1, -0.0);
278 try test_powi_f64(-0.0, 2, 0);
279 try test_powi_f64(-0.0, 3, -0.0);
280 try test_powi_f64(-0.0, 4, 0);
281 try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
282 try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
283
284 try test_powi_f64(1, 1, 1);
285 try test_powi_f64(1, 2, 1);
286 try test_powi_f64(1, 3, 1);
287 try test_powi_f64(1, 4, 1);
288 try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
289 try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
290
291 try test_powi_f64(inf_f64, 1, inf_f64);
292 try test_powi_f64(inf_f64, 2, inf_f64);
293 try test_powi_f64(inf_f64, 3, inf_f64);
294 try test_powi_f64(inf_f64, 4, inf_f64);
295 try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64);
296 try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f64);
297
298 try test_powi_f64(-inf_f64, 1, -inf_f64);
299 try test_powi_f64(-inf_f64, 2, inf_f64);
300 try test_powi_f64(-inf_f64, 3, -inf_f64);
301 try test_powi_f64(-inf_f64, 4, inf_f64);
302 try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64);
303 try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f64);
304
305 try test_powi_f64(0, -1, inf_f64);
306 try test_powi_f64(0, -2, inf_f64);
307 try test_powi_f64(0, -3, inf_f64);
308 try test_powi_f64(0, -4, inf_f64);
309 try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64);
310 try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f64);
311 try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64);
312
313 try test_powi_f64(-0.0, -1, -inf_f64);
314 try test_powi_f64(-0.0, -2, inf_f64);
315 try test_powi_f64(-0.0, -3, -inf_f64);
316 try test_powi_f64(-0.0, -4, inf_f64);
317 try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64);
318 try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f64);
319 try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64);
320
321 try test_powi_f64(1, -1, 1);
322 try test_powi_f64(1, -2, 1);
323 try test_powi_f64(1, -3, 1);
324 try test_powi_f64(1, -4, 1);
325 try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
326 try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
327 try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
328
329 try test_powi_f64(inf_f64, -1, 0);
330 try test_powi_f64(inf_f64, -2, 0);
331 try test_powi_f64(inf_f64, -3, 0);
332 try test_powi_f64(inf_f64, -4, 0);
333 try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
334 try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
335 try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
336
337 try test_powi_f64(-inf_f64, -1, -0.0);
338 try test_powi_f64(-inf_f64, -2, 0);
339 try test_powi_f64(-inf_f64, -3, -0.0);
340 try test_powi_f64(-inf_f64, -4, 0);
341 try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
342 try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
343 try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
344
345 try test_powi_f64(2, 10, 1024.0);
346 try test_powi_f64(-2, 10, 1024.0);
347 try test_powi_f64(2, -10, 1.0 / 1024.0);
348 try test_powi_f64(-2, -10, 1.0 / 1024.0);
349
350 try test_powi_f64(2, 19, 524288.0);
351 try test_powi_f64(-2, 19, -524288.0);
352 try test_powi_f64(2, -19, 1.0 / 524288.0);
353 try test_powi_f64(-2, -19, -1.0 / 524288.0);
354
355 try test_powi_f64(2, 31, 2147483648.0);
356 try test_powi_f64(-2, 31, -2147483648.0);
357 try test_powi_f64(2, -31, 1.0 / 2147483648.0);
358 try test_powi_f64(-2, -31, -1.0 / 2147483648.0);
353359}
354360
355test "powitf2" {
356 const inf_f128 = math.inf(f128);
357 try test__powitf2(0, 0, 1);
358 try test__powitf2(1, 0, 1);
359 try test__powitf2(1.5, 0, 1);
360 try test__powitf2(2, 0, 1);
361 try test__powitf2(inf_f128, 0, 1);
362
363 try test__powitf2(-0.0, 0, 1);
364 try test__powitf2(-1, 0, 1);
365 try test__powitf2(-1.5, 0, 1);
366 try test__powitf2(-2, 0, 1);
367 try test__powitf2(-inf_f128, 0, 1);
368
369 try test__powitf2(0, 1, 0);
370 try test__powitf2(0, 2, 0);
371 try test__powitf2(0, 3, 0);
372 try test__powitf2(0, 4, 0);
373 try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
374 try test__powitf2(0, 0x7FFFFFFF, 0);
375
376 try test__powitf2(-0.0, 1, -0.0);
377 try test__powitf2(-0.0, 2, 0);
378 try test__powitf2(-0.0, 3, -0.0);
379 try test__powitf2(-0.0, 4, 0);
380 try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
381 try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
382
383 try test__powitf2(1, 1, 1);
384 try test__powitf2(1, 2, 1);
385 try test__powitf2(1, 3, 1);
386 try test__powitf2(1, 4, 1);
387 try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
388 try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
389
390 try test__powitf2(inf_f128, 1, inf_f128);
391 try test__powitf2(inf_f128, 2, inf_f128);
392 try test__powitf2(inf_f128, 3, inf_f128);
393 try test__powitf2(inf_f128, 4, inf_f128);
394 try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128);
395 try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f128);
396
397 try test__powitf2(-inf_f128, 1, -inf_f128);
398 try test__powitf2(-inf_f128, 2, inf_f128);
399 try test__powitf2(-inf_f128, 3, -inf_f128);
400 try test__powitf2(-inf_f128, 4, inf_f128);
401 try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128);
402 try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f128);
403
404 try test__powitf2(0, -1, inf_f128);
405 try test__powitf2(0, -2, inf_f128);
406 try test__powitf2(0, -3, inf_f128);
407 try test__powitf2(0, -4, inf_f128);
408 try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128);
409 try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f128);
410 try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128);
411
412 try test__powitf2(-0.0, -1, -inf_f128);
413 try test__powitf2(-0.0, -2, inf_f128);
414 try test__powitf2(-0.0, -3, -inf_f128);
415 try test__powitf2(-0.0, -4, inf_f128);
416 try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128);
417 try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f128);
418 try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128);
419
420 try test__powitf2(1, -1, 1);
421 try test__powitf2(1, -2, 1);
422 try test__powitf2(1, -3, 1);
423 try test__powitf2(1, -4, 1);
424 try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
425 try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
426 try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
427
428 try test__powitf2(inf_f128, -1, 0);
429 try test__powitf2(inf_f128, -2, 0);
430 try test__powitf2(inf_f128, -3, 0);
431 try test__powitf2(inf_f128, -4, 0);
432 try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
433 try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
434 try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
435
436 try test__powitf2(-inf_f128, -1, -0.0);
437 try test__powitf2(-inf_f128, -2, 0);
438 try test__powitf2(-inf_f128, -3, -0.0);
439 try test__powitf2(-inf_f128, -4, 0);
440 try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
441 try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
442 try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
443
444 try test__powitf2(2, 10, 1024.0);
445 try test__powitf2(-2, 10, 1024.0);
446 try test__powitf2(2, -10, 1.0 / 1024.0);
447 try test__powitf2(-2, -10, 1.0 / 1024.0);
448
449 try test__powitf2(2, 19, 524288.0);
450 try test__powitf2(-2, 19, -524288.0);
451 try test__powitf2(2, -19, 1.0 / 524288.0);
452 try test__powitf2(-2, -19, -1.0 / 524288.0);
453
454 try test__powitf2(2, 31, 2147483648.0);
455 try test__powitf2(-2, 31, -2147483648.0);
456 try test__powitf2(2, -31, 1.0 / 2147483648.0);
457 try test__powitf2(-2, -31, -1.0 / 2147483648.0);
361test powi_f80 {
362 const inf_f80 = math.inf(f80);
363 try test_powi_f80(0, 0, 1);
364 try test_powi_f80(1, 0, 1);
365 try test_powi_f80(1.5, 0, 1);
366 try test_powi_f80(2, 0, 1);
367 try test_powi_f80(inf_f80, 0, 1);
368
369 try test_powi_f80(-0.0, 0, 1);
370 try test_powi_f80(-1, 0, 1);
371 try test_powi_f80(-1.5, 0, 1);
372 try test_powi_f80(-2, 0, 1);
373 try test_powi_f80(-inf_f80, 0, 1);
374
375 try test_powi_f80(0, 1, 0);
376 try test_powi_f80(0, 2, 0);
377 try test_powi_f80(0, 3, 0);
378 try test_powi_f80(0, 4, 0);
379 try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
380 try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
381
382 try test_powi_f80(-0.0, 1, -0.0);
383 try test_powi_f80(-0.0, 2, 0);
384 try test_powi_f80(-0.0, 3, -0.0);
385 try test_powi_f80(-0.0, 4, 0);
386 try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
387 try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
388
389 try test_powi_f80(1, 1, 1);
390 try test_powi_f80(1, 2, 1);
391 try test_powi_f80(1, 3, 1);
392 try test_powi_f80(1, 4, 1);
393 try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
394 try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
395
396 try test_powi_f80(inf_f80, 1, inf_f80);
397 try test_powi_f80(inf_f80, 2, inf_f80);
398 try test_powi_f80(inf_f80, 3, inf_f80);
399 try test_powi_f80(inf_f80, 4, inf_f80);
400 try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80);
401 try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f80);
402
403 try test_powi_f80(-inf_f80, 1, -inf_f80);
404 try test_powi_f80(-inf_f80, 2, inf_f80);
405 try test_powi_f80(-inf_f80, 3, -inf_f80);
406 try test_powi_f80(-inf_f80, 4, inf_f80);
407 try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80);
408 try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f80);
409
410 try test_powi_f80(0, -1, inf_f80);
411 try test_powi_f80(0, -2, inf_f80);
412 try test_powi_f80(0, -3, inf_f80);
413 try test_powi_f80(0, -4, inf_f80);
414 try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80);
415 try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f80);
416 try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80);
417
418 try test_powi_f80(-0.0, -1, -inf_f80);
419 try test_powi_f80(-0.0, -2, inf_f80);
420 try test_powi_f80(-0.0, -3, -inf_f80);
421 try test_powi_f80(-0.0, -4, inf_f80);
422 try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80);
423 try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f80);
424 try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80);
425
426 try test_powi_f80(1, -1, 1);
427 try test_powi_f80(1, -2, 1);
428 try test_powi_f80(1, -3, 1);
429 try test_powi_f80(1, -4, 1);
430 try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
431 try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
432 try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
433
434 try test_powi_f80(inf_f80, -1, 0);
435 try test_powi_f80(inf_f80, -2, 0);
436 try test_powi_f80(inf_f80, -3, 0);
437 try test_powi_f80(inf_f80, -4, 0);
438 try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
439 try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
440 try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
441
442 try test_powi_f80(-inf_f80, -1, -0.0);
443 try test_powi_f80(-inf_f80, -2, 0);
444 try test_powi_f80(-inf_f80, -3, -0.0);
445 try test_powi_f80(-inf_f80, -4, 0);
446 try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
447 try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
448 try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
449
450 try test_powi_f80(2, 10, 1024.0);
451 try test_powi_f80(-2, 10, 1024.0);
452 try test_powi_f80(2, -10, 1.0 / 1024.0);
453 try test_powi_f80(-2, -10, 1.0 / 1024.0);
454
455 try test_powi_f80(2, 19, 524288.0);
456 try test_powi_f80(-2, 19, -524288.0);
457 try test_powi_f80(2, -19, 1.0 / 524288.0);
458 try test_powi_f80(-2, -19, -1.0 / 524288.0);
459
460 try test_powi_f80(2, 31, 2147483648.0);
461 try test_powi_f80(-2, 31, -2147483648.0);
462 try test_powi_f80(2, -31, 1.0 / 2147483648.0);
463 try test_powi_f80(-2, -31, -1.0 / 2147483648.0);
458464}
459465
460test "powixf2" {
461 const inf_f80 = math.inf(f80);
462 try test__powixf2(0, 0, 1);
463 try test__powixf2(1, 0, 1);
464 try test__powixf2(1.5, 0, 1);
465 try test__powixf2(2, 0, 1);
466 try test__powixf2(inf_f80, 0, 1);
467
468 try test__powixf2(-0.0, 0, 1);
469 try test__powixf2(-1, 0, 1);
470 try test__powixf2(-1.5, 0, 1);
471 try test__powixf2(-2, 0, 1);
472 try test__powixf2(-inf_f80, 0, 1);
473
474 try test__powixf2(0, 1, 0);
475 try test__powixf2(0, 2, 0);
476 try test__powixf2(0, 3, 0);
477 try test__powixf2(0, 4, 0);
478 try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
479 try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
480
481 try test__powixf2(-0.0, 1, -0.0);
482 try test__powixf2(-0.0, 2, 0);
483 try test__powixf2(-0.0, 3, -0.0);
484 try test__powixf2(-0.0, 4, 0);
485 try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
486 try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
487
488 try test__powixf2(1, 1, 1);
489 try test__powixf2(1, 2, 1);
490 try test__powixf2(1, 3, 1);
491 try test__powixf2(1, 4, 1);
492 try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
493 try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
494
495 try test__powixf2(inf_f80, 1, inf_f80);
496 try test__powixf2(inf_f80, 2, inf_f80);
497 try test__powixf2(inf_f80, 3, inf_f80);
498 try test__powixf2(inf_f80, 4, inf_f80);
499 try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80);
500 try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f80);
501
502 try test__powixf2(-inf_f80, 1, -inf_f80);
503 try test__powixf2(-inf_f80, 2, inf_f80);
504 try test__powixf2(-inf_f80, 3, -inf_f80);
505 try test__powixf2(-inf_f80, 4, inf_f80);
506 try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80);
507 try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f80);
508
509 try test__powixf2(0, -1, inf_f80);
510 try test__powixf2(0, -2, inf_f80);
511 try test__powixf2(0, -3, inf_f80);
512 try test__powixf2(0, -4, inf_f80);
513 try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80);
514 try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f80);
515 try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80);
516
517 try test__powixf2(-0.0, -1, -inf_f80);
518 try test__powixf2(-0.0, -2, inf_f80);
519 try test__powixf2(-0.0, -3, -inf_f80);
520 try test__powixf2(-0.0, -4, inf_f80);
521 try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80);
522 try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f80);
523 try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80);
524
525 try test__powixf2(1, -1, 1);
526 try test__powixf2(1, -2, 1);
527 try test__powixf2(1, -3, 1);
528 try test__powixf2(1, -4, 1);
529 try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
530 try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
531 try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
532
533 try test__powixf2(inf_f80, -1, 0);
534 try test__powixf2(inf_f80, -2, 0);
535 try test__powixf2(inf_f80, -3, 0);
536 try test__powixf2(inf_f80, -4, 0);
537 try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
538 try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
539 try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
540
541 try test__powixf2(-inf_f80, -1, -0.0);
542 try test__powixf2(-inf_f80, -2, 0);
543 try test__powixf2(-inf_f80, -3, -0.0);
544 try test__powixf2(-inf_f80, -4, 0);
545 try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
546 try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
547 try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
548
549 try test__powixf2(2, 10, 1024.0);
550 try test__powixf2(-2, 10, 1024.0);
551 try test__powixf2(2, -10, 1.0 / 1024.0);
552 try test__powixf2(-2, -10, 1.0 / 1024.0);
553
554 try test__powixf2(2, 19, 524288.0);
555 try test__powixf2(-2, 19, -524288.0);
556 try test__powixf2(2, -19, 1.0 / 524288.0);
557 try test__powixf2(-2, -19, -1.0 / 524288.0);
558
559 try test__powixf2(2, 31, 2147483648.0);
560 try test__powixf2(-2, 31, -2147483648.0);
561 try test__powixf2(2, -31, 1.0 / 2147483648.0);
562 try test__powixf2(-2, -31, -1.0 / 2147483648.0);
466test powi_f128 {
467 const inf_f128 = math.inf(f128);
468 try test_powi_f128(0, 0, 1);
469 try test_powi_f128(1, 0, 1);
470 try test_powi_f128(1.5, 0, 1);
471 try test_powi_f128(2, 0, 1);
472 try test_powi_f128(inf_f128, 0, 1);
473
474 try test_powi_f128(-0.0, 0, 1);
475 try test_powi_f128(-1, 0, 1);
476 try test_powi_f128(-1.5, 0, 1);
477 try test_powi_f128(-2, 0, 1);
478 try test_powi_f128(-inf_f128, 0, 1);
479
480 try test_powi_f128(0, 1, 0);
481 try test_powi_f128(0, 2, 0);
482 try test_powi_f128(0, 3, 0);
483 try test_powi_f128(0, 4, 0);
484 try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
485 try test_powi_f128(0, 0x7FFFFFFF, 0);
486
487 try test_powi_f128(-0.0, 1, -0.0);
488 try test_powi_f128(-0.0, 2, 0);
489 try test_powi_f128(-0.0, 3, -0.0);
490 try test_powi_f128(-0.0, 4, 0);
491 try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
492 try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
493
494 try test_powi_f128(1, 1, 1);
495 try test_powi_f128(1, 2, 1);
496 try test_powi_f128(1, 3, 1);
497 try test_powi_f128(1, 4, 1);
498 try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
499 try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
500
501 try test_powi_f128(inf_f128, 1, inf_f128);
502 try test_powi_f128(inf_f128, 2, inf_f128);
503 try test_powi_f128(inf_f128, 3, inf_f128);
504 try test_powi_f128(inf_f128, 4, inf_f128);
505 try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128);
506 try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f128);
507
508 try test_powi_f128(-inf_f128, 1, -inf_f128);
509 try test_powi_f128(-inf_f128, 2, inf_f128);
510 try test_powi_f128(-inf_f128, 3, -inf_f128);
511 try test_powi_f128(-inf_f128, 4, inf_f128);
512 try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128);
513 try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f128);
514
515 try test_powi_f128(0, -1, inf_f128);
516 try test_powi_f128(0, -2, inf_f128);
517 try test_powi_f128(0, -3, inf_f128);
518 try test_powi_f128(0, -4, inf_f128);
519 try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128);
520 try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f128);
521 try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128);
522
523 try test_powi_f128(-0.0, -1, -inf_f128);
524 try test_powi_f128(-0.0, -2, inf_f128);
525 try test_powi_f128(-0.0, -3, -inf_f128);
526 try test_powi_f128(-0.0, -4, inf_f128);
527 try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128);
528 try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f128);
529 try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128);
530
531 try test_powi_f128(1, -1, 1);
532 try test_powi_f128(1, -2, 1);
533 try test_powi_f128(1, -3, 1);
534 try test_powi_f128(1, -4, 1);
535 try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
536 try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
537 try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
538
539 try test_powi_f128(inf_f128, -1, 0);
540 try test_powi_f128(inf_f128, -2, 0);
541 try test_powi_f128(inf_f128, -3, 0);
542 try test_powi_f128(inf_f128, -4, 0);
543 try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
544 try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
545 try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
546
547 try test_powi_f128(-inf_f128, -1, -0.0);
548 try test_powi_f128(-inf_f128, -2, 0);
549 try test_powi_f128(-inf_f128, -3, -0.0);
550 try test_powi_f128(-inf_f128, -4, 0);
551 try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
552 try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
553 try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
554
555 try test_powi_f128(2, 10, 1024.0);
556 try test_powi_f128(-2, 10, 1024.0);
557 try test_powi_f128(2, -10, 1.0 / 1024.0);
558 try test_powi_f128(-2, -10, 1.0 / 1024.0);
559
560 try test_powi_f128(2, 19, 524288.0);
561 try test_powi_f128(-2, 19, -524288.0);
562 try test_powi_f128(2, -19, 1.0 / 524288.0);
563 try test_powi_f128(-2, -19, -1.0 / 524288.0);
564
565 try test_powi_f128(2, 31, 2147483648.0);
566 try test_powi_f128(-2, 31, -2147483648.0);
567 try test_powi_f128(2, -31, 1.0 / 2147483648.0);
568 try test_powi_f128(-2, -31, -1.0 / 2147483648.0);
563569}
lib/compiler_rt/round.zig+87-50
......@@ -18,19 +18,22 @@ comptime {
1818 symbol(&roundf, "roundf");
1919 symbol(&round, "round");
2020 symbol(&__roundx, "__roundx");
21 if (compiler_rt.want_ppc_abi) {
22 symbol(&roundq, "roundf128");
23 }
24 symbol(&roundq, "roundq");
21 symbol(&roundq, "roundf128");
2522 symbol(&roundl, "roundl");
2623}
2724
28pub fn __roundh(x: f16) callconv(.c) f16 {
25fn __roundh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
26 return compiler_rt.f16.toAbi(round_f16(compiler_rt.f16.fromAbi(x)));
27}
28pub fn round_f16(x: f16) f16 {
2929 // TODO: more efficient implementation
30 return @floatCast(roundf(x));
30 return @floatCast(round_f32(x));
3131}
3232
33pub fn roundf(x_: f32) callconv(.c) f32 {
33fn roundf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
34 return compiler_rt.f32.toAbi(round_f32(compiler_rt.f32.fromAbi(x)));
35}
36pub fn round_f32(x_: f32) f32 {
3437 const f32_toint = 1.0 / math.floatEps(f32);
3538
3639 var x = x_;
......@@ -65,7 +68,10 @@ pub fn roundf(x_: f32) callconv(.c) f32 {
6568 }
6669}
6770
68pub fn round(x_: f64) callconv(.c) f64 {
71fn round(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
72 return compiler_rt.f64.toAbi(round_f64(compiler_rt.f64.fromAbi(x)));
73}
74pub fn round_f64(x_: f64) f64 {
6975 const f64_toint = 1.0 / math.floatEps(f64);
7076
7177 var x = x_;
......@@ -100,12 +106,18 @@ pub fn round(x_: f64) callconv(.c) f64 {
100106 }
101107}
102108
103pub fn __roundx(x: f80) callconv(.c) f80 {
109fn __roundx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
110 return compiler_rt.f80.toAbi(round_f80(compiler_rt.f80.fromAbi(x)));
111}
112pub fn round_f80(x: f80) f80 {
104113 // TODO: more efficient implementation
105 return @floatCast(roundq(x));
114 return @floatCast(round_f128(x));
106115}
107116
108pub fn roundq(x_: f128) callconv(.c) f128 {
117fn roundq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
118 return compiler_rt.f128.toAbi(round_f128(compiler_rt.f128.fromAbi(x)));
119}
120pub fn round_f128(x_: f128) f128 {
109121 const f128_toint = 1.0 / math.floatEps(f128);
110122
111123 var x = x_;
......@@ -142,54 +154,79 @@ pub fn roundq(x_: f128) callconv(.c) f128 {
142154
143155pub fn roundl(x: c_longdouble) callconv(.c) c_longdouble {
144156 switch (@typeInfo(c_longdouble).float.bits) {
145 64 => return round(x),
146 80 => return __roundx(x),
147 128 => return roundq(x),
148 else => @compileError("unreachable"),
157 64 => return round_f64(x),
158 80 => return round_f80(x),
159 128 => return round_f128(x),
160 else => comptime unreachable,
149161 }
150162}
151163
152test "round32" {
153 try expect(roundf(1.3) == 1.0);
154 try expect(roundf(-1.3) == -1.0);
155 try expect(roundf(0.2) == 0.0);
156 try expect(roundf(1.8) == 2.0);
157}
158
159test "round64" {
160 try expect(round(1.3) == 1.0);
161 try expect(round(-1.3) == -1.0);
162 try expect(round(0.2) == 0.0);
163 try expect(round(1.8) == 2.0);
164test round_f16 {
165 try expect(round_f16(1.3) == 1.0);
166 try expect(round_f16(-1.3) == -1.0);
167 try expect(round_f16(1.8) == 2.0);
168 try expect(round_f16(-1.8) == -2.0);
169 try expect(math.isPositiveZero(round_f16(0.2)));
170 try expect(math.isNegativeZero(round_f16(-0.2)));
171 try expect(math.isPositiveZero(round_f16(0.0)));
172 try expect(math.isNegativeZero(round_f16(-0.0)));
173 try expect(math.isPositiveInf(round_f16(math.inf(f32))));
174 try expect(math.isNegativeInf(round_f16(-math.inf(f32))));
175 try expect(math.isNan(round_f16(math.nan(f32))));
164176}
165177
166test "round128" {
167 try expect(roundq(1.3) == 1.0);
168 try expect(roundq(-1.3) == -1.0);
169 try expect(roundq(0.2) == 0.0);
170 try expect(roundq(1.8) == 2.0);
178test round_f32 {
179 try expect(round_f32(1.3) == 1.0);
180 try expect(round_f32(-1.3) == -1.0);
181 try expect(round_f32(1.8) == 2.0);
182 try expect(round_f32(-1.8) == -2.0);
183 try expect(math.isPositiveZero(round_f32(0.2)));
184 try expect(math.isNegativeZero(round_f32(-0.2)));
185 try expect(math.isPositiveZero(round_f32(0.0)));
186 try expect(math.isNegativeZero(round_f32(-0.0)));
187 try expect(math.isPositiveInf(round_f32(math.inf(f32))));
188 try expect(math.isNegativeInf(round_f32(-math.inf(f32))));
189 try expect(math.isNan(round_f32(math.nan(f32))));
171190}
172191
173test "round32.special" {
174 try expect(roundf(0.0) == 0.0);
175 try expect(roundf(-0.0) == -0.0);
176 try expect(math.isPositiveInf(roundf(math.inf(f32))));
177 try expect(math.isNegativeInf(roundf(-math.inf(f32))));
178 try expect(math.isNan(roundf(math.nan(f32))));
192test round_f64 {
193 try expect(round_f64(1.3) == 1.0);
194 try expect(round_f64(-1.3) == -1.0);
195 try expect(round_f64(1.8) == 2.0);
196 try expect(round_f64(-1.8) == -2.0);
197 try expect(math.isPositiveZero(round_f64(0.2)));
198 try expect(math.isNegativeZero(round_f64(-0.2)));
199 try expect(math.isPositiveZero(round_f64(0.0)));
200 try expect(math.isNegativeZero(round_f64(-0.0)));
201 try expect(math.isPositiveInf(round_f64(math.inf(f64))));
202 try expect(math.isNegativeInf(round_f64(-math.inf(f64))));
203 try expect(math.isNan(round_f64(math.nan(f64))));
179204}
180205
181test "round64.special" {
182 try expect(round(0.0) == 0.0);
183 try expect(round(-0.0) == -0.0);
184 try expect(math.isPositiveInf(round(math.inf(f64))));
185 try expect(math.isNegativeInf(round(-math.inf(f64))));
186 try expect(math.isNan(round(math.nan(f64))));
206test round_f80 {
207 try expect(round_f80(1.3) == 1.0);
208 try expect(round_f80(-1.3) == -1.0);
209 try expect(round_f80(1.8) == 2.0);
210 try expect(round_f80(-1.8) == -2.0);
211 try expect(math.isPositiveZero(round_f80(0.2)));
212 try expect(math.isNegativeZero(round_f80(-0.2)));
213 try expect(math.isPositiveZero(round_f80(0.0)));
214 try expect(math.isNegativeZero(round_f80(-0.0)));
215 try expect(math.isPositiveInf(round_f80(math.inf(f64))));
216 try expect(math.isNegativeInf(round_f80(-math.inf(f64))));
217 try expect(math.isNan(round_f80(math.nan(f64))));
187218}
188219
189test "round128.special" {
190 try expect(roundq(0.0) == 0.0);
191 try expect(roundq(-0.0) == -0.0);
192 try expect(math.isPositiveInf(roundq(math.inf(f128))));
193 try expect(math.isNegativeInf(roundq(-math.inf(f128))));
194 try expect(math.isNan(roundq(math.nan(f128))));
220test round_f128 {
221 try expect(round_f128(1.3) == 1.0);
222 try expect(round_f128(-1.3) == -1.0);
223 try expect(round_f128(1.8) == 2.0);
224 try expect(round_f128(-1.8) == -2.0);
225 try expect(math.isPositiveZero(round_f128(0.2)));
226 try expect(math.isNegativeZero(round_f128(-0.2)));
227 try expect(math.isPositiveZero(round_f128(0.0)));
228 try expect(math.isNegativeZero(round_f128(-0.0)));
229 try expect(math.isPositiveInf(round_f128(math.inf(f128))));
230 try expect(math.isNegativeInf(round_f128(-math.inf(f128))));
231 try expect(math.isNan(round_f128(math.nan(f128))));
195232}
lib/compiler_rt/sin.zig+66-53
......@@ -13,31 +13,34 @@ const expect = std.testing.expect;
1313const expectApproxEqAbs = std.testing.expectApproxEqAbs;
1414
1515const compiler_rt = @import("../compiler_rt.zig");
16const symbol = @import("../compiler_rt.zig").symbol;
16const symbol = compiler_rt.symbol;
1717const trig = @import("trig.zig");
1818const rem_pio2 = @import("rem_pio2.zig").rem_pio2;
1919const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f;
2020const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l;
2121
2222comptime {
23 symbol(&sinh, "__sinh");
24 symbol(&sinl, "__sinl");
23 symbol(&__sinh, "__sinh");
2524 symbol(&sinf, "sinf");
2625 symbol(&sin, "sin");
27 symbol(&sinx, "__sinx");
28 if (compiler_rt.want_ppc_abi) {
29 symbol(&sinq, "sinf128");
30 }
31 symbol(&sinq, "sinq");
26 symbol(&__sinx, "__sinx");
27 symbol(&sinq, "sinf128");
3228 symbol(&sinl, "sinl");
29 symbol(&sinl, "__sinl"); // required by musl
3330}
3431
35pub fn sinh(x: f16) callconv(.c) f16 {
32fn __sinh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
33 return compiler_rt.f16.toAbi(sin_f16(compiler_rt.f16.fromAbi(x)));
34}
35pub fn sin_f16(x: f16) f16 {
3636 // TODO: more efficient implementation
37 return @floatCast(sinf(x));
37 return @floatCast(sin_f32(x));
3838}
3939
40pub fn sinf(x: f32) callconv(.c) f32 {
40fn sinf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
41 return compiler_rt.f32.toAbi(sin_f32(compiler_rt.f32.fromAbi(x)));
42}
43pub fn sin_f32(x: f32) f32 {
4144 // Small multiples of pi/2 rounded to double precision.
4245 const s1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18
4346 const s2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18
......@@ -98,7 +101,10 @@ pub fn sinf(x: f32) callconv(.c) f32 {
98101 };
99102}
100103
101pub fn sin(x: f64) callconv(.c) f64 {
104fn sin(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
105 return compiler_rt.f64.toAbi(sin_f64(compiler_rt.f64.fromAbi(x)));
106}
107pub fn sin_f64(x: f64) f64 {
102108 var ix = @as(u64, @bitCast(x)) >> 32;
103109 ix &= 0x7fffffff;
104110
......@@ -133,7 +139,10 @@ pub fn sin(x: f64) callconv(.c) f64 {
133139 };
134140}
135141
136fn sinx(x: f80) callconv(.c) f80 {
142fn __sinx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
143 return compiler_rt.f80.toAbi(sin_f80(compiler_rt.f80.fromAbi(x)));
144}
145pub fn sin_f80(x: f80) f80 {
137146 const se = ld.signExponent(x) & 0x7fff;
138147 if (se == 0x7fff) {
139148 return x - x;
......@@ -160,7 +169,10 @@ fn sinx(x: f80) callconv(.c) f80 {
160169 };
161170}
162171
163pub fn sinq(x: f128) callconv(.c) f128 {
172fn sinq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
173 return compiler_rt.f128.toAbi(sin_f128(compiler_rt.f128.fromAbi(x)));
174}
175pub fn sin_f128(x: f128) f128 {
164176 const se = ld.signExponent(x) & 0x7fff;
165177 if (se == 0x7fff) {
166178 return x - x;
......@@ -189,20 +201,21 @@ pub fn sinq(x: f128) callconv(.c) f128 {
189201
190202pub fn sinl(x: c_longdouble) callconv(.c) c_longdouble {
191203 switch (@typeInfo(c_longdouble).float.bits) {
192 64 => return sin(x),
193 80 => return sinx(x),
194 128 => return sinq(x),
195 else => @compileError("unreachable"),
204 64 => return sin_f64(x),
205 80 => return sin_f80(x),
206 128 => return sin_f128(x),
207 else => comptime unreachable,
196208 }
197209}
198210
199211fn testSinSpecial(comptime T: type) !void {
200212 const f = switch (T) {
201 f32 => sinf,
202 f64 => sin,
203 f80 => sinx,
204 f128 => sinq,
205 else => @compileError("unimplemented"),
213 f16 => sin_f16,
214 f32 => sin_f32,
215 f64 => sin_f64,
216 f80 => sin_f80,
217 f128 => sin_f128,
218 else => comptime unreachable,
206219 };
207220
208221 try expect(math.isPositiveZero(f(0.0)));
......@@ -214,13 +227,13 @@ fn testSinSpecial(comptime T: type) !void {
214227
215228test "sin32.normal" {
216229 const epsilon = math.floatEps(f32);
217 try expectApproxEqAbs(@as(f32, 0.0), sinf(0.0), epsilon);
218 try expectApproxEqAbs(@as(f32, 0.19866933), sinf(0.2), epsilon);
219 try expectApproxEqAbs(@as(f32, 0.77851737), sinf(0.8923), epsilon);
220 try expectApproxEqAbs(@as(f32, 0.997495), sinf(1.5), epsilon);
221 try expectApproxEqAbs(@as(f32, -0.997495), sinf(-1.5), epsilon);
222 try expectApproxEqAbs(@as(f32, -0.24654257), sinf(37.45), epsilon);
223 try expectApproxEqAbs(@as(f32, 0.9161657), sinf(89.123), epsilon);
230 try expectApproxEqAbs(@as(f32, 0.0), sin_f32(0.0), epsilon);
231 try expectApproxEqAbs(@as(f32, 0.19866933), sin_f32(0.2), epsilon);
232 try expectApproxEqAbs(@as(f32, 0.77851737), sin_f32(0.8923), epsilon);
233 try expectApproxEqAbs(@as(f32, 0.997495), sin_f32(1.5), epsilon);
234 try expectApproxEqAbs(@as(f32, -0.997495), sin_f32(-1.5), epsilon);
235 try expectApproxEqAbs(@as(f32, -0.24654257), sin_f32(37.45), epsilon);
236 try expectApproxEqAbs(@as(f32, 0.9161657), sin_f32(89.123), epsilon);
224237}
225238
226239test "sin32.special" {
......@@ -229,13 +242,13 @@ test "sin32.special" {
229242
230243test "sin64.normal" {
231244 const epsilon = math.floatEps(f64);
232 try expectApproxEqAbs(@as(f64, 0.0), sin(0.0), epsilon);
233 try expectApproxEqAbs(@as(f64, 0.19866933079506122), sin(0.2), epsilon);
234 try expectApproxEqAbs(@as(f64, 0.7785173385577349), sin(0.8923), epsilon);
235 try expectApproxEqAbs(@as(f64, 0.9974949866040544), sin(1.5), epsilon);
236 try expectApproxEqAbs(@as(f64, -0.9974949866040544), sin(-1.5), epsilon);
237 try expectApproxEqAbs(@as(f64, -0.24654331551411082), sin(37.45), epsilon);
238 try expectApproxEqAbs(@as(f64, 0.9161652766622714), sin(89.123), epsilon);
245 try expectApproxEqAbs(@as(f64, 0.0), sin_f64(0.0), epsilon);
246 try expectApproxEqAbs(@as(f64, 0.19866933079506122), sin_f64(0.2), epsilon);
247 try expectApproxEqAbs(@as(f64, 0.7785173385577349), sin_f64(0.8923), epsilon);
248 try expectApproxEqAbs(@as(f64, 0.9974949866040544), sin_f64(1.5), epsilon);
249 try expectApproxEqAbs(@as(f64, -0.9974949866040544), sin_f64(-1.5), epsilon);
250 try expectApproxEqAbs(@as(f64, -0.24654331551411082), sin_f64(37.45), epsilon);
251 try expectApproxEqAbs(@as(f64, 0.9161652766622714), sin_f64(89.123), epsilon);
239252}
240253
241254test "sin64.special" {
......@@ -244,13 +257,13 @@ test "sin64.special" {
244257
245258test "sin80.normal" {
246259 const epsilon = math.floatEps(f80);
247 try expectApproxEqAbs(@as(f80, 0.0), sinx(0.0), epsilon);
248 try expectApproxEqAbs(@as(f80, 0.19866933079506121545941262711838975), sinx(0.2), epsilon);
249 try expectApproxEqAbs(@as(f80, 0.77851733855773487830689285621486050), sinx(0.8923), epsilon);
250 try expectApproxEqAbs(@as(f80, 0.99749498660405443094172337114148732), sinx(1.5), epsilon);
251 try expectApproxEqAbs(@as(f80, -0.99749498660405443094172337114148732), sinx(-1.5), epsilon);
252 try expectApproxEqAbs(@as(f80, -0.24654331551411356504), sinx(37.45), epsilon);
253 try expectApproxEqAbs(@as(f80, 0.91616527666226951006), sinx(89.123), epsilon);
260 try expectApproxEqAbs(@as(f80, 0.0), sin_f80(0.0), epsilon);
261 try expectApproxEqAbs(@as(f80, 0.19866933079506121545941262711838975), sin_f80(0.2), epsilon);
262 try expectApproxEqAbs(@as(f80, 0.77851733855773487830689285621486050), sin_f80(0.8923), epsilon);
263 try expectApproxEqAbs(@as(f80, 0.99749498660405443094172337114148732), sin_f80(1.5), epsilon);
264 try expectApproxEqAbs(@as(f80, -0.99749498660405443094172337114148732), sin_f80(-1.5), epsilon);
265 try expectApproxEqAbs(@as(f80, -0.24654331551411356504), sin_f80(37.45), epsilon);
266 try expectApproxEqAbs(@as(f80, 0.91616527666226951006), sin_f80(89.123), epsilon);
254267}
255268
256269test "sin80.special" {
......@@ -259,13 +272,13 @@ test "sin80.special" {
259272
260273test "sin128.normal" {
261274 const epsilon = math.floatEps(f128);
262 try expectApproxEqAbs(@as(f128, 0.0), sinq(0.0), epsilon);
263 try expectApproxEqAbs(@as(f128, 0.19866933079506121545941262711838975), sinq(0.2), epsilon);
264 try expectApproxEqAbs(@as(f128, 0.77851733855773487830689285621486050), sinq(0.8923), epsilon);
265 try expectApproxEqAbs(@as(f128, 0.99749498660405443094172337114148732), sinq(1.5), epsilon);
266 try expectApproxEqAbs(@as(f128, -0.99749498660405443094172337114148732), sinq(-1.5), epsilon);
267 try expectApproxEqAbs(@as(f128, -0.24654331551411356571238581321661085), sinq(37.45), epsilon);
268 try expectApproxEqAbs(@as(f128, 0.91616527666226951075019849560482170), sinq(89.123), epsilon);
275 try expectApproxEqAbs(@as(f128, 0.0), sin_f128(0.0), epsilon);
276 try expectApproxEqAbs(@as(f128, 0.19866933079506121545941262711838975), sin_f128(0.2), epsilon);
277 try expectApproxEqAbs(@as(f128, 0.77851733855773487830689285621486050), sin_f128(0.8923), epsilon);
278 try expectApproxEqAbs(@as(f128, 0.99749498660405443094172337114148732), sin_f128(1.5), epsilon);
279 try expectApproxEqAbs(@as(f128, -0.99749498660405443094172337114148732), sin_f128(-1.5), epsilon);
280 try expectApproxEqAbs(@as(f128, -0.24654331551411356571238581321661085), sin_f128(37.45), epsilon);
281 try expectApproxEqAbs(@as(f128, 0.91616527666226951075019849560482170), sin_f128(89.123), epsilon);
269282}
270283
271284test "sin128.special" {
......@@ -274,10 +287,10 @@ test "sin128.special" {
274287
275288test "sin32 #9901" {
276289 const float: f32 = @bitCast(@as(u32, 0b11100011111111110000000000000000));
277 _ = sinf(float);
290 _ = sin_f32(float);
278291}
279292
280293test "sin64 #9901" {
281294 const float: f64 = @bitCast(@as(u64, 0b1111111101000001000000001111110111111111100000000000000000000001));
282 _ = sin(float);
295 _ = sin_f64(float);
283296}
lib/compiler_rt/sincos.zig+125-181
......@@ -18,23 +18,27 @@ comptime {
1818 symbol(&sincosf, "sincosf");
1919 symbol(&sincos, "sincos");
2020 symbol(&sincosx, "__sincosx");
21 if (compiler_rt.want_ppc_abi) {
22 symbol(&sincosq, "sincosf128");
23 }
24 symbol(&sincosq, "sincosq");
21 symbol(&sincosq, "sincosf128");
2522 symbol(&sincosl, "sincosl");
2623}
2724
28pub fn sincosh(x: f16, r_sin: *f16, r_cos: *f16) callconv(.c) void {
25fn sincosh(x: compiler_rt.f16.Abi, r_sin: *compiler_rt.f16.Abi, r_cos: *compiler_rt.f16.Abi) callconv(.c) void {
26 const s, const c = sincos_f16(compiler_rt.f16.fromAbi(x));
27 r_sin.* = compiler_rt.f16.toAbi(s);
28 r_cos.* = compiler_rt.f16.toAbi(c);
29}
30pub fn sincos_f16(x: f16) struct { f16, f16 } {
2931 // TODO: more efficient implementation
30 var big_sin: f32 = undefined;
31 var big_cos: f32 = undefined;
32 sincosf(x, &big_sin, &big_cos);
33 r_sin.* = @as(f16, @floatCast(big_sin));
34 r_cos.* = @as(f16, @floatCast(big_cos));
32 const s, const c = sincos_f32(x);
33 return .{ @floatCast(s), @floatCast(c) };
3534}
3635
37pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void {
36fn sincosf(x: compiler_rt.f32.Abi, r_sin: *compiler_rt.f32.Abi, r_cos: *compiler_rt.f32.Abi) callconv(.c) void {
37 const s, const c = sincos_f32(compiler_rt.f32.fromAbi(x));
38 r_sin.* = compiler_rt.f32.toAbi(s);
39 r_cos.* = compiler_rt.f32.toAbi(c);
40}
41pub fn sincos_f32(x: f32) struct { f32, f32 } {
3842 const sc1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18
3943 const sc2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18
4044 const sc3pio2: f64 = 3.0 * math.pi / 2.0; // 0x4012D97C, 0x7F3321D2
......@@ -56,13 +60,9 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void {
5660 mem.doNotOptimizeAway(x + 0x1p120);
5761 }
5862 }
59 r_sin.* = x;
60 r_cos.* = 1.0;
61 return;
63 return .{ x, 1.0 };
6264 }
63 r_sin.* = trig.sindf(x);
64 r_cos.* = trig.cosdf(x);
65 return;
65 return .{ trig.sindf(x), trig.cosdf(x) };
6666 }
6767
6868 // |x| ~<= 5*pi/4
......@@ -70,18 +70,16 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void {
7070 // |x| ~<= 3pi/4
7171 if (ix <= 0x4016cbe3) {
7272 if (sign) {
73 r_sin.* = -trig.cosdf(x + sc1pio2);
74 r_cos.* = trig.sindf(x + sc1pio2);
73 return .{ -trig.cosdf(x + sc1pio2), trig.sindf(x + sc1pio2) };
7574 } else {
76 r_sin.* = trig.cosdf(sc1pio2 - x);
77 r_cos.* = trig.sindf(sc1pio2 - x);
75 return .{ trig.cosdf(sc1pio2 - x), trig.sindf(sc1pio2 - x) };
7876 }
79 return;
8077 }
8178 // -sin(x+c) is not correct if x+c could be 0: -0 vs +0
82 r_sin.* = -trig.sindf(if (sign) x + sc2pio2 else x - sc2pio2);
83 r_cos.* = -trig.cosdf(if (sign) x + sc2pio2 else x - sc2pio2);
84 return;
79 return .{
80 -trig.sindf(if (sign) x + sc2pio2 else x - sc2pio2),
81 -trig.cosdf(if (sign) x + sc2pio2 else x - sc2pio2),
82 };
8583 }
8684
8785 // |x| ~<= 9*pi/4
......@@ -89,25 +87,21 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void {
8987 // |x| ~<= 7*pi/4
9088 if (ix <= 0x40afeddf) {
9189 if (sign) {
92 r_sin.* = trig.cosdf(x + sc3pio2);
93 r_cos.* = -trig.sindf(x + sc3pio2);
90 return .{ trig.cosdf(x + sc3pio2), -trig.sindf(x + sc3pio2) };
9491 } else {
95 r_sin.* = -trig.cosdf(x - sc3pio2);
96 r_cos.* = trig.sindf(x - sc3pio2);
92 return .{ -trig.cosdf(x - sc3pio2), trig.sindf(x - sc3pio2) };
9793 }
98 return;
9994 }
100 r_sin.* = trig.sindf(if (sign) x + sc4pio2 else x - sc4pio2);
101 r_cos.* = trig.cosdf(if (sign) x + sc4pio2 else x - sc4pio2);
102 return;
95 return .{
96 trig.sindf(if (sign) x + sc4pio2 else x - sc4pio2),
97 trig.cosdf(if (sign) x + sc4pio2 else x - sc4pio2),
98 };
10399 }
104100
105101 // sin(Inf or NaN) is NaN
106102 if (ix >= 0x7f800000) {
107103 const result = x - x;
108 r_sin.* = result;
109 r_cos.* = result;
110 return;
104 return .{ result, result };
111105 }
112106
113107 // general argument reduction needed
......@@ -115,27 +109,20 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void {
115109 const n = rem_pio2f(x, &y);
116110 const s = trig.sindf(y);
117111 const c = trig.cosdf(y);
118 switch (n & 3) {
119 0 => {
120 r_sin.* = s;
121 r_cos.* = c;
122 },
123 1 => {
124 r_sin.* = c;
125 r_cos.* = -s;
126 },
127 2 => {
128 r_sin.* = -s;
129 r_cos.* = -c;
130 },
131 else => {
132 r_sin.* = -c;
133 r_cos.* = s;
134 },
135 }
112 return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) {
113 0 => .{ s, c },
114 1 => .{ c, -s },
115 2 => .{ -s, -c },
116 3 => .{ -c, s },
117 };
136118}
137119
138pub fn sincos(x: f64, r_sin: *f64, r_cos: *f64) callconv(.c) void {
120fn sincos(x: compiler_rt.f64.Abi, r_sin: *compiler_rt.f64.Abi, r_cos: *compiler_rt.f64.Abi) callconv(.c) void {
121 const s, const c = sincos_f64(compiler_rt.f64.fromAbi(x));
122 r_sin.* = compiler_rt.f64.toAbi(s);
123 r_cos.* = compiler_rt.f64.toAbi(c);
124}
125pub fn sincos_f64(x: f64) struct { f64, f64 } {
139126 const ix = @as(u32, @truncate(@as(u64, @bitCast(x)) >> 32)) & 0x7fffffff;
140127
141128 // |x| ~< pi/4
......@@ -150,21 +137,15 @@ pub fn sincos(x: f64, r_sin: *f64, r_cos: *f64) callconv(.c) void {
150137 mem.doNotOptimizeAway(x + 0x1p120);
151138 }
152139 }
153 r_sin.* = x;
154 r_cos.* = 1.0;
155 return;
140 return .{ x, 1.0 };
156141 }
157 r_sin.* = trig.sin(x, 0.0, 0);
158 r_cos.* = trig.cos(x, 0.0);
159 return;
142 return .{ trig.sin(x, 0.0, 0), trig.cos(x, 0.0) };
160143 }
161144
162145 // sincos(Inf or NaN) is NaN
163146 if (ix >= 0x7ff00000) {
164147 const result = x - x;
165 r_sin.* = result;
166 r_cos.* = result;
167 return;
148 return .{ result, result };
168149 }
169150
170151 // argument reduction needed
......@@ -172,33 +153,24 @@ pub fn sincos(x: f64, r_sin: *f64, r_cos: *f64) callconv(.c) void {
172153 const n = rem_pio2(x, &y);
173154 const s = trig.sin(y[0], y[1], 1);
174155 const c = trig.cos(y[0], y[1]);
175 switch (n & 3) {
176 0 => {
177 r_sin.* = s;
178 r_cos.* = c;
179 },
180 1 => {
181 r_sin.* = c;
182 r_cos.* = -s;
183 },
184 2 => {
185 r_sin.* = -s;
186 r_cos.* = -c;
187 },
188 else => {
189 r_sin.* = -c;
190 r_cos.* = s;
191 },
192 }
156 return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) {
157 0 => .{ s, c },
158 1 => .{ c, -s },
159 2 => .{ -s, -c },
160 3 => .{ -c, s },
161 };
193162}
194163
195pub fn sincosx(x: f80, r_sin: *f80, r_cos: *f80) callconv(.c) void {
164fn sincosx(x: compiler_rt.f80.Abi, r_sin: *compiler_rt.f80.Abi, r_cos: *compiler_rt.f80.Abi) callconv(.c) void {
165 const s, const c = sincos_f80(compiler_rt.f80.fromAbi(x));
166 r_sin.* = compiler_rt.f80.toAbi(s);
167 r_cos.* = compiler_rt.f80.toAbi(c);
168}
169pub fn sincos_f80(x: f80) struct { f80, f80 } {
196170 const se = ld.signExponent(x) & 0x7fff;
197171 if (se == 0x7fff) {
198172 const result = x - x;
199 r_sin.* = result;
200 r_cos.* = result;
201 return;
173 return .{ result, result };
202174 }
203175
204176 if (@abs(x) < trig.pi_4) {
......@@ -207,47 +179,34 @@ pub fn sincosx(x: f80, r_sin: *f80, r_cos: *f80) callconv(.c) void {
207179 if (compiler_rt.want_float_exceptions and se == 0) {
208180 mem.doNotOptimizeAway(x * 0x1p-120);
209181 }
210 r_sin.* = x;
211182 // raise inexact if x!=0
212 r_cos.* = 1.0 + x;
213 return;
183 return .{ x, 1.0 + x };
214184 }
215 r_sin.* = trig.sinx(x, 0.0, 0);
216 r_cos.* = trig.cosx(x, 0.0);
217 return;
185 return .{ trig.sinx(x, 0.0, 0), trig.cosx(x, 0.0) };
218186 }
219187
220188 var y: [2]f80 = undefined;
221189 const n = rem_pio2l(f80, x, &y);
222190 const s = trig.sinx(y[0], y[1], 1);
223191 const c = trig.cosx(y[0], y[1]);
224 switch (n & 3) {
225 0 => {
226 r_sin.* = s;
227 r_cos.* = c;
228 },
229 1 => {
230 r_sin.* = c;
231 r_cos.* = -s;
232 },
233 2 => {
234 r_sin.* = -s;
235 r_cos.* = -c;
236 },
237 else => {
238 r_sin.* = -c;
239 r_cos.* = s;
240 },
241 }
192 return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) {
193 0 => .{ s, c },
194 1 => .{ c, -s },
195 2 => .{ -s, -c },
196 3 => .{ -c, s },
197 };
242198}
243199
244pub fn sincosq(x: f128, r_sin: *f128, r_cos: *f128) callconv(.c) void {
200fn sincosq(x: compiler_rt.f128.Abi, r_sin: *compiler_rt.f128.Abi, r_cos: *compiler_rt.f128.Abi) callconv(.c) void {
201 const s, const c = sincos_f128(compiler_rt.f128.fromAbi(x));
202 r_sin.* = compiler_rt.f128.toAbi(s);
203 r_cos.* = compiler_rt.f128.toAbi(c);
204}
205pub fn sincos_f128(x: f128) struct { f128, f128 } {
245206 const se = ld.signExponent(x) & 0x7fff;
246207 if (se == 0x7fff) {
247208 const result = x - x;
248 r_sin.* = result;
249 r_cos.* = result;
250 return;
209 return .{ result, result };
251210 }
252211
253212 if (@abs(x) < trig.pi_4) {
......@@ -256,78 +215,63 @@ pub fn sincosq(x: f128, r_sin: *f128, r_cos: *f128) callconv(.c) void {
256215 if (compiler_rt.want_float_exceptions and se == 0) {
257216 mem.doNotOptimizeAway(x * 0x1p-120);
258217 }
259 r_sin.* = x;
260218 // raise inexact if x!=0
261 r_cos.* = 1.0 + x;
262 return;
219 return .{ x, 1.0 + x };
263220 }
264 r_sin.* = trig.sinq(x, 0.0, 0);
265 r_cos.* = trig.cosq(x, 0.0);
266 return;
221 return .{ trig.sinq(x, 0.0, 0), trig.cosq(x, 0.0) };
267222 }
268223
269224 var y: [2]f128 = undefined;
270225 const n = rem_pio2l(f128, x, &y);
271226 const s = trig.sinq(y[0], y[1], 1);
272227 const c = trig.cosq(y[0], y[1]);
273 switch (n & 3) {
274 0 => {
275 r_sin.* = s;
276 r_cos.* = c;
277 },
278 1 => {
279 r_sin.* = c;
280 r_cos.* = -s;
281 },
282 2 => {
283 r_sin.* = -s;
284 r_cos.* = -c;
285 },
286 else => {
287 r_sin.* = -c;
288 r_cos.* = s;
289 },
290 }
228 return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) {
229 0 => .{ s, c },
230 1 => .{ c, -s },
231 2 => .{ -s, -c },
232 3 => .{ -c, s },
233 };
291234}
292235
293236pub fn sincosl(x: c_longdouble, r_sin: *c_longdouble, r_cos: *c_longdouble) callconv(.c) void {
294 switch (@typeInfo(c_longdouble).float.bits) {
295 64 => return sincos(x, r_sin, r_cos),
296 80 => return sincosx(x, r_sin, r_cos),
297 128 => return sincosq(x, r_sin, r_cos),
298 else => @compileError("unreachable"),
299 }
237 r_sin.*, r_cos.* = switch (@typeInfo(c_longdouble).float.bits) {
238 64 => sincos_f64(x),
239 80 => sincos_f80(x),
240 128 => sincos_f128(x),
241 else => comptime unreachable,
242 };
300243}
301244
302245fn testSincosSpecial(comptime T: type) !void {
303246 const f = switch (T) {
304 f32 => sincosf,
305 f64 => sincos,
306 f80 => sincosx,
307 f128 => sincosq,
247 f16 => sincos_f16,
248 f32 => sincos_f32,
249 f64 => sincos_f64,
250 f80 => sincos_f80,
251 f128 => sincos_f128,
308252 else => @compileError("unimplemented"),
309253 };
310254
311255 var s: T = undefined;
312256 var c: T = undefined;
313257
314 f(0.0, &s, &c);
258 s, c = f(0.0);
315259 try expect(math.isPositiveZero(s));
316260 try expect(c == 1.0);
317261
318 f(-0.0, &s, &c);
262 s, c = f(-0.0);
319263 try expect(math.isNegativeZero(s));
320264 try expect(c == 1.0);
321265
322 f(math.inf(T), &s, &c);
266 s, c = f(math.inf(T));
323267 try expect(math.isNan(s));
324268 try expect(math.isNan(c));
325269
326 f(-math.inf(T), &s, &c);
270 s, c = f(-math.inf(T));
327271 try expect(math.isNan(s));
328272 try expect(math.isNan(c));
329273
330 f(math.nan(T), &s, &c);
274 s, c = f(math.nan(T));
331275 try expect(math.isNan(s));
332276 try expect(math.isNan(c));
333277}
......@@ -337,31 +281,31 @@ test "sincos32.normal" {
337281 var s: f32 = undefined;
338282 var c: f32 = undefined;
339283
340 sincosf(0.0, &s, &c);
284 s, c = sincos_f32(0.0);
341285 try expectApproxEqAbs(@as(f32, 0.0), s, epsilon);
342286 try expectApproxEqAbs(@as(f32, 1.0), c, epsilon);
343287
344 sincosf(0.2, &s, &c);
288 s, c = sincos_f32(0.2);
345289 try expectApproxEqAbs(@as(f32, 0.19866933), s, epsilon);
346290 try expectApproxEqAbs(@as(f32, 0.9800666), c, epsilon);
347291
348 sincosf(0.8923, &s, &c);
292 s, c = sincos_f32(0.8923);
349293 try expectApproxEqAbs(@as(f32, 0.77851737), s, epsilon);
350294 try expectApproxEqAbs(@as(f32, 0.6276231), c, epsilon);
351295
352 sincosf(1.5, &s, &c);
296 s, c = sincos_f32(1.5);
353297 try expectApproxEqAbs(@as(f32, 0.997495), s, epsilon);
354298 try expectApproxEqAbs(@as(f32, 0.0707372), c, epsilon);
355299
356 sincosf(-1.5, &s, &c);
300 s, c = sincos_f32(-1.5);
357301 try expectApproxEqAbs(@as(f32, -0.997495), s, epsilon);
358302 try expectApproxEqAbs(@as(f32, 0.0707372), c, epsilon);
359303
360 sincosf(37.45, &s, &c);
304 s, c = sincos_f32(37.45);
361305 try expectApproxEqAbs(@as(f32, -0.24654257), s, epsilon);
362306 try expectApproxEqAbs(@as(f32, 0.96913195), c, epsilon);
363307
364 sincosf(89.123, &s, &c);
308 s, c = sincos_f32(89.123);
365309 try expectApproxEqAbs(@as(f32, 0.9161657), s, epsilon);
366310 try expectApproxEqAbs(@as(f32, 0.40079966), c, epsilon);
367311}
......@@ -375,31 +319,31 @@ test "sincos64.normal" {
375319 var s: f64 = undefined;
376320 var c: f64 = undefined;
377321
378 sincos(0.0, &s, &c);
322 s, c = sincos_f64(0.0);
379323 try expectApproxEqAbs(@as(f64, 0.0), s, epsilon);
380324 try expectApproxEqAbs(@as(f64, 1.0), c, epsilon);
381325
382 sincos(0.2, &s, &c);
326 s, c = sincos_f64(0.2);
383327 try expectApproxEqAbs(@as(f64, 0.19866933079506122), s, epsilon);
384328 try expectApproxEqAbs(@as(f64, 0.9800665778412416), c, epsilon);
385329
386 sincos(0.8923, &s, &c);
330 s, c = sincos_f64(0.8923);
387331 try expectApproxEqAbs(@as(f64, 0.7785173385577349), s, epsilon);
388332 try expectApproxEqAbs(@as(f64, 0.6276230983360804), c, epsilon);
389333
390 sincos(1.5, &s, &c);
334 s, c = sincos_f64(1.5);
391335 try expectApproxEqAbs(@as(f64, 0.9974949866040544), s, epsilon);
392336 try expectApproxEqAbs(@as(f64, 0.0707372016677029), c, epsilon);
393337
394 sincos(-1.5, &s, &c);
338 s, c = sincos_f64(-1.5);
395339 try expectApproxEqAbs(@as(f64, -0.9974949866040544), s, epsilon);
396340 try expectApproxEqAbs(@as(f64, 0.0707372016677029), c, epsilon);
397341
398 sincos(37.45, &s, &c);
342 s, c = sincos_f64(37.45);
399343 try expectApproxEqAbs(@as(f64, -0.24654331551411082), s, epsilon);
400344 try expectApproxEqAbs(@as(f64, 0.9691317730707778), c, epsilon);
401345
402 sincos(89.123, &s, &c);
346 s, c = sincos_f64(89.123);
403347 try expectApproxEqAbs(@as(f64, 0.9161652766622714), s, epsilon);
404348 try expectApproxEqAbs(@as(f64, 0.4008006809354791), c, epsilon);
405349}
......@@ -413,31 +357,31 @@ test "sincos80.normal" {
413357 var s: f80 = undefined;
414358 var c: f80 = undefined;
415359
416 sincosx(0.0, &s, &c);
360 s, c = sincos_f80(0.0);
417361 try expectApproxEqAbs(@as(f80, 0.0), s, epsilon);
418362 try expectApproxEqAbs(@as(f80, 1.0), c, epsilon);
419363
420 sincosx(0.2, &s, &c);
364 s, c = sincos_f80(0.2);
421365 try expectApproxEqAbs(@as(f80, 0.19866933079506121545941262711838975), s, epsilon);
422366 try expectApproxEqAbs(@as(f80, 0.98006657784124163112419651674816888), c, epsilon);
423367
424 sincosx(0.8923, &s, &c);
368 s, c = sincos_f80(0.8923);
425369 try expectApproxEqAbs(@as(f80, 0.77851733855773487830689285621486050), s, epsilon);
426370 try expectApproxEqAbs(@as(f80, 0.62762309833608037003563995939286067), c, epsilon);
427371
428 sincosx(1.5, &s, &c);
372 s, c = sincos_f80(1.5);
429373 try expectApproxEqAbs(@as(f80, 0.99749498660405443094172337114148732), s, epsilon);
430374 try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), c, epsilon);
431375
432 sincosx(-1.5, &s, &c);
376 s, c = sincos_f80(-1.5);
433377 try expectApproxEqAbs(@as(f80, -0.99749498660405443094172337114148732), s, epsilon);
434378 try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), c, epsilon);
435379
436 sincosx(37.45, &s, &c);
380 s, c = sincos_f80(37.45);
437381 try expectApproxEqAbs(@as(f80, -0.24654331551411356504), s, epsilon);
438382 try expectApproxEqAbs(@as(f80, 0.9691317730707771246), c, epsilon);
439383
440 sincosx(89.123, &s, &c);
384 s, c = sincos_f80(89.123);
441385 try expectApproxEqAbs(@as(f80, 0.91616527666226951006), s, epsilon);
442386 try expectApproxEqAbs(@as(f80, 0.4008006809354834001), c, epsilon);
443387}
......@@ -451,31 +395,31 @@ test "sincos128.normal" {
451395 var s: f128 = undefined;
452396 var c: f128 = undefined;
453397
454 sincosq(0.0, &s, &c);
398 s, c = sincos_f128(0.0);
455399 try expectApproxEqAbs(@as(f128, 0.0), s, epsilon);
456400 try expectApproxEqAbs(@as(f128, 1.0), c, epsilon);
457401
458 sincosq(0.2, &s, &c);
402 s, c = sincos_f128(0.2);
459403 try expectApproxEqAbs(@as(f128, 0.19866933079506121545941262711838975), s, epsilon);
460404 try expectApproxEqAbs(@as(f128, 0.98006657784124163112419651674816888), c, epsilon);
461405
462 sincosq(0.8923, &s, &c);
406 s, c = sincos_f128(0.8923);
463407 try expectApproxEqAbs(@as(f128, 0.77851733855773487830689285621486050), s, epsilon);
464408 try expectApproxEqAbs(@as(f128, 0.62762309833608037003563995939286067), c, epsilon);
465409
466 sincosq(1.5, &s, &c);
410 s, c = sincos_f128(1.5);
467411 try expectApproxEqAbs(@as(f128, 0.99749498660405443094172337114148732), s, epsilon);
468412 try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), c, epsilon);
469413
470 sincosq(-1.5, &s, &c);
414 s, c = sincos_f128(-1.5);
471415 try expectApproxEqAbs(@as(f128, -0.99749498660405443094172337114148732), s, epsilon);
472416 try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), c, epsilon);
473417
474 sincosq(37.45, &s, &c);
418 s, c = sincos_f128(37.45);
475419 try expectApproxEqAbs(@as(f128, -0.24654331551411356571238581321661085), s, epsilon);
476420 try expectApproxEqAbs(@as(f128, 0.96913177307077712443149563847233230), c, epsilon);
477421
478 sincosq(89.123, &s, &c);
422 s, c = sincos_f128(89.123);
479423 try expectApproxEqAbs(@as(f128, 0.91616527666226951075019849560482170), s, epsilon);
480424 try expectApproxEqAbs(@as(f128, 0.40080068093548339848199454493704702), c, epsilon);
481425}
lib/compiler_rt/sqrt.zig+150-137
......@@ -17,18 +17,19 @@ comptime {
1717 symbol(&sqrtf, "sqrtf");
1818 symbol(&sqrt, "sqrt");
1919 symbol(&__sqrtx, "__sqrtx");
20 if (compiler_rt.want_ppc_abi) {
21 symbol(&sqrtq, "sqrtf128");
22 } else if (compiler_rt.want_sparc64_abi) {
20 symbol(&sqrtq, "sqrtf128");
21 if (compiler_rt.want_sparc64_abi) {
2322 symbol(&_Qp_sqrt, "_Qp_sqrt");
2423 } else if (compiler_rt.want_sparc32_abi) {
2524 symbol(&sqrtq, "_Q_sqrt");
2625 }
27 symbol(&sqrtq, "sqrtq");
2826 symbol(&sqrtl, "sqrtl");
2927}
3028
31pub fn __sqrth(x: f16) callconv(.c) f16 {
29fn __sqrth(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
30 return compiler_rt.f16.toAbi(sqrt_f16(compiler_rt.f16.fromAbi(x)));
31}
32pub fn sqrt_f16(x: f16) f16 {
3233 var ix: u16 = @bitCast(x);
3334 var top = ix >> 10;
3435
......@@ -93,7 +94,10 @@ pub fn __sqrth(x: f16) callconv(.c) f16 {
9394 return y;
9495}
9596
96pub fn sqrtf(x: f32) callconv(.c) f32 {
97fn sqrtf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
98 return compiler_rt.f32.toAbi(sqrt_f32(compiler_rt.f32.fromAbi(x)));
99}
100pub fn sqrt_f32(x: f32) f32 {
97101 var ix: u32 = @bitCast(x);
98102
99103 if (ix < @as(u32, @bitCast(@as(f32, 0x1p-126))) or @as(u32, @bitCast(std.math.inf(f32))) <= ix) {
......@@ -147,7 +151,10 @@ pub fn sqrtf(x: f32) callconv(.c) f32 {
147151 return y + t;
148152}
149153
150pub fn sqrt(x: f64) callconv(.c) f64 {
154fn sqrt(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
155 return compiler_rt.f64.toAbi(sqrt_f64(compiler_rt.f64.fromAbi(x)));
156}
157pub fn sqrt_f64(x: f64) f64 {
151158 var ix: u64 = @bitCast(x);
152159 var top = ix >> 52;
153160
......@@ -284,7 +291,10 @@ pub fn sqrt(x: f64) callconv(.c) f64 {
284291 return y;
285292}
286293
287pub fn __sqrtx(x: f80) callconv(.c) f80 {
294fn __sqrtx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
295 return compiler_rt.f80.toAbi(sqrt_f80(compiler_rt.f80.fromAbi(x)));
296}
297pub fn sqrt_f80(x: f80) f80 {
288298 var ix: u80 = @bitCast(x);
289299 var top = ix >> 64;
290300
......@@ -381,7 +391,10 @@ pub fn __sqrtx(x: f80) callconv(.c) f80 {
381391 return y;
382392}
383393
384pub fn sqrtq(x: f128) callconv(.c) f128 {
394fn sqrtq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
395 return compiler_rt.f128.toAbi(sqrt_f128(compiler_rt.f128.fromAbi(x)));
396}
397pub fn sqrt_f128(x: f128) f128 {
385398 var ix: u128 = @bitCast(x);
386399 var top = ix >> 112;
387400
......@@ -483,10 +496,10 @@ fn _Qp_sqrt(c: *f128, a: *f128) callconv(.c) void {
483496
484497pub fn sqrtl(x: c_longdouble) callconv(.c) c_longdouble {
485498 switch (@typeInfo(c_longdouble).float.bits) {
486 64 => return sqrt(x),
487 80 => return __sqrtx(x),
488 128 => return sqrtq(x),
489 else => @compileError("unreachable"),
499 64 => return sqrt_f64(x),
500 80 => return sqrt_f80(x),
501 128 => return sqrt_f128(x),
502 else => comptime unreachable,
490503 }
491504}
492505
......@@ -545,187 +558,187 @@ inline fn mul80_tail(a: u80, b: u80) u80 {
545558 return alo * blo +% ((ahi * blo) << 40) +% ((alo * bhi) << 40);
546559}
547560
548test "__sqrth" {
561test "sqrt_f16" {
549562 // sqrt(±0) is ±0
550 try std.testing.expectEqual(__sqrth(0x0.0p0), 0x0.0p0);
551 try std.testing.expectEqual(__sqrth(-0x0.0p0), -0x0.0p0);
563 try std.testing.expectEqual(sqrt_f16(0x0.0p0), 0x0.0p0);
564 try std.testing.expectEqual(sqrt_f16(-0x0.0p0), -0x0.0p0);
552565 // sqrt(+max) is finite
553 try std.testing.expectEqual(__sqrth(0x1.FFCp15), 0x1.FFCp7);
566 try std.testing.expectEqual(sqrt_f16(0x1.FFCp15), 0x1.FFCp7);
554567 // sqrt(4)=2
555 try std.testing.expectEqual(__sqrth(0x1p2), 0x1p1);
568 try std.testing.expectEqual(sqrt_f16(0x1p2), 0x1p1);
556569 // sqrt(x) for x=1, 1±ulp
557 try std.testing.expectEqual(__sqrth(0x1p0), 0x1p0);
558 try std.testing.expectEqual(__sqrth(0x1.004p0), 0x1p0);
559 try std.testing.expectEqual(__sqrth(0x1.FF8p-1), 0x1.FFCp-1);
570 try std.testing.expectEqual(sqrt_f16(0x1p0), 0x1p0);
571 try std.testing.expectEqual(sqrt_f16(0x1.004p0), 0x1p0);
572 try std.testing.expectEqual(sqrt_f16(0x1.FF8p-1), 0x1.FFCp-1);
560573 // sqrt(+min) is non-zero
561 try std.testing.expectEqual(__sqrth(0x1p-14), 0x1p-7);
574 try std.testing.expectEqual(sqrt_f16(0x1p-14), 0x1p-7);
562575 // sqrt(min subnormal) is non-zero
563 try std.testing.expectEqual(__sqrth(0x0.004p-14), 0x1p-12);
576 try std.testing.expectEqual(sqrt_f16(0x0.004p-14), 0x1p-12);
564577 // sqrt(inf) is inf
565 try std.testing.expect(math.isInf(__sqrth(math.inf(f16))));
578 try std.testing.expect(math.isInf(sqrt_f16(math.inf(f16))));
566579 // sqrt(nan) is nan
567 try std.testing.expect(math.isNan(__sqrth(math.nan(f16))));
580 try std.testing.expect(math.isNan(sqrt_f16(math.nan(f16))));
568581 // sqrt(-ve) is nan
569 try std.testing.expect(math.isNan(__sqrth(-0x1p-14)));
570 try std.testing.expect(math.isNan(__sqrth(-0x1p+0)));
571 try std.testing.expect(math.isNan(__sqrth(-math.inf(f16))));
582 try std.testing.expect(math.isNan(sqrt_f16(-0x1p-14)));
583 try std.testing.expect(math.isNan(sqrt_f16(-0x1p+0)));
584 try std.testing.expect(math.isNan(sqrt_f16(-math.inf(f16))));
572585 // random arguments
573 try std.testing.expectEqual(__sqrth(0x1.1p14), 0x1.08p7);
574 try std.testing.expectEqual(__sqrth(0x1.C9p-12), 0x1.56p-6);
575 try std.testing.expectEqual(__sqrth(0x1.CE8p-7), 0x1.E68p-4);
576 try std.testing.expectEqual(__sqrth(0x1.134p-7), 0x1.778p-4);
577 try std.testing.expectEqual(__sqrth(0x1.E9Cp-10), 0x1.62p-5);
578 try std.testing.expectEqual(__sqrth(0x1.3Dp9), 0x1.92Cp4);
579 try std.testing.expectEqual(__sqrth(0x1.AA4p8), 0x1.4A4p4);
580 try std.testing.expectEqual(__sqrth(0x1.8A8p4), 0x1.3DCp2);
581 try std.testing.expectEqual(__sqrth(0x1.8Fp-7), 0x1.C4p-4);
582 try std.testing.expectEqual(__sqrth(0x1.584p-11), 0x1.A3Cp-6);
586 try std.testing.expectEqual(sqrt_f16(0x1.1p14), 0x1.08p7);
587 try std.testing.expectEqual(sqrt_f16(0x1.C9p-12), 0x1.56p-6);
588 try std.testing.expectEqual(sqrt_f16(0x1.CE8p-7), 0x1.E68p-4);
589 try std.testing.expectEqual(sqrt_f16(0x1.134p-7), 0x1.778p-4);
590 try std.testing.expectEqual(sqrt_f16(0x1.E9Cp-10), 0x1.62p-5);
591 try std.testing.expectEqual(sqrt_f16(0x1.3Dp9), 0x1.92Cp4);
592 try std.testing.expectEqual(sqrt_f16(0x1.AA4p8), 0x1.4A4p4);
593 try std.testing.expectEqual(sqrt_f16(0x1.8A8p4), 0x1.3DCp2);
594 try std.testing.expectEqual(sqrt_f16(0x1.8Fp-7), 0x1.C4p-4);
595 try std.testing.expectEqual(sqrt_f16(0x1.584p-11), 0x1.A3Cp-6);
583596}
584597
585test "sqrtf" {
598test "sqrt_f32" {
586599 // sqrt(±0) is ±0
587 try std.testing.expectEqual(sqrtf(0x0.0p0), 0x0.0p0);
588 try std.testing.expectEqual(sqrtf(-0x0.0p0), -0x0.0p0);
600 try std.testing.expectEqual(sqrt_f32(0x0.0p0), 0x0.0p0);
601 try std.testing.expectEqual(sqrt_f32(-0x0.0p0), -0x0.0p0);
589602 // sqrt(+max) is finite
590 try std.testing.expectEqual(sqrtf(0x1.FFFFFEp127), 0x1.FFFFFEp63);
603 try std.testing.expectEqual(sqrt_f32(0x1.FFFFFEp127), 0x1.FFFFFEp63);
591604 // sqrt(4)=2
592 try std.testing.expectEqual(sqrtf(0x1p2), 0x1p1);
605 try std.testing.expectEqual(sqrt_f32(0x1p2), 0x1p1);
593606 // sqrt(x) for x=1, 1±ulp
594 try std.testing.expectEqual(sqrtf(0x1p0), 0x1p0);
595 try std.testing.expectEqual(sqrtf(0x1.000002p0), 0x1p0);
596 try std.testing.expectEqual(sqrtf(0x1.FFFFFEp-1), 0x1.FFFFFEp-1);
607 try std.testing.expectEqual(sqrt_f32(0x1p0), 0x1p0);
608 try std.testing.expectEqual(sqrt_f32(0x1.000002p0), 0x1p0);
609 try std.testing.expectEqual(sqrt_f32(0x1.FFFFFEp-1), 0x1.FFFFFEp-1);
597610 // sqrt(+min) is non-zero
598 try std.testing.expectEqual(sqrtf(0x1p-126), 0x1p-63);
611 try std.testing.expectEqual(sqrt_f32(0x1p-126), 0x1p-63);
599612 // sqrt(min subnormal) is non-zero
600 try std.testing.expectEqual(sqrtf(0x0.000002p-126), 0x1.6a09e6p-75);
613 try std.testing.expectEqual(sqrt_f32(0x0.000002p-126), 0x1.6a09e6p-75);
601614 // sqrt(inf) is inf
602 try std.testing.expect(math.isInf(sqrtf(math.inf(f32))));
615 try std.testing.expect(math.isInf(sqrt_f32(math.inf(f32))));
603616 // sqrt(nan) is nan
604 try std.testing.expect(math.isNan(sqrtf(math.nan(f32))));
617 try std.testing.expect(math.isNan(sqrt_f32(math.nan(f32))));
605618 // sqrt(-ve) is nan
606 try std.testing.expect(math.isNan(sqrtf(-0x1p-149)));
607 try std.testing.expect(math.isNan(sqrtf(-0x1p0)));
608 try std.testing.expect(math.isNan(sqrtf(-math.inf(f32))));
619 try std.testing.expect(math.isNan(sqrt_f32(-0x1p-149)));
620 try std.testing.expect(math.isNan(sqrt_f32(-0x1p0)));
621 try std.testing.expect(math.isNan(sqrt_f32(-math.inf(f32))));
609622 // random arguments
610 try std.testing.expectEqual(sqrtf(0x1.4DD57Ep77), 0x1.9D6DA8p38);
611 try std.testing.expectEqual(sqrtf(0x1.871848p102), 0x1.3C6AFAp51);
612 try std.testing.expectEqual(sqrtf(0x1.A1D748p-112), 0x1.470EFCp-56);
613 try std.testing.expectEqual(sqrtf(0x1.E626C2p18), 0x1.60C80Ep9);
614 try std.testing.expectEqual(sqrtf(0x1.E80E66p-29), 0x1.F3E282p-15);
615 try std.testing.expectEqual(sqrtf(0x1.B47204p89), 0x1.D8B732p44);
616 try std.testing.expectEqual(sqrtf(0x1.77F45p15), 0x1.B6BC3Ap7);
617 try std.testing.expectEqual(sqrtf(0x1.AD5F5p-48), 0x1.4B8A72p-24);
618 try std.testing.expectEqual(sqrtf(0x1.91A39p-76), 0x1.40A7A8p-38);
619 try std.testing.expectEqual(sqrtf(0x1.DAE088p79), 0x1.ED16DCp39);
623 try std.testing.expectEqual(sqrt_f32(0x1.4DD57Ep77), 0x1.9D6DA8p38);
624 try std.testing.expectEqual(sqrt_f32(0x1.871848p102), 0x1.3C6AFAp51);
625 try std.testing.expectEqual(sqrt_f32(0x1.A1D748p-112), 0x1.470EFCp-56);
626 try std.testing.expectEqual(sqrt_f32(0x1.E626C2p18), 0x1.60C80Ep9);
627 try std.testing.expectEqual(sqrt_f32(0x1.E80E66p-29), 0x1.F3E282p-15);
628 try std.testing.expectEqual(sqrt_f32(0x1.B47204p89), 0x1.D8B732p44);
629 try std.testing.expectEqual(sqrt_f32(0x1.77F45p15), 0x1.B6BC3Ap7);
630 try std.testing.expectEqual(sqrt_f32(0x1.AD5F5p-48), 0x1.4B8A72p-24);
631 try std.testing.expectEqual(sqrt_f32(0x1.91A39p-76), 0x1.40A7A8p-38);
632 try std.testing.expectEqual(sqrt_f32(0x1.DAE088p79), 0x1.ED16DCp39);
620633}
621634
622test "sqrt" {
635test "sqrt_f64" {
623636 // sqrt(±0) is ±0
624 try std.testing.expectEqual(sqrt(0x0.0p0), 0x0.0p0);
625 try std.testing.expectEqual(sqrt(-0x0.0p0), -0x0.0p0);
637 try std.testing.expectEqual(sqrt_f64(0x0.0p0), 0x0.0p0);
638 try std.testing.expectEqual(sqrt_f64(-0x0.0p0), -0x0.0p0);
626639 // sqrt(+max) is finite
627 try std.testing.expectEqual(sqrt(math.floatMax(f64)), 0x1.FFFFFFFFFFFFFp511);
640 try std.testing.expectEqual(sqrt_f64(math.floatMax(f64)), 0x1.FFFFFFFFFFFFFp511);
628641 // sqrt(4)=2
629 try std.testing.expectEqual(sqrt(0x1p2), 0x1p1);
642 try std.testing.expectEqual(sqrt_f64(0x1p2), 0x1p1);
630643 // sqrt(x) for x=1, 1±ulp
631 try std.testing.expectEqual(sqrt(0x1p0), 0x1p0);
632 try std.testing.expectEqual(sqrt(0x1p0 + math.floatEps(f64)), 0x1p0);
633 try std.testing.expectEqual(sqrt(0x1p0 - math.floatEps(f64)), 0x1.FFFFFFFFFFFFFp-1);
644 try std.testing.expectEqual(sqrt_f64(0x1p0), 0x1p0);
645 try std.testing.expectEqual(sqrt_f64(0x1p0 + math.floatEps(f64)), 0x1p0);
646 try std.testing.expectEqual(sqrt_f64(0x1p0 - math.floatEps(f64)), 0x1.FFFFFFFFFFFFFp-1);
634647 // sqrt(+min) is non-zero
635 try std.testing.expectEqual(sqrt(math.floatMin(f64)), 0x1p-511);
648 try std.testing.expectEqual(sqrt_f64(math.floatMin(f64)), 0x1p-511);
636649 // sqrt(min subnormal) is non-zero
637 try std.testing.expectEqual(sqrt(math.floatTrueMin(f64)), 0x1p-537);
650 try std.testing.expectEqual(sqrt_f64(math.floatTrueMin(f64)), 0x1p-537);
638651 // sqrt(inf) is inf
639 try std.testing.expect(math.isInf(sqrt(math.inf(f64))));
652 try std.testing.expect(math.isInf(sqrt_f64(math.inf(f64))));
640653 // sqrt(nan) is nan
641 try std.testing.expect(math.isNan(sqrt(math.nan(f64))));
654 try std.testing.expect(math.isNan(sqrt_f64(math.nan(f64))));
642655 // sqrt(-ve) is nan
643 try std.testing.expect(math.isNan(sqrt(-0x1p-1074)));
644 try std.testing.expect(math.isNan(sqrt(-0x1p0)));
645 try std.testing.expect(math.isNan(sqrt(-math.inf(f64))));
656 try std.testing.expect(math.isNan(sqrt_f64(-0x1p-1074)));
657 try std.testing.expect(math.isNan(sqrt_f64(-0x1p0)));
658 try std.testing.expect(math.isNan(sqrt_f64(-math.inf(f64))));
646659 // random arguments
647 try std.testing.expectEqual(sqrt(0x1.27D3510D4789Bp471), 0x1.852E97E58CFB7p235);
648 try std.testing.expectEqual(sqrt(0x1.8C4FCD5A07846p791), 0x1.C27504E56D938p395);
649 try std.testing.expectEqual(sqrt(0x1.B1B69324F96E7p-137), 0x1.D73BD0414D8BFp-69);
650 try std.testing.expectEqual(sqrt(0x1.1CBD179A811FEp278), 0x1.0DFCB9A114A61p139);
651 try std.testing.expectEqual(sqrt(0x1.1D0C7EFB04A56p917), 0x1.7E0708A25DDCDp458);
652 try std.testing.expectEqual(sqrt(0x1.21B355DA8C94Bp-249), 0x1.8121CBE2608E3p-125);
653 try std.testing.expectEqual(sqrt(0x1.63024D4C5E987p487), 0x1.AA56AEA589DCDp243);
654 try std.testing.expectEqual(sqrt(0x1.45AC3BE941F6Ep339), 0x1.9857F3F453E2Dp169);
655 try std.testing.expectEqual(sqrt(0x1.3B719C733AA24p267), 0x1.91E12E3AC8F71p133);
656 try std.testing.expectEqual(sqrt(0x1.0B150433A2275p357), 0x1.71CAB87F8277Cp178);
660 try std.testing.expectEqual(sqrt_f64(0x1.27D3510D4789Bp471), 0x1.852E97E58CFB7p235);
661 try std.testing.expectEqual(sqrt_f64(0x1.8C4FCD5A07846p791), 0x1.C27504E56D938p395);
662 try std.testing.expectEqual(sqrt_f64(0x1.B1B69324F96E7p-137), 0x1.D73BD0414D8BFp-69);
663 try std.testing.expectEqual(sqrt_f64(0x1.1CBD179A811FEp278), 0x1.0DFCB9A114A61p139);
664 try std.testing.expectEqual(sqrt_f64(0x1.1D0C7EFB04A56p917), 0x1.7E0708A25DDCDp458);
665 try std.testing.expectEqual(sqrt_f64(0x1.21B355DA8C94Bp-249), 0x1.8121CBE2608E3p-125);
666 try std.testing.expectEqual(sqrt_f64(0x1.63024D4C5E987p487), 0x1.AA56AEA589DCDp243);
667 try std.testing.expectEqual(sqrt_f64(0x1.45AC3BE941F6Ep339), 0x1.9857F3F453E2Dp169);
668 try std.testing.expectEqual(sqrt_f64(0x1.3B719C733AA24p267), 0x1.91E12E3AC8F71p133);
669 try std.testing.expectEqual(sqrt_f64(0x1.0B150433A2275p357), 0x1.71CAB87F8277Cp178);
657670}
658671
659672test "__sqrtx" {
660673 // sqrt(±0) is ±0
661 try std.testing.expectEqual(__sqrtx(0x0.0p0), 0x0.0p0);
662 try std.testing.expectEqual(__sqrtx(-0x0.0p0), -0x0.0p0);
674 try std.testing.expectEqual(sqrt_f80(0x0.0p0), 0x0.0p0);
675 try std.testing.expectEqual(sqrt_f80(-0x0.0p0), -0x0.0p0);
663676 // sqrt(+max) is finite
664 try std.testing.expectEqual(__sqrtx(math.floatMax(f80)), 0x1.FFFFFFFFFFFFFFFEp8191);
677 try std.testing.expectEqual(sqrt_f80(math.floatMax(f80)), 0x1.FFFFFFFFFFFFFFFEp8191);
665678 // sqrt(4)=2
666 try std.testing.expectEqual(__sqrtx(0x1p2), 0x1p1);
679 try std.testing.expectEqual(sqrt_f80(0x1p2), 0x1p1);
667680 // sqrt(x) for x=1, 1±ulp
668 try std.testing.expectEqual(__sqrtx(0x1p0), 0x1p0);
669 try std.testing.expectEqual(__sqrtx(0x1p0 + math.floatEps(f80)), 0x1p0);
670 try std.testing.expectEqual(__sqrtx(0x1p0 - math.floatEps(f80)), 0x1.FFFFFFFFFFFFFFFEp-1);
681 try std.testing.expectEqual(sqrt_f80(0x1p0), 0x1p0);
682 try std.testing.expectEqual(sqrt_f80(0x1p0 + math.floatEps(f80)), 0x1p0);
683 try std.testing.expectEqual(sqrt_f80(0x1p0 - math.floatEps(f80)), 0x1.FFFFFFFFFFFFFFFEp-1);
671684 // sqrt(+min) is non-zero
672 try std.testing.expectEqual(__sqrtx(math.floatMin(f80)), 0x1p-8191);
685 try std.testing.expectEqual(sqrt_f80(math.floatMin(f80)), 0x1p-8191);
673686 // sqrt(min subnormal) is non-zero
674 try std.testing.expectEqual(__sqrtx(math.floatTrueMin(f80)), 0x1.6A09E667F3BCC908p-8223);
687 try std.testing.expectEqual(sqrt_f80(math.floatTrueMin(f80)), 0x1.6A09E667F3BCC908p-8223);
675688 // sqrt(inf) is inf
676 try std.testing.expect(math.isInf(__sqrtx(math.inf(f80))));
689 try std.testing.expect(math.isInf(sqrt_f80(math.inf(f80))));
677690 // sqrt(nan) is nan
678 try std.testing.expect(math.isNan(__sqrtx(math.nan(f80))));
691 try std.testing.expect(math.isNan(sqrt_f80(math.nan(f80))));
679692 // sqrt(-ve) is nan
680 try std.testing.expect(math.isNan(__sqrtx(-0x1p-16442)));
681 try std.testing.expect(math.isNan(__sqrtx(-0x1p0)));
682 try std.testing.expect(math.isNan(__sqrtx(-math.inf(f80))));
693 try std.testing.expect(math.isNan(sqrt_f80(-0x1p-16442)));
694 try std.testing.expect(math.isNan(sqrt_f80(-0x1p0)));
695 try std.testing.expect(math.isNan(sqrt_f80(-math.inf(f80))));
683696 // random arguments
684 try std.testing.expectEqual(__sqrtx(0x1.087F3953486918A4p15482), 0x1.0436BBE03D02F32p7741);
685 try std.testing.expectEqual(__sqrtx(0x1.530CF9E2AE84D8Fp-6330), 0x1.269CFEF51933BE58p-3165);
686 try std.testing.expectEqual(__sqrtx(0x1.3F971515EADD574Ap5713), 0x1.9483232AB780B006p2856);
687 try std.testing.expectEqual(__sqrtx(0x1.4CC0DC7379222954p864), 0x1.23DD4D0A4758C2Cp432);
688 try std.testing.expectEqual(__sqrtx(0x1.920E5649559A839Ep-3181), 0x1.C5B5BC0F98DD83D2p-1591);
689 try std.testing.expectEqual(__sqrtx(0x1.2E59726F87CD1746p-629), 0x1.8973327E95CB350Cp-315);
690 try std.testing.expectEqual(__sqrtx(0x1.D3A16391F57B4D64p-9034), 0x1.59FF08B7DEEF5DB2p-4517);
691 try std.testing.expectEqual(__sqrtx(0x1.E7053D8DAA49BCEEp-11411), 0x1.F35AA3EA5E18E344p-5706);
692 try std.testing.expectEqual(__sqrtx(0x1.797ED0B05DD4A984p7521), 0x1.B7A22E40C6A7867Ap3760);
693 try std.testing.expectEqual(__sqrtx(0x1.FC50806445C7226Ap15371), 0x1.FE2766142653F5BEp7685);
697 try std.testing.expectEqual(sqrt_f80(0x1.087F3953486918A4p15482), 0x1.0436BBE03D02F32p7741);
698 try std.testing.expectEqual(sqrt_f80(0x1.530CF9E2AE84D8Fp-6330), 0x1.269CFEF51933BE58p-3165);
699 try std.testing.expectEqual(sqrt_f80(0x1.3F971515EADD574Ap5713), 0x1.9483232AB780B006p2856);
700 try std.testing.expectEqual(sqrt_f80(0x1.4CC0DC7379222954p864), 0x1.23DD4D0A4758C2Cp432);
701 try std.testing.expectEqual(sqrt_f80(0x1.920E5649559A839Ep-3181), 0x1.C5B5BC0F98DD83D2p-1591);
702 try std.testing.expectEqual(sqrt_f80(0x1.2E59726F87CD1746p-629), 0x1.8973327E95CB350Cp-315);
703 try std.testing.expectEqual(sqrt_f80(0x1.D3A16391F57B4D64p-9034), 0x1.59FF08B7DEEF5DB2p-4517);
704 try std.testing.expectEqual(sqrt_f80(0x1.E7053D8DAA49BCEEp-11411), 0x1.F35AA3EA5E18E344p-5706);
705 try std.testing.expectEqual(sqrt_f80(0x1.797ED0B05DD4A984p7521), 0x1.B7A22E40C6A7867Ap3760);
706 try std.testing.expectEqual(sqrt_f80(0x1.FC50806445C7226Ap15371), 0x1.FE2766142653F5BEp7685);
694707}
695708
696test "sqrtq" {
709test "sqrt_f128" {
697710 // sqrt(±0) is ±0
698 try std.testing.expectEqual(sqrtq(0x0.0p0), 0x0.0p0);
699 try std.testing.expectEqual(sqrtq(-0x0.0p0), -0x0.0p0);
711 try std.testing.expectEqual(sqrt_f128(0x0.0p0), 0x0.0p0);
712 try std.testing.expectEqual(sqrt_f128(-0x0.0p0), -0x0.0p0);
700713 // sqrt(+max) is finite
701 try std.testing.expectEqual(sqrtq(math.floatMax(f128)), 0x1.FFFFFFFFFFFFFFFFFFFFFFFFFFFFp8191);
714 try std.testing.expectEqual(sqrt_f128(math.floatMax(f128)), 0x1.FFFFFFFFFFFFFFFFFFFFFFFFFFFFp8191);
702715 // sqrt(4)=2
703 try std.testing.expectEqual(sqrtq(0x1p2), 0x1p1);
716 try std.testing.expectEqual(sqrt_f128(0x1p2), 0x1p1);
704717 // sqrt(x) for x=1, 1±ulp
705 try std.testing.expectEqual(sqrtq(0x1p0), 0x1p0);
706 try std.testing.expectEqual(sqrtq(0x1p0 + math.floatEps(f128)), 0x1p0);
707 try std.testing.expectEqual(sqrtq(0x1p0 - math.floatEps(f128)), 0x1.FFFFFFFFFFFFFFFFFFFFFFFFFFFFp-1);
718 try std.testing.expectEqual(sqrt_f128(0x1p0), 0x1p0);
719 try std.testing.expectEqual(sqrt_f128(0x1p0 + math.floatEps(f128)), 0x1p0);
720 try std.testing.expectEqual(sqrt_f128(0x1p0 - math.floatEps(f128)), 0x1.FFFFFFFFFFFFFFFFFFFFFFFFFFFFp-1);
708721 // sqrt(+min) is non-zero
709 try std.testing.expectEqual(sqrtq(math.floatMin(f128)), 0x1p-8191);
722 try std.testing.expectEqual(sqrt_f128(math.floatMin(f128)), 0x1p-8191);
710723 // sqrt(min subnormal) is non-zero
711 try std.testing.expectEqual(sqrtq(math.floatTrueMin(f128)), 0x1p-8247);
724 try std.testing.expectEqual(sqrt_f128(math.floatTrueMin(f128)), 0x1p-8247);
712725 // sqrt(inf) is inf
713 try std.testing.expect(math.isInf(sqrtq(math.inf(f128))));
726 try std.testing.expect(math.isInf(sqrt_f128(math.inf(f128))));
714727 // sqrt(nan) is nan
715 try std.testing.expect(math.isNan(sqrtq(math.nan(f128))));
728 try std.testing.expect(math.isNan(sqrt_f128(math.nan(f128))));
716729 // sqrt(-ve) is nan
717 try std.testing.expect(math.isNan(sqrtq(-0x1p-16442)));
718 try std.testing.expect(math.isNan(sqrtq(-0x1p0)));
719 try std.testing.expect(math.isNan(sqrtq(-math.inf(f128))));
730 try std.testing.expect(math.isNan(sqrt_f128(-0x1p-16442)));
731 try std.testing.expect(math.isNan(sqrt_f128(-0x1p0)));
732 try std.testing.expect(math.isNan(sqrt_f128(-math.inf(f128))));
720733 // random arguments
721 try std.testing.expectEqual(sqrtq(0x1.B6942D29A331751600C9F3AF7E5Fp3363), 0x1.D9DE9AFEF0F2D25586A50CA39D4Dp1681);
722 try std.testing.expectEqual(sqrtq(0x1.5E65C405F84D471A8070ADD7A42Dp11765), 0x1.A78F7F9452B4D9EC2403C81D9D42p5882);
723 try std.testing.expectEqual(sqrtq(0x1.B42334D68F8016D8AE6F5E22B044p-5624), 0x1.4E247A7F2FF2A325E9377BB09C8p-2812);
724 try std.testing.expectEqual(sqrtq(0x1.E61715047F80F2E0B9382B38E06Bp10062), 0x1.60C25D9DFDC0116B78EF5AFDE0E9p5031);
725 try std.testing.expectEqual(sqrtq(0x1.2ED0B53B494CB55A7B04E653D40Ep-1026), 0x1.166CE78D658D2453D700B04C5748p-513);
726 try std.testing.expectEqual(sqrtq(0x1.1BA756B9790E78A4E6F0B083AA89p1835), 0x1.7D1767EA3303DB7A46940033988p917);
727 try std.testing.expectEqual(sqrtq(0x1.5B6C574319C1120335C8E1609704p4512), 0x1.2A3A8A415BB1648C548FBA2A4182p2256);
728 try std.testing.expectEqual(sqrtq(0x1.FF91E8CDEE1552A2B74E77B602Ep14953), 0x1.FFC8F171267D4FE75CBE7AB4D851p7476);
729 try std.testing.expectEqual(sqrtq(0x1.9B1837CFC629A1B6B1BB97099E7Dp2892), 0x1.4468511B909EAF8641BD59105A6Bp1446);
730 try std.testing.expectEqual(sqrtq(0x1.0E2115475E64A92340914E7F7B37p-13951), 0x1.73E536F82F414134012F55BA5368p-6976);
734 try std.testing.expectEqual(sqrt_f128(0x1.B6942D29A331751600C9F3AF7E5Fp3363), 0x1.D9DE9AFEF0F2D25586A50CA39D4Dp1681);
735 try std.testing.expectEqual(sqrt_f128(0x1.5E65C405F84D471A8070ADD7A42Dp11765), 0x1.A78F7F9452B4D9EC2403C81D9D42p5882);
736 try std.testing.expectEqual(sqrt_f128(0x1.B42334D68F8016D8AE6F5E22B044p-5624), 0x1.4E247A7F2FF2A325E9377BB09C8p-2812);
737 try std.testing.expectEqual(sqrt_f128(0x1.E61715047F80F2E0B9382B38E06Bp10062), 0x1.60C25D9DFDC0116B78EF5AFDE0E9p5031);
738 try std.testing.expectEqual(sqrt_f128(0x1.2ED0B53B494CB55A7B04E653D40Ep-1026), 0x1.166CE78D658D2453D700B04C5748p-513);
739 try std.testing.expectEqual(sqrt_f128(0x1.1BA756B9790E78A4E6F0B083AA89p1835), 0x1.7D1767EA3303DB7A46940033988p917);
740 try std.testing.expectEqual(sqrt_f128(0x1.5B6C574319C1120335C8E1609704p4512), 0x1.2A3A8A415BB1648C548FBA2A4182p2256);
741 try std.testing.expectEqual(sqrt_f128(0x1.FF91E8CDEE1552A2B74E77B602Ep14953), 0x1.FFC8F171267D4FE75CBE7AB4D851p7476);
742 try std.testing.expectEqual(sqrt_f128(0x1.9B1837CFC629A1B6B1BB97099E7Dp2892), 0x1.4468511B909EAF8641BD59105A6Bp1446);
743 try std.testing.expectEqual(sqrt_f128(0x1.0E2115475E64A92340914E7F7B37p-13951), 0x1.73E536F82F414134012F55BA5368p-6976);
731744}
lib/compiler_rt/ssp.zig+2-2
......@@ -17,7 +17,7 @@ const compiler_rt = @import("../compiler_rt.zig");
1717const symbol = compiler_rt.symbol;
1818const builtin = @import("builtin");
1919
20extern fn memset(dest: ?[*]u8, c: u8, n: usize) callconv(.c) ?[*]u8;
20extern fn memset(dest: ?[*]u8, c: c_int, n: usize) callconv(.c) ?[*]u8;
2121extern fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, n: usize) callconv(.c) ?[*]u8;
2222extern fn memmove(dest: ?[*]u8, src: ?[*]const u8, n: usize) callconv(.c) ?[*]u8;
2323
......@@ -138,7 +138,7 @@ fn __memmove_chk(dest: ?[*]u8, src: ?[*]const u8, n: usize, dest_n: usize) callc
138138 return memmove(dest, src, n);
139139}
140140
141fn __memset_chk(dest: ?[*]u8, c: u8, n: usize, dest_n: usize) callconv(.c) ?[*]u8 {
141fn __memset_chk(dest: ?[*]u8, c: c_int, n: usize, dest_n: usize) callconv(.c) ?[*]u8 {
142142 if (dest_n < n) __chk_fail();
143143 return memset(dest, c, n);
144144}
lib/compiler_rt/subdf3.zig deleted-24
......@@ -1,24 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const addf3 = @import("./addf3.zig").addf3;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_dsub, "__aeabi_dsub");
8 } else {
9 symbol(&__subdf3, "__subdf3");
10 }
11}
12
13fn __subdf3(a: f64, b: f64) callconv(.c) f64 {
14 return sub(a, b);
15}
16
17fn __aeabi_dsub(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 {
18 return sub(a, b);
19}
20
21inline fn sub(a: f64, b: f64) f64 {
22 const neg_b = @as(f64, @bitCast(@as(u64, @bitCast(b)) ^ (@as(u64, 1) << 63)));
23 return addf3(f64, a, neg_b);
24}
lib/compiler_rt/subhf3.zig deleted-12
......@@ -1,12 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const addf3 = @import("./addf3.zig").addf3;
4
5comptime {
6 symbol(&__subhf3, "__subhf3");
7}
8
9fn __subhf3(a: f16, b: f16) callconv(.c) f16 {
10 const neg_b = @as(f16, @bitCast(@as(u16, @bitCast(b)) ^ (@as(u16, 1) << 15)));
11 return addf3(f16, a, neg_b);
12}
lib/compiler_rt/subsf3.zig deleted-24
......@@ -1,24 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const addf3 = @import("./addf3.zig").addf3;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_fsub, "__aeabi_fsub");
8 } else {
9 symbol(&__subsf3, "__subsf3");
10 }
11}
12
13fn __subsf3(a: f32, b: f32) callconv(.c) f32 {
14 return sub(a, b);
15}
16
17fn __aeabi_fsub(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 {
18 return sub(a, b);
19}
20
21inline fn sub(a: f32, b: f32) f32 {
22 const neg_b = @as(f32, @bitCast(@as(u32, @bitCast(b)) ^ (@as(u32, 1) << 31)));
23 return addf3(f32, a, neg_b);
24}
lib/compiler_rt/subtf3.zig deleted-27
......@@ -1,27 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const addf3 = @import("./addf3.zig").addf3;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__subtf3, "__subkf3");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_sub, "_Qp_sub");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__subtf3, "_Q_sub");
12 }
13 symbol(&__subtf3, "__subtf3");
14}
15
16pub fn __subtf3(a: f128, b: f128) callconv(.c) f128 {
17 return sub(a, b);
18}
19
20fn _Qp_sub(c: *f128, a: *const f128, b: *const f128) callconv(.c) void {
21 c.* = sub(a.*, b.*);
22}
23
24inline fn sub(a: f128, b: f128) f128 {
25 const neg_b = @as(f128, @bitCast(@as(u128, @bitCast(b)) ^ (@as(u128, 1) << 127)));
26 return addf3(f128, a, neg_b);
27}
lib/compiler_rt/subvdi3.zig+3-2
......@@ -1,5 +1,6 @@
1const symbol = @import("../compiler_rt.zig").symbol;
21const testing = @import("std").testing;
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
34
45comptime {
56 symbol(&__subvdi3, "__subvdi3");
......@@ -9,7 +10,7 @@ pub fn __subvdi3(a: i64, b: i64) callconv(.c) i64 {
910 const sum = a -% b;
1011 // Overflow occurred iff the operands have opposite signs, and the sign of the
1112 // sum is the opposite of the lhs sign.
12 if (((a ^ b) & (sum ^ a)) < 0) @panic("compiler-rt: integer overflow");
13 if (((a ^ b) & (sum ^ a)) < 0) @panic("integer overflow");
1314 return sum;
1415}
1516
lib/compiler_rt/subvsi3.zig+1-1
......@@ -10,7 +10,7 @@ pub fn __subvsi3(a: i32, b: i32) callconv(.c) i32 {
1010 const sum = a -% b;
1111 // Overflow occurred iff the operands have opposite signs, and the sign of the
1212 // sum is the opposite of the lhs sign.
13 if (((a ^ b) & (sum ^ a)) < 0) @panic("compiler-rt: integer overflow");
13 if (((a ^ b) & (sum ^ a)) < 0) @panic("integer overflow");
1414 return sum;
1515}
1616
lib/compiler_rt/subxf3.zig deleted-13
......@@ -1,13 +0,0 @@
1const std = @import("std");
2const symbol = @import("../compiler_rt.zig").symbol;
3
4comptime {
5 symbol(&__subxf3, "__subxf3");
6}
7
8fn __subxf3(a: f80, b: f80) callconv(.c) f80 {
9 var b_rep = std.math.F80.fromFloat(b);
10 b_rep.exp ^= 0x8000;
11 const neg_b = b_rep.toFloat();
12 return a + neg_b;
13}
lib/compiler_rt/tan.zig+53-37
......@@ -21,26 +21,29 @@ const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l;
2121
2222const arch = builtin.cpu.arch;
2323const compiler_rt = @import("../compiler_rt.zig");
24const symbol = @import("../compiler_rt.zig").symbol;
24const symbol = compiler_rt.symbol;
2525
2626comptime {
27 symbol(&tanh, "__tanh");
27 symbol(&__tanh, "__tanh");
2828 symbol(&tanf, "tanf");
2929 symbol(&tan, "tan");
30 symbol(&tanx, "__tanx");
31 if (compiler_rt.want_ppc_abi) {
32 symbol(&tanq, "tanf128");
33 }
34 symbol(&tanq, "tanq");
30 symbol(&__tanx, "__tanx");
31 symbol(&tanq, "tanf128");
3532 symbol(&tanl, "tanl");
3633}
3734
38pub fn tanh(x: f16) callconv(.c) f16 {
35fn __tanh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
36 return compiler_rt.f16.toAbi(tan_f16(compiler_rt.f16.fromAbi(x)));
37}
38pub fn tan_f16(x: f16) f16 {
3939 // TODO: more efficient implementation
40 return @floatCast(tanf(x));
40 return @floatCast(tan_f32(x));
4141}
4242
43pub fn tanf(x: f32) callconv(.c) f32 {
43fn tanf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
44 return compiler_rt.f32.toAbi(tan_f32(compiler_rt.f32.fromAbi(x)));
45}
46pub fn tan_f32(x: f32) f32 {
4447 // Small multiples of pi/2 rounded to double precision.
4548 const t1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18
4649 const t2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18
......@@ -90,7 +93,10 @@ pub fn tanf(x: f32) callconv(.c) f32 {
9093 return kernel.tandf(y, n & 1 != 0);
9194}
9295
93pub fn tan(x: f64) callconv(.c) f64 {
96fn tan(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
97 return compiler_rt.f64.toAbi(tan_f64(compiler_rt.f64.fromAbi(x)));
98}
99pub fn tan_f64(x: f64) f64 {
94100 var ix = @as(u64, @bitCast(x)) >> 32;
95101 ix &= 0x7fffffff;
96102
......@@ -120,7 +126,10 @@ pub fn tan(x: f64) callconv(.c) f64 {
120126 return kernel.tan(y[0], y[1], n & 1 != 0);
121127}
122128
123pub fn tanx(x: f80) callconv(.c) f80 {
129fn __tanx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
130 return compiler_rt.f80.toAbi(tan_f80(compiler_rt.f80.fromAbi(x)));
131}
132pub fn tan_f80(x: f80) f80 {
124133 const se = ld.signExponent(x) & 0x7fff;
125134 if (se == 0x7fff) {
126135 return x - x;
......@@ -141,7 +150,10 @@ pub fn tanx(x: f80) callconv(.c) f80 {
141150 return kernel.tanx(y[0], y[1], n & 1);
142151}
143152
144pub fn tanq(x: f128) callconv(.c) f128 {
153fn tanq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
154 return compiler_rt.f128.toAbi(tan_f128(compiler_rt.f128.fromAbi(x)));
155}
156pub fn tan_f128(x: f128) f128 {
145157 const se = ld.signExponent(x) & 0x7fff;
146158 if (se == 0x7fff) {
147159 return x - x;
......@@ -164,18 +176,21 @@ pub fn tanq(x: f128) callconv(.c) f128 {
164176
165177pub fn tanl(x: c_longdouble) callconv(.c) c_longdouble {
166178 switch (@typeInfo(c_longdouble).float.bits) {
167 64 => return tan(x),
168 80 => return tanx(x),
169 128 => return tanq(x),
170 else => @compileError("unreachable"),
179 64 => return tan_f64(x),
180 80 => return tan_f80(x),
181 128 => return tan_f128(x),
182 else => comptime unreachable,
171183 }
172184}
173185
174186fn testTanNormal(comptime T: type) !void {
175187 const f = switch (T) {
176 f32 => tanf,
177 f64 => tan,
178 else => @compileError("unimplemented"),
188 f16 => tan_f16,
189 f32 => tan_f32,
190 f64 => tan_f64,
191 f80 => tan_f80,
192 f128 => tan_f128,
193 else => comptime unreachable,
179194 };
180195 const epsilon = 0.00001;
181196
......@@ -189,11 +204,12 @@ fn testTanNormal(comptime T: type) !void {
189204
190205fn testTanSpecial(comptime T: type) !void {
191206 const f = switch (T) {
192 f32 => tanf,
193 f64 => tan,
194 f80 => tanx,
195 f128 => tanq,
196 else => @compileError("unimplemented"),
207 f16 => tan_f16,
208 f32 => tan_f32,
209 f64 => tan_f64,
210 f80 => tan_f80,
211 f128 => tan_f128,
212 else => comptime unreachable,
197213 };
198214
199215 try expect(math.isPositiveZero(f(0.0)));
......@@ -214,23 +230,23 @@ test "tan64.normal" {
214230test "tan80.normal" {
215231 const epsilon = math.floatEps(f80);
216232
217 try expectApproxEqAbs(@as(f80, 0.0), tanx(0.0), epsilon);
218 try expectApproxEqAbs(@as(f80, 0.2027100355086724833213582716475345), tanx(0.2), epsilon);
219 try expectApproxEqAbs(@as(f80, 1.2404217445497097995561220131857544), tanx(0.8923), epsilon);
220 try expectApproxEqAbs(@as(f80, 14.10141994717171938764), tanx(1.5), epsilon);
221 try expectApproxEqAbs(@as(f80, -0.25439607116885656232), tanx(37.45), epsilon);
222 try expectApproxEqAbs(@as(f80, 2.2858376251355320963), tanx(89.123), epsilon);
233 try expectApproxEqAbs(@as(f80, 0.0), tan_f80(0.0), epsilon);
234 try expectApproxEqAbs(@as(f80, 0.2027100355086724833213582716475345), tan_f80(0.2), epsilon);
235 try expectApproxEqAbs(@as(f80, 1.2404217445497097995561220131857544), tan_f80(0.8923), epsilon);
236 try expectApproxEqAbs(@as(f80, 14.10141994717171938764), tan_f80(1.5), epsilon);
237 try expectApproxEqAbs(@as(f80, -0.25439607116885656232), tan_f80(37.45), epsilon);
238 try expectApproxEqAbs(@as(f80, 2.2858376251355320963), tan_f80(89.123), epsilon);
223239}
224240
225241test "tan128.normal" {
226242 const epsilon = math.floatEps(f128);
227243
228 try expectApproxEqAbs(@as(f128, 0.0), tanq(0.0), epsilon);
229 try expectApproxEqAbs(@as(f128, 0.2027100355086724833213582716475345), tanq(0.2), epsilon);
230 try expectApproxEqAbs(@as(f128, 1.2404217445497097995561220131857544), tanq(0.8923), epsilon);
231 try expectApproxEqAbs(@as(f128, 14.101419947171719387646083651987755), tanq(1.5), epsilon);
232 try expectApproxEqAbs(@as(f128, -0.2543960711688565630469573224504774), tanq(37.45), epsilon);
233 try expectApproxEqAbs(@as(f128, 2.2858376251355321074066028114094292), tanq(89.123), epsilon);
244 try expectApproxEqAbs(@as(f128, 0.0), tan_f128(0.0), epsilon);
245 try expectApproxEqAbs(@as(f128, 0.2027100355086724833213582716475345), tan_f128(0.2), epsilon);
246 try expectApproxEqAbs(@as(f128, 1.2404217445497097995561220131857544), tan_f128(0.8923), epsilon);
247 try expectApproxEqAbs(@as(f128, 14.101419947171719387646083651987755), tan_f128(1.5), epsilon);
248 try expectApproxEqAbs(@as(f128, -0.2543960711688565630469573224504774), tan_f128(37.45), epsilon);
249 try expectApproxEqAbs(@as(f128, 2.2858376251355321074066028114094292), tan_f128(89.123), epsilon);
234250}
235251
236252test "tan32.special" {
lib/compiler_rt/trunc.zig+77-47
......@@ -17,19 +17,22 @@ comptime {
1717 symbol(&truncf, "truncf");
1818 symbol(&trunc, "trunc");
1919 symbol(&__truncx, "__truncx");
20 if (compiler_rt.want_ppc_abi) {
21 symbol(&truncq, "truncf128");
22 }
23 symbol(&truncq, "truncq");
20 symbol(&truncq, "truncf128");
2421 symbol(&truncl, "truncl");
2522}
2623
27pub fn __trunch(x: f16) callconv(.c) f16 {
24fn __trunch(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
25 return compiler_rt.f16.toAbi(trunc_f16(compiler_rt.f16.fromAbi(x)));
26}
27pub fn trunc_f16(x: f16) f16 {
2828 // TODO: more efficient implementation
29 return @floatCast(truncf(x));
29 return @floatCast(trunc_f32(x));
3030}
3131
32pub fn truncf(x: f32) callconv(.c) f32 {
32fn truncf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
33 return compiler_rt.f32.toAbi(trunc_f32(compiler_rt.f32.fromAbi(x)));
34}
35pub fn trunc_f32(x: f32) f32 {
3336 const u: u32 = @bitCast(x);
3437 var e = @as(i32, @intCast(((u >> 23) & 0xFF))) - 0x7F + 9;
3538 var m: u32 = undefined;
......@@ -50,7 +53,10 @@ pub fn truncf(x: f32) callconv(.c) f32 {
5053 }
5154}
5255
53pub fn trunc(x: f64) callconv(.c) f64 {
56fn trunc(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
57 return compiler_rt.f64.toAbi(trunc_f64(compiler_rt.f64.fromAbi(x)));
58}
59pub fn trunc_f64(x: f64) f64 {
5460 const u: u64 = @bitCast(x);
5561 var e = @as(i32, @intCast(((u >> 52) & 0x7FF))) - 0x3FF + 12;
5662 var m: u64 = undefined;
......@@ -71,12 +77,18 @@ pub fn trunc(x: f64) callconv(.c) f64 {
7177 }
7278}
7379
74pub fn __truncx(x: f80) callconv(.c) f80 {
80fn __truncx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
81 return compiler_rt.f80.toAbi(trunc_f80(compiler_rt.f80.fromAbi(x)));
82}
83pub fn trunc_f80(x: f80) f80 {
7584 // TODO: more efficient implementation
76 return @floatCast(truncq(x));
85 return @floatCast(trunc_f128(x));
7786}
7887
79pub fn truncq(x: f128) callconv(.c) f128 {
88fn truncq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
89 return compiler_rt.f128.toAbi(trunc_f128(compiler_rt.f128.fromAbi(x)));
90}
91pub fn trunc_f128(x: f128) f128 {
8092 const u: u128 = @bitCast(x);
8193 var e = @as(i32, @intCast(((u >> 112) & 0x7FFF))) - 0x3FFF + 16;
8294 var m: u128 = undefined;
......@@ -99,51 +111,69 @@ pub fn truncq(x: f128) callconv(.c) f128 {
99111
100112pub fn truncl(x: c_longdouble) callconv(.c) c_longdouble {
101113 switch (@typeInfo(c_longdouble).float.bits) {
102 64 => return trunc(x),
103 80 => return __truncx(x),
104 128 => return truncq(x),
105 else => @compileError("unreachable"),
114 64 => return trunc_f64(x),
115 80 => return trunc_f80(x),
116 128 => return trunc_f128(x),
117 else => comptime unreachable,
106118 }
107119}
108120
109test "trunc32" {
110 try expect(truncf(1.3) == 1.0);
111 try expect(truncf(-1.3) == -1.0);
112 try expect(truncf(0.2) == 0.0);
113}
114
115test "trunc64" {
116 try expect(trunc(1.3) == 1.0);
117 try expect(trunc(-1.3) == -1.0);
118 try expect(trunc(0.2) == 0.0);
121test trunc_f16 {
122 try expect(trunc_f16(1.3) == 1.0);
123 try expect(trunc_f16(-1.3) == -1.0);
124 try expect(math.isPositiveZero(trunc_f16(0.2)));
125 try expect(math.isNegativeZero(trunc_f16(-0.2)));
126 try expect(math.isPositiveZero(trunc_f16(0.0)));
127 try expect(math.isNegativeZero(trunc_f16(-0.0)));
128 try expect(math.isPositiveInf(trunc_f16(math.inf(f32))));
129 try expect(math.isNegativeInf(trunc_f16(-math.inf(f32))));
130 try expect(math.isNan(trunc_f16(math.nan(f32))));
119131}
120132
121test "trunc128" {
122 try expect(truncq(1.3) == 1.0);
123 try expect(truncq(-1.3) == -1.0);
124 try expect(truncq(0.2) == 0.0);
133test trunc_f32 {
134 try expect(trunc_f32(1.3) == 1.0);
135 try expect(trunc_f32(-1.3) == -1.0);
136 try expect(math.isPositiveZero(trunc_f32(0.2)));
137 try expect(math.isNegativeZero(trunc_f32(-0.2)));
138 try expect(math.isPositiveZero(trunc_f32(0.0)));
139 try expect(math.isNegativeZero(trunc_f32(-0.0)));
140 try expect(math.isPositiveInf(trunc_f32(math.inf(f32))));
141 try expect(math.isNegativeInf(trunc_f32(-math.inf(f32))));
142 try expect(math.isNan(trunc_f32(math.nan(f32))));
125143}
126144
127test "trunc32.special" {
128 try expect(truncf(0.0) == 0.0); // 0x3F800000
129 try expect(truncf(-0.0) == -0.0);
130 try expect(math.isPositiveInf(truncf(math.inf(f32))));
131 try expect(math.isNegativeInf(truncf(-math.inf(f32))));
132 try expect(math.isNan(truncf(math.nan(f32))));
145test trunc_f64 {
146 try expect(trunc_f64(1.3) == 1.0);
147 try expect(trunc_f64(-1.3) == -1.0);
148 try expect(math.isPositiveZero(trunc_f64(0.2)));
149 try expect(math.isNegativeZero(trunc_f64(-0.2)));
150 try expect(math.isPositiveZero(trunc_f64(0.0)));
151 try expect(math.isNegativeZero(trunc_f64(-0.0)));
152 try expect(math.isPositiveInf(trunc_f64(math.inf(f64))));
153 try expect(math.isNegativeInf(trunc_f64(-math.inf(f64))));
154 try expect(math.isNan(trunc_f64(math.nan(f64))));
133155}
134156
135test "trunc64.special" {
136 try expect(trunc(0.0) == 0.0);
137 try expect(trunc(-0.0) == -0.0);
138 try expect(math.isPositiveInf(trunc(math.inf(f64))));
139 try expect(math.isNegativeInf(trunc(-math.inf(f64))));
140 try expect(math.isNan(trunc(math.nan(f64))));
157test trunc_f80 {
158 try expect(trunc_f80(1.3) == 1.0);
159 try expect(trunc_f80(-1.3) == -1.0);
160 try expect(math.isPositiveZero(trunc_f80(0.2)));
161 try expect(math.isNegativeZero(trunc_f80(-0.2)));
162 try expect(math.isPositiveZero(trunc_f80(0.0)));
163 try expect(math.isNegativeZero(trunc_f80(-0.0)));
164 try expect(math.isPositiveInf(trunc_f80(math.inf(f64))));
165 try expect(math.isNegativeInf(trunc_f80(-math.inf(f64))));
166 try expect(math.isNan(trunc_f80(math.nan(f64))));
141167}
142168
143test "trunc128.special" {
144 try expect(truncq(0.0) == 0.0);
145 try expect(truncq(-0.0) == -0.0);
146 try expect(math.isPositiveInf(truncq(math.inf(f128))));
147 try expect(math.isNegativeInf(truncq(-math.inf(f128))));
148 try expect(math.isNan(truncq(math.nan(f128))));
169test trunc_f128 {
170 try expect(trunc_f128(1.3) == 1.0);
171 try expect(trunc_f128(-1.3) == -1.0);
172 try expect(math.isPositiveZero(trunc_f128(0.2)));
173 try expect(math.isNegativeZero(trunc_f128(-0.2)));
174 try expect(math.isPositiveZero(trunc_f128(0.0)));
175 try expect(math.isNegativeZero(trunc_f128(-0.0)));
176 try expect(math.isPositiveInf(trunc_f128(math.inf(f128))));
177 try expect(math.isNegativeInf(trunc_f128(-math.inf(f128))));
178 try expect(math.isNan(trunc_f128(math.nan(f128))));
149179}
lib/compiler_rt/truncdfhf2.zig deleted-18
......@@ -1,18 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const truncf = @import("./truncf.zig").truncf;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_d2h, "__aeabi_d2h");
8 }
9 symbol(&__truncdfhf2, "__truncdfhf2");
10}
11
12pub fn __truncdfhf2(a: f64) callconv(.c) compiler_rt.F16T(f64) {
13 return @bitCast(truncf(f16, f64, a));
14}
15
16fn __aeabi_d2h(a: f64) callconv(.{ .arm_aapcs = .{} }) u16 {
17 return @bitCast(truncf(f16, f64, a));
18}
lib/compiler_rt/truncdfsf2.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const truncf = @import("./truncf.zig").truncf;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_d2f, "__aeabi_d2f");
8 } else {
9 symbol(&__truncdfsf2, "__truncdfsf2");
10 }
11}
12
13pub fn __truncdfsf2(a: f64) callconv(.c) f32 {
14 return truncf(f32, f64, a);
15}
16
17fn __aeabi_d2f(a: f64) callconv(.{ .arm_aapcs = .{} }) f32 {
18 return truncf(f32, f64, a);
19}
lib/compiler_rt/truncf.zig+200-2
......@@ -1,6 +1,204 @@
11const std = @import("std");
22
3pub inline fn truncf(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5
6comptime {
7 if (compiler_rt.want_aeabi) {
8 if (compiler_rt.gnu_f16_abi) {
9 symbol(&__aeabi_f2h, "__gnu_f2h_ieee");
10 } else {
11 symbol(&__aeabi_f2h, "__aeabi_f2h");
12 }
13 symbol(&__aeabi_d2h, "__aeabi_d2h");
14 } else if (compiler_rt.gnu_f16_abi) {
15 symbol(&__truncsfhf2, "__gnu_f2h_ieee");
16 }
17 symbol(&__truncsfhf2, "__truncsfhf2");
18 symbol(&__truncdfhf2, "__truncdfhf2");
19 symbol(&__truncxfhf2, "__truncxfhf2");
20 if (compiler_rt.want_ppc_abi) {
21 symbol(&__trunctfhf2, "__trunckfhf2");
22 } else {
23 symbol(&__trunctfhf2, "__trunctfhf2");
24 }
25
26 if (compiler_rt.want_aeabi) {
27 symbol(&__aeabi_d2f, "__aeabi_d2f");
28 } else {
29 symbol(&__truncdfsf2, "__truncdfsf2");
30 }
31 symbol(&__truncxfsf2, "__truncxfsf2");
32 if (compiler_rt.want_ppc_abi) {
33 symbol(&__trunctfsf2, "__trunckfsf2");
34 } else if (compiler_rt.want_sparc64_abi) {
35 symbol(&_Qp_qtos, "_Qp_qtos");
36 } else if (compiler_rt.want_sparc32_abi) {
37 symbol(&__trunctfsf2, "_Q_qtos");
38 } else {
39 symbol(&__trunctfsf2, "__trunctfsf2");
40 }
41
42 symbol(&__truncxfdf2, "__truncxfdf2");
43
44 if (compiler_rt.want_ppc_abi) {
45 symbol(&__trunctfdf2, "__trunckfdf2");
46 } else if (compiler_rt.want_sparc64_abi) {
47 symbol(&_Qp_qtod, "_Qp_qtod");
48 } else if (compiler_rt.want_sparc32_abi) {
49 symbol(&__trunctfdf2, "_Q_qtod");
50 } else {
51 symbol(&__trunctfdf2, "__trunctfdf2");
52 }
53
54 if (compiler_rt.want_ppc_abi) {
55 symbol(&__trunctfxf2, "__trunckfxf2");
56 } else {
57 symbol(&__trunctfxf2, "__trunctfxf2");
58 }
59}
60
61fn __truncsfhf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f16Conv(f32).Abi {
62 return compiler_rt.f16Conv(f32).toAbi(f16_floatCast_f32(compiler_rt.f32.fromAbi(a)));
63}
64fn __aeabi_f2h(a: u32) callconv(.{ .arm_aapcs = .{} }) u16 {
65 return @bitCast(f16_floatCast_f32(@bitCast(a)));
66}
67pub fn f16_floatCast_f32(a: f32) f16 {
68 return truncf(f16, f32, a);
69}
70
71fn __truncdfhf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f16Conv(f64).Abi {
72 return compiler_rt.f16Conv(f64).toAbi(f16_floatCast_f64(compiler_rt.f64.fromAbi(a)));
73}
74fn __aeabi_d2h(a: u64) callconv(.{ .arm_aapcs = .{} }) u16 {
75 return @bitCast(f16_floatCast_f64(@bitCast(a)));
76}
77pub fn f16_floatCast_f64(a: f64) f16 {
78 return truncf(f16, f64, a);
79}
80
81fn __truncxfhf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f16Conv(f80).Abi {
82 return compiler_rt.f16Conv(f80).toAbi(f16_floatCast_f80(compiler_rt.f80.fromAbi(a)));
83}
84pub fn f16_floatCast_f80(a: f80) f16 {
85 return trunc_f80(f16, a);
86}
87
88fn __trunctfhf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f16Conv(f128).Abi {
89 return compiler_rt.f16Conv(f128).toAbi(f16_floatCast_f128(compiler_rt.f128.fromAbi(a)));
90}
91pub fn f16_floatCast_f128(a: f128) f16 {
92 return truncf(f16, f128, a);
93}
94
95fn __truncdfsf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f32.Abi {
96 return compiler_rt.f32.toAbi(f32_floatCast_f64(compiler_rt.f64.fromAbi(a)));
97}
98fn __aeabi_d2f(a: f64) callconv(.{ .arm_aapcs = .{} }) f32 {
99 return f32_floatCast_f64(a);
100}
101pub fn f32_floatCast_f64(a: f64) f32 {
102 return truncf(f32, f64, a);
103}
104
105fn __truncxfsf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f32.Abi {
106 return compiler_rt.f32.toAbi(f32_floatCast_f80(compiler_rt.f80.fromAbi(a)));
107}
108pub fn f32_floatCast_f80(a: f80) f32 {
109 return trunc_f80(f32, a);
110}
111
112fn __trunctfsf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f32.Abi {
113 return compiler_rt.f32.toAbi(f32_floatCast_f128(compiler_rt.f128.fromAbi(a)));
114}
115fn _Qp_qtos(a: *const f128) callconv(.c) f32 {
116 return f32_floatCast_f128(a.*);
117}
118pub fn f32_floatCast_f128(a: f128) f32 {
119 return truncf(f32, f128, a);
120}
121
122fn __truncxfdf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f64.Abi {
123 return compiler_rt.f64.toAbi(f64_floatCast_f80(compiler_rt.f80.fromAbi(a)));
124}
125pub fn f64_floatCast_f80(a: f80) f64 {
126 return trunc_f80(f64, a);
127}
128
129fn __trunctfdf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f64.Abi {
130 return compiler_rt.f64.toAbi(f64_floatCast_f128(compiler_rt.f128.fromAbi(a)));
131}
132fn _Qp_qtod(a: *const f128) callconv(.c) f64 {
133 return f64_floatCast_f128(a.*);
134}
135pub fn f64_floatCast_f128(a: f128) f64 {
136 return truncf(f64, f128, a);
137}
138
139fn __trunctfxf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f80.Abi {
140 return compiler_rt.f80.toAbi(f80_floatCast_f128(compiler_rt.f128.fromAbi(a)));
141}
142pub fn f80_floatCast_f128(a: f128) f80 {
143 const src_sig_bits = std.math.floatMantissaBits(f128);
144 const dst_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit
145
146 // Various constants whose values follow from the type parameters.
147 // Any reasonable optimizer will fold and propagate all of these.
148 const src_bits = @typeInfo(f128).float.bits;
149 const src_exp_bits = src_bits - src_sig_bits - 1;
150 const src_inf_exp = 0x7FFF;
151
152 const src_inf = src_inf_exp << src_sig_bits;
153 const src_sign_mask = 1 << (src_sig_bits + src_exp_bits);
154 const src_abs_mask = src_sign_mask - 1;
155 const round_mask = (1 << (src_sig_bits - dst_sig_bits)) - 1;
156 const halfway = 1 << (src_sig_bits - dst_sig_bits - 1);
157
158 // Break a into a sign and representation of the absolute value
159 const a_rep: u128 = @bitCast(a);
160 const a_abs = a_rep & src_abs_mask;
161 const sign: u16 = if (a_rep & src_sign_mask != 0) 0x8000 else 0;
162 const integer_bit = 1 << 63;
163
164 var res: std.math.F80 = undefined;
165
166 if (a_abs > src_inf) {
167 // a is NaN.
168 // Conjure the result by beginning with infinity, setting the qNaN
169 // bit and inserting the (truncated) trailing NaN field.
170 res.exp = 0x7fff;
171 res.fraction = 0x8000000000000000;
172 res.fraction |= @as(u64, @truncate(a_abs >> (src_sig_bits - dst_sig_bits)));
173 } else {
174 // The exponent of a is within the range of normal numbers in the
175 // destination format. We can convert by simply right-shifting with
176 // rounding, adding the explicit integer bit, and adjusting the exponent
177 res.fraction = @as(u64, @truncate(a_abs >> (src_sig_bits - dst_sig_bits))) | integer_bit;
178 res.exp = @truncate(a_abs >> src_sig_bits);
179
180 const round_bits = a_abs & round_mask;
181 if (round_bits > halfway) {
182 // Round to nearest
183 const ov = @addWithOverflow(res.fraction, 1);
184 res.fraction = ov[0];
185 res.exp += ov[1];
186 res.fraction |= @as(u64, ov[1]) << 63; // Restore integer bit after carry
187 } else if (round_bits == halfway) {
188 // Ties to even
189 const ov = @addWithOverflow(res.fraction, res.fraction & 1);
190 res.fraction = ov[0];
191 res.exp += ov[1];
192 res.fraction |= @as(u64, ov[1]) << 63; // Restore integer bit after carry
193 }
194 if (res.exp == 0) res.fraction &= ~@as(u64, integer_bit); // Remove integer bit for de-normals
195 }
196
197 res.exp |= sign;
198 return res.toFloat();
199}
200
201inline fn truncf(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {
4202 const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits);
5203 const dst_rep_t = @Int(.unsigned, @typeInfo(dst_t).float.bits);
6204 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
99297 return @bitCast(result);
100298}
101299
102pub inline fn trunc_f80(comptime dst_t: type, a: f80) dst_t {
300inline fn trunc_f80(comptime dst_t: type, a: f80) dst_t {
103301 const dst_rep_t = @Int(.unsigned, @typeInfo(dst_t).float.bits);
104302 const src_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit
105303 const dst_sig_bits = std.math.floatMantissaBits(dst_t);
lib/compiler_rt/truncf_test.zig+160-174
......@@ -1,79 +1,82 @@
11const std = @import("std");
22const testing = std.testing;
33
4const __truncsfhf2 = @import("truncsfhf2.zig").__truncsfhf2;
5const __truncdfhf2 = @import("truncdfhf2.zig").__truncdfhf2;
6const __truncdfsf2 = @import("truncdfsf2.zig").__truncdfsf2;
7const __trunctfhf2 = @import("trunctfhf2.zig").__trunctfhf2;
8const __trunctfsf2 = @import("trunctfsf2.zig").__trunctfsf2;
9const __trunctfdf2 = @import("trunctfdf2.zig").__trunctfdf2;
10const __trunctfxf2 = @import("trunctfxf2.zig").__trunctfxf2;
11
12fn test__truncsfhf2(a: u32, expected: u16) !void {
13 const actual: u16 = @bitCast(__truncsfhf2(@bitCast(a)));
14
15 if (actual == expected) {
16 return;
17 }
4const impl = @import("truncf.zig");
185
19 return error.TestFailure;
6const f16_floatCast_f32 = impl.f16_floatCast_f32;
7const f16_floatCast_f64 = impl.f16_floatCast_f64;
8const f16_floatCast_f80 = impl.f16_floatCast_f80;
9const f16_floatCast_f128 = impl.f16_floatCast_f128;
10
11const f32_floatCast_f64 = impl.f32_floatCast_f64;
12const f32_floatCast_f80 = impl.f32_floatCast_f80;
13const f32_floatCast_f128 = impl.f32_floatCast_f128;
14
15const f64_floatCast_f80 = impl.f64_floatCast_f80;
16const f64_floatCast_f128 = impl.f64_floatCast_f128;
17
18const f80_floatCast_f128 = impl.f80_floatCast_f128;
19
20fn test_f16_floatCast_f32(a: u32, expected: u16) !void {
21 const actual: u16 = @bitCast(f16_floatCast_f32(@bitCast(a)));
22 try testing.expect(actual == expected);
2023}
2124
22test "truncsfhf2" {
23 try test__truncsfhf2(0x7fc00000, 0x7e00); // qNaN
24 try test__truncsfhf2(0x7fe00000, 0x7f00); // sNaN
25test f16_floatCast_f32 {
26 try test_f16_floatCast_f32(0x7fc00000, 0x7e00); // qNaN
27 try test_f16_floatCast_f32(0x7fe00000, 0x7f00); // sNaN
2528
26 try test__truncsfhf2(0, 0); // 0
27 try test__truncsfhf2(0x80000000, 0x8000); // -0
29 try test_f16_floatCast_f32(0, 0); // 0
30 try test_f16_floatCast_f32(0x80000000, 0x8000); // -0
2831
29 try test__truncsfhf2(0x7f800000, 0x7c00); // inf
30 try test__truncsfhf2(0xff800000, 0xfc00); // -inf
32 try test_f16_floatCast_f32(0x7f800000, 0x7c00); // inf
33 try test_f16_floatCast_f32(0xff800000, 0xfc00); // -inf
3134
32 try test__truncsfhf2(0x477ff000, 0x7c00); // 65520 -> inf
33 try test__truncsfhf2(0xc77ff000, 0xfc00); // -65520 -> -inf
35 try test_f16_floatCast_f32(0x477ff000, 0x7c00); // 65520 -> inf
36 try test_f16_floatCast_f32(0xc77ff000, 0xfc00); // -65520 -> -inf
3437
35 try test__truncsfhf2(0x71cc3892, 0x7c00); // 0x1.987124876876324p+100 -> inf
36 try test__truncsfhf2(0xf1cc3892, 0xfc00); // -0x1.987124876876324p+100 -> -inf
38 try test_f16_floatCast_f32(0x71cc3892, 0x7c00); // 0x1.987124876876324p+100 -> inf
39 try test_f16_floatCast_f32(0xf1cc3892, 0xfc00); // -0x1.987124876876324p+100 -> -inf
3740
38 try test__truncsfhf2(0x38800000, 0x0400); // normal (min), 2**-14
39 try test__truncsfhf2(0xb8800000, 0x8400); // normal (min), -2**-14
41 try test_f16_floatCast_f32(0x38800000, 0x0400); // normal (min), 2**-14
42 try test_f16_floatCast_f32(0xb8800000, 0x8400); // normal (min), -2**-14
4043
41 try test__truncsfhf2(0x477fe000, 0x7bff); // normal (max), 65504
42 try test__truncsfhf2(0xc77fe000, 0xfbff); // normal (max), -65504
44 try test_f16_floatCast_f32(0x477fe000, 0x7bff); // normal (max), 65504
45 try test_f16_floatCast_f32(0xc77fe000, 0xfbff); // normal (max), -65504
4346
44 try test__truncsfhf2(0x477fe100, 0x7bff); // normal, 65505 -> 65504
45 try test__truncsfhf2(0xc77fe100, 0xfbff); // normal, -65505 -> -65504
47 try test_f16_floatCast_f32(0x477fe100, 0x7bff); // normal, 65505 -> 65504
48 try test_f16_floatCast_f32(0xc77fe100, 0xfbff); // normal, -65505 -> -65504
4649
47 try test__truncsfhf2(0x477fef00, 0x7bff); // normal, 65519 -> 65504
48 try test__truncsfhf2(0xc77fef00, 0xfbff); // normal, -65519 -> -65504
50 try test_f16_floatCast_f32(0x477fef00, 0x7bff); // normal, 65519 -> 65504
51 try test_f16_floatCast_f32(0xc77fef00, 0xfbff); // normal, -65519 -> -65504
4952
50 try test__truncsfhf2(0x3f802000, 0x3c01); // normal, 1 + 2**-10
51 try test__truncsfhf2(0xbf802000, 0xbc01); // normal, -1 - 2**-10
53 try test_f16_floatCast_f32(0x3f802000, 0x3c01); // normal, 1 + 2**-10
54 try test_f16_floatCast_f32(0xbf802000, 0xbc01); // normal, -1 - 2**-10
5255
53 try test__truncsfhf2(0x3eaaa000, 0x3555); // normal, approx. 1/3
54 try test__truncsfhf2(0xbeaaa000, 0xb555); // normal, approx. -1/3
56 try test_f16_floatCast_f32(0x3eaaa000, 0x3555); // normal, approx. 1/3
57 try test_f16_floatCast_f32(0xbeaaa000, 0xb555); // normal, approx. -1/3
5558
56 try test__truncsfhf2(0x40490fdb, 0x4248); // normal, 3.1415926535
57 try test__truncsfhf2(0xc0490fdb, 0xc248); // normal, -3.1415926535
59 try test_f16_floatCast_f32(0x40490fdb, 0x4248); // normal, 3.1415926535
60 try test_f16_floatCast_f32(0xc0490fdb, 0xc248); // normal, -3.1415926535
5861
59 try test__truncsfhf2(0x45cc3892, 0x6e62); // normal, 0x1.987124876876324p+12
62 try test_f16_floatCast_f32(0x45cc3892, 0x6e62); // normal, 0x1.987124876876324p+12
6063
61 try test__truncsfhf2(0x3f800000, 0x3c00); // normal, 1
62 try test__truncsfhf2(0x38800000, 0x0400); // normal, 0x1.0p-14
64 try test_f16_floatCast_f32(0x3f800000, 0x3c00); // normal, 1
65 try test_f16_floatCast_f32(0x38800000, 0x0400); // normal, 0x1.0p-14
6366
64 try test__truncsfhf2(0x33800000, 0x0001); // denormal (min), 2**-24
65 try test__truncsfhf2(0xb3800000, 0x8001); // denormal (min), -2**-24
67 try test_f16_floatCast_f32(0x33800000, 0x0001); // denormal (min), 2**-24
68 try test_f16_floatCast_f32(0xb3800000, 0x8001); // denormal (min), -2**-24
6669
67 try test__truncsfhf2(0x387fc000, 0x03ff); // denormal (max), 2**-14 - 2**-24
68 try test__truncsfhf2(0xb87fc000, 0x83ff); // denormal (max), -2**-14 + 2**-24
70 try test_f16_floatCast_f32(0x387fc000, 0x03ff); // denormal (max), 2**-14 - 2**-24
71 try test_f16_floatCast_f32(0xb87fc000, 0x83ff); // denormal (max), -2**-14 + 2**-24
6972
70 try test__truncsfhf2(0x35800000, 0x0010); // denormal, 0x1.0p-20
71 try test__truncsfhf2(0x33280000, 0x0001); // denormal, 0x1.5p-25 -> 0x1.0p-24
72 try test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero
73 try test_f16_floatCast_f32(0x35800000, 0x0010); // denormal, 0x1.0p-20
74 try test_f16_floatCast_f32(0x33280000, 0x0001); // denormal, 0x1.5p-25 -> 0x1.0p-24
75 try test_f16_floatCast_f32(0x33000000, 0x0000); // 0x1.0p-25 -> zero
7376}
7477
75fn test__truncdfhf2(a: f64, expected: u16) void {
76 const rep: u16 = @bitCast(__truncdfhf2(a));
78fn test_f16_floatCast_f64(a: f64, expected: u16) !void {
79 const rep: u16 = @bitCast(f16_floatCast_f64(a));
7780
7881 if (rep == expected) {
7982 return;
......@@ -84,62 +87,56 @@ fn test__truncdfhf2(a: f64, expected: u16) void {
8487 return;
8588 }
8689 }
87
88 @panic("__truncdfhf2 test failure");
90 return error.TestFailure;
8991}
9092
91fn test__truncdfhf2_raw(a: u64, expected: u16) void {
92 const actual: u16 = @bitCast(__truncdfhf2(@bitCast(a)));
93
94 if (actual == expected) {
95 return;
96 }
97
98 @panic("__truncdfhf2 test failure");
93fn test_f16_floatCast_f64_raw(a: u64, expected: u16) !void {
94 const actual: u16 = @bitCast(f16_floatCast_f64(@bitCast(a)));
95 try testing.expect(actual == expected);
9996}
10097
101test "truncdfhf2" {
102 test__truncdfhf2_raw(0x7ff8000000000000, 0x7e00); // qNaN
103 test__truncdfhf2_raw(0x7ff0000000008000, 0x7e00); // NaN
98test f16_floatCast_f64 {
99 try test_f16_floatCast_f64_raw(0x7ff8000000000000, 0x7e00); // qNaN
100 try test_f16_floatCast_f64_raw(0x7ff0000000008000, 0x7e00); // NaN
104101
105 test__truncdfhf2_raw(0x7ff0000000000000, 0x7c00); //inf
106 test__truncdfhf2_raw(0xfff0000000000000, 0xfc00); // -inf
102 try test_f16_floatCast_f64_raw(0x7ff0000000000000, 0x7c00); //inf
103 try test_f16_floatCast_f64_raw(0xfff0000000000000, 0xfc00); // -inf
107104
108 test__truncdfhf2(0.0, 0x0); // zero
109 test__truncdfhf2_raw(0x80000000 << 32, 0x8000); // -zero
105 try test_f16_floatCast_f64(0.0, 0x0); // zero
106 try test_f16_floatCast_f64_raw(0x80000000 << 32, 0x8000); // -zero
110107
111 test__truncdfhf2(3.1415926535, 0x4248);
112 test__truncdfhf2(-3.1415926535, 0xc248);
108 try test_f16_floatCast_f64(3.1415926535, 0x4248);
109 try test_f16_floatCast_f64(-3.1415926535, 0xc248);
113110
114 test__truncdfhf2(0x1.987124876876324p+1000, 0x7c00);
115 test__truncdfhf2(0x1.987124876876324p+12, 0x6e62);
116 test__truncdfhf2(0x1.0p+0, 0x3c00);
117 test__truncdfhf2(0x1.0p-14, 0x0400);
111 try test_f16_floatCast_f64(0x1.987124876876324p+1000, 0x7c00);
112 try test_f16_floatCast_f64(0x1.987124876876324p+12, 0x6e62);
113 try test_f16_floatCast_f64(0x1.0p+0, 0x3c00);
114 try test_f16_floatCast_f64(0x1.0p-14, 0x0400);
118115
119116 // denormal
120 test__truncdfhf2(0x1.0p-20, 0x0010);
121 test__truncdfhf2(0x1.0p-24, 0x0001);
122 test__truncdfhf2(-0x1.0p-24, 0x8001);
123 test__truncdfhf2(0x1.5p-25, 0x0001);
117 try test_f16_floatCast_f64(0x1.0p-20, 0x0010);
118 try test_f16_floatCast_f64(0x1.0p-24, 0x0001);
119 try test_f16_floatCast_f64(-0x1.0p-24, 0x8001);
120 try test_f16_floatCast_f64(0x1.5p-25, 0x0001);
124121
125122 // and back to zero
126 test__truncdfhf2(0x1.0p-25, 0x0000);
127 test__truncdfhf2(-0x1.0p-25, 0x8000);
123 try test_f16_floatCast_f64(0x1.0p-25, 0x0000);
124 try test_f16_floatCast_f64(-0x1.0p-25, 0x8000);
128125
129126 // max (precise)
130 test__truncdfhf2(65504.0, 0x7bff);
127 try test_f16_floatCast_f64(65504.0, 0x7bff);
131128
132129 // max (rounded)
133 test__truncdfhf2(65519.0, 0x7bff);
130 try test_f16_floatCast_f64(65519.0, 0x7bff);
134131
135132 // max (to +inf)
136 test__truncdfhf2(65520.0, 0x7c00);
137 test__truncdfhf2(-65520.0, 0xfc00);
138 test__truncdfhf2(65536.0, 0x7c00);
133 try test_f16_floatCast_f64(65520.0, 0x7c00);
134 try test_f16_floatCast_f64(-65520.0, 0xfc00);
135 try test_f16_floatCast_f64(65536.0, 0x7c00);
139136}
140137
141fn test__trunctfsf2(a: f128, expected: u32) void {
142 const x = __trunctfsf2(a);
138fn test_f32_floatCast_f128(a: f128, expected: u32) !void {
139 const x = f32_floatCast_f128(a);
143140
144141 const rep: u32 = @bitCast(x);
145142 if (rep == expected) {
......@@ -151,28 +148,27 @@ fn test__trunctfsf2(a: f128, expected: u32) void {
151148 return;
152149 }
153150 }
154
155 @panic("__trunctfsf2 test failure");
151 return error.TestFailure;
156152}
157153
158test "trunctfsf2" {
154test f32_floatCast_f128 {
159155 // qnan
160 test__trunctfsf2(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7fc00000);
156 try test_f32_floatCast_f128(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7fc00000);
161157 // nan
162 test__trunctfsf2(@bitCast(@as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7fc08000);
158 try test_f32_floatCast_f128(@bitCast(@as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7fc08000);
163159 // inf
164 test__trunctfsf2(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7f800000);
160 try test_f32_floatCast_f128(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7f800000);
165161 // zero
166 test__trunctfsf2(0.0, 0x0);
162 try test_f32_floatCast_f128(0.0, 0x0);
167163
168 test__trunctfsf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x4211d156);
169 test__trunctfsf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x3b71e9e2);
170 test__trunctfsf2(0x1.234eebb5faa678f4488693abcdefp+4534, 0x7f800000);
171 test__trunctfsf2(0x1.edcba9bb8c76a5a43dd21f334634p-435, 0x0);
164 try test_f32_floatCast_f128(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x4211d156);
165 try test_f32_floatCast_f128(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x3b71e9e2);
166 try test_f32_floatCast_f128(0x1.234eebb5faa678f4488693abcdefp+4534, 0x7f800000);
167 try test_f32_floatCast_f128(0x1.edcba9bb8c76a5a43dd21f334634p-435, 0x0);
172168}
173169
174fn test__trunctfdf2(a: f128, expected: u64) void {
175 const x = __trunctfdf2(a);
170fn test_f64_floatCast_f128(a: f128, expected: u64) !void {
171 const x = f64_floatCast_f128(a);
176172
177173 const rep: u64 = @bitCast(x);
178174 if (rep == expected) {
......@@ -184,28 +180,27 @@ fn test__trunctfdf2(a: f128, expected: u64) void {
184180 return;
185181 }
186182 }
187
188 @panic("__trunctfsf2 test failure");
183 return error.TestFailure;
189184}
190185
191test "trunctfdf2" {
186test f64_floatCast_f128 {
192187 // qnan
193 test__trunctfdf2(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7ff8000000000000);
188 try test_f64_floatCast_f128(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7ff8000000000000);
194189 // nan
195 test__trunctfdf2(@bitCast(@as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7ff8100000000000);
190 try test_f64_floatCast_f128(@bitCast(@as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7ff8100000000000);
196191 // inf
197 test__trunctfdf2(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7ff0000000000000);
192 try test_f64_floatCast_f128(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7ff0000000000000);
198193 // zero
199 test__trunctfdf2(0.0, 0x0);
194 try test_f64_floatCast_f128(0.0, 0x0);
200195
201 test__trunctfdf2(0x1.af23456789bbaaab347645365cdep+5, 0x404af23456789bbb);
202 test__trunctfdf2(0x1.dedafcff354b6ae9758763545432p-9, 0x3f6dedafcff354b7);
203 test__trunctfdf2(0x1.2f34dd5f437e849b4baab754cdefp+4534, 0x7ff0000000000000);
204 test__trunctfdf2(0x1.edcbff8ad76ab5bf46463233214fp-435, 0x24cedcbff8ad76ab);
196 try test_f64_floatCast_f128(0x1.af23456789bbaaab347645365cdep+5, 0x404af23456789bbb);
197 try test_f64_floatCast_f128(0x1.dedafcff354b6ae9758763545432p-9, 0x3f6dedafcff354b7);
198 try test_f64_floatCast_f128(0x1.2f34dd5f437e849b4baab754cdefp+4534, 0x7ff0000000000000);
199 try test_f64_floatCast_f128(0x1.edcbff8ad76ab5bf46463233214fp-435, 0x24cedcbff8ad76ab);
205200}
206201
207fn test__truncdfsf2(a: f64, expected: u32) void {
208 const x = __truncdfsf2(a);
202fn test_f32_floatCast_f64(a: f64, expected: u32) !void {
203 const x = f32_floatCast_f64(a);
209204
210205 const rep: u32 = @bitCast(x);
211206 if (rep == expected) {
......@@ -217,90 +212,81 @@ fn test__truncdfsf2(a: f64, expected: u32) void {
217212 return;
218213 }
219214 }
220
221 std.debug.print("got 0x{x} wanted 0x{x}\n", .{ rep, expected });
222
223 @panic("__trunctfsf2 test failure");
215 return error.TestFailure;
224216}
225217
226test "truncdfsf2" {
218test f32_floatCast_f64 {
227219 // nan & qnan
228 test__truncdfsf2(@bitCast(@as(u64, 0x7ff8000000000000)), 0x7fc00000);
229 test__truncdfsf2(@bitCast(@as(u64, 0x7ff0000000000001)), 0x7fc00000);
220 try test_f32_floatCast_f64(@bitCast(@as(u64, 0x7ff8000000000000)), 0x7fc00000);
221 try test_f32_floatCast_f64(@bitCast(@as(u64, 0x7ff0000000000001)), 0x7fc00000);
230222 // inf
231 test__truncdfsf2(@bitCast(@as(u64, 0x7ff0000000000000)), 0x7f800000);
232 test__truncdfsf2(@bitCast(@as(u64, 0xfff0000000000000)), 0xff800000);
223 try test_f32_floatCast_f64(@bitCast(@as(u64, 0x7ff0000000000000)), 0x7f800000);
224 try test_f32_floatCast_f64(@bitCast(@as(u64, 0xfff0000000000000)), 0xff800000);
233225
234 test__truncdfsf2(0.0, 0x0);
235 test__truncdfsf2(1.0, 0x3f800000);
236 test__truncdfsf2(-1.0, 0xbf800000);
226 try test_f32_floatCast_f64(0.0, 0x0);
227 try test_f32_floatCast_f64(1.0, 0x3f800000);
228 try test_f32_floatCast_f64(-1.0, 0xbf800000);
237229
238230 // huge number becomes inf
239 test__truncdfsf2(340282366920938463463374607431768211456.0, 0x7f800000);
231 try test_f32_floatCast_f64(340282366920938463463374607431768211456.0, 0x7f800000);
240232}
241233
242fn test__trunctfhf2(a: f128, expected: u16) void {
243 const x = __trunctfhf2(a);
234fn test_f16_floatCast_f128(a: f128, expected: u16) !void {
235 const x = f16_floatCast_f128(a);
244236
245237 const rep: u16 = @bitCast(x);
246 if (rep == expected) {
247 return;
248 }
249
250 std.debug.print("got 0x{x} wanted 0x{x}\n", .{ rep, expected });
251
252 @panic("__trunctfhf2 test failure");
238 try testing.expect(rep == expected);
253239}
254240
255test "trunctfhf2" {
241test f16_floatCast_f128 {
256242 // qNaN
257 test__trunctfhf2(@bitCast(@as(u128, 0x7fff8000000000000000000000000000)), 0x7e00);
243 try test_f16_floatCast_f128(@bitCast(@as(u128, 0x7fff8000000000000000000000000000)), 0x7e00);
258244 // NaN
259 test__trunctfhf2(@bitCast(@as(u128, 0x7fff0000000000000000000000000001)), 0x7e00);
245 try test_f16_floatCast_f128(@bitCast(@as(u128, 0x7fff0000000000000000000000000001)), 0x7e00);
260246 // inf
261 test__trunctfhf2(@bitCast(@as(u128, 0x7fff0000000000000000000000000000)), 0x7c00);
262 test__trunctfhf2(-@as(f128, @bitCast(@as(u128, 0x7fff0000000000000000000000000000))), 0xfc00);
247 try test_f16_floatCast_f128(@bitCast(@as(u128, 0x7fff0000000000000000000000000000)), 0x7c00);
248 try test_f16_floatCast_f128(-@as(f128, @bitCast(@as(u128, 0x7fff0000000000000000000000000000))), 0xfc00);
263249 // zero
264 test__trunctfhf2(0.0, 0x0);
265 test__trunctfhf2(-0.0, 0x8000);
266
267 test__trunctfhf2(3.1415926535, 0x4248);
268 test__trunctfhf2(-3.1415926535, 0xc248);
269 test__trunctfhf2(0x1.987124876876324p+100, 0x7c00);
270 test__trunctfhf2(0x1.987124876876324p+12, 0x6e62);
271 test__trunctfhf2(0x1.0p+0, 0x3c00);
272 test__trunctfhf2(0x1.0p-14, 0x0400);
250 try test_f16_floatCast_f128(0.0, 0x0);
251 try test_f16_floatCast_f128(-0.0, 0x8000);
252
253 try test_f16_floatCast_f128(3.1415926535, 0x4248);
254 try test_f16_floatCast_f128(-3.1415926535, 0xc248);
255 try test_f16_floatCast_f128(0x1.987124876876324p+100, 0x7c00);
256 try test_f16_floatCast_f128(0x1.987124876876324p+12, 0x6e62);
257 try test_f16_floatCast_f128(0x1.0p+0, 0x3c00);
258 try test_f16_floatCast_f128(0x1.0p-14, 0x0400);
273259 // denormal
274 test__trunctfhf2(0x1.0p-20, 0x0010);
275 test__trunctfhf2(0x1.0p-24, 0x0001);
276 test__trunctfhf2(-0x1.0p-24, 0x8001);
277 test__trunctfhf2(0x1.5p-25, 0x0001);
260 try test_f16_floatCast_f128(0x1.0p-20, 0x0010);
261 try test_f16_floatCast_f128(0x1.0p-24, 0x0001);
262 try test_f16_floatCast_f128(-0x1.0p-24, 0x8001);
263 try test_f16_floatCast_f128(0x1.5p-25, 0x0001);
278264 // and back to zero
279 test__trunctfhf2(0x1.0p-25, 0x0000);
280 test__trunctfhf2(-0x1.0p-25, 0x8000);
265 try test_f16_floatCast_f128(0x1.0p-25, 0x0000);
266 try test_f16_floatCast_f128(-0x1.0p-25, 0x8000);
281267 // max (precise)
282 test__trunctfhf2(65504.0, 0x7bff);
268 try test_f16_floatCast_f128(65504.0, 0x7bff);
283269 // max (rounded)
284 test__trunctfhf2(65519.0, 0x7bff);
270 try test_f16_floatCast_f128(65519.0, 0x7bff);
285271 // max (to +inf)
286 test__trunctfhf2(65520.0, 0x7c00);
287 test__trunctfhf2(65536.0, 0x7c00);
288 test__trunctfhf2(-65520.0, 0xfc00);
289
290 test__trunctfhf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x508f);
291 test__trunctfhf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x1b8f);
292 test__trunctfhf2(0x1.234eebb5faa678f4488693abcdefp+453, 0x7c00);
293 test__trunctfhf2(0x1.edcba9bb8c76a5a43dd21f334634p-43, 0x0);
272 try test_f16_floatCast_f128(65520.0, 0x7c00);
273 try test_f16_floatCast_f128(65536.0, 0x7c00);
274 try test_f16_floatCast_f128(-65520.0, 0xfc00);
275
276 try test_f16_floatCast_f128(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x508f);
277 try test_f16_floatCast_f128(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x1b8f);
278 try test_f16_floatCast_f128(0x1.234eebb5faa678f4488693abcdefp+453, 0x7c00);
279 try test_f16_floatCast_f128(0x1.edcba9bb8c76a5a43dd21f334634p-43, 0x0);
294280}
295281
296test "trunctfxf2" {
297 try test__trunctfxf2(1.5, 1.5);
298 try test__trunctfxf2(2.5, 2.5);
299 try test__trunctfxf2(-2.5, -2.5);
300 try test__trunctfxf2(0.0, 0.0);
282fn test_f80_floatCast_f128(a: f128, expected: f80) !void {
283 const x = f80_floatCast_f128(a);
284 try testing.expect(x == expected);
301285}
302286
303fn test__trunctfxf2(a: f128, expected: f80) !void {
304 const x = __trunctfxf2(a);
305 try testing.expect(x == expected);
287test f80_floatCast_f128 {
288 try test_f80_floatCast_f128(1.5, 1.5);
289 try test_f80_floatCast_f128(2.5, 2.5);
290 try test_f80_floatCast_f128(-2.5, -2.5);
291 try test_f80_floatCast_f128(0.0, 0.0);
306292}
lib/compiler_rt/truncsfhf2.zig deleted-24
......@@ -1,24 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const truncf = @import("./truncf.zig").truncf;
4
5comptime {
6 if (compiler_rt.gnu_f16_abi) {
7 symbol(&__gnu_f2h_ieee, "__gnu_f2h_ieee");
8 } else if (compiler_rt.want_aeabi) {
9 symbol(&__aeabi_f2h, "__aeabi_f2h");
10 }
11 symbol(&__truncsfhf2, "__truncsfhf2");
12}
13
14pub fn __truncsfhf2(a: f32) callconv(.c) compiler_rt.F16T(f32) {
15 return @bitCast(truncf(f16, f32, a));
16}
17
18fn __gnu_f2h_ieee(a: f32) callconv(.c) compiler_rt.F16T(f32) {
19 return @bitCast(truncf(f16, f32, a));
20}
21
22fn __aeabi_f2h(a: f32) callconv(.{ .arm_aapcs = .{} }) u16 {
23 return @bitCast(truncf(f16, f32, a));
24}
lib/compiler_rt/trunctfdf2.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const truncf = @import("./truncf.zig").truncf;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__trunctfdf2, "__trunckfdf2");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_qtod, "_Qp_qtod");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__trunctfdf2, "_Q_qtod");
12 }
13 symbol(&__trunctfdf2, "__trunctfdf2");
14}
15
16pub fn __trunctfdf2(a: f128) callconv(.c) f64 {
17 return truncf(f64, f128, a);
18}
19
20fn _Qp_qtod(a: *const f128) callconv(.c) f64 {
21 return truncf(f64, f128, a.*);
22}
lib/compiler_rt/trunctfhf2.zig deleted-14
......@@ -1,14 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const truncf = @import("./truncf.zig").truncf;
4
5comptime {
6 symbol(&__trunctfhf2, "__trunctfhf2");
7 if (compiler_rt.want_ppc_abi) {
8 symbol(&__trunctfhf2, "__trunckfhf2");
9 }
10}
11
12pub fn __trunctfhf2(a: f128) callconv(.c) compiler_rt.F16T(f128) {
13 return @bitCast(truncf(f16, f128, a));
14}
lib/compiler_rt/trunctfsf2.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const truncf = @import("./truncf.zig").truncf;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__trunctfsf2, "__trunckfsf2");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_qtos, "_Qp_qtos");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__trunctfsf2, "_Q_qtos");
12 }
13 symbol(&__trunctfsf2, "__trunctfsf2");
14}
15
16pub fn __trunctfsf2(a: f128) callconv(.c) f32 {
17 return truncf(f32, f128, a);
18}
19
20fn _Qp_qtos(a: *const f128) callconv(.c) f32 {
21 return truncf(f32, f128, a.*);
22}
lib/compiler_rt/trunctfxf2.zig deleted-67
......@@ -1,67 +0,0 @@
1const math = @import("std").math;
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const trunc_f80 = @import("./truncf.zig").trunc_f80;
5
6comptime {
7 symbol(&__trunctfxf2, "__trunctfxf2");
8}
9
10pub fn __trunctfxf2(a: f128) callconv(.c) f80 {
11 const src_sig_bits = math.floatMantissaBits(f128);
12 const dst_sig_bits = math.floatMantissaBits(f80) - 1; // -1 for the integer bit
13
14 // Various constants whose values follow from the type parameters.
15 // Any reasonable optimizer will fold and propagate all of these.
16 const src_bits = @typeInfo(f128).float.bits;
17 const src_exp_bits = src_bits - src_sig_bits - 1;
18 const src_inf_exp = 0x7FFF;
19
20 const src_inf = src_inf_exp << src_sig_bits;
21 const src_sign_mask = 1 << (src_sig_bits + src_exp_bits);
22 const src_abs_mask = src_sign_mask - 1;
23 const round_mask = (1 << (src_sig_bits - dst_sig_bits)) - 1;
24 const halfway = 1 << (src_sig_bits - dst_sig_bits - 1);
25
26 // Break a into a sign and representation of the absolute value
27 const a_rep = @as(u128, @bitCast(a));
28 const a_abs = a_rep & src_abs_mask;
29 const sign: u16 = if (a_rep & src_sign_mask != 0) 0x8000 else 0;
30 const integer_bit = 1 << 63;
31
32 var res: math.F80 = undefined;
33
34 if (a_abs > src_inf) {
35 // a is NaN.
36 // Conjure the result by beginning with infinity, setting the qNaN
37 // bit and inserting the (truncated) trailing NaN field.
38 res.exp = 0x7fff;
39 res.fraction = 0x8000000000000000;
40 res.fraction |= @as(u64, @truncate(a_abs >> (src_sig_bits - dst_sig_bits)));
41 } else {
42 // The exponent of a is within the range of normal numbers in the
43 // destination format. We can convert by simply right-shifting with
44 // rounding, adding the explicit integer bit, and adjusting the exponent
45 res.fraction = @as(u64, @truncate(a_abs >> (src_sig_bits - dst_sig_bits))) | integer_bit;
46 res.exp = @truncate(a_abs >> src_sig_bits);
47
48 const round_bits = a_abs & round_mask;
49 if (round_bits > halfway) {
50 // Round to nearest
51 const ov = @addWithOverflow(res.fraction, 1);
52 res.fraction = ov[0];
53 res.exp += ov[1];
54 res.fraction |= @as(u64, ov[1]) << 63; // Restore integer bit after carry
55 } else if (round_bits == halfway) {
56 // Ties to even
57 const ov = @addWithOverflow(res.fraction, res.fraction & 1);
58 res.fraction = ov[0];
59 res.exp += ov[1];
60 res.fraction |= @as(u64, ov[1]) << 63; // Restore integer bit after carry
61 }
62 if (res.exp == 0) res.fraction &= ~@as(u64, integer_bit); // Remove integer bit for de-normals
63 }
64
65 res.exp |= sign;
66 return res.toFloat();
67}
lib/compiler_rt/truncxfdf2.zig deleted-10
......@@ -1,10 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const trunc_f80 = @import("./truncf.zig").trunc_f80;
3
4comptime {
5 symbol(&__truncxfdf2, "__truncxfdf2");
6}
7
8fn __truncxfdf2(a: f80) callconv(.c) f64 {
9 return trunc_f80(f64, a);
10}
lib/compiler_rt/truncxfhf2.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const trunc_f80 = @import("./truncf.zig").trunc_f80;
4
5comptime {
6 symbol(&__truncxfhf2, "__truncxfhf2");
7}
8
9fn __truncxfhf2(a: f80) callconv(.c) compiler_rt.F16T(f80) {
10 return @bitCast(trunc_f80(f16, a));
11}
lib/compiler_rt/truncxfsf2.zig deleted-10
......@@ -1,10 +0,0 @@
1const trunc_f80 = @import("./truncf.zig").trunc_f80;
2const symbol = @import("../compiler_rt.zig").symbol;
3
4comptime {
5 symbol(&__truncxfsf2, "__truncxfsf2");
6}
7
8fn __truncxfsf2(a: f80) callconv(.c) f32 {
9 return trunc_f80(f32, a);
10}
lib/compiler_rt/udivmodei4.zig+1-1
......@@ -6,7 +6,7 @@ const shr = std.math.shr;
66const shl = std.math.shl;
77
88const compiler_rt = @import("../compiler_rt.zig");
9const symbol = @import("../compiler_rt.zig").symbol;
9const symbol = compiler_rt.symbol;
1010
1111const max_limbs = @divCeil(65535, 32); // max supported type is u65535
1212
lib/compiler_rt/unorddf2.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const comparef = @import("./comparef.zig");
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_dcmpun, "__aeabi_dcmpun");
8 } else {
9 symbol(&__unorddf2, "__unorddf2");
10 }
11}
12
13pub fn __unorddf2(a: f64, b: f64) callconv(.c) i32 {
14 return comparef.unordcmp(f64, a, b);
15}
16
17fn __aeabi_dcmpun(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
18 return comparef.unordcmp(f64, a, b);
19}
lib/docs/wasm/html_render.zig+1-1
......@@ -62,7 +62,7 @@ pub fn fileSourceHtml(
6262 var cursor: usize = ast.tokenStart(start_token);
6363
6464 var indent: usize = 0;
65 if (std.mem.lastIndexOf(u8, ast.source[0..cursor], "\n")) |newline_index| {
65 if (std.mem.findLast(u8, ast.source[0..cursor], "\n")) |newline_index| {
6666 for (ast.source[newline_index + 1 .. cursor]) |c| {
6767 if (c == ' ') {
6868 indent += 1;
lib/docs/wasm/main.zig+3-3
......@@ -153,11 +153,11 @@ fn query_exec_fallible(query: []const u8, ignore_case: bool) !void {
153153 continue;
154154 }
155155 // substring, case insensitive match of full decl path
156 if (std.mem.indexOf(u8, g.full_path_search_text_lower.items, term) != null) {
156 if (std.mem.find(u8, g.full_path_search_text_lower.items, term) != null) {
157157 points += 2;
158158 continue;
159159 }
160 if (std.mem.indexOf(u8, g.doc_search_text.items, term) != null) {
160 if (std.mem.find(u8, g.doc_search_text.items, term) != null) {
161161 points += 1;
162162 continue;
163163 }
......@@ -803,7 +803,7 @@ fn unpackInner(tar_bytes: []u8) !void {
803803 if (std.mem.endsWith(u8, tar_file.name, ".zig")) {
804804 log.debug("found file: '{s}'", .{tar_file.name});
805805 const file_name = try gpa.dupe(u8, tar_file.name);
806 if (std.mem.indexOfScalar(u8, file_name, '/')) |pkg_name_end| {
806 if (std.mem.findScalar(u8, file_name, '/')) |pkg_name_end| {
807807 const pkg_name = file_name[0..pkg_name_end];
808808 const gop = try Walk.modules.getOrPut(gpa, pkg_name);
809809 const file: Walk.File.Index = @fromBackingInt(@intCast(Walk.files.entries.len));
lib/docs/wasm/markdown/Document.zig+1-1
......@@ -108,7 +108,7 @@ pub const Node = struct {
108108 // In Debug and ReleaseSafe builds, there may be hidden extra fields
109109 // included for safety checks. Without such safety checks enabled,
110110 // we always want this union to be 8 bytes.
111 if (builtin.mode != .Debug and builtin.mode != .ReleaseSafe) {
111 if (builtin.mode != .debug and builtin.mode != .safe) {
112112 assert(@sizeOf(Data) == 8);
113113 }
114114 }
lib/docs/wasm/markdown/Parser.zig+21-21
......@@ -159,7 +159,7 @@ const Block = struct {
159159 .heading => null,
160160 .code_block => code_block: {
161161 const trimmed = mem.trimEnd(u8, unindented, " \t");
162 if (mem.indexOfNone(u8, trimmed, "`") != null or trimmed.len != b.data.code_block.fence_len) {
162 if (mem.findNone(u8, trimmed, "`") != null or trimmed.len != b.data.code_block.fence_len) {
163163 const effective_indent = @min(indent, b.data.code_block.indent);
164164 break :code_block line[effective_indent..];
165165 } else {
......@@ -209,7 +209,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void {
209209 } else p.pending_blocks.items.len;
210210
211211 const in_code_block = p.pending_blocks.items.len > 0 and
212 p.pending_blocks.getLast().?.tag == .code_block;
212 p.pending_blocks.last().?.tag == .code_block;
213213 const code_block_end = in_code_block and
214214 first_unmatched + 1 == p.pending_blocks.items.len;
215215 // 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 {
225225 if (maybe_block_start == null and
226226 !isBlank(rest_line) and
227227 p.pending_blocks.items.len > 0 and
228 p.pending_blocks.getLast().?.tag == .paragraph)
228 p.pending_blocks.last().?.tag == .paragraph)
229229 {
230230 try p.addScratchStringLine(mem.trimStart(u8, rest_line, " \t"));
231231 return;
......@@ -236,7 +236,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void {
236236 // paragraphs.
237237 if (maybe_block_start != null and
238238 p.pending_blocks.items.len > 0 and
239 p.pending_blocks.getLast().?.tag == .paragraph)
239 p.pending_blocks.last().?.tag == .paragraph)
240240 {
241241 try p.closeLastBlock();
242242 }
......@@ -259,7 +259,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void {
259259 // Do not append the end of a code block (```) as textual content.
260260 if (code_block_end) return;
261261
262 const can_accept = if (p.pending_blocks.getLast()) |last_pending_block|
262 const can_accept = if (p.pending_blocks.last()) |last_pending_block|
263263 last_pending_block.canAccept()
264264 else
265265 .blocks;
......@@ -273,7 +273,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void {
273273 // loose, since we might just be looking at a blank line after the
274274 // end of the last item in the list. The final determination will be
275275 // made when appending the next child of the list or list item.
276 const maybe_containing_list_index = if (p.pending_blocks.items.len > 0 and p.pending_blocks.getLast().?.tag == .list_item)
276 const maybe_containing_list_index = if (p.pending_blocks.items.len > 0 and p.pending_blocks.last().?.tag == .list_item)
277277 p.pending_blocks.items.len - 2
278278 else
279279 null;
......@@ -368,7 +368,7 @@ const BlockStart = struct {
368368};
369369
370370fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {
371 if (p.pending_blocks.getLast()) |last_pending_block| {
371 if (p.pending_blocks.last()) |last_pending_block| {
372372 // Close the last block if it is a list and the new block is not a list item
373373 // or not of the same marker type.
374374 const should_close_list = last_pending_block.tag == .list and
......@@ -383,7 +383,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {
383383 }
384384 }
385385
386 if (p.pending_blocks.getLast()) |last_pending_block| {
386 if (p.pending_blocks.last()) |last_pending_block| {
387387 // If the last block is a list or list item, check for tightness based
388388 // on the last line.
389389 const maybe_containing_list = switch (last_pending_block.tag) {
......@@ -401,7 +401,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {
401401 // Start a new list if the new block is a list item and there is no
402402 // containing list yet.
403403 if (block_start.tag == .list_item and
404 (p.pending_blocks.items.len == 0 or p.pending_blocks.getLast().?.tag != .list))
404 (p.pending_blocks.items.len == 0 or p.pending_blocks.last().?.tag != .list))
405405 {
406406 try p.pending_blocks.append(p.allocator, .{
407407 .tag = .list,
......@@ -417,7 +417,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {
417417
418418 if (block_start.tag == .table_row) {
419419 // Likewise, table rows start a table implicitly.
420 if (p.pending_blocks.items.len == 0 or p.pending_blocks.getLast().?.tag != .table) {
420 if (p.pending_blocks.items.len == 0 or p.pending_blocks.last().?.tag != .table) {
421421 try p.pending_blocks.append(p.allocator, .{
422422 .tag = .table,
423423 .data = .{ .table = .{
......@@ -429,7 +429,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {
429429 });
430430 }
431431
432 const current_row = p.scratch_extra.items.len - p.pending_blocks.getLast().?.extra_start;
432 const current_row = p.scratch_extra.items.len - p.pending_blocks.last().?.extra_start;
433433 if (current_row <= 1) {
434434 var buffer: [max_table_columns]Node.TableCellAlignment = undefined;
435435 const table_row = &block_start.data.table_row;
......@@ -441,7 +441,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {
441441 // We need to go back and mark the header row and its column
442442 // alignments.
443443 const datas = p.nodes.items(.data);
444 const header_data = datas[p.scratch_extra.getLast().?];
444 const header_data = datas[p.scratch_extra.last().?];
445445 for (p.extraChildren(header_data.container.children), 0..) |header_cell, i| {
446446 const alignment = if (i < alignments.len) alignments[i] else .unset;
447447 const cell_data = &datas[@backingInt(header_cell)].table_cell;
......@@ -594,7 +594,7 @@ fn startListItem(unindented_line: []const u8) ?ListItemStart {
594594 };
595595 }
596596
597 const number_end = mem.indexOfNone(u8, unindented_line, "0123456789") orelse return null;
597 const number_end = mem.findNone(u8, unindented_line, "0123456789") orelse return null;
598598 const after_number = unindented_line[number_end..];
599599 const marker: Block.Data.ListMarker = if (mem.startsWith(u8, after_number, ". "))
600600 .number_dot
......@@ -639,10 +639,10 @@ fn startTableRow(unindented_line: []const u8) ?TableRowStart {
639639 // Ignoring pipes in code spans allows table cells to contain
640640 // code using ||, for example.
641641 const open_start = i;
642 i = mem.indexOfNonePos(u8, table_row_content, i, "`") orelse return null;
642 i = mem.findNonePos(u8, table_row_content, i, "`") orelse return null;
643643 const open_len = i - open_start;
644 while (mem.indexOfScalarPos(u8, table_row_content, i, '`')) |close_start| {
645 i = mem.indexOfNonePos(u8, table_row_content, close_start, "`") orelse return null;
644 while (mem.findScalarPos(u8, table_row_content, i, '`')) |close_start| {
645 i = mem.findNonePos(u8, table_row_content, close_start, "`") orelse return null;
646646 const close_len = i - close_start;
647647 if (close_len == open_len) break;
648648 } else return null;
......@@ -794,7 +794,7 @@ fn startCodeBlock(p: *Parser, unindented_line: []const u8) !?CodeBlockStart {
794794 } else "";
795795 // Code block tags may not contain backticks, since that would create
796796 // potential confusion with inline code spans.
797 if (fence_len < 3 or mem.indexOfScalar(u8, tag_bytes, '`') != null) return null;
797 if (fence_len < 3 or mem.findScalar(u8, tag_bytes, '`') != null) return null;
798798 return .{
799799 .tag = try p.addString(mem.trim(u8, tag_bytes, " ")),
800800 .fence_len = fence_len,
......@@ -1382,12 +1382,12 @@ const InlineParser = struct {
13821382 /// parsing.
13831383 fn parseCodeSpan(ip: *InlineParser) !void {
13841384 const opener_start = ip.pos;
1385 ip.pos = mem.indexOfNonePos(u8, ip.content, ip.pos, "`") orelse ip.content.len;
1385 ip.pos = mem.findNonePos(u8, ip.content, ip.pos, "`") orelse ip.content.len;
13861386 const opener_len = ip.pos - opener_start;
13871387
13881388 const start = ip.pos;
1389 const end = while (mem.indexOfScalarPos(u8, ip.content, ip.pos, '`')) |closer_start| {
1390 ip.pos = mem.indexOfNonePos(u8, ip.content, closer_start, "`") orelse ip.content.len;
1389 const end = while (mem.findScalarPos(u8, ip.content, ip.pos, '`')) |closer_start| {
1390 ip.pos = mem.findNonePos(u8, ip.content, closer_start, "`") orelse ip.content.len;
13911391 const closer_len = ip.pos - closer_start;
13921392
13931393 if (closer_len == opener_len) break closer_start;
......@@ -1627,7 +1627,7 @@ fn addScratchStringLine(p: *Parser, line: []const u8) !void {
16271627}
16281628
16291629fn isBlank(line: []const u8) bool {
1630 return mem.indexOfNone(u8, line, " \t") == null;
1630 return mem.findNone(u8, line, " \t") == null;
16311631}
16321632
16331633fn isPunctuation(c: u8) bool {
lib/fuzzer.zig+4-4
......@@ -41,8 +41,8 @@ fn logOverride(
4141
4242var safe_allocator: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{});
4343const gpa = switch (builtin.mode) {
44 .Debug, .ReleaseSafe => safe_allocator.allocator(),
45 .ReleaseFast, .ReleaseSmall => std.heap.smp_allocator,
44 .debug, .safe => safe_allocator.allocator(),
45 .fast, .small => std.heap.smp_allocator,
4646};
4747
4848// Seperate from `exec` to allow initialization before `exec` is.
......@@ -1085,7 +1085,7 @@ const Fuzzer = struct {
10851085 fn removeBest(f: *Fuzzer, i: Input.Index, best_i: u32) void {
10861086 const t = &f.tests[f.test_i];
10871087 const ref = &t.corpus.items(.ref)[@backingInt(i)];
1088 const list_i = mem.indexOfScalar(u32, ref.best_i_buf[0..ref.best_i_len], best_i).?;
1088 const list_i = mem.findScalar(u32, ref.best_i_buf[0..ref.best_i_len], best_i).?;
10891089 ref.best_i_len -= 1;
10901090 ref.best_i_buf[list_i] = ref.best_i_buf[ref.best_i_len];
10911091
......@@ -1209,7 +1209,7 @@ const Fuzzer = struct {
12091209 f.req_bytes = @intCast(f.input_builder.bytes_table.items.len);
12101210 const quality: Input.Best.Quality = .{
12111211 .n_pcs = n_pcs: {
1212 @setRuntimeSafety(builtin.mode == .Debug); // Necessary for vectorization
1212 @setRuntimeSafety(builtin.mode == .debug); // Necessary for vectorization
12131213 var n: u32 = 0;
12141214 for (exec.pc_counters) |c| {
12151215 n += @intFromBool(c != 0);
lib/libc/glibc/abilists
Binary files a/lib/libc/glibc/abilists and b/lib/libc/glibc/abilists differ
lib/libc/glibc/elf/elf.h+6-2
......@@ -798,7 +798,8 @@ typedef struct
798798#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */
799799#define NT_X86_SHSTK 0x204 /* x86 SHSTK state */
800800#define NT_X86_XSAVE_LAYOUT 0x205 /* XSAVE layout description. */
801#define NT_S390_HIGH_GPRS 0x300 /* s390 upper register halves */
801#define NT_S390_HIGH_GPRS 0x300 /* s390 upper register halves. This was
802 used in now removed s390-32 arch. */
802803#define NT_S390_TIMER 0x301 /* s390 timer register */
803804#define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */
804805#define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */
......@@ -846,6 +847,7 @@ typedef struct
846847#define NT_RISCV_VECTOR 0x901 /* RISC-V vector registers */
847848#define NT_RISCV_TAGGED_ADDR_CTRL 0x902 /* RISC-V tagged
848849 address control */
850#define NT_RISCV_USER_CFI 0x903 /* RISC-V shadow stack state */
849851#define NT_LOONGARCH_CPUCFG 0xa00 /* LoongArch CPU config registers. */
850852#define NT_LOONGARCH_CSR 0xa01 /* LoongArch control and
851853 status registers. */
......@@ -3470,7 +3472,9 @@ enum
34703472
34713473/* Valid values for the e_flags field. */
34723474
3473#define EF_S390_HIGH_GPRS 0x00000001 /* High GPRs kernel facility needed. */
3475#define EF_S390_HIGH_GPRS 0x00000001 /* High GPRs kernel facility needed.
3476 This was used in now removed s390-32
3477 arch. */
34743478
34753479/* Additional s390 relocs */
34763480
lib/libc/glibc/include/libc-symbols.h+2-1
......@@ -113,6 +113,7 @@
113113#define HAVE_LIBINTL_H 1
114114#define HAVE_WCTYPE_H 1
115115#define HAVE_ISWCTYPE 1
116#define HAVE_MEMPCPY 1
116117#define ENABLE_NLS 1
117118
118119/* The symbols in all the user (non-_) macros are C symbols. */
......@@ -682,7 +683,7 @@ for linking")
682683
683684/* Helper / base macros for indirect function symbols. */
684685#define __ifunc_resolver(type_name, name, expr, init, classifier, ...) \
685 classifier inhibit_stack_protector \
686 classifier \
686687 __typeof (type_name) *name##_ifunc (__VA_ARGS__) \
687688 { \
688689 init (); \
lib/libc/glibc/sysdeps/aarch64/sysdep.h+28-4
......@@ -43,7 +43,6 @@
4343#define FEATURE_1_PAC 2
4444#define FEATURE_1_GCS 4
4545
46/* Add a NT_GNU_PROPERTY_TYPE_0 note. */
4746#define GNU_PROPERTY(type, value) \
4847 .section .note.gnu.property, "a"; \
4948 .p2align 3; \
......@@ -57,9 +56,34 @@
5756 .word 0; \
5857 .text
5958
60/* Add GNU property note with the supported features to all asm code
61 where sysdep.h is included. */
62GNU_PROPERTY (FEATURE_1_AND, FEATURE_1_BTI|FEATURE_1_PAC|FEATURE_1_GCS)
59#ifdef __ARM_BUILDATTR64_FV
60/* Add AArch64 feature bits build attributes. */
61# define FEATURE_1_AND_MARK(value) \
62 .aeabi_subsection aeabi_feature_and_bits, optional, ULEB128; \
63 .if ((value) & FEATURE_1_BTI); \
64 .aeabi_attribute Tag_Feature_BTI, 1; \
65 .else; \
66 .aeabi_attribute Tag_Feature_BTI, 0; \
67 .endif; \
68 .if ((value) & FEATURE_1_GCS); \
69 .aeabi_attribute Tag_Feature_GCS, 1; \
70 .else; \
71 .aeabi_attribute Tag_Feature_GCS, 0; \
72 .endif; \
73 .if ((value) & FEATURE_1_PAC); \
74 .aeabi_attribute Tag_Feature_PAC, 1; \
75 .else; \
76 .aeabi_attribute Tag_Feature_PAC, 0; \
77 .endif; \
78 .text
79#else
80/* Add a NT_GNU_PROPERTY_TYPE_0 note. */
81# define FEATURE_1_AND_MARK(value) GNU_PROPERTY (FEATURE_1_AND, value)
82#endif /* __ARM_BUILDATTR64_FV */
83
84/* Add marking with the supported features to all asm code where sysdep.h
85 is included. */
86FEATURE_1_AND_MARK (FEATURE_1_BTI | FEATURE_1_PAC | FEATURE_1_GCS)
6387
6488/* Define an entry point visible from C. */
6589#define ENTRY(name) \
lib/libc/glibc/sysdeps/arm/start.S+27
......@@ -90,6 +90,7 @@ _start:
9090 push { a1 }
9191
9292#ifdef PIC
93# ifdef SHARED
9394 ldr sl, .L_GOT
9495 adr a4, .L_GOT
9596 add sl, sl, a4
......@@ -103,6 +104,16 @@ _start:
103104 /* __libc_start_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
104105 /* Let the libc call main and exit with its return code. */
105106 bl __libc_start_main(PLT)
107# else
108 ldr a1, .L_main_rel /* Load the relative offset of __wrap_main. */
109 adr a4, .L_main_rel /* Load the actual runtime address of the label. */
110 add a1, a4, a1 /* Add them together to get the absolute address. */
111
112 mov a4, #0 /* Used to be init. */
113 push { a4 } /* Used to be fini. */
114
115 bl __libc_start_main
116# endif /* ifdef SHARED */
106117#else
107118
108119 mov a4, #0 /* Used to init. */
......@@ -119,14 +130,30 @@ _start:
119130
120131#ifdef PIC
121132 .align 2
133# ifdef SHARED
122134.L_GOT:
123135 .word _GLOBAL_OFFSET_TABLE_ - .L_GOT
124136 .word main(GOT)
137# else
138.L_main_rel:
139 .word __wrap_main - .L_main_rel
140# endif
125141#endif
126142
127143 .cantunwind
128144 .fnend
129145
146#if defined PIC && !defined SHARED
147/* When main is not defined in the executable but in a shared library then
148 a wrapper is needed, because crt1.o and rcrt1.o share this code and the
149 latter (static PIE) must avoid GOT relocations before __libc_start_main
150 is called. The branch to main is turned into a PLT entry by every linker,
151 unlike a REL32 data relocation against main. */
152 .type __wrap_main, %function
153__wrap_main:
154 b main
155#endif
156
130157/* Define a symbol for the first piece of initialized data. */
131158 .data
132159 .globl __data_start
lib/libc/glibc/sysdeps/htl/libc-lockP.h+14
......@@ -21,6 +21,20 @@
2121
2222#include <pthread.h>
2323
24typedef pthread_rwlock_t __libc_rwlock_t;
25
26#define __libc_rwlock_define(CLASS,NAME) \
27 CLASS __libc_rwlock_t NAME;
28#define __libc_rwlock_define_initialized(CLASS,NAME) \
29 CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
30#define __libc_rwlock_init(NAME) __pthread_rwlock_init (&(NAME), NULL)
31#define __libc_rwlock_fini(NAME) ((void) 0)
32#define __libc_rwlock_rdlock(NAME) __pthread_rwlock_rdlock (&(NAME))
33#define __libc_rwlock_wrlock(NAME) __pthread_rwlock_wrlock (&(NAME))
34#define __libc_rwlock_tryrdlock(NAME) __pthread_rwlock_tryrdlock (&(NAME))
35#define __libc_rwlock_trywrlock(NAME) __pthread_rwlock_trywrlock (&(NAME))
36#define __libc_rwlock_unlock(NAME) __pthread_rwlock_unlock (&(NAME))
37
2438/* If we check for a weakly referenced symbol and then perform a
2539 normal jump to it te code generated for some platforms in case of
2640 PIC is unnecessarily slow. What would happen is that the function
lib/libc/glibc/sysdeps/loongarch/start.S+18-8
......@@ -36,6 +36,7 @@
3636#define __ASSEMBLY__ 1
3737#include <entry.h>
3838#include <sys/asm.h>
39#include <sysdep.h>
3940
4041/* The entry point's job is to call __libc_start_main. Per the ABI,
4142 a0 contains the address of a function to be passed to atexit.
......@@ -57,23 +58,32 @@ ENTRY (ENTRY_POINT)
5758/* Terminate call stack by noting ra is undefined. Use a dummy
5859 .cfi_label to force starting the FDE. */
5960 .cfi_label .Ldummy
60 cfi_undefined (1)
61 cfi_undefined (1)
6162 or a5, a0, zero /* rtld_fini */
6263
63 la.pcrel a0, t0, main
64#if defined PIC && !defined SHARED
65 /* Avoid relocation in static PIE since _start is called before it
66 is relocated. */
67 la.pcrel a0, __wrap_main
68#else
69 LA_GOT (a0, main)
70#endif
71
6472 REG_L a1, sp, 0
6573 ADDI a2, sp, SZREG
6674
67 /* Adjust $sp for 16-aligned */
68 BSTRINS sp, zero, 3, 0
75 /* Adjust $sp for 16-bytes aligned */
76 REG_ALIGN_ASM (sp, 4)
6977
7078 move a3, zero /* used to be init */
7179 move a4, zero /* used to be fini */
7280 or a6, sp, zero /* stack_end */
7381
74 la.pcrel ra, t0, __libc_start_main
75 jirl ra, ra, 0
82 CALL (__libc_start_main)
83 CALL (abort)
7684
77 la.pcrel ra, t0, abort
78 jirl ra, ra, 0
85#if defined PIC && !defined SHARED
86__wrap_main:
87 TAIL (main)
88#endif
7989END (ENTRY_POINT)
lib/libc/glibc/sysdeps/loongarch/sys/asm.h created+104
......@@ -0,0 +1,104 @@
1/* Miscellaneous macros.
2 Copyright (C) 2022-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library. If not, see
17 <https://www.gnu.org/licenses/>. */
18
19#ifndef _SYS_ASM_H
20#define _SYS_ASM_H
21
22#include <sys/regdef.h>
23#include <sysdeps/generic/sysdep.h>
24
25/* Macros to handle different pointer/register sizes for 32/64-bit code. */
26#if __loongarch_grlen == 64
27#define SZREG 8
28#define REG_L ld.d
29#define REG_S st.d
30#define SRLI srli.d
31#define SLLI slli.d
32#define ADDI addi.d
33#define ADD add.d
34#define SUB sub.d
35#define LI li.d
36#define BSTRINS bstrins.d
37
38#elif __loongarch_grlen == 32
39
40#define SZREG 4
41#define REG_L ld.w
42#define REG_S st.w
43#define SRLI srli.w
44#define SLLI slli.w
45#define ADDI addi.w
46#define ADD add.w
47#define SUB sub.w
48#define LI li.w
49#define BSTRINS bstrins.w
50
51#else
52#error __loongarch_grlen must equal 32 or 64
53#endif
54
55#if __loongarch_frlen == 64
56 #define SZFREG 8
57 #define FREG_L fld.d
58 #define FREG_S fst.d
59#elif __loongarch_frlen == 32
60 #define SZFREG 4
61 #define FREG_L fld.s
62 #define FREG_S fst.s
63#endif
64
65#define SZVREG 16
66#define SZXREG 32
67
68/* Declare leaf routine.
69 The usage of macro LEAF/ENTRY is as follows:
70 1. LEAF(fcn) -- the align value of fcn is .align 3 (default value)
71 2. LEAF(fcn, 6) -- the align value of fcn is .align 6
72*/
73#define LEAF_IMPL(symbol, aln, ...) \
74 .text; \
75 .globl symbol; \
76 .align aln; \
77 .type symbol, @function; \
78symbol: \
79 cfi_startproc;
80
81
82#define LEAF(...) LEAF_IMPL(__VA_ARGS__, 3)
83#define ENTRY(...) LEAF(__VA_ARGS__)
84
85#define LEAF_NO_ALIGN(symbol) \
86 .text; \
87 .globl symbol; \
88 .type symbol, @function; \
89symbol: \
90 cfi_startproc;
91
92#define ENTRY_NO_ALIGN(symbol) LEAF_NO_ALIGN(symbol)
93
94
95/* Mark end of function. */
96#undef END
97#define END(function) \
98 cfi_endproc; \
99 .size function, .- function;
100
101/* Stack alignment. */
102#define ALMASK ~15
103
104#endif /* sys/asm.h */
lib/libc/glibc/sysdeps/loongarch/sysdep.h created+94
......@@ -0,0 +1,94 @@
1/* Macros for LoongArch.
2 Copyright (C) 2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library. If not, see
17 <https://www.gnu.org/licenses/>. */
18
19#ifndef _LOONGARCH_SYSDEP_H
20#define _LOONGARCH_SYSDEP_H
21
22#if __loongarch_grlen == 64
23
24#define PTRLOG 3
25/* Align reg to 2^n. Used in C. */
26#define REG_ALIGN_C(reg, n) \
27 "bstrins.d\t" __STRING(reg) ", $zero, (" __STRING(n) "-1), 0"
28
29#elif __loongarch_grlen == 32
30
31#define PTRLOG 2
32#define REG_ALIGN_C(reg, n) \
33 "srli.w\t" __STRING(reg)", " __STRING(reg)", " __STRING(n) "\n\t" \
34 "slli.w\t" __STRING(reg)", " __STRING(reg)", " __STRING(n)
35
36#else
37#error __loongarch_grlen must equal 32 or 64
38#endif
39
40#ifdef __ASSEMBLER__
41
42/* Stack alignment bytes. */
43#define STACK_ALIGN 16
44
45/* Macros to handle different pointer/register sizes for 32/64-bit code. */
46#if __loongarch_grlen == 64
47#define SRAI srai.d
48
49/* Align reg to 2^n. Used in assembly. */
50#define REG_ALIGN_ASM(reg, n) bstrins.d reg, zero, (n-1), 0
51
52#define LOAD_LOCAL(reg, sym) \
53 pcalau12i reg, %pc_hi20(sym); \
54 ld.d reg, reg, %pc_lo12(sym);
55
56#define LOAD_GLOBAL(reg, sym) \
57 la.got reg, sym; \
58 ld.d reg, reg, 0;
59
60#define LA_GOT(reg, sym) la.got reg, t0, sym
61
62#define CALL(sym) call36 sym
63#define TAIL(sym) tail36 t0, sym
64
65#elif __loongarch_grlen == 32 /* __loongarch_grlen == 64 */
66
67#define SRAI srai.w
68
69/* LA32R not have bstrins.w, use srli.w and slli.w on both LA32S and LA32R. */
70#define REG_ALIGN_ASM(reg, n) \
71 srli.w reg, reg, n; \
72 slli.w reg, reg, n;
73
74#define LOAD_LOCAL(reg, sym) \
75 1: pcaddu12i reg, %pcadd_hi20(sym); \
76 ld.w reg, reg, %pcadd_lo12(1b);
77
78#define LOAD_GLOBAL(reg, sym) \
79 1: pcaddu12i reg, %got_pcadd_hi20(sym); \
80 ld.w reg, reg, %pcadd_lo12(1b); \
81 ld.w reg, reg, 0;
82
83#define LA_GOT(reg, sym) la.got reg, sym
84
85#define CALL(sym) call30 sym
86#define TAIL(sym) tail30 t0, sym
87
88#else /* __loongarch_grlen == 64 */
89#error __loongarch_grlen must equal 32 or 64
90#endif /* __loongarch_grlen == 64 */
91
92#endif /* __ASSEMBLER__ */
93
94#endif /* _LOONGARCH_SYSDEP_H */
lib/libc/glibc/sysdeps/mach/libc-lock.h+10-10
......@@ -145,16 +145,16 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
145145#define __rtld_lock_unlock_recursive(NAME) \
146146 __libc_lock_unlock_recursive (NAME)
147147
148/* XXX for now */
149#define __libc_rwlock_define __libc_lock_define
150#define __libc_rwlock_define_initialized __libc_lock_define_initialized
151#define __libc_rwlock_init __libc_lock_init
152#define __libc_rwlock_fini __libc_lock_fini
153#define __libc_rwlock_rdlock __libc_lock_lock
154#define __libc_rwlock_wrlock __libc_lock_lock
155#define __libc_rwlock_tryrdlock __libc_lock_trylock
156#define __libc_rwlock_trywrlock __libc_lock_trylock
157#define __libc_rwlock_unlock __libc_lock_unlock
148/* XXX for now, waiting for a futex-based pthread_rwlock implementation */
149#define __mach_rwlock_define __libc_lock_define
150#define __mach_rwlock_define_initialized __libc_lock_define_initialized
151#define __mach_rwlock_init __libc_lock_init
152#define __mach_rwlock_fini __libc_lock_fini
153#define __mach_rwlock_rdlock __libc_lock_lock
154#define __mach_rwlock_wrlock __libc_lock_lock
155#define __mach_rwlock_tryrdlock __libc_lock_trylock
156#define __mach_rwlock_trywrlock __libc_lock_trylock
157#define __mach_rwlock_unlock __libc_lock_unlock
158158
159159struct __libc_cleanup_frame
160160{
lib/libc/glibc/sysdeps/s390/s390-64/start-2.33.S deleted-107
......@@ -1,107 +0,0 @@
1/* Startup code compliant to the 64 bit S/390 ELF ABI.
2 Copyright (C) 2001-2020 Free Software Foundation, Inc.
3 Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
4 This file is part of the GNU C Library.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 In addition to the permissions in the GNU Lesser General Public
12 License, the Free Software Foundation gives you unlimited
13 permission to link the compiled version of this file with other
14 programs, and to distribute those programs without any restriction
15 coming from the use of this file. (The GNU Lesser General Public
16 License restrictions do apply in other respects; for example, they
17 cover modification of the file, and distribution when not linked
18 into another program.)
19
20 Note that people who make modified versions of this file are not
21 obligated to grant this special exception for their modified
22 versions; it is their choice whether to do so. The GNU Lesser
23 General Public License gives permission to release a modified
24 version without this exception; this exception also makes it
25 possible to release a modified version which carries forward this
26 exception.
27
28 The GNU C Library is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
31 Lesser General Public License for more details.
32
33 You should have received a copy of the GNU Lesser General Public
34 License along with the GNU C Library; if not, see
35 <https://www.gnu.org/licenses/>. */
36
37#include <sysdep.h>
38
39/*
40 This is the canonical entry point, usually the first thing in the text
41 segment. Most registers' values are unspecified, except for:
42
43 %r14 Contains a function pointer to be registered with `atexit'.
44 This is how the dynamic linker arranges to have DT_FINI
45 functions called for shared libraries that have been loaded
46 before this code runs.
47
48 %r15 The stack contains the arguments and environment:
49 0(%r15) argc
50 8(%r15) argv[0]
51 ...
52 (8*argc)(%r15) NULL
53 (8*(argc+1))(%r15) envp[0]
54 ...
55 NULL
56*/
57
58 .text
59 .globl _start
60 .type _start,@function
61_start:
62 cfi_startproc
63 /* Mark r14 as undefined in order to stop unwinding here! */
64 cfi_undefined (r14)
65 /* Load argc and argv from stack. */
66 la %r4,8(%r15) # get argv
67 lg %r3,0(%r15) # get argc
68
69 /* Align the stack to a double word boundary. */
70 lghi %r0,-16
71 ngr %r15,%r0
72
73 /* Setup a stack frame and a parameter area. */
74 aghi %r15,-176 # make room on stack
75 xc 0(8,%r15),0(%r15) # clear back-chain
76
77 /* Set up arguments for __libc_start_main:
78 main, argc, argv, envp, _init, _fini, rtld_fini, stack_end
79 Note that envp will be determined later in __libc_start_main.
80 */
81 stmg %r14,%r15,160(%r15) # store rtld_fini/stack_end to parameter area
82 la %r7,160(%r15)
83 larl %r6,__libc_csu_fini # load pointer to __libc_csu_fini
84 larl %r5,__libc_csu_init # load pointer to __libc_csu_init
85
86 /* Ok, now branch to the libc main routine. */
87#ifdef PIC
88 larl %r2,main@GOTENT # load pointer to main
89 lg %r2,0(%r2)
90 brasl %r14,__libc_start_main@plt
91#else
92 larl %r2,main # load pointer to main
93 brasl %r14,__libc_start_main
94#endif
95
96 /* Crash if __libc_start_main returns. */
97 .word 0
98
99 cfi_endproc
100
101 /* Define a symbol for the first piece of initialized data. */
102 .data
103 .globl __data_start
104__data_start:
105 .long 0
106 .weak data_start
107 data_start = __data_start
lib/libc/glibc/sysdeps/s390/s390-64/start.S deleted-134
......@@ -1,134 +0,0 @@
1/* Startup code compliant to the 64 bit S/390 ELF ABI.
2 Copyright (C) 2001-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 In addition to the permissions in the GNU Lesser General Public
11 License, the Free Software Foundation gives you unlimited
12 permission to link the compiled version of this file with other
13 programs, and to distribute those programs without any restriction
14 coming from the use of this file. (The GNU Lesser General Public
15 License restrictions do apply in other respects; for example, they
16 cover modification of the file, and distribution when not linked
17 into another program.)
18
19 Note that people who make modified versions of this file are not
20 obligated to grant this special exception for their modified
21 versions; it is their choice whether to do so. The GNU Lesser
22 General Public License gives permission to release a modified
23 version without this exception; this exception also makes it
24 possible to release a modified version which carries forward this
25 exception.
26
27 The GNU C Library is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 Lesser General Public License for more details.
31
32 You should have received a copy of the GNU Lesser General Public
33 License along with the GNU C Library; if not, see
34 <https://www.gnu.org/licenses/>. */
35
36#include <sysdep.h>
37
38/*
39 This is the canonical entry point, usually the first thing in the text
40 segment. Most registers' values are unspecified, except for:
41
42 %r14 Contains a function pointer to be registered with `atexit'.
43 This is how the dynamic linker arranges to have DT_FINI
44 functions called for shared libraries that have been loaded
45 before this code runs.
46
47 %r15 The stack contains the arguments and environment:
48 0(%r15) argc
49 8(%r15) argv[0]
50 ...
51 (8*argc)(%r15) NULL
52 (8*(argc+1))(%r15) envp[0]
53 ...
54 NULL
55*/
56
57 .text
58 .globl _start
59 .type _start,@function
60_start:
61 cfi_startproc
62 /* Mark r14 as undefined in order to stop unwinding here! */
63 cfi_undefined (r14)
64 /* Load argc and argv from stack. */
65 la %r4,8(%r15) # get argv
66 lg %r3,0(%r15) # get argc
67
68 /* Align the stack to a double word boundary. */
69 lghi %r0,-16
70 ngr %r15,%r0
71
72 /* Setup a stack frame and a parameter area. */
73 aghi %r15,-176 # make room on stack
74 xc 0(8,%r15),0(%r15) # clear back-chain
75
76 /* Set up arguments for __libc_start_main:
77 main, argc, argv, envp, _init, _fini, rtld_fini, stack_end
78 Note that envp will be determined later in __libc_start_main.
79 */
80 stmg %r14,%r15,160(%r15) # store rtld_fini/stack_end to parameter area
81 la %r7,160(%r15)
82 lghi %r6,0 # Used to be fini.
83 lghi %r5,0 # Used to be init.
84
85 /* Ok, now branch to the libc main routine. */
86#ifdef PIC
87# ifdef SHARED
88 /* Used for dynamic linked position independent executable.
89 => Scrt1.o */
90 larl %r2,main@GOTENT # load pointer to main
91 lg %r2,0(%r2)
92# else
93 /* Used for dynamic linked position dependent executable.
94 => crt1.o (glibc configured without --disable-default-pie:
95 PIC is defined)
96 Or for static linked position independent executable.
97 => rcrt1.o (only available if glibc configured without
98 --disable-default-pie: PIC is defined) */
99 larl %r2,__wrap_main
100# endif
101 brasl %r14,__libc_start_main@plt
102#else
103 /* Used for dynamic/static linked position dependent executable.
104 => crt1.o (glibc configured with --disable-default-pie:
105 PIC and SHARED are not defined) */
106 larl %r2,main # load pointer to main
107 brasl %r14,__libc_start_main
108#endif
109
110 /* Crash if __libc_start_main returns. */
111 .word 0
112
113 cfi_endproc
114
115#if defined PIC && !defined SHARED
116 /* When main is not defined in the executable but in a shared library
117 then a wrapper is needed in crt1.o of the static-pie enabled libc,
118 because crt1.o and rcrt1.o share code and the later must avoid the
119 use of GOT relocations before __libc_start_main is called. */
120__wrap_main:
121 cfi_startproc
122 larl %r1,main@GOTENT # load pointer to main
123 lg %r1,0(%r1)
124 br %r1
125 cfi_endproc
126#endif
127
128 /* Define a symbol for the first piece of initialized data. */
129 .data
130 .globl __data_start
131__data_start:
132 .long 0
133 .weak data_start
134 data_start = __data_start
lib/libc/glibc/sysdeps/s390/s390-64/sysdep.h deleted-93
......@@ -1,93 +0,0 @@
1/* Assembler macros for 64 bit S/390.
2 Copyright (C) 2001-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#include <sysdeps/generic/sysdep.h>
20
21#ifdef __ASSEMBLER__
22
23/* Syntactic details of assembler. */
24
25/* ELF uses byte-counts for .align, most others use log2 of count of bytes. */
26#define ALIGNARG(log2) 1<<log2
27#define ASM_SIZE_DIRECTIVE(name) .size name,.-name;
28
29
30/* Define an entry point visible from C. */
31#define ENTRY(name) \
32 .globl C_SYMBOL_NAME(name); \
33 .type C_SYMBOL_NAME(name),@function; \
34 .align ALIGNARG(4); \
35 C_LABEL(name) \
36 cfi_startproc; \
37 CALL_MCOUNT
38
39#undef END
40#define END(name) \
41 cfi_endproc; \
42 ASM_SIZE_DIRECTIVE(name) \
43
44/* If compiled for profiling, call `mcount' at the start of each function. */
45#ifdef PROF
46#ifdef PIC
47#define CALL_MCOUNT \
48 lgr 0,14 ; larl 1,0f ; brasl 14,_mcount@PLT ; lgr 14,0 ; \
49 .data ; .align 4 ; 0: .long 0 ; .text ;
50#else
51#define CALL_MCOUNT \
52 lgr 0,14 ; larl 1,0f ; brasl 14,_mcount ; lgr 14,0 ; \
53 .data ; .align 4 ; 0: .long 0 ; .text ;
54#endif
55#else
56#define CALL_MCOUNT /* Do nothing. */
57#endif
58
59/* Since C identifiers are not normally prefixed with an underscore
60 on this system, the asm identifier `syscall_error' intrudes on the
61 C name space. Make sure we use an innocuous name. */
62#define syscall_error __syscall_error
63#define mcount _mcount
64
65#undef PSEUDO
66#define PSEUDO(name, syscall_name, args) \
67lose: SYSCALL_PIC_SETUP \
68 jg JUMPTARGET(syscall_error); \
69 .globl syscall_error; \
70 ENTRY (name) \
71 DO_CALL (syscall_name, args); \
72 jm lose
73
74#undef PSEUDO_END
75#define PSEUDO_END(name) \
76 END (name)
77
78#undef JUMPTARGET
79#ifdef SHARED
80#define JUMPTARGET(name) name##@PLT
81#define SYSCALL_PIC_SETUP \
82 larl %r12,_GLOBAL_OFFSET_TABLE_
83#else
84#define JUMPTARGET(name) name
85#define SYSCALL_PIC_SETUP /* Nothing. */
86#endif
87
88/* Local label name for asm code. */
89#ifndef L
90#define L(name) .L##name
91#endif
92
93#endif /* __ASSEMBLER__ */
lib/libc/glibc/sysdeps/s390/start-2.33.S created+107
......@@ -0,0 +1,107 @@
1/* Startup code compliant to the 64 bit S/390 ELF ABI.
2 Copyright (C) 2001-2020 Free Software Foundation, Inc.
3 Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
4 This file is part of the GNU C Library.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 In addition to the permissions in the GNU Lesser General Public
12 License, the Free Software Foundation gives you unlimited
13 permission to link the compiled version of this file with other
14 programs, and to distribute those programs without any restriction
15 coming from the use of this file. (The GNU Lesser General Public
16 License restrictions do apply in other respects; for example, they
17 cover modification of the file, and distribution when not linked
18 into another program.)
19
20 Note that people who make modified versions of this file are not
21 obligated to grant this special exception for their modified
22 versions; it is their choice whether to do so. The GNU Lesser
23 General Public License gives permission to release a modified
24 version without this exception; this exception also makes it
25 possible to release a modified version which carries forward this
26 exception.
27
28 The GNU C Library is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
31 Lesser General Public License for more details.
32
33 You should have received a copy of the GNU Lesser General Public
34 License along with the GNU C Library; if not, see
35 <https://www.gnu.org/licenses/>. */
36
37#include <sysdep.h>
38
39/*
40 This is the canonical entry point, usually the first thing in the text
41 segment. Most registers' values are unspecified, except for:
42
43 %r14 Contains a function pointer to be registered with `atexit'.
44 This is how the dynamic linker arranges to have DT_FINI
45 functions called for shared libraries that have been loaded
46 before this code runs.
47
48 %r15 The stack contains the arguments and environment:
49 0(%r15) argc
50 8(%r15) argv[0]
51 ...
52 (8*argc)(%r15) NULL
53 (8*(argc+1))(%r15) envp[0]
54 ...
55 NULL
56*/
57
58 .text
59 .globl _start
60 .type _start,@function
61_start:
62 cfi_startproc
63 /* Mark r14 as undefined in order to stop unwinding here! */
64 cfi_undefined (r14)
65 /* Load argc and argv from stack. */
66 la %r4,8(%r15) # get argv
67 lg %r3,0(%r15) # get argc
68
69 /* Align the stack to a double word boundary. */
70 lghi %r0,-16
71 ngr %r15,%r0
72
73 /* Setup a stack frame and a parameter area. */
74 aghi %r15,-176 # make room on stack
75 xc 0(8,%r15),0(%r15) # clear back-chain
76
77 /* Set up arguments for __libc_start_main:
78 main, argc, argv, envp, _init, _fini, rtld_fini, stack_end
79 Note that envp will be determined later in __libc_start_main.
80 */
81 stmg %r14,%r15,160(%r15) # store rtld_fini/stack_end to parameter area
82 la %r7,160(%r15)
83 larl %r6,__libc_csu_fini # load pointer to __libc_csu_fini
84 larl %r5,__libc_csu_init # load pointer to __libc_csu_init
85
86 /* Ok, now branch to the libc main routine. */
87#ifdef PIC
88 larl %r2,main@GOTENT # load pointer to main
89 lg %r2,0(%r2)
90 brasl %r14,__libc_start_main@plt
91#else
92 larl %r2,main # load pointer to main
93 brasl %r14,__libc_start_main
94#endif
95
96 /* Crash if __libc_start_main returns. */
97 .word 0
98
99 cfi_endproc
100
101 /* Define a symbol for the first piece of initialized data. */
102 .data
103 .globl __data_start
104__data_start:
105 .long 0
106 .weak data_start
107 data_start = __data_start
lib/libc/glibc/sysdeps/s390/start.S created+134
......@@ -0,0 +1,134 @@
1/* Startup code compliant to the 64 bit S/390 ELF ABI.
2 Copyright (C) 2001-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 In addition to the permissions in the GNU Lesser General Public
11 License, the Free Software Foundation gives you unlimited
12 permission to link the compiled version of this file with other
13 programs, and to distribute those programs without any restriction
14 coming from the use of this file. (The GNU Lesser General Public
15 License restrictions do apply in other respects; for example, they
16 cover modification of the file, and distribution when not linked
17 into another program.)
18
19 Note that people who make modified versions of this file are not
20 obligated to grant this special exception for their modified
21 versions; it is their choice whether to do so. The GNU Lesser
22 General Public License gives permission to release a modified
23 version without this exception; this exception also makes it
24 possible to release a modified version which carries forward this
25 exception.
26
27 The GNU C Library is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 Lesser General Public License for more details.
31
32 You should have received a copy of the GNU Lesser General Public
33 License along with the GNU C Library; if not, see
34 <https://www.gnu.org/licenses/>. */
35
36#include <sysdep.h>
37
38/*
39 This is the canonical entry point, usually the first thing in the text
40 segment. Most registers' values are unspecified, except for:
41
42 %r14 Contains a function pointer to be registered with `atexit'.
43 This is how the dynamic linker arranges to have DT_FINI
44 functions called for shared libraries that have been loaded
45 before this code runs.
46
47 %r15 The stack contains the arguments and environment:
48 0(%r15) argc
49 8(%r15) argv[0]
50 ...
51 (8*argc)(%r15) NULL
52 (8*(argc+1))(%r15) envp[0]
53 ...
54 NULL
55*/
56
57 .text
58 .globl _start
59 .type _start,@function
60_start:
61 cfi_startproc
62 /* Mark r14 as undefined in order to stop unwinding here! */
63 cfi_undefined (r14)
64 /* Load argc and argv from stack. */
65 la %r4,8(%r15) # get argv
66 lg %r3,0(%r15) # get argc
67
68 /* Align the stack to a double word boundary. */
69 lghi %r0,-16
70 ngr %r15,%r0
71
72 /* Setup a stack frame and a parameter area. */
73 aghi %r15,-176 # make room on stack
74 xc 0(8,%r15),0(%r15) # clear back-chain
75
76 /* Set up arguments for __libc_start_main:
77 main, argc, argv, envp, _init, _fini, rtld_fini, stack_end
78 Note that envp will be determined later in __libc_start_main.
79 */
80 stmg %r14,%r15,160(%r15) # store rtld_fini/stack_end to parameter area
81 la %r7,160(%r15)
82 lghi %r6,0 # Used to be fini.
83 lghi %r5,0 # Used to be init.
84
85 /* Ok, now branch to the libc main routine. */
86#ifdef PIC
87# ifdef SHARED
88 /* Used for dynamic linked position independent executable.
89 => Scrt1.o */
90 larl %r2,main@GOTENT # load pointer to main
91 lg %r2,0(%r2)
92# else
93 /* Used for dynamic linked position dependent executable.
94 => crt1.o (glibc configured without --disable-default-pie:
95 PIC is defined)
96 Or for static linked position independent executable.
97 => rcrt1.o (only available if glibc configured without
98 --disable-default-pie: PIC is defined) */
99 larl %r2,__wrap_main
100# endif
101 brasl %r14,__libc_start_main@plt
102#else
103 /* Used for dynamic/static linked position dependent executable.
104 => crt1.o (glibc configured with --disable-default-pie:
105 PIC and SHARED are not defined) */
106 larl %r2,main # load pointer to main
107 brasl %r14,__libc_start_main
108#endif
109
110 /* Crash if __libc_start_main returns. */
111 .word 0
112
113 cfi_endproc
114
115#if defined PIC && !defined SHARED
116 /* When main is not defined in the executable but in a shared library
117 then a wrapper is needed in crt1.o of the static-pie enabled libc,
118 because crt1.o and rcrt1.o share code and the later must avoid the
119 use of GOT relocations before __libc_start_main is called. */
120__wrap_main:
121 cfi_startproc
122 larl %r1,main@GOTENT # load pointer to main
123 lg %r1,0(%r1)
124 br %r1
125 cfi_endproc
126#endif
127
128 /* Define a symbol for the first piece of initialized data. */
129 .data
130 .globl __data_start
131__data_start:
132 .long 0
133 .weak data_start
134 data_start = __data_start
lib/libc/glibc/sysdeps/s390/sysdep.h created+93
......@@ -0,0 +1,93 @@
1/* Assembler macros for 64 bit S/390.
2 Copyright (C) 2001-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#include <sysdeps/generic/sysdep.h>
20
21#ifdef __ASSEMBLER__
22
23/* Syntactic details of assembler. */
24
25/* ELF uses byte-counts for .align, most others use log2 of count of bytes. */
26#define ALIGNARG(log2) 1<<log2
27#define ASM_SIZE_DIRECTIVE(name) .size name,.-name;
28
29
30/* Define an entry point visible from C. */
31#define ENTRY(name) \
32 .globl C_SYMBOL_NAME(name); \
33 .type C_SYMBOL_NAME(name),@function; \
34 .align ALIGNARG(4); \
35 C_LABEL(name) \
36 cfi_startproc; \
37 CALL_MCOUNT
38
39#undef END
40#define END(name) \
41 cfi_endproc; \
42 ASM_SIZE_DIRECTIVE(name) \
43
44/* If compiled for profiling, call `mcount' at the start of each function. */
45#ifdef PROF
46#ifdef PIC
47#define CALL_MCOUNT \
48 lgr 0,14 ; larl 1,0f ; brasl 14,_mcount@PLT ; lgr 14,0 ; \
49 .data ; .align 4 ; 0: .long 0 ; .text ;
50#else
51#define CALL_MCOUNT \
52 lgr 0,14 ; larl 1,0f ; brasl 14,_mcount ; lgr 14,0 ; \
53 .data ; .align 4 ; 0: .long 0 ; .text ;
54#endif
55#else
56#define CALL_MCOUNT /* Do nothing. */
57#endif
58
59/* Since C identifiers are not normally prefixed with an underscore
60 on this system, the asm identifier `syscall_error' intrudes on the
61 C name space. Make sure we use an innocuous name. */
62#define syscall_error __syscall_error
63#define mcount _mcount
64
65#undef PSEUDO
66#define PSEUDO(name, syscall_name, args) \
67lose: SYSCALL_PIC_SETUP \
68 jg JUMPTARGET(syscall_error); \
69 .globl syscall_error; \
70 ENTRY (name) \
71 DO_CALL (syscall_name, args); \
72 jm lose
73
74#undef PSEUDO_END
75#define PSEUDO_END(name) \
76 END (name)
77
78#undef JUMPTARGET
79#ifdef SHARED
80#define JUMPTARGET(name) name##@PLT
81#define SYSCALL_PIC_SETUP \
82 larl %r12,_GLOBAL_OFFSET_TABLE_
83#else
84#define JUMPTARGET(name) name
85#define SYSCALL_PIC_SETUP /* Nothing. */
86#endif
87
88/* Local label name for asm code. */
89#ifndef L
90#define L(name) .L##name
91#endif
92
93#endif /* __ASSEMBLER__ */
lib/libc/glibc/sysdeps/unix/sysv/linux/kernel-features.h+6-1
......@@ -155,7 +155,7 @@
155155 similar to kernel:
156156
157157 - __ASSUME_CLONE_BACKWARDS: for variant 1.
158 - __ASSUME_CLONE_BACKWARDS2: for variant 2 (s390).
158 - __ASSUME_CLONE_BACKWARDS2: for variant 2 (s390x).
159159 - __ASSUME_CLONE_BACKWARDS3: for variant 3 (microblaze).
160160 - __ASSUME_CLONE_DEFAULT: for variant 4.
161161 */
......@@ -266,4 +266,9 @@
266266/* zig patch: don't assume kernel version */
267267#define __ASSUME_MSEAL 0
268268
269/* The PIDFD_GET_INFO ioctl was introduced across all architectures in Linux
270 6.13. */
271/* zig patch: don't assume kernel version */
272#define __ASSUME_PIDFD_GET_INFO 0
273
269274#endif /* kernel-features.h */
lib/libc/glibc/sysdeps/unix/sysv/linux/loongarch/sysdep.h+25-6
......@@ -19,6 +19,7 @@
1919#ifndef _LINUX_LOONGARCH_SYSDEP_H
2020#define _LINUX_LOONGARCH_SYSDEP_H 1
2121
22#include <sysdeps/loongarch/sysdep.h>
2223#include <sysdeps/unix/sysv/linux/sysdep.h>
2324#include <sysdeps/unix/sysdep.h>
2425#include <tls.h>
......@@ -34,9 +35,9 @@
3435#undef PSEUDO
3536#define PSEUDO(name, syscall_name, args) \
3637 ENTRY (name); \
37 li.d a7, SYS_ify (syscall_name); \
38 LI a7, SYS_ify (syscall_name); \
3839 syscall 0; \
39 li.d a7, -4096; \
40 LI a7, -4096; \
4041 bltu a7, a0, .Lsyscall_error##name;
4142
4243#undef PSEUDO_END
......@@ -52,16 +53,16 @@
5253 .Lsyscall_error##name : la t0, rtld_errno; \
5354 sub.w a0, zero, a0; \
5455 st.w a0, t0, 0; \
55 li.d a0, -1;
56 LI a0, -1;
5657
5758#else
5859
5960#define SYSCALL_ERROR_HANDLER(name) \
6061 .Lsyscall_error##name : la.tls.ie t0, errno; \
61 add.d t0, tp, t0; \
62 ADD t0, tp, t0; \
6263 sub.w a0, zero, a0; \
6364 st.w a0, t0, 0; \
64 li.d a0, -1;
65 LI a0, -1;
6566
6667#endif
6768#else
......@@ -74,7 +75,7 @@
7475#undef PSEUDO_NEORRNO
7576#define PSEUDO_NOERRNO(name, syscall_name, args) \
7677 ENTRY (name); \
77 li.d a7, SYS_ify (syscall_name); \
78 LI a7, SYS_ify (syscall_name); \
7879 syscall 0;
7980
8081#undef PSEUDO_END_NOERRNO
......@@ -85,11 +86,17 @@
8586
8687/* Performs a system call, returning the error code. */
8788#undef PSEUDO_ERRVAL
89#if __loongarch_grlen == 64
8890#define PSEUDO_ERRVAL(name, syscall_name, args) \
8991 PSEUDO_NOERRNO (name, syscall_name, args); \
9092 slli.d a0, a0, 32; \
9193 srai.d a0, a0, 32; /* sign_ext */ \
9294 sub.d a0, zero, a0;
95#else
96#define PSEUDO_ERRVAL(name, syscall_name, args) \
97 PSEUDO_NOERRNO (name, syscall_name, args); \
98 sub.w a0, zero, a0;
99#endif
93100
94101#undef PSEUDO_END_ERRVAL
95102#define PSEUDO_END_ERRVAL(name) END (name);
......@@ -109,6 +116,18 @@
109116#undef SYS_ify
110117#define SYS_ify(syscall_name) __NR_##syscall_name
111118
119#if __WORDSIZE == 32
120/* Workarounds for generic code needing to handle 64-bit time_t. */
121#define __NR_clock_getres __NR_clock_getres_time64
122#define __NR_futex __NR_futex_time64
123#define __NR_ppoll __NR_ppoll_time64
124#define __NR_pselect6 __NR_pselect6_time64
125#define __NR_recvmmsg __NR_recvmmsg_time64
126#define __NR_rt_sigtimedwait __NR_rt_sigtimedwait_time64
127#define __NR_semtimedop __NR_semtimedop_time64
128#define __NR_utimensat __NR_utimensat_time64
129#endif /* __WORDSIZE == 32 */
130
112131#ifndef __ASSEMBLER__
113132
114133#define VDSO_NAME "LINUX_5.10"
lib/libc/glibc/sysdeps/unix/sysv/linux/s390/bits/typesizes.h+14-22
......@@ -57,42 +57,34 @@
5757#define __TIMER_T_TYPE void *
5858#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE
5959#define __FSID_T_TYPE struct { int __val[2]; }
60#if defined __GNUC__ && __GNUC__ <= 2
61/* Compatibility with g++ 2.95.x. */
62#define __SSIZE_T_TYPE __SWORD_TYPE
63#else
64/* size_t is unsigned long int on s390 -m31. */
65#define __SSIZE_T_TYPE __SLONGWORD_TYPE
66#endif
60
61/* With s390-32, __SSIZE_T_TYPE was __SWORD_TYPE for compatibility with
62 g++ 2.95.x. Afterwards __SLONGWORD_TYPE was needed as size_t was
63 unsigned long int on s390-32.
64 Now as only s390-64 exists, __SWORD_TYPE can be used as also used in the
65 generic version as both types result in long int. */
66#define __SSIZE_T_TYPE __SWORD_TYPE
67
6768#define __SYSCALL_SLONG_TYPE __SLONGWORD_TYPE
6869#define __SYSCALL_ULONG_TYPE __ULONGWORD_TYPE
69#define __CPU_MASK_TYPE __ULONGWORD_TYPE
70#define __CPU_MASK_TYPE __ULONGWORD_TYPE
7071
71#ifdef __s390x__
7272/* Tell the libc code that off_t and off64_t are actually the same type
7373 for all ABI purposes, even if possibly expressed as different base types
7474 for C type-checking purposes. */
75# define __OFF_T_MATCHES_OFF64_T 1
75#define __OFF_T_MATCHES_OFF64_T 1
7676
7777/* Same for ino_t and ino64_t. */
78# define __INO_T_MATCHES_INO64_T 1
78#define __INO_T_MATCHES_INO64_T 1
7979
8080/* And for __rlim_t and __rlim64_t. */
81# define __RLIM_T_MATCHES_RLIM64_T 1
81#define __RLIM_T_MATCHES_RLIM64_T 1
8282
8383/* And for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t. */
84# define __STATFS_MATCHES_STATFS64 1
84#define __STATFS_MATCHES_STATFS64 1
8585
8686/* And for getitimer, setitimer and rusage */
87# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1
88#else
89# define __RLIM_T_MATCHES_RLIM64_T 0
90
91# define __STATFS_MATCHES_STATFS64 0
92
93/* And for getitimer, setitimer and rusage */
94# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 0
95#endif
87#define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1
9688
9789/* Number of descriptors that can fit in an `fd_set'. */
9890#define __FD_SETSIZE 1024
lib/libc/glibc/sysdeps/unix/sysv/linux/s390/kernel-features.h-3
......@@ -47,9 +47,6 @@
4747# undef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
4848# undef __ASSUME_SYSVIPC_DEFAULT_IPC_64
4949#endif
50#ifndef __s390x__
51# define __ASSUME_SYSVIPC_BROKEN_MODE_T
52#endif
5350
5451#undef __ASSUME_CLONE_DEFAULT
5552#define __ASSUME_CLONE_BACKWARDS2
lib/libc/glibc/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h deleted-178
......@@ -1,178 +0,0 @@
1/* Assembler macros for 64 bit S/390.
2 Copyright (C) 2001-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#ifndef _LINUX_S390_SYSDEP_H
20#define _LINUX_S390_SYSDEP_H
21
22#include <sysdeps/s390/s390-64/sysdep.h>
23#include <sysdeps/unix/sysdep.h>
24#include <sysdeps/unix/sysv/linux/s390/sysdep.h>
25#include <sysdeps/unix/sysv/linux/sysdep.h>
26#include <dl-sysdep.h> /* For RTLD_PRIVATE_ERRNO. */
27#include <tls.h>
28
29/* For Linux we can use the system call table in the header file
30 /usr/include/asm/unistd.h
31 of the kernel. But these symbols do not follow the SYS_* syntax
32 so we have to redefine the `SYS_ify' macro here. */
33/* In newer 2.1 kernels __NR_syscall is missing so we define it here. */
34#define __NR_syscall 0
35
36#undef SYS_ify
37#define SYS_ify(syscall_name) __NR_##syscall_name
38
39#ifdef __ASSEMBLER__
40
41/* Linux uses a negative return value to indicate syscall errors, unlike
42 most Unices, which use the condition codes' carry flag.
43
44 Since version 2.1 the return value of a system call might be negative
45 even if the call succeeded. E.g., the `lseek' system call might return
46 a large offset. Therefore we must not anymore test for < 0, but test
47 for a real error by making sure the value in gpr2 is a real error
48 number. Linus said he will make sure that no syscall returns a value
49 in -1 .. -4095 as a valid result so we can safely test with -4095. */
50
51#undef PSEUDO
52#define PSEUDO(name, syscall_name, args) \
53 .text; \
54 ENTRY (name) \
55 DO_CALL (syscall_name, args); \
56 lghi %r4,-4095 ; \
57 clgr %r2,%r4 ; \
58 jgnl SYSCALL_ERROR_LABEL
59
60#undef PSEUDO_END
61#define PSEUDO_END(name) \
62 SYSCALL_ERROR_HANDLER; \
63 END (name)
64
65#undef PSEUDO_NOERRNO
66#define PSEUDO_NOERRNO(name, syscall_name, args) \
67 .text; \
68 ENTRY (name) \
69 DO_CALL (syscall_name, args)
70
71#undef PSEUDO_END_NOERRNO
72#define PSEUDO_END_NOERRNO(name) \
73 SYSCALL_ERROR_HANDLER; \
74 END (name)
75
76#undef PSEUDO_ERRVAL
77#define PSEUDO_ERRVAL(name, syscall_name, args) \
78 .text; \
79 ENTRY (name) \
80 DO_CALL (syscall_name, args); \
81 lcgr %r2,%r2
82
83#undef PSEUDO_END_ERRVAL
84#define PSEUDO_END_ERRVAL(name) \
85 SYSCALL_ERROR_HANDLER; \
86 END (name)
87
88#undef SYSCALL_ERROR_LABEL
89#ifndef PIC
90# undef SYSCALL_ERROR_LABEL
91# define SYSCALL_ERROR_LABEL syscall_error
92# define SYSCALL_ERROR_HANDLER
93#else
94# if RTLD_PRIVATE_ERRNO
95# undef SYSCALL_ERROR_LABEL
96# define SYSCALL_ERROR_LABEL 0f
97# define SYSCALL_ERROR_HANDLER \
980: larl %r1,rtld_errno; \
99 lcr %r2,%r2; \
100 st %r2,0(%r1); \
101 lghi %r2,-1; \
102 br %r14
103# elif defined _LIBC_REENTRANT
104# if IS_IN (libc)
105# define SYSCALL_ERROR_ERRNO __libc_errno
106# else
107# define SYSCALL_ERROR_ERRNO errno
108# endif
109# undef SYSCALL_ERROR_LABEL
110# define SYSCALL_ERROR_LABEL 0f
111# define SYSCALL_ERROR_HANDLER \
1120: lcr %r0,%r2; \
113 larl %r1,SYSCALL_ERROR_ERRNO@indntpoff; \
114 lg %r1,0(%r1); \
115 ear %r2,%a0; \
116 sllg %r2,%r2,32; \
117 ear %r2,%a1; \
118 st %r0,0(%r1,%r2); \
119 lghi %r2,-1; \
120 br %r14
121# else
122# undef SYSCALL_ERROR_LABEL
123# define SYSCALL_ERROR_LABEL 0f
124# define SYSCALL_ERROR_HANDLER \
1250: larl %r1,_GLOBAL_OFFSET_TABLE_; \
126 lg %r1,errno@GOT(%r1); \
127 lcr %r2,%r2; \
128 st %r2,0(%r1); \
129 lghi %r2,-1; \
130 br %r14
131# endif /* _LIBC_REENTRANT */
132#endif /* PIC */
133
134/* Linux takes system call arguments in registers:
135
136 syscall number 1 call-clobbered
137 arg 1 2 call-clobbered
138 arg 2 3 call-clobbered
139 arg 3 4 call-clobbered
140 arg 4 5 call-clobbered
141 arg 5 6 call-saved
142 arg 6 7 call-saved
143
144 (Of course a function with say 3 arguments does not have entries for
145 arguments 4 and 5.)
146 For system calls with 6 parameters a stack operation is required
147 to load the 6th parameter to register 7. Call saved register 7 is
148 moved to register 0 and back to avoid an additional stack frame.
149 */
150
151#define DO_CALL(syscall, args) \
152 .if args > 5; \
153 lgr %r0,%r7; \
154 lg %r7,160(%r15); \
155 .endif; \
156 lghi %r1,SYS_ify (syscall); \
157 svc 0; \
158 .if args > 5; \
159 lgr %r7,%r0; \
160 .endif
161
162#define ret \
163 br 14
164
165#define ret_NOERRNO \
166 br 14
167
168#define ret_ERRVAL \
169 br 14
170
171#else
172
173# undef HAVE_INTERNAL_BRK_ADDR_SYMBOL
174# define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1
175
176#endif /* __ASSEMBLER__ */
177
178#endif /* _LINUX_S390_SYSDEP_H */
lib/libc/glibc/sysdeps/unix/sysv/linux/s390/sysdep.h+186-37
......@@ -1,5 +1,5 @@
1/* Syscall definitions, Linux s390 version.
2 Copyright (C) 2019-2026 Free Software Foundation, Inc.
1/* Assembler macros for 64 bit S/390.
2 Copyright (C) 2001-2026 Free Software Foundation, Inc.
33 This file is part of the GNU C Library.
44
55 The GNU C Library is free software; you can redistribute it and/or
......@@ -14,15 +14,163 @@
1414
1515 You should have received a copy of the GNU Lesser General Public
1616 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
17 <https://www.gnu.org/licenses/>. */
1818
19#ifndef __ASSEMBLY__
19#ifndef _LINUX_S390_SYSDEP_H
20#define _LINUX_S390_SYSDEP_H
21
22#include <sysdeps/s390/sysdep.h>
23#include <sysdeps/unix/sysdep.h>
24#include <sysdeps/unix/sysv/linux/sysdep.h>
25#include <dl-sysdep.h> /* For RTLD_PRIVATE_ERRNO. */
26#include <tls.h>
27
28/* For Linux we can use the system call table in the header file
29 /usr/include/asm/unistd.h
30 of the kernel. But these symbols do not follow the SYS_* syntax
31 so we have to redefine the `SYS_ify' macro here. */
32/* In newer 2.1 kernels __NR_syscall is missing so we define it here. */
33#define __NR_syscall 0
2034
2135#undef SYS_ify
2236#define SYS_ify(syscall_name) __NR_##syscall_name
2337
24#undef INTERNAL_SYSCALL_NCS
25#define INTERNAL_SYSCALL_NCS(no, nr, args...) \
38#ifdef __ASSEMBLER__
39
40/* Linux uses a negative return value to indicate syscall errors, unlike
41 most Unices, which use the condition codes' carry flag.
42
43 Since version 2.1 the return value of a system call might be negative
44 even if the call succeeded. E.g., the `lseek' system call might return
45 a large offset. Therefore we must not anymore test for < 0, but test
46 for a real error by making sure the value in gpr2 is a real error
47 number. Linus said he will make sure that no syscall returns a value
48 in -1 .. -4095 as a valid result so we can safely test with -4095. */
49
50# undef PSEUDO
51# define PSEUDO(name, syscall_name, args) \
52 .text; \
53 ENTRY (name) \
54 DO_CALL (syscall_name, args); \
55 lghi %r4,-4095 ; \
56 clgr %r2,%r4 ; \
57 jgnl SYSCALL_ERROR_LABEL
58
59# undef PSEUDO_END
60# define PSEUDO_END(name) \
61 SYSCALL_ERROR_HANDLER; \
62 END (name)
63
64# undef PSEUDO_NOERRNO
65# define PSEUDO_NOERRNO(name, syscall_name, args) \
66 .text; \
67 ENTRY (name) \
68 DO_CALL (syscall_name, args)
69
70# undef PSEUDO_END_NOERRNO
71# define PSEUDO_END_NOERRNO(name) \
72 SYSCALL_ERROR_HANDLER; \
73 END (name)
74
75# undef PSEUDO_ERRVAL
76# define PSEUDO_ERRVAL(name, syscall_name, args) \
77 .text; \
78 ENTRY (name) \
79 DO_CALL (syscall_name, args); \
80 lcgr %r2,%r2
81
82# undef PSEUDO_END_ERRVAL
83# define PSEUDO_END_ERRVAL(name) \
84 SYSCALL_ERROR_HANDLER; \
85 END (name)
86
87# undef SYSCALL_ERROR_LABEL
88# ifndef PIC
89# undef SYSCALL_ERROR_LABEL
90# define SYSCALL_ERROR_LABEL syscall_error
91# define SYSCALL_ERROR_HANDLER
92# else
93# if RTLD_PRIVATE_ERRNO
94# undef SYSCALL_ERROR_LABEL
95# define SYSCALL_ERROR_LABEL 0f
96# define SYSCALL_ERROR_HANDLER \
970: larl %r1,rtld_errno; \
98 lcr %r2,%r2; \
99 st %r2,0(%r1); \
100 lghi %r2,-1; \
101 br %r14
102# elif defined _LIBC_REENTRANT
103# if IS_IN (libc)
104# define SYSCALL_ERROR_ERRNO __libc_errno
105# else
106# define SYSCALL_ERROR_ERRNO errno
107# endif
108# undef SYSCALL_ERROR_LABEL
109# define SYSCALL_ERROR_LABEL 0f
110# define SYSCALL_ERROR_HANDLER \
1110: lcr %r0,%r2; \
112 larl %r1,SYSCALL_ERROR_ERRNO@indntpoff; \
113 lg %r1,0(%r1); \
114 ear %r2,%a0; \
115 sllg %r2,%r2,32; \
116 ear %r2,%a1; \
117 st %r0,0(%r1,%r2); \
118 lghi %r2,-1; \
119 br %r14
120# else
121# undef SYSCALL_ERROR_LABEL
122# define SYSCALL_ERROR_LABEL 0f
123# define SYSCALL_ERROR_HANDLER \
1240: larl %r1,_GLOBAL_OFFSET_TABLE_; \
125 lg %r1,errno@GOT(%r1); \
126 lcr %r2,%r2; \
127 st %r2,0(%r1); \
128 lghi %r2,-1; \
129 br %r14
130# endif /* _LIBC_REENTRANT */
131# endif /* PIC */
132
133/* Linux takes system call arguments in registers:
134
135 syscall number 1 call-clobbered
136 arg 1 2 call-clobbered
137 arg 2 3 call-clobbered
138 arg 3 4 call-clobbered
139 arg 4 5 call-clobbered
140 arg 5 6 call-saved
141 arg 6 7 call-saved
142
143 (Of course a function with say 3 arguments does not have entries for
144 arguments 4 and 5.)
145 For system calls with 6 parameters a stack operation is required
146 to load the 6th parameter to register 7. Call saved register 7 is
147 moved to register 0 and back to avoid an additional stack frame.
148 */
149
150# define DO_CALL(syscall, args) \
151 .if args > 5; \
152 lgr %r0,%r7; \
153 lg %r7,160(%r15); \
154 .endif; \
155 lghi %r1,SYS_ify (syscall); \
156 svc 0; \
157 .if args > 5; \
158 lgr %r7,%r0; \
159 .endif
160
161# define ret \
162 br 14
163
164# define ret_NOERRNO \
165 br 14
166
167# define ret_ERRVAL \
168 br 14
169
170#else /* not __ASSEMBLER__ */
171
172# undef INTERNAL_SYSCALL_NCS
173# define INTERNAL_SYSCALL_NCS(no, nr, args...) \
26174 ({ \
27175 DECLARGS_##nr(args) \
28176 register unsigned long int _nr __asm__("1") = (unsigned long int)(no); \
......@@ -34,51 +182,52 @@
34182 : "memory" ); \
35183 _ret; })
36184
37#undef INTERNAL_SYSCALL
38#define INTERNAL_SYSCALL(name, nr, args...) \
185# undef INTERNAL_SYSCALL
186# define INTERNAL_SYSCALL(name, nr, args...) \
39187 INTERNAL_SYSCALL_NCS(__NR_##name, nr, args)
40188
41#define DECLARGS_0()
42#define DECLARGS_1(arg1) \
189# define DECLARGS_0()
190# define DECLARGS_1(arg1) \
43191 register unsigned long int gpr2 __asm__ ("2") = (unsigned long int)(arg1);
44#define DECLARGS_2(arg1, arg2) \
192# define DECLARGS_2(arg1, arg2) \
45193 DECLARGS_1(arg1) \
46194 register unsigned long int gpr3 __asm__ ("3") = (unsigned long int)(arg2);
47#define DECLARGS_3(arg1, arg2, arg3) \
195# define DECLARGS_3(arg1, arg2, arg3) \
48196 DECLARGS_2(arg1, arg2) \
49197 register unsigned long int gpr4 __asm__ ("4") = (unsigned long int)(arg3);
50#define DECLARGS_4(arg1, arg2, arg3, arg4) \
198# define DECLARGS_4(arg1, arg2, arg3, arg4) \
51199 DECLARGS_3(arg1, arg2, arg3) \
52200 register unsigned long int gpr5 __asm__ ("5") = (unsigned long int)(arg4);
53#define DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \
201# define DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \
54202 DECLARGS_4(arg1, arg2, arg3, arg4) \
55203 register unsigned long int gpr6 __asm__ ("6") = (unsigned long int)(arg5);
56#define DECLARGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \
204# define DECLARGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \
57205 DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \
58206 register unsigned long int gpr7 __asm__ ("7") = (unsigned long int)(arg6);
59207
60#define ASMFMT_0
61#define ASMFMT_1 , "0" (gpr2)
62#define ASMFMT_2 , "0" (gpr2), "d" (gpr3)
63#define ASMFMT_3 , "0" (gpr2), "d" (gpr3), "d" (gpr4)
64#define ASMFMT_4 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5)
65#define ASMFMT_5 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6)
66#define ASMFMT_6 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6), "d" (gpr7)
208# define ASMFMT_0
209# define ASMFMT_1 , "0" (gpr2)
210# define ASMFMT_2 , "0" (gpr2), "d" (gpr3)
211# define ASMFMT_3 , "0" (gpr2), "d" (gpr3), "d" (gpr4)
212# define ASMFMT_4 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5)
213# define ASMFMT_5 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6)
214# define ASMFMT_6 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6), "d" (gpr7)
67215
68#define VDSO_NAME "LINUX_2.6.29"
69#define VDSO_HASH 123718585
216# define VDSO_NAME "LINUX_2.6.29"
217# define VDSO_HASH 123718585
70218
71219/* List of system calls which are supported as vsyscalls. */
72#ifdef __s390x__
73#define HAVE_CLOCK_GETRES64_VSYSCALL "__kernel_clock_getres"
74#define HAVE_CLOCK_GETTIME64_VSYSCALL "__kernel_clock_gettime"
75#define HAVE_GETRANDOM_VSYSCALL "__kernel_getrandom"
76#else
77#define HAVE_CLOCK_GETRES_VSYSCALL "__kernel_clock_getres"
78#define HAVE_CLOCK_GETTIME_VSYSCALL "__kernel_clock_gettime"
79#endif
80#define HAVE_GETTIMEOFDAY_VSYSCALL "__kernel_gettimeofday"
81#define HAVE_GETCPU_VSYSCALL "__kernel_getcpu"
82
83#define HAVE_CLONE3_WRAPPER 1
84#endif
220# define HAVE_CLOCK_GETRES64_VSYSCALL "__kernel_clock_getres"
221# define HAVE_CLOCK_GETTIME64_VSYSCALL "__kernel_clock_gettime"
222# define HAVE_GETRANDOM_VSYSCALL "__kernel_getrandom"
223# define HAVE_GETTIMEOFDAY_VSYSCALL "__kernel_gettimeofday"
224# define HAVE_GETCPU_VSYSCALL "__kernel_getcpu"
225
226# define HAVE_CLONE3_WRAPPER 1
227
228# undef HAVE_INTERNAL_BRK_ADDR_SYMBOL
229# define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1
230
231#endif /* __ASSEMBLER__ */
232
233#endif /* _LINUX_S390_SYSDEP_H */
lib/libc/glibc/sysdeps/unix/sysv/linux/s390/xstatver.h+6-15
......@@ -1,19 +1,10 @@
11/* Versions of the 'struct stat' data structure used in compatibility xstat
22 functions. */
3
4#include <bits/wordsize.h>
5
6#if __WORDSIZE == 64
7# define _STAT_VER_KERNEL 0
8# define _STAT_VER_LINUX 1
9# define _MKNOD_VER_LINUX 0
10#else
11# define _STAT_VER_LINUX_OLD 1
12# define _STAT_VER_KERNEL 1
13# define _STAT_VER_SVR4 2
14# define _STAT_VER_LINUX 3
15# define _MKNOD_VER_LINUX 1
16# define _MKNOD_VER_SVR4 2
17#endif
3#define _STAT_VER_KERNEL 0
4#define _STAT_VER_LINUX 1
185#define _STAT_VER _STAT_VER_LINUX
6
7/* Versions of the 'xmknod' interface used in compatibility xmknod
8 functions. */
9#define _MKNOD_VER_LINUX 0
1910#define _MKNOD_VER _MKNOD_VER_LINUX
lib/libc/include/aarch64-linux-gnu/bits/hwcap.h+18-1
......@@ -55,6 +55,21 @@
5555#define HWCAP_PACA (1 << 30)
5656#define HWCAP_PACG (1UL << 31)
5757#define HWCAP_GCS (1UL << 32)
58#define HWCAP_CMPBR (1UL << 33)
59#define HWCAP_FPRCVT (1UL << 34)
60#define HWCAP_F8MM8 (1UL << 35)
61#define HWCAP_F8MM4 (1UL << 36)
62#define HWCAP_SVE_F16MM (1UL << 37)
63#define HWCAP_SVE_ELTPERM (1UL << 38)
64#define HWCAP_SVE_AES2 (1UL << 39)
65#define HWCAP_SVE_BFSCALE (1UL << 40)
66#define HWCAP_SVE2P2 (1UL << 41)
67#define HWCAP_SME2P2 (1UL << 42)
68#define HWCAP_SME_SBITPERM (1UL << 43)
69#define HWCAP_SME_AES (1UL << 44)
70#define HWCAP_SME_SFEXPA (1UL << 45)
71#define HWCAP_SME_STMOP (1UL << 46)
72#define HWCAP_SME_SMOP4 (1UL << 47)
5873
5974#define HWCAP2_DCPODP (1 << 0)
6075#define HWCAP2_SVE2 (1 << 1)
......@@ -122,4 +137,6 @@
122137#define HWCAP2_POE (1UL << 63)
123138
124139#define HWCAP3_MTE_FAR (1UL << 0)
125#define HWCAP3_MTE_STORE_ONLY (1UL << 1)
\ No newline at end of file
140#define HWCAP3_MTE_STORE_ONLY (1UL << 1)
141#define HWCAP3_LSFE (1UL << 2)
142#define HWCAP3_LS64 (1UL << 3)
\ No newline at end of file
lib/libc/include/aarch64-linux-gnu/bits/long-double.h deleted-21
......@@ -1,21 +0,0 @@
1/* Properties of long double type. ldbl-128 version.
2 Copyright (C) 2016-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19/* long double is distinct from double, so there is nothing to
20 define here. */
21#define __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI 0
\ No newline at end of file
lib/libc/include/aarch64-linux-gnu/bits/math-vector.h+8
......@@ -157,6 +157,10 @@
157157# define __DECL_SIMD_pow __DECL_SIMD_aarch64
158158# undef __DECL_SIMD_powf
159159# define __DECL_SIMD_powf __DECL_SIMD_aarch64
160# undef __DECL_SIMD_powr
161# define __DECL_SIMD_powr __DECL_SIMD_aarch64
162# undef __DECL_SIMD_powrf
163# define __DECL_SIMD_powrf __DECL_SIMD_aarch64
160164# undef __DECL_SIMD_rsqrt
161165# define __DECL_SIMD_rsqrt __DECL_SIMD_aarch64
162166# undef __DECL_SIMD_rsqrtf
......@@ -243,6 +247,7 @@ __vpcs __f32x4_t _ZGVnN4v_log2f (__f32x4_t);
243247__vpcs __f32x4_t _ZGVnN4v_log2p1f (__f32x4_t);
244248__vpcs __f32x4_t _ZGVnN4v_logp1f (__f32x4_t);
245249__vpcs __f32x4_t _ZGVnN4vv_powf (__f32x4_t, __f32x4_t);
250__vpcs __f32x4_t _ZGVnN4vv_powrf (__f32x4_t, __f32x4_t);
246251__vpcs __f32x4_t _ZGVnN4v_rsqrtf (__f32x4_t);
247252__vpcs __f32x4_t _ZGVnN4v_sinf (__f32x4_t);
248253__vpcs __f32x4_t _ZGVnN4v_sinhf (__f32x4_t);
......@@ -283,6 +288,7 @@ __vpcs __f64x2_t _ZGVnN2v_log2 (__f64x2_t);
283288__vpcs __f64x2_t _ZGVnN2v_log2p1 (__f64x2_t);
284289__vpcs __f64x2_t _ZGVnN2v_logp1 (__f64x2_t);
285290__vpcs __f64x2_t _ZGVnN2vv_pow (__f64x2_t, __f64x2_t);
291__vpcs __f64x2_t _ZGVnN2vv_powr (__f64x2_t, __f64x2_t);
286292__vpcs __f64x2_t _ZGVnN2v_rsqrt (__f64x2_t);
287293__vpcs __f64x2_t _ZGVnN2v_sin (__f64x2_t);
288294__vpcs __f64x2_t _ZGVnN2v_sinh (__f64x2_t);
......@@ -328,6 +334,7 @@ __sv_f32_t _ZGVsMxv_log2f (__sv_f32_t, __sv_bool_t);
328334__sv_f32_t _ZGVsMxv_log2p1f (__sv_f32_t, __sv_bool_t);
329335__sv_f32_t _ZGVsMxv_logp1f (__sv_f32_t, __sv_bool_t);
330336__sv_f32_t _ZGVsMxvv_powf (__sv_f32_t, __sv_f32_t, __sv_bool_t);
337__sv_f32_t _ZGVsMxvv_powrf (__sv_f32_t, __sv_f32_t, __sv_bool_t);
331338__sv_f32_t _ZGVsMxv_rsqrtf (__sv_f32_t, __sv_bool_t);
332339__sv_f32_t _ZGVsMxv_sinf (__sv_f32_t, __sv_bool_t);
333340__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);
368375__sv_f64_t _ZGVsMxv_log2p1 (__sv_f64_t, __sv_bool_t);
369376__sv_f64_t _ZGVsMxv_logp1 (__sv_f64_t, __sv_bool_t);
370377__sv_f64_t _ZGVsMxvv_pow (__sv_f64_t, __sv_f64_t, __sv_bool_t);
378__sv_f64_t _ZGVsMxvv_powr (__sv_f64_t, __sv_f64_t, __sv_bool_t);
371379__sv_f64_t _ZGVsMxv_rsqrt (__sv_f64_t, __sv_bool_t);
372380__sv_f64_t _ZGVsMxv_sin (__sv_f64_t, __sv_bool_t);
373381__sv_f64_t _ZGVsMxv_sinh (__sv_f64_t, __sv_bool_t);
lib/libc/include/aarch64-linux-gnu/bits/struct_stat.h deleted-127
......@@ -1,127 +0,0 @@
1/* Definition for struct stat.
2 Copyright (C) 2020-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library. If not, see
17 <https://www.gnu.org/licenses/>. */
18
19#if !defined _SYS_STAT_H && !defined _FCNTL_H
20# error "Never include <bits/struct_stat.h> directly; use <sys/stat.h> instead."
21#endif
22
23#ifndef _BITS_STRUCT_STAT_H
24#define _BITS_STRUCT_STAT_H 1
25
26#include <bits/endian.h>
27#include <bits/wordsize.h>
28
29#if defined __USE_FILE_OFFSET64
30# define __field64(type, type64, name) type64 name
31#elif __WORDSIZE == 64 || defined __INO_T_MATCHES_INO64_T
32# if defined __INO_T_MATCHES_INO64_T && !defined __OFF_T_MATCHES_OFF64_T
33# error "ino_t and off_t must both be the same type"
34# endif
35# define __field64(type, type64, name) type name
36#elif __BYTE_ORDER == __LITTLE_ENDIAN
37# define __field64(type, type64, name) \
38 type name __attribute__((__aligned__ (__alignof__ (type64)))); int __##name##_pad
39#else
40# define __field64(type, type64, name) \
41 int __##name##_pad __attribute__((__aligned__ (__alignof__ (type64)))); type name
42#endif
43
44struct stat
45 {
46 __dev_t st_dev; /* Device. */
47 __field64(__ino_t, __ino64_t, st_ino); /* File serial number. */
48 __mode_t st_mode; /* File mode. */
49 __nlink_t st_nlink; /* Link count. */
50 __uid_t st_uid; /* User ID of the file's owner. */
51 __gid_t st_gid; /* Group ID of the file's group.*/
52 __dev_t st_rdev; /* Device number, if device. */
53 __dev_t __pad1;
54 __field64(__off_t, __off64_t, st_size); /* Size of file, in bytes. */
55 __blksize_t st_blksize; /* Optimal block size for I/O. */
56 int __pad2;
57 __field64(__blkcnt_t, __blkcnt64_t, st_blocks); /* 512-byte blocks */
58#ifdef __USE_XOPEN2K8
59 /* Nanosecond resolution timestamps are stored in a format
60 equivalent to 'struct timespec'. This is the type used
61 whenever possible but the Unix namespace rules do not allow the
62 identifier 'timespec' to appear in the <sys/stat.h> header.
63 Therefore we have to handle the use of this header in strictly
64 standard-compliant sources special. */
65 struct timespec st_atim; /* Time of last access. */
66 struct timespec st_mtim; /* Time of last modification. */
67 struct timespec st_ctim; /* Time of last status change. */
68# define st_atime st_atim.tv_sec /* Backward compatibility. */
69# define st_mtime st_mtim.tv_sec
70# define st_ctime st_ctim.tv_sec
71#else
72 __time_t st_atime; /* Time of last access. */
73 unsigned long int st_atimensec; /* Nscecs of last access. */
74 __time_t st_mtime; /* Time of last modification. */
75 unsigned long int st_mtimensec; /* Nsecs of last modification. */
76 __time_t st_ctime; /* Time of last status change. */
77 unsigned long int st_ctimensec; /* Nsecs of last status change. */
78#endif
79 int __glibc_reserved[2];
80 };
81
82#undef __field64
83
84#ifdef __USE_LARGEFILE64
85struct stat64
86 {
87 __dev_t st_dev; /* Device. */
88 __ino64_t st_ino; /* File serial number. */
89 __mode_t st_mode; /* File mode. */
90 __nlink_t st_nlink; /* Link count. */
91 __uid_t st_uid; /* User ID of the file's owner. */
92 __gid_t st_gid; /* Group ID of the file's group.*/
93 __dev_t st_rdev; /* Device number, if device. */
94 __dev_t __pad1;
95 __off64_t st_size; /* Size of file, in bytes. */
96 __blksize_t st_blksize; /* Optimal block size for I/O. */
97 int __pad2;
98 __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */
99#ifdef __USE_XOPEN2K8
100 /* Nanosecond resolution timestamps are stored in a format
101 equivalent to 'struct timespec'. This is the type used
102 whenever possible but the Unix namespace rules do not allow the
103 identifier 'timespec' to appear in the <sys/stat.h> header.
104 Therefore we have to handle the use of this header in strictly
105 standard-compliant sources special. */
106 struct timespec st_atim; /* Time of last access. */
107 struct timespec st_mtim; /* Time of last modification. */
108 struct timespec st_ctim; /* Time of last status change. */
109#else
110 __time_t st_atime; /* Time of last access. */
111 unsigned long int st_atimensec; /* Nscecs of last access. */
112 __time_t st_mtime; /* Time of last modification. */
113 unsigned long int st_mtimensec; /* Nsecs of last modification. */
114 __time_t st_ctime; /* Time of last status change. */
115 unsigned long int st_ctimensec; /* Nsecs of last status change. */
116#endif
117 int __glibc_reserved[2];
118 };
119#endif
120
121/* Tell code we have these members. */
122#define _STATBUF_ST_BLKSIZE
123#define _STATBUF_ST_RDEV
124/* Nanosecond resolution time values are supported. */
125#define _STATBUF_ST_NSEC
126
127#endif /* _BITS_STRUCT_STAT_H */
\ No newline at end of file
lib/libc/include/aarch64-linux-gnu/bits/timesize.h deleted-20
......@@ -1,20 +0,0 @@
1/* Bit size of the time_t type at glibc build time, general case.
2 Copyright (C) 2018-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19/* Size in bits of the 'time_t' type of the default ABI. */
20#define __TIMESIZE 64
\ No newline at end of file
lib/libc/include/aarch64-linux-gnu/finclude/math-vector-fortran.h+80-78
......@@ -16,81 +16,83 @@
1616! License along with the GNU C Library; if not, see
1717! <https://www.gnu.org/licenses/>.
1818
19!GCC$ builtin (acos) attributes simd (notinbranch)
20!GCC$ builtin (acosf) attributes simd (notinbranch)
21!GCC$ builtin (acosh) attributes simd (notinbranch)
22!GCC$ builtin (acoshf) attributes simd (notinbranch)
23!GCC$ builtin (acospi) attributes simd (notinbranch)
24!GCC$ builtin (acospif) attributes simd (notinbranch)
25!GCC$ builtin (asin) attributes simd (notinbranch)
26!GCC$ builtin (asinf) attributes simd (notinbranch)
27!GCC$ builtin (asinh) attributes simd (notinbranch)
28!GCC$ builtin (asinhf) attributes simd (notinbranch)
29!GCC$ builtin (asinpi) attributes simd (notinbranch)
30!GCC$ builtin (asinpif) attributes simd (notinbranch)
31!GCC$ builtin (atan) attributes simd (notinbranch)
32!GCC$ builtin (atan2) attributes simd (notinbranch)
33!GCC$ builtin (atan2f) attributes simd (notinbranch)
34!GCC$ builtin (atan2pi) attributes simd (notinbranch)
35!GCC$ builtin (atan2pif) attributes simd (notinbranch)
36!GCC$ builtin (atanf) attributes simd (notinbranch)
37!GCC$ builtin (atanh) attributes simd (notinbranch)
38!GCC$ builtin (atanhf) attributes simd (notinbranch)
39!GCC$ builtin (atanpi) attributes simd (notinbranch)
40!GCC$ builtin (atanpif) attributes simd (notinbranch)
41!GCC$ builtin (cbrt) attributes simd (notinbranch)
42!GCC$ builtin (cbrtf) attributes simd (notinbranch)
43!GCC$ builtin (cos) attributes simd (notinbranch)
44!GCC$ builtin (cosf) attributes simd (notinbranch)
45!GCC$ builtin (cosh) attributes simd (notinbranch)
46!GCC$ builtin (coshf) attributes simd (notinbranch)
47!GCC$ builtin (cospi) attributes simd (notinbranch)
48!GCC$ builtin (cospif) attributes simd (notinbranch)
49!GCC$ builtin (erf) attributes simd (notinbranch)
50!GCC$ builtin (erfc) attributes simd (notinbranch)
51!GCC$ builtin (erfcf) attributes simd (notinbranch)
52!GCC$ builtin (erff) attributes simd (notinbranch)
53!GCC$ builtin (exp) attributes simd (notinbranch)
54!GCC$ builtin (exp10) attributes simd (notinbranch)
55!GCC$ builtin (exp10f) attributes simd (notinbranch)
56!GCC$ builtin (exp10m1) attributes simd (notinbranch)
57!GCC$ builtin (exp10m1f) attributes simd (notinbranch)
58!GCC$ builtin (exp2) attributes simd (notinbranch)
59!GCC$ builtin (exp2f) attributes simd (notinbranch)
60!GCC$ builtin (exp2m1) attributes simd (notinbranch)
61!GCC$ builtin (exp2m1f) attributes simd (notinbranch)
62!GCC$ builtin (expf) attributes simd (notinbranch)
63!GCC$ builtin (expm1) attributes simd (notinbranch)
64!GCC$ builtin (expm1f) attributes simd (notinbranch)
65!GCC$ builtin (hypot) attributes simd (notinbranch)
66!GCC$ builtin (hypotf) attributes simd (notinbranch)
67!GCC$ builtin (log) attributes simd (notinbranch)
68!GCC$ builtin (log10) attributes simd (notinbranch)
69!GCC$ builtin (log10f) attributes simd (notinbranch)
70!GCC$ builtin (log10p1) attributes simd (notinbranch)
71!GCC$ builtin (log10p1f) attributes simd (notinbranch)
72!GCC$ builtin (log1p) attributes simd (notinbranch)
73!GCC$ builtin (log1pf) attributes simd (notinbranch)
74!GCC$ builtin (log2) attributes simd (notinbranch)
75!GCC$ builtin (log2f) attributes simd (notinbranch)
76!GCC$ builtin (log2p1) attributes simd (notinbranch)
77!GCC$ builtin (log2p1f) attributes simd (notinbranch)
78!GCC$ builtin (logf) attributes simd (notinbranch)
79!GCC$ builtin (logp1) attributes simd (notinbranch)
80!GCC$ builtin (logp1f) attributes simd (notinbranch)
81!GCC$ builtin (pow) attributes simd (notinbranch)
82!GCC$ builtin (powf) attributes simd (notinbranch)
83!GCC$ builtin (rsqrt) attributes simd (notinbranch)
84!GCC$ builtin (rsqrtf) attributes simd (notinbranch)
85!GCC$ builtin (sin) attributes simd (notinbranch)
86!GCC$ builtin (sinf) attributes simd (notinbranch)
87!GCC$ builtin (sinh) attributes simd (notinbranch)
88!GCC$ builtin (sinhf) attributes simd (notinbranch)
89!GCC$ builtin (sinpi) attributes simd (notinbranch)
90!GCC$ builtin (sinpif) attributes simd (notinbranch)
91!GCC$ builtin (tan) attributes simd (notinbranch)
92!GCC$ builtin (tanf) attributes simd (notinbranch)
93!GCC$ builtin (tanh) attributes simd (notinbranch)
94!GCC$ builtin (tanhf) attributes simd (notinbranch)
95!GCC$ builtin (tanpi) attributes simd (notinbranch)
96!GCC$ builtin (tanpif) attributes simd (notinbranch)
\ No newline at end of file
19!GCC$ builtin (acos) attributes simd (notinbranch) if('fastmath')
20!GCC$ builtin (acosf) attributes simd (notinbranch) if('fastmath')
21!GCC$ builtin (acosh) attributes simd (notinbranch) if('fastmath')
22!GCC$ builtin (acoshf) attributes simd (notinbranch) if('fastmath')
23!GCC$ builtin (acospi) attributes simd (notinbranch) if('fastmath')
24!GCC$ builtin (acospif) attributes simd (notinbranch) if('fastmath')
25!GCC$ builtin (asin) attributes simd (notinbranch) if('fastmath')
26!GCC$ builtin (asinf) attributes simd (notinbranch) if('fastmath')
27!GCC$ builtin (asinh) attributes simd (notinbranch) if('fastmath')
28!GCC$ builtin (asinhf) attributes simd (notinbranch) if('fastmath')
29!GCC$ builtin (asinpi) attributes simd (notinbranch) if('fastmath')
30!GCC$ builtin (asinpif) attributes simd (notinbranch) if('fastmath')
31!GCC$ builtin (atan) attributes simd (notinbranch) if('fastmath')
32!GCC$ builtin (atan2) attributes simd (notinbranch) if('fastmath')
33!GCC$ builtin (atan2f) attributes simd (notinbranch) if('fastmath')
34!GCC$ builtin (atan2pi) attributes simd (notinbranch) if('fastmath')
35!GCC$ builtin (atan2pif) attributes simd (notinbranch) if('fastmath')
36!GCC$ builtin (atanf) attributes simd (notinbranch) if('fastmath')
37!GCC$ builtin (atanh) attributes simd (notinbranch) if('fastmath')
38!GCC$ builtin (atanhf) attributes simd (notinbranch) if('fastmath')
39!GCC$ builtin (atanpi) attributes simd (notinbranch) if('fastmath')
40!GCC$ builtin (atanpif) attributes simd (notinbranch) if('fastmath')
41!GCC$ builtin (cbrt) attributes simd (notinbranch) if('fastmath')
42!GCC$ builtin (cbrtf) attributes simd (notinbranch) if('fastmath')
43!GCC$ builtin (cos) attributes simd (notinbranch) if('fastmath')
44!GCC$ builtin (cosf) attributes simd (notinbranch) if('fastmath')
45!GCC$ builtin (cosh) attributes simd (notinbranch) if('fastmath')
46!GCC$ builtin (coshf) attributes simd (notinbranch) if('fastmath')
47!GCC$ builtin (cospi) attributes simd (notinbranch) if('fastmath')
48!GCC$ builtin (cospif) attributes simd (notinbranch) if('fastmath')
49!GCC$ builtin (erf) attributes simd (notinbranch) if('fastmath')
50!GCC$ builtin (erfc) attributes simd (notinbranch) if('fastmath')
51!GCC$ builtin (erfcf) attributes simd (notinbranch) if('fastmath')
52!GCC$ builtin (erff) attributes simd (notinbranch) if('fastmath')
53!GCC$ builtin (exp) attributes simd (notinbranch) if('fastmath')
54!GCC$ builtin (exp10) attributes simd (notinbranch) if('fastmath')
55!GCC$ builtin (exp10f) attributes simd (notinbranch) if('fastmath')
56!GCC$ builtin (exp10m1) attributes simd (notinbranch) if('fastmath')
57!GCC$ builtin (exp10m1f) attributes simd (notinbranch) if('fastmath')
58!GCC$ builtin (exp2) attributes simd (notinbranch) if('fastmath')
59!GCC$ builtin (exp2f) attributes simd (notinbranch) if('fastmath')
60!GCC$ builtin (exp2m1) attributes simd (notinbranch) if('fastmath')
61!GCC$ builtin (exp2m1f) attributes simd (notinbranch) if('fastmath')
62!GCC$ builtin (expf) attributes simd (notinbranch) if('fastmath')
63!GCC$ builtin (expm1) attributes simd (notinbranch) if('fastmath')
64!GCC$ builtin (expm1f) attributes simd (notinbranch) if('fastmath')
65!GCC$ builtin (hypot) attributes simd (notinbranch) if('fastmath')
66!GCC$ builtin (hypotf) attributes simd (notinbranch) if('fastmath')
67!GCC$ builtin (log) attributes simd (notinbranch) if('fastmath')
68!GCC$ builtin (log10) attributes simd (notinbranch) if('fastmath')
69!GCC$ builtin (log10f) attributes simd (notinbranch) if('fastmath')
70!GCC$ builtin (log10p1) attributes simd (notinbranch) if('fastmath')
71!GCC$ builtin (log10p1f) attributes simd (notinbranch) if('fastmath')
72!GCC$ builtin (log1p) attributes simd (notinbranch) if('fastmath')
73!GCC$ builtin (log1pf) attributes simd (notinbranch) if('fastmath')
74!GCC$ builtin (log2) attributes simd (notinbranch) if('fastmath')
75!GCC$ builtin (log2f) attributes simd (notinbranch) if('fastmath')
76!GCC$ builtin (log2p1) attributes simd (notinbranch) if('fastmath')
77!GCC$ builtin (log2p1f) attributes simd (notinbranch) if('fastmath')
78!GCC$ builtin (logf) attributes simd (notinbranch) if('fastmath')
79!GCC$ builtin (logp1) attributes simd (notinbranch) if('fastmath')
80!GCC$ builtin (logp1f) attributes simd (notinbranch) if('fastmath')
81!GCC$ builtin (pow) attributes simd (notinbranch) if('fastmath')
82!GCC$ builtin (powf) attributes simd (notinbranch) if('fastmath')
83!GCC$ builtin (powr) attributes simd (notinbranch) if('fastmath')
84!GCC$ builtin (powrf) attributes simd (notinbranch) if('fastmath')
85!GCC$ builtin (rsqrt) attributes simd (notinbranch) if('fastmath')
86!GCC$ builtin (rsqrtf) attributes simd (notinbranch) if('fastmath')
87!GCC$ builtin (sin) attributes simd (notinbranch) if('fastmath')
88!GCC$ builtin (sinf) attributes simd (notinbranch) if('fastmath')
89!GCC$ builtin (sinh) attributes simd (notinbranch) if('fastmath')
90!GCC$ builtin (sinhf) attributes simd (notinbranch) if('fastmath')
91!GCC$ builtin (sinpi) attributes simd (notinbranch) if('fastmath')
92!GCC$ builtin (sinpif) attributes simd (notinbranch) if('fastmath')
93!GCC$ builtin (tan) attributes simd (notinbranch) if('fastmath')
94!GCC$ builtin (tanf) attributes simd (notinbranch) if('fastmath')
95!GCC$ builtin (tanh) attributes simd (notinbranch) if('fastmath')
96!GCC$ builtin (tanhf) attributes simd (notinbranch) if('fastmath')
97!GCC$ builtin (tanpi) attributes simd (notinbranch) if('fastmath')
98!GCC$ builtin (tanpif) attributes simd (notinbranch) if('fastmath')
\ No newline at end of file
lib/libc/include/aarch64-linux-gnu/gnu/lib-names-lp64.h+1
......@@ -24,4 +24,5 @@
2424#define LIBRESOLV_SO "libresolv.so.2"
2525#define LIBRT_SO "librt.so.1"
2626#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
2728#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/aarch64-linux-gnu/gnu/lib-names-lp64_be.h+1
......@@ -24,4 +24,5 @@
2424#define LIBRESOLV_SO "libresolv.so.2"
2525#define LIBRT_SO "librt.so.1"
2626#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
2728#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/arc-linux-gnu/bits/struct_stat.h deleted-127
......@@ -1,127 +0,0 @@
1/* Definition for struct stat.
2 Copyright (C) 2020-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library. If not, see
17 <https://www.gnu.org/licenses/>. */
18
19#if !defined _SYS_STAT_H && !defined _FCNTL_H
20# error "Never include <bits/struct_stat.h> directly; use <sys/stat.h> instead."
21#endif
22
23#ifndef _BITS_STRUCT_STAT_H
24#define _BITS_STRUCT_STAT_H 1
25
26#include <bits/endian.h>
27#include <bits/wordsize.h>
28
29#if defined __USE_FILE_OFFSET64
30# define __field64(type, type64, name) type64 name
31#elif __WORDSIZE == 64 || defined __INO_T_MATCHES_INO64_T
32# if defined __INO_T_MATCHES_INO64_T && !defined __OFF_T_MATCHES_OFF64_T
33# error "ino_t and off_t must both be the same type"
34# endif
35# define __field64(type, type64, name) type name
36#elif __BYTE_ORDER == __LITTLE_ENDIAN
37# define __field64(type, type64, name) \
38 type name __attribute__((__aligned__ (__alignof__ (type64)))); int __##name##_pad
39#else
40# define __field64(type, type64, name) \
41 int __##name##_pad __attribute__((__aligned__ (__alignof__ (type64)))); type name
42#endif
43
44struct stat
45 {
46 __dev_t st_dev; /* Device. */
47 __field64(__ino_t, __ino64_t, st_ino); /* File serial number. */
48 __mode_t st_mode; /* File mode. */
49 __nlink_t st_nlink; /* Link count. */
50 __uid_t st_uid; /* User ID of the file's owner. */
51 __gid_t st_gid; /* Group ID of the file's group.*/
52 __dev_t st_rdev; /* Device number, if device. */
53 __dev_t __pad1;
54 __field64(__off_t, __off64_t, st_size); /* Size of file, in bytes. */
55 __blksize_t st_blksize; /* Optimal block size for I/O. */
56 int __pad2;
57 __field64(__blkcnt_t, __blkcnt64_t, st_blocks); /* 512-byte blocks */
58#ifdef __USE_XOPEN2K8
59 /* Nanosecond resolution timestamps are stored in a format
60 equivalent to 'struct timespec'. This is the type used
61 whenever possible but the Unix namespace rules do not allow the
62 identifier 'timespec' to appear in the <sys/stat.h> header.
63 Therefore we have to handle the use of this header in strictly
64 standard-compliant sources special. */
65 struct timespec st_atim; /* Time of last access. */
66 struct timespec st_mtim; /* Time of last modification. */
67 struct timespec st_ctim; /* Time of last status change. */
68# define st_atime st_atim.tv_sec /* Backward compatibility. */
69# define st_mtime st_mtim.tv_sec
70# define st_ctime st_ctim.tv_sec
71#else
72 __time_t st_atime; /* Time of last access. */
73 unsigned long int st_atimensec; /* Nscecs of last access. */
74 __time_t st_mtime; /* Time of last modification. */
75 unsigned long int st_mtimensec; /* Nsecs of last modification. */
76 __time_t st_ctime; /* Time of last status change. */
77 unsigned long int st_ctimensec; /* Nsecs of last status change. */
78#endif
79 int __glibc_reserved[2];
80 };
81
82#undef __field64
83
84#ifdef __USE_LARGEFILE64
85struct stat64
86 {
87 __dev_t st_dev; /* Device. */
88 __ino64_t st_ino; /* File serial number. */
89 __mode_t st_mode; /* File mode. */
90 __nlink_t st_nlink; /* Link count. */
91 __uid_t st_uid; /* User ID of the file's owner. */
92 __gid_t st_gid; /* Group ID of the file's group.*/
93 __dev_t st_rdev; /* Device number, if device. */
94 __dev_t __pad1;
95 __off64_t st_size; /* Size of file, in bytes. */
96 __blksize_t st_blksize; /* Optimal block size for I/O. */
97 int __pad2;
98 __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */
99#ifdef __USE_XOPEN2K8
100 /* Nanosecond resolution timestamps are stored in a format
101 equivalent to 'struct timespec'. This is the type used
102 whenever possible but the Unix namespace rules do not allow the
103 identifier 'timespec' to appear in the <sys/stat.h> header.
104 Therefore we have to handle the use of this header in strictly
105 standard-compliant sources special. */
106 struct timespec st_atim; /* Time of last access. */
107 struct timespec st_mtim; /* Time of last modification. */
108 struct timespec st_ctim; /* Time of last status change. */
109#else
110 __time_t st_atime; /* Time of last access. */
111 unsigned long int st_atimensec; /* Nscecs of last access. */
112 __time_t st_mtime; /* Time of last modification. */
113 unsigned long int st_mtimensec; /* Nsecs of last modification. */
114 __time_t st_ctime; /* Time of last status change. */
115 unsigned long int st_ctimensec; /* Nsecs of last status change. */
116#endif
117 int __glibc_reserved[2];
118 };
119#endif
120
121/* Tell code we have these members. */
122#define _STATBUF_ST_BLKSIZE
123#define _STATBUF_ST_RDEV
124/* Nanosecond resolution time values are supported. */
125#define _STATBUF_ST_NSEC
126
127#endif /* _BITS_STRUCT_STAT_H */
\ No newline at end of file
lib/libc/include/arc-linux-gnu/bits/timesize.h deleted-20
......@@ -1,20 +0,0 @@
1/* Bit size of the time_t type at glibc build time, general case.
2 Copyright (C) 2018-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19/* Size in bits of the 'time_t' type of the default ABI. */
20#define __TIMESIZE 64
\ No newline at end of file
lib/libc/include/arc-linux-gnu/gnu/lib-names.h+1
......@@ -25,6 +25,7 @@
2525#define LIBRESOLV_SO "libresolv.so.2"
2626#define LIBRT_SO "librt.so.1"
2727#define LIBTHREAD_DB_SO "libthread_db.so.1"
28#define LIBUNWIND_SO "libunwind.so.1"
2829#define LIBUTIL_SO "libutil.so.1"
2930
3031#endif /* gnu/lib-names.h */
\ No newline at end of file
lib/libc/include/csky-linux-gnu/gnu/lib-names.h+2-1
......@@ -31,6 +31,7 @@
3131#define LIBRESOLV_SO "libresolv.so.2"
3232#define LIBRT_SO "librt.so.1"
3333#define LIBTHREAD_DB_SO "libthread_db.so.1"
34#define LIBUNWIND_SO "libunwind.so.1"
3435#define LIBUTIL_SO "libutil.so.1"
3536
36#endif /* gnu/lib-names.h */
37#endif /* gnu/lib-names.h */
\ No newline at end of file
lib/libc/include/generic-glibc/assert.h+19-9
......@@ -52,13 +52,12 @@
5252 comma in the initializer list, can be passed to assert. This
5353 depends on support for variadic macros (added in C99 and GCC 2.95),
5454 and on support for _Bool (added in C99 and GCC 3.0) in order to
55 validate that only a single expression is passed as an argument,
56 and is currently implemented only for C. */
57#if (__GLIBC_USE (ISOC23) \
58 && (defined __GNUC__ \
59 ? __GNUC_PREREQ (3, 0) \
60 : defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) \
61 && !defined __cplusplus)
55 validate that only a single expression is passed as an argument. */
56#if ((__GLIBC_USE (ISOC23) \
57 && (defined __GNUC__ \
58 ? __GNUC_PREREQ (3, 0) \
59 : defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)) \
60 || (defined __cplusplus && __cplusplus > 202302L))
6261# define __ASSERT_VARIADIC 1
6362#else
6463# define __ASSERT_VARIADIC 0
......@@ -108,7 +107,7 @@ extern void __assert (const char *__assertion, const char *__file, int __line)
108107 __THROW __attribute__ ((__noreturn__)) __COLD;
109108
110109
111# if __ASSERT_VARIADIC
110# if __ASSERT_VARIADIC && !defined __cplusplus
112111/* This function is not defined and is not called outside of an
113112 unevaluated sizeof, but serves to verify that the argument to
114113 assert is a single expression. */
......@@ -131,11 +130,22 @@ __END_DECLS
131130# define __ASSERT_FILE __FILE__
132131# define __ASSERT_LINE __LINE__
133132# endif
134# define assert(expr) \
133# if __ASSERT_VARIADIC
134/* The first test of __VA_ARGS__ evaluates it without converting scoped
135 enumeration values to bool, and the second test checks that it is a
136 single expression without evaluating it. */
137# define assert(...) \
138 ((__VA_ARGS__) \
139 ? void (1 ? 1 : bool (__VA_ARGS__)) \
140 : __assert_fail (#__VA_ARGS__, __ASSERT_FILE, __ASSERT_LINE, \
141 __ASSERT_FUNCTION))
142# else
143# define assert(expr) \
135144 (static_cast <bool> (expr) \
136145 ? void (0) \
137146 : __assert_fail (#expr, __ASSERT_FILE, __ASSERT_LINE, \
138147 __ASSERT_FUNCTION))
148# endif
139149# elif !defined __GNUC__ || defined __STRICT_ANSI__
140150# if __ASSERT_VARIADIC
141151# define assert(...) \
lib/libc/include/generic-glibc/bits/cloexec.h created+1
......@@ -0,0 +1 @@
1#define __O_CLOEXEC 02000000
\ No newline at end of file
lib/libc/include/generic-glibc/bits/fcntl-linux.h+11-10
......@@ -81,9 +81,7 @@
8181#ifndef __O_NOFOLLOW
8282# define __O_NOFOLLOW 0400000
8383#endif
84#ifndef __O_CLOEXEC
85# define __O_CLOEXEC 02000000
86#endif
84#include <bits/cloexec.h>
8785#ifndef __O_DIRECT
8886# define __O_DIRECT 040000
8987#endif
......@@ -176,8 +174,8 @@
176174#endif
177175
178176#if defined __USE_UNIX98 || defined __USE_XOPEN2K8
179# define F_SETOWN __F_SETOWN /* Get owner (process receiving SIGIO). */
180# define F_GETOWN __F_GETOWN /* Set owner (process receiving SIGIO). */
177# define F_SETOWN __F_SETOWN /* Set owner (process receiving SIGIO). */
178# define F_GETOWN __F_GETOWN /* Get owner (process receiving SIGIO). */
181179#endif
182180
183181#ifndef __F_SETSIG
......@@ -185,15 +183,15 @@
185183# define __F_GETSIG 11 /* Get number of signal to be sent. */
186184#endif
187185#ifndef __F_SETOWN_EX
188# define __F_SETOWN_EX 15 /* Get owner (thread receiving SIGIO). */
189# define __F_GETOWN_EX 16 /* Set owner (thread receiving SIGIO). */
186# define __F_SETOWN_EX 15 /* Set owner (thread receiving SIGIO). */
187# define __F_GETOWN_EX 16 /* Get owner (thread receiving SIGIO). */
190188#endif
191189
192190#ifdef __USE_GNU
193191# define F_SETSIG __F_SETSIG /* Set number of signal to be sent. */
194192# define F_GETSIG __F_GETSIG /* Get number of signal to be sent. */
195# define F_SETOWN_EX __F_SETOWN_EX /* Get owner (thread receiving SIGIO). */
196# define F_GETOWN_EX __F_GETOWN_EX /* Set owner (thread receiving SIGIO). */
193# define F_SETOWN_EX __F_SETOWN_EX /* Set owner (thread receiving SIGIO). */
194# define F_GETOWN_EX __F_GETOWN_EX /* Get owner (thread receiving SIGIO). */
197195#endif
198196
199197#ifdef __USE_GNU
......@@ -203,7 +201,7 @@
203201# define F_DUPFD_QUERY 1027 /* Compare two file descriptors for sameness. */
204202# define F_CREATED_QUERY 1028 /* Was the file just created? */
205203# define F_SETPIPE_SZ 1031 /* Set pipe page size array. */
206# define F_GETPIPE_SZ 1032 /* Set pipe page size array. */
204# define F_GETPIPE_SZ 1032 /* Get pipe page size array. */
207205# define F_ADD_SEALS 1033 /* Add seals to file. */
208206# define F_GET_SEALS 1034 /* Get seals for file. */
209207/* Set / get write life time hints. */
......@@ -211,6 +209,8 @@
211209# define F_SET_RW_HINT 1036
212210# define F_GET_FILE_RW_HINT 1037
213211# define F_SET_FILE_RW_HINT 1038
212# define F_GETDELEG 1039 /* Get delegation. */
213# define F_SETDELEG 1040 /* Set delegation. */
214214#endif
215215#ifdef __USE_XOPEN2K8
216216# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with
......@@ -221,6 +221,7 @@
221221#define FD_CLOEXEC 1 /* Actually anything with low bit set goes */
222222#ifdef __USE_GNU
223223# define FD_PIDFS_ROOT -10002 /* Root of the pidfs filesystem */
224# define FD_NSFS_ROOT -10003 /* Root of the nsfs filesystem */
224225#endif
225226
226227#ifndef F_RDLCK
lib/libc/include/generic-glibc/bits/libm-simd-decl-stubs.h+11
......@@ -99,6 +99,17 @@
9999#define __DECL_SIMD_powf64x
100100#define __DECL_SIMD_powf128x
101101
102#define __DECL_SIMD_powr
103#define __DECL_SIMD_powrf
104#define __DECL_SIMD_powrl
105#define __DECL_SIMD_powrf16
106#define __DECL_SIMD_powrf32
107#define __DECL_SIMD_powrf64
108#define __DECL_SIMD_powrf128
109#define __DECL_SIMD_powrf32x
110#define __DECL_SIMD_powrf64x
111#define __DECL_SIMD_powrf128x
112
102113#define __DECL_SIMD_acos
103114#define __DECL_SIMD_acosf
104115#define __DECL_SIMD_acosl
lib/libc/include/generic-glibc/bits/long-double.h+3-6
......@@ -1,4 +1,4 @@
1/* Properties of long double type. MIPS version.
1/* Properties of long double type. ldbl-128 version.
22 Copyright (C) 2016-2026 Free Software Foundation, Inc.
33 This file is part of the GNU C Library.
44
......@@ -16,9 +16,6 @@
1616 License along with the GNU C Library; if not, see
1717 <https://www.gnu.org/licenses/>. */
1818
19#include <sgidefs.h>
20
21#if !defined __NO_LONG_DOUBLE_MATH && _MIPS_SIM == _ABIO32
22# define __NO_LONG_DOUBLE_MATH 1
23#endif
19/* long double is distinct from double, so there is nothing to
20 define here. */
2421#define __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI 0
\ No newline at end of file
lib/libc/include/generic-glibc/bits/mathcalls.h+1
......@@ -197,6 +197,7 @@ __MATHCALL (compoundn,, (_Mdouble_ __x, long long int __y));
197197__MATHCALL (pown,, (_Mdouble_ __x, long long int __y));
198198
199199/* Return X to the Y power. */
200__MATHCALL_VEC (powr,, (_Mdouble_ __x, _Mdouble_ __y));
200201__MATHCALL (powr,, (_Mdouble_ __x, _Mdouble_ __y));
201202
202203/* Return the Yth root of X. */
lib/libc/include/generic-glibc/bits/ppc.h deleted-33
......@@ -1,33 +0,0 @@
1/* Facilities specific to the PowerPC architecture on Linux
2 Copyright (C) 2012-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#ifndef _BITS_PPC_H
20#define _BITS_PPC_H
21
22#ifndef _SYS_PLATFORM_PPC_H
23# error "Never include this file directly; use <sys/platform/ppc.h> instead."
24#endif
25
26__BEGIN_DECLS
27
28/* Read the time base frequency. */
29extern uint64_t __ppc_get_timebase_freq (void);
30
31__END_DECLS
32
33#endif
\ No newline at end of file
lib/libc/include/generic-glibc/bits/sched.h+3
......@@ -54,6 +54,9 @@
5454#define SCHED_FLAG_UTIL_CLAMP \
5555 (SCHED_FLAG_UTIL_CLAMP_MIN | SCHED_FLAG_UTIL_CLAMP_MAX)
5656
57/* Flags for the flags argument of sched_getattr. */
58#define SCHED_GETATTR_FLAG_DL_DYNAMIC 0x01
59
5760/* Use "" to work around incorrect macro expansion of the
5861 __has_include argument (GCC PR 80005). */
5962# ifdef __has_include
lib/libc/include/generic-glibc/bits/struct_stat.h+54-164
......@@ -23,215 +23,105 @@
2323#ifndef _BITS_STRUCT_STAT_H
2424#define _BITS_STRUCT_STAT_H 1
2525
26#include <sgidefs.h>
26#include <bits/endian.h>
27#include <bits/wordsize.h>
28
29#if defined __USE_FILE_OFFSET64
30# define __field64(type, type64, name) type64 name
31#elif __WORDSIZE == 64 || defined __INO_T_MATCHES_INO64_T
32# if defined __INO_T_MATCHES_INO64_T && !defined __OFF_T_MATCHES_OFF64_T
33# error "ino_t and off_t must both be the same type"
34# endif
35# define __field64(type, type64, name) type name
36#elif __BYTE_ORDER == __LITTLE_ENDIAN
37# define __field64(type, type64, name) \
38 type name __attribute__((__aligned__ (__alignof__ (type64)))); int __##name##_pad
39#else
40# define __field64(type, type64, name) \
41 int __##name##_pad __attribute__((__aligned__ (__alignof__ (type64)))); type name
42#endif
2743
28#if _MIPS_SIM == _ABIO32
29/* Structure describing file characteristics. */
3044struct stat
3145 {
32# ifdef __USE_TIME64_REDIRECTS
33# include <bits/struct_stat_time64_helper.h>
34# else
35 unsigned long int st_dev;
36 long int st_pad1[3];
37# ifndef __USE_FILE_OFFSET64
38 __ino_t st_ino; /* File serial number. */
39# else
40 __ino64_t st_ino; /* File serial number. */
41# endif
46 __dev_t st_dev; /* Device. */
47 __field64(__ino_t, __ino64_t, st_ino); /* File serial number. */
4248 __mode_t st_mode; /* File mode. */
4349 __nlink_t st_nlink; /* Link count. */
4450 __uid_t st_uid; /* User ID of the file's owner. */
4551 __gid_t st_gid; /* Group ID of the file's group.*/
46 unsigned long int st_rdev; /* Device number, if device. */
47# ifndef __USE_FILE_OFFSET64
48 long int st_pad2[2];
49 __off_t st_size; /* Size of file, in bytes. */
50 /* SVR4 added this extra long to allow for expansion of off_t. */
51 long int st_pad3;
52# else
53 long int st_pad2[3];
54 __off64_t st_size; /* Size of file, in bytes. */
55# endif
56# ifdef __USE_XOPEN2K8
52 __dev_t st_rdev; /* Device number, if device. */
53 __dev_t __pad1;
54 __field64(__off_t, __off64_t, st_size); /* Size of file, in bytes. */
55 __blksize_t st_blksize; /* Optimal block size for I/O. */
56 int __pad2;
57 __field64(__blkcnt_t, __blkcnt64_t, st_blocks); /* 512-byte blocks */
58#ifdef __USE_XOPEN2K8
5759 /* Nanosecond resolution timestamps are stored in a format
5860 equivalent to 'struct timespec'. This is the type used
5961 whenever possible but the Unix namespace rules do not allow the
6062 identifier 'timespec' to appear in the <sys/stat.h> header.
6163 Therefore we have to handle the use of this header in strictly
6264 standard-compliant sources special. */
63 struct timespec st_atim; /* Time of last access. */
64 struct timespec st_mtim; /* Time of last modification. */
65 struct timespec st_ctim; /* Time of last status change. */
66# define st_atime st_atim.tv_sec /* Backward compatibility. */
67# define st_mtime st_mtim.tv_sec
68# define st_ctime st_ctim.tv_sec
69# else
65 struct timespec st_atim; /* Time of last access. */
66 struct timespec st_mtim; /* Time of last modification. */
67 struct timespec st_ctim; /* Time of last status change. */
68# define st_atime st_atim.tv_sec /* Backward compatibility. */
69# define st_mtime st_mtim.tv_sec
70# define st_ctime st_ctim.tv_sec
71#else
7072 __time_t st_atime; /* Time of last access. */
7173 unsigned long int st_atimensec; /* Nscecs of last access. */
7274 __time_t st_mtime; /* Time of last modification. */
7375 unsigned long int st_mtimensec; /* Nsecs of last modification. */
7476 __time_t st_ctime; /* Time of last status change. */
7577 unsigned long int st_ctimensec; /* Nsecs of last status change. */
76# endif
77 __blksize_t st_blksize; /* Optimal block size for I/O. */
78# ifndef __USE_FILE_OFFSET64
79 __blkcnt_t st_blocks; /* Number of 512-byte blocks allocated. */
80# else
81 long int st_pad4;
82 __blkcnt64_t st_blocks; /* Number of 512-byte blocks allocated. */
83# endif
84 long int st_pad5[14];
85# endif /* __USE_TIME64_REDIRECTS */
78#endif
79 int __glibc_reserved[2];
8680 };
8781
88# ifdef __USE_LARGEFILE64
82#undef __field64
83
84#ifdef __USE_LARGEFILE64
8985struct stat64
9086 {
91# ifdef __USE_TIME64_REDIRECTS
92# include <bits/struct_stat_time64_helper.h>
93# else
94 unsigned long int st_dev;
95 long int st_pad1[3];
96 __ino64_t st_ino; /* File serial number. */
87 __dev_t st_dev; /* Device. */
88 __ino64_t st_ino; /* File serial number. */
9789 __mode_t st_mode; /* File mode. */
9890 __nlink_t st_nlink; /* Link count. */
9991 __uid_t st_uid; /* User ID of the file's owner. */
10092 __gid_t st_gid; /* Group ID of the file's group.*/
101 unsigned long int st_rdev; /* Device number, if device. */
102 long int st_pad2[3];
93 __dev_t st_rdev; /* Device number, if device. */
94 __dev_t __pad1;
10395 __off64_t st_size; /* Size of file, in bytes. */
104# ifdef __USE_XOPEN2K8
105 /* Nanosecond resolution timestamps are stored in a format
106 equivalent to 'struct timespec'. This is the type used
107 whenever possible but the Unix namespace rules do not allow the
108 identifier 'timespec' to appear in the <sys/stat.h> header.
109 Therefore we have to handle the use of this header in strictly
110 standard-compliant sources special. */
111 struct timespec st_atim; /* Time of last access. */
112 struct timespec st_mtim; /* Time of last modification. */
113 struct timespec st_ctim; /* Time of last status change. */
114# else
115 __time_t st_atime; /* Time of last access. */
116 unsigned long int st_atimensec; /* Nscecs of last access. */
117 __time_t st_mtime; /* Time of last modification. */
118 unsigned long int st_mtimensec; /* Nsecs of last modification. */
119 __time_t st_ctime; /* Time of last status change. */
120 unsigned long int st_ctimensec; /* Nsecs of last status change. */
121# endif
12296 __blksize_t st_blksize; /* Optimal block size for I/O. */
123 long int st_pad3;
124 __blkcnt64_t st_blocks; /* Number of 512-byte blocks allocated. */
125 long int st_pad4[14];
126# endif /* __USE_TIME64_REDIRECTS */
127 };
128# endif /* __USE_LARGEFILE64 */
129
130#else /* _MIPS_SIM != _ABIO32 */
131
132struct stat
133 {
134# ifdef __USE_TIME64_REDIRECTS
135# include <bits/struct_stat_time64_helper.h>
136# else
137 __dev_t st_dev;
138 int st_pad1[3]; /* Reserved for st_dev expansion */
139# ifndef __USE_FILE_OFFSET64
140 __ino_t st_ino;
141# else
142 __ino64_t st_ino;
143# endif
144 __mode_t st_mode;
145 __nlink_t st_nlink;
146 __uid_t st_uid;
147 __gid_t st_gid;
148 __dev_t st_rdev;
149# if !defined __USE_FILE_OFFSET64
150 unsigned int st_pad2[2]; /* Reserved for st_rdev expansion */
151 __off_t st_size;
152 int st_pad3;
153# else
154 unsigned int st_pad2[3]; /* Reserved for st_rdev expansion */
155 __off64_t st_size;
156# endif
157# ifdef __USE_XOPEN2K8
97 int __pad2;
98 __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */
99#ifdef __USE_XOPEN2K8
158100 /* Nanosecond resolution timestamps are stored in a format
159101 equivalent to 'struct timespec'. This is the type used
160102 whenever possible but the Unix namespace rules do not allow the
161103 identifier 'timespec' to appear in the <sys/stat.h> header.
162104 Therefore we have to handle the use of this header in strictly
163105 standard-compliant sources special. */
164 struct timespec st_atim; /* Time of last access. */
165 struct timespec st_mtim; /* Time of last modification. */
166 struct timespec st_ctim; /* Time of last status change. */
167# define st_atime st_atim.tv_sec /* Backward compatibility. */
168# define st_mtime st_mtim.tv_sec
169# define st_ctime st_ctim.tv_sec
170# else
106 struct timespec st_atim; /* Time of last access. */
107 struct timespec st_mtim; /* Time of last modification. */
108 struct timespec st_ctim; /* Time of last status change. */
109#else
171110 __time_t st_atime; /* Time of last access. */
172111 unsigned long int st_atimensec; /* Nscecs of last access. */
173112 __time_t st_mtime; /* Time of last modification. */
174113 unsigned long int st_mtimensec; /* Nsecs of last modification. */
175114 __time_t st_ctime; /* Time of last status change. */
176115 unsigned long int st_ctimensec; /* Nsecs of last status change. */
177# endif
178 __blksize_t st_blksize;
179 unsigned int st_pad4;
180# ifndef __USE_FILE_OFFSET64
181 __blkcnt_t st_blocks;
182# else
183 __blkcnt64_t st_blocks;
184# endif
185 int st_pad5[14];
186# endif
187 };
188
189#ifdef __USE_LARGEFILE64
190struct stat64
191 {
192# ifdef __USE_TIME64_REDIRECTS
193# include <bits/struct_stat_time64_helper.h>
194# else
195 __dev_t st_dev;
196 unsigned int st_pad1[3]; /* Reserved for st_dev expansion */
197 __ino64_t st_ino;
198 __mode_t st_mode;
199 __nlink_t st_nlink;
200 __uid_t st_uid;
201 __gid_t st_gid;
202 __dev_t st_rdev;
203 unsigned int st_pad2[3]; /* Reserved for st_rdev expansion */
204 __off64_t st_size;
205# ifdef __USE_XOPEN2K8
206 /* Nanosecond resolution timestamps are stored in a format
207 equivalent to 'struct timespec'. This is the type used
208 whenever possible but the Unix namespace rules do not allow the
209 identifier 'timespec' to appear in the <sys/stat.h> header.
210 Therefore we have to handle the use of this header in strictly
211 standard-compliant sources special. */
212 struct timespec st_atim; /* Time of last access. */
213 struct timespec st_mtim; /* Time of last modification. */
214 struct timespec st_ctim; /* Time of last status change. */
215# else
216 __time_t st_atime; /* Time of last access. */
217 unsigned long int st_atimensec; /* Nscecs of last access. */
218 __time_t st_mtime; /* Time of last modification. */
219 unsigned long int st_mtimensec; /* Nsecs of last modification. */
220 __time_t st_ctime; /* Time of last status change. */
221 unsigned long int st_ctimensec; /* Nsecs of last status change. */
222# endif
223 __blksize_t st_blksize;
224 unsigned int st_pad3;
225 __blkcnt64_t st_blocks;
226 int st_pad4[14];
227# endif /* __USE_TIME64_REDIRECTS */
228};
229116#endif
230
117 int __glibc_reserved[2];
118 };
231119#endif
232120
233121/* Tell code we have these members. */
234122#define _STATBUF_ST_BLKSIZE
235#define _STATBUF_ST_RDEV
123#define _STATBUF_ST_RDEV
124/* Nanosecond resolution time values are supported. */
125#define _STATBUF_ST_NSEC
236126
237127#endif /* _BITS_STRUCT_STAT_H */
\ No newline at end of file
lib/libc/include/generic-glibc/bits/syscall.h+14-2
......@@ -1,11 +1,11 @@
11/* Generated at libc build time from syscall list. */
2/* The system call list corresponds to kernel 6.17. */
2/* The system call list corresponds to kernel 7.1. */
33
44#ifndef _SYSCALL_H
55# error "Never use <bits/syscall.h> directly; include <sys/syscall.h> instead."
66#endif
77
8#define __GLIBC_LINUX_VERSION_CODE 397568
8#define __GLIBC_LINUX_VERSION_CODE 459008
99
1010#ifdef __NR_FAST_atomic_update
1111# define SYS_FAST_atomic_update __NR_FAST_atomic_update
......@@ -883,6 +883,10 @@
883883# define SYS_listmount __NR_listmount
884884#endif
885885
886#ifdef __NR_listns
887# define SYS_listns __NR_listns
888#endif
889
886890#ifdef __NR_listxattr
887891# define SYS_listxattr __NR_listxattr
888892#endif
......@@ -1899,6 +1903,10 @@
18991903# define SYS_rseq __NR_rseq
19001904#endif
19011905
1906#ifdef __NR_rseq_slice_yield
1907# define SYS_rseq_slice_yield __NR_rseq_slice_yield
1908#endif
1909
19021910#ifdef __NR_rt_sigaction
19031911# define SYS_rt_sigaction __NR_rt_sigaction
19041912#endif
......@@ -2551,6 +2559,10 @@
25512559# define SYS_unshare __NR_unshare
25522560#endif
25532561
2562#ifdef __NR_uprobe
2563# define SYS_uprobe __NR_uprobe
2564#endif
2565
25542566#ifdef __NR_uretprobe
25552567# define SYS_uretprobe __NR_uretprobe
25562568#endif
lib/libc/include/generic-glibc/bits/timesize.h+3-5
......@@ -1,5 +1,5 @@
1/* Bit size of the time_t type at glibc build time, Linux/MIPS.
2 Copyright (C) 2021-2026 Free Software Foundation, Inc.
1/* Bit size of the time_t type at glibc build time, general case.
2 Copyright (C) 2018-2026 Free Software Foundation, Inc.
33 This file is part of the GNU C Library.
44
55 The GNU C Library is free software; you can redistribute it and/or
......@@ -16,7 +16,5 @@
1616 License along with the GNU C Library; if not, see
1717 <https://www.gnu.org/licenses/>. */
1818
19#include <bits/wordsize.h>
20
2119/* Size in bits of the 'time_t' type of the default ABI. */
22#define __TIMESIZE __WORDSIZE
\ No newline at end of file
20#define __TIMESIZE 64
\ No newline at end of file
lib/libc/include/generic-glibc/bits/uio-ext.h+1
......@@ -51,6 +51,7 @@ extern ssize_t process_vm_writev (pid_t __pid, const struct iovec *__lvec,
5151#define RWF_ATOMIC 0x00000040 /* Write is to be issued with torn-write
5252 prevention. */
5353#define RWF_DONTCACHE 0x00000080 /* Uncached buffered IO. */
54#define RWF_NOSIGNAL 0x00000100 /* Do not generate SIGPIPE on error. */
5455
5556__END_DECLS
5657
lib/libc/include/generic-glibc/dlfcn.h+6-1
......@@ -167,7 +167,12 @@ enum
167167 the number of program headers in the array. */
168168 RTLD_DI_PHDR = 11,
169169
170 RTLD_DI_MAX = 11
170 /* Treat ARG as `const char **' and at that location, store the address
171 of the directory name used to expand $ORIGIN in this shared object's
172 dependency file names. */
173 RTLD_DI_ORIGIN_PATH = 12,
174
175 RTLD_DI_MAX = 12
171176 };
172177
173178
lib/libc/include/generic-glibc/elf.h+6-2
......@@ -798,7 +798,8 @@ typedef struct
798798#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */
799799#define NT_X86_SHSTK 0x204 /* x86 SHSTK state */
800800#define NT_X86_XSAVE_LAYOUT 0x205 /* XSAVE layout description. */
801#define NT_S390_HIGH_GPRS 0x300 /* s390 upper register halves */
801#define NT_S390_HIGH_GPRS 0x300 /* s390 upper register halves. This was
802 used in now removed s390-32 arch. */
802803#define NT_S390_TIMER 0x301 /* s390 timer register */
803804#define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */
804805#define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */
......@@ -846,6 +847,7 @@ typedef struct
846847#define NT_RISCV_VECTOR 0x901 /* RISC-V vector registers */
847848#define NT_RISCV_TAGGED_ADDR_CTRL 0x902 /* RISC-V tagged
848849 address control */
850#define NT_RISCV_USER_CFI 0x903 /* RISC-V shadow stack state */
849851#define NT_LOONGARCH_CPUCFG 0xa00 /* LoongArch CPU config registers. */
850852#define NT_LOONGARCH_CSR 0xa01 /* LoongArch control and
851853 status registers. */
......@@ -3470,7 +3472,9 @@ enum
34703472
34713473/* Valid values for the e_flags field. */
34723474
3473#define EF_S390_HIGH_GPRS 0x00000001 /* High GPRs kernel facility needed. */
3475#define EF_S390_HIGH_GPRS 0x00000001 /* High GPRs kernel facility needed.
3476 This was used in now removed s390-32
3477 arch. */
34743478
34753479/* Additional s390 relocs */
34763480
lib/libc/include/generic-glibc/features.h+2-2
......@@ -162,7 +162,7 @@
162162#undef __GLIBC_USE_DEPRECATED_SCANF
163163#undef __GLIBC_USE_C23_STRTOL
164164
165/* Suppress kernel-name space pollution unless user expressedly asks
165/* Suppress kernel-name space pollution unless user explicitly asks
166166 for it. */
167167#ifndef _LOOSE_KERNEL_NAMES
168168# define __KERNEL_STRICT_NAMES
......@@ -580,4 +580,4 @@
580580#include <gnu/stubs.h>
581581
582582
583#endif /* features.h */
583#endif /* features.h */
\ No newline at end of file
lib/libc/include/generic-glibc/fts.h+126-2
......@@ -52,7 +52,29 @@
5252
5353#include <features.h>
5454#include <sys/types.h>
55
55#include <sys/stat.h>
56#include <dirent.h>
57#include <stdbool.h>
58
59enum { __I_RING_SIZE = 4 };
60
61/* When ir_empty is true, the ring is empty.
62 Otherwise, ir_data[B..F] are defined, where B..F is the contiguous
63 range of indices, modulo I_RING_SIZE, from back to front, inclusive.
64 Undefined elements of ir_data are always set to ir_default_val.
65 Popping from an empty ring aborts.
66 Pushing onto a full ring returns the displaced value.
67 An empty ring has F==B and ir_empty == true.
68 A ring with one entry still has F==B, but now ir_empty == false. */
69struct __I_ring
70{
71 int ir_data[__I_RING_SIZE];
72 int ir_default_val;
73 unsigned int ir_front;
74 unsigned int ir_back;
75 bool ir_empty;
76};
77typedef struct __I_ring __I_ring;
5678
5779typedef struct {
5880 struct _ftsent *fts_cur; /* current node */
......@@ -73,11 +95,106 @@ typedef struct {
7395#define FTS_SEEDOT 0x0020 /* return dot and dot-dot */
7496#define FTS_XDEV 0x0040 /* don't cross devices */
7597#define FTS_WHITEOUT 0x0080 /* return whiteout information */
76#define FTS_OPTIONMASK 0x00ff /* valid user option mask */
98
99 /* There are two ways to detect cycles.
100 The lazy way (which works only with FTS_PHYSICAL),
101 with which one may process a directory that is a
102 part of the cycle several times before detecting the cycle.
103 The "tight" way, whereby fts uses more memory (proportional
104 to number of "active" directories, aka distance from root
105 of current tree to current directory -- see active_dir_ht)
106 to detect any cycle right away. For example, du must use
107 this option to avoid counting disk space in a cycle multiple
108 times, but chown -R need not.
109 The default is to use the constant-memory lazy way, when possible
110 (see below).
111
112 However, with FTS_LOGICAL (when following symlinks, e.g., chown -L)
113 using lazy cycle detection is inadequate. For example, traversing
114 a directory containing a symbolic link to a peer directory, it is
115 possible to encounter the same directory twice even though there
116 is no cycle:
117 dir
118 ...
119 slink -> dir
120 So, when FTS_LOGICAL is selected, we have to use a different
121 mode of cycle detection: FTS_TIGHT_CYCLE_CHECK. */
122#define FTS_TIGHT_CYCLE_CHECK 0x0400
123
124 /* Use this flag to enable semantics with which the parent
125 application may be made both more efficient and more robust.
126 Whereas the default is to visit each directory in a recursive
127 traversal (via chdir), using this flag makes it so the initial
128 working directory is never changed. Instead, these functions
129 perform the traversal via a virtual working directory, maintained
130 through the file descriptor member, fts_cwd_fd. */
131# define FTS_CWDFD 0x0800
132
133 /* Historically, for each directory that fts initially encounters, it would
134 open it, read all entries, and stat each entry, storing the results, and
135 then it would process the first entry. But that behavior is bad for
136 locality of reference, and also causes trouble with inode-simulating
137 file systems like FAT, CIFS, FUSE-based ones, etc., when entries from
138 their name/inode cache are flushed too early.
139 Use this flag to make fts_open and fts_read defer the stat/lstat/fststat
140 of each entry until it is actually processed. However, note that if you
141 use this option and also specify a comparison function, that function may
142 not examine any data via fts_statp. However, when fts_statp->st_mode is
143 nonzero, the S_IFMT type bits are valid, with mapped dirent.d_type data.
144 Of course, that happens only on file systems that provide useful
145 dirent.d_type data. */
146#define FTS_DEFER_STAT 0x1000
147
148 /* Use this flag to disable stripping of trailing slashes
149 from input path names during fts_open initialization. */
150#define FTS_VERBATIM 0x2000
151
152#define FTS_MOUNT 0x4000 /* skip other devices */
153#define FTS_OPTIONMASK 0x7fff /* valid user option mask */
77154
78155#define FTS_NAMEONLY 0x0100 /* (private) child names only */
79156#define FTS_STOP 0x0200 /* (private) unrecoverable error */
157
80158 int fts_options; /* fts_open options, global flags */
159
160 int fts_cwd_fd; /* the file descriptor on which the
161 virtual cwd is open, or AT_FDCWD */
162
163 /* Map a directory's device number to a boolean. The boolean is
164 true if for that file system (type determined by a single fstatfs
165 call per FS) st_nlink can be used to calculate the number of
166 sub-directory entries in a directory.
167 Using this table is an optimization that permits us to look up
168 file system type on a per-inode basis at the minimal cost of
169 calling fstatfs only once per traversed device. */
170 struct hash_table *fts_leaf_optimization_works_ht;
171
172 union {
173 /* This data structure is used if FTS_TIGHT_CYCLE_CHECK is
174 specified. It records the directories between a starting
175 point and the current directory. I.e., a directory is
176 recorded here IFF we have visited it once, but we have not
177 yet completed processing of all its entries. Every time we
178 visit a new directory, we add that directory to this set.
179 When we finish with a directory (usually by visiting it a
180 second time), we remove it from this set. Each entry in
181 this data structure is a device/inode pair. This data
182 structure is used to detect directory cycles efficiently and
183 promptly even when the depth of a hierarchy is in the tens
184 of thousands. */
185 struct hash_table *ht;
186
187 /* FIXME: rename these two members to have the fts_ prefix */
188 /* This data structure uses a lazy cycle-detection algorithm,
189 as done by rm via cycle-check.c. It's the default,
190 but it's not appropriate for programs like du. */
191 struct cycle_check_state *state;
192 } fts_cycle;
193
194 /* A stack of the file descriptors corresponding to the
195 most-recently traversed parent directories.
196 Currently used only in FTS_CWDFD mode. */
197 __I_ring fts_fd_ring;
81198} FTS;
82199
83200#ifdef __USE_LARGEFILE64
......@@ -92,6 +209,13 @@ typedef struct {
92209 int fts_nitems; /* elements in the sort array */
93210 int (*fts_compar) (const void *, const void *); /* compare fn */
94211 int fts_options; /* fts_open options, global flags */
212 int fts_cwd_fd;
213 struct hash_table *fts_leaf_optimization_works_ht;
214 union {
215 struct hash_table *ht;
216 struct cycle_check_state *state;
217 } fts_cycle;
218 __I_ring fts_fd_ring;
95219} FTS64;
96220#endif
97221
lib/libc/include/generic-glibc/gnu/lib-names-32.h+1
......@@ -24,4 +24,5 @@
2424#define LIBRESOLV_SO "libresolv.so.2"
2525#define LIBRT_SO "librt.so.1"
2626#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
2728#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/generic-glibc/gnu/lib-names-hard.h+1
......@@ -24,4 +24,5 @@
2424#define LIBRESOLV_SO "libresolv.so.2"
2525#define LIBRT_SO "librt.so.1"
2626#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
2728#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/generic-glibc/gnu/lib-names-n32_hard.h+1
......@@ -23,4 +23,5 @@
2323#define LIBRESOLV_SO "libresolv.so.2"
2424#define LIBRT_SO "librt.so.1"
2525#define LIBTHREAD_DB_SO "libthread_db.so.1"
26#define LIBUNWIND_SO "libunwind.so.1"
2627#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/generic-glibc/gnu/lib-names-n64_hard.h+1
......@@ -23,4 +23,5 @@
2323#define LIBRESOLV_SO "libresolv.so.2"
2424#define LIBRT_SO "librt.so.1"
2525#define LIBTHREAD_DB_SO "libthread_db.so.1"
26#define LIBUNWIND_SO "libunwind.so.1"
2627#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/generic-glibc/gnu/lib-names-o32_hard.h+1
......@@ -23,4 +23,5 @@
2323#define LIBRESOLV_SO "libresolv.so.2"
2424#define LIBRT_SO "librt.so.1"
2525#define LIBTHREAD_DB_SO "libthread_db.so.1"
26#define LIBUNWIND_SO "libunwind.so.1"
2627#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/generic-glibc/gnu/lib-names-o32_soft.h+1
......@@ -23,4 +23,5 @@
2323#define LIBRESOLV_SO "libresolv.so.2"
2424#define LIBRT_SO "librt.so.1"
2525#define LIBTHREAD_DB_SO "libthread_db.so.1"
26#define LIBUNWIND_SO "libunwind.so.1"
2627#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/generic-glibc/gnu/lib-names-soft.h+1
......@@ -24,4 +24,5 @@
2424#define LIBRESOLV_SO "libresolv.so.2"
2525#define LIBRT_SO "librt.so.1"
2626#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
2728#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/generic-glibc/gnu/stubs-64.h deleted-16
......@@ -1,16 +0,0 @@
1/* This file is automatically generated.
2 It defines a symbol `__stub_FUNCTION' for each function
3 in the C library which is a stub, meaning it will fail
4 every time called, usually setting errno to ENOSYS. */
5
6#ifdef _LIBC
7 #error Applications may not define the macro _LIBC
8#endif
9
10#define __stub_chflags
11#define __stub_fchflags
12#define __stub_gtty
13#define __stub_revoke
14#define __stub_setlogin
15#define __stub_sigreturn
16#define __stub_stty
\ No newline at end of file
lib/libc/include/generic-glibc/netinet/in.h+2
......@@ -91,6 +91,8 @@ enum
9191#define IPPROTO_MPLS IPPROTO_MPLS
9292 IPPROTO_ETHERNET = 143, /* Ethernet-within-IPv6 Encapsulation. */
9393#define IPPROTO_ETHERNET IPPROTO_ETHERNET
94 IPPROTO_AGGFRAG = 144, /* AGGFRAG in ESP (RFC 9347). */
95#define IPPROTO_AGGFRAG IPPROTO_AGGFRAG
9496 IPPROTO_RAW = 255, /* Raw IP packets. */
9597#define IPPROTO_RAW IPPROTO_RAW
9698 IPPROTO_SMC = 256, /* Shared Memory Communications. */
lib/libc/include/generic-glibc/netinet/tcp.h+25-2
......@@ -80,6 +80,9 @@
8080 as a cmsg on read. */
8181#define TCP_CM_INQ TCP_INQ
8282#define TCP_TX_DELAY 37 /* Delay outgoing packets by XX usec. */
83#define TCP_RTO_MAX_MS 44 /* Max time to retransmit (msec). */
84#define TCP_RTO_MIN_US 45 /* Min time to retransmit (usec). */
85#define TCP_DELACK_MAX_US 46 /* Max delayed ack time (usec). */
8386
8487#define TCP_REPAIR_ON 1
8588#define TCP_REPAIR_OFF 0
......@@ -226,6 +229,24 @@ enum tcp_ca_state
226229 TCP_CA_Loss = 4
227230};
228231
232/* Values for tcpi_ecn_mode after negotiation. */
233#define TCPI_ECN_MODE_DISABLED 0x0
234#define TCPI_ECN_MODE_RFC3168 0x1
235#define TCPI_ECN_MODE_ACCECN 0x2
236#define TCPI_ECN_MODE_PENDING 0x3
237
238/* Values for tcpi_accecn_opt_seen. */
239#define TCP_ACCECN_OPT_NOT_SEEN 0x0
240#define TCP_ACCECN_OPT_EMPTY_SEEN 0x1
241#define TCP_ACCECN_OPT_COUNTER_SEEN 0x2
242#define TCP_ACCECN_OPT_FAIL_SEEN 0x3
243
244/* Values for tcpi_accecn_fail_mode. */
245#define TCP_ACCECN_ACE_FAIL_SEND 0x1
246#define TCP_ACCECN_ACE_FAIL_RECV 0x2
247#define TCP_ACCECN_OPT_FAIL_SEND 0x4
248#define TCP_ACCECN_OPT_FAIL_RECV 0x8
249
229250struct tcp_info
230251{
231252 uint8_t tcpi_state;
......@@ -319,8 +340,10 @@ struct tcp_info
319340 uint32_t tcpi_received_e1_bytes;
320341 uint32_t tcpi_received_e0_bytes;
321342 uint32_t tcpi_received_ce_bytes;
322 uint16_t tcpi_accecn_fail_mode;
323 uint16_t tcpi_accecn_opt_seen;
343 uint32_t tcpi_ecn_mode:2,
344 tcpi_accecn_opt_seen:2,
345 tcpi_accecn_fail_mode:4,
346 tcpi_options2:24;
324347};
325348
326349/* Netlink attributes types for SCM_TIMESTAMPING_OPT_STATS */
lib/libc/include/generic-glibc/regex.h+1-1
......@@ -74,7 +74,7 @@ typedef unsigned long int reg_syntax_t;
7474#ifdef __USE_GNU
7575/* If this bit is not set, then \ inside a bracket expression is literal.
7676 If set, then such a \ quotes the following character. */
77# define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1)
77# define RE_BACKSLASH_ESCAPE_IN_LISTS 1ul
7878
7979/* If this bit is not set, then + and ? are operators, and \+ and \? are
8080 literals.
lib/libc/include/generic-glibc/spawn.h+20
......@@ -200,6 +200,26 @@ extern int posix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t *
200200 int __fd, int __newfd)
201201 __THROW __nonnull ((1));
202202
203#ifdef __USE_XOPEN2K24XSI
204
205/* Add an action changing the directory to PATH during spawn. This
206 affects the subsequent file actions.
207 Alias of posix_spawn_file_actions_addchdir_np. */
208extern int __REDIRECT_NTH (posix_spawn_file_actions_addchdir,
209 (posix_spawn_file_actions_t * __restrict __actions,
210 const char *__restrict __path),
211 posix_spawn_file_actions_addchdir_np);
212
213/* Add an action changing the directory to FD during spawn. This
214 affects the subsequent file actions. FD is not duplicated and must
215 be open when the file action is executed.
216 Alias of posix_spawn_file_actions_addfchdir_np. */
217extern int __REDIRECT_NTH (posix_spawn_file_actions_addfchdir,
218 (posix_spawn_file_actions_t *, int __fd),
219 posix_spawn_file_actions_addfchdir_np);
220
221#endif /* __USE_XOPEN2K24XSI */
222
203223#ifdef __USE_MISC
204224/* Add an action changing the directory to PATH during spawn. This
205225 affects the subsequent file actions. */
lib/libc/include/generic-glibc/stdlib.h+1-1
......@@ -1225,4 +1225,4 @@ extern size_t memalignment (const void *__p);
12251225
12261226__END_DECLS
12271227
1228#endif /* stdlib.h */
1228#endif /* stdlib.h */
\ No newline at end of file
lib/libc/include/generic-glibc/sys/mount.h+18-4
......@@ -21,7 +21,6 @@
2121#ifndef _SYS_MOUNT_H
2222#define _SYS_MOUNT_H 1
2323
24#include <fcntl.h>
2524#include <features.h>
2625#include <stdint.h>
2726#include <stddef.h>
......@@ -190,6 +189,11 @@ enum
190189
191190/* fsmount flags. */
192191#define FSMOUNT_CLOEXEC 0x00000001
192// zig patch: check target glibc version
193#if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 44) || __GLIBC__ > 2
194#define FSMOUNT_NAMESPACE 0x00000002 /* Create the mount in a new mount
195 namespace. */
196#endif /* (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 44) || __GLIBC__ > 2 */
193197
194198/* mount attributes used on fsmount. */
195199#define MOUNT_ATTR_RDONLY 0x00000001 /* Mount read-only. */
......@@ -267,10 +271,20 @@ enum fsconfig_command
267271#define FSOPEN_CLOEXEC 0x00000001
268272
269273/* open_tree flags. */
270#define OPEN_TREE_CLONE 1 /* Clone the target tree and attach the clone */
271#define OPEN_TREE_CLOEXEC O_CLOEXEC /* Close the file on execve() */
272
274#ifndef OPEN_TREE_CLONE
275# define OPEN_TREE_CLONE 1 /* Clone the target tree and attach the clone */
276#endif
277#define OPEN_TREE_NAMESPACE (1 << 1) /* Clone the target tree into a new mount
278 namespace */
279#ifndef O_CLOEXEC
280# include <bits/cloexec.h>
281# define O_CLOEXEC __O_CLOEXEC
273282#endif
283#ifndef OPEN_TREE_CLOEXEC
284# define OPEN_TREE_CLOEXEC O_CLOEXEC /* Close the file on execve() */
285#endif
286
287#endif /* (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 36) || __GLIBC__ > 2 */
274288
275289__BEGIN_DECLS
276290
lib/libc/include/generic-glibc/sys/pidfd.h+26
......@@ -64,6 +64,15 @@
6464#define PIDFD_INFO_EXIT (1UL << 3)
6565/* Only returned if requested. */
6666#define PIDFD_INFO_COREDUMP (1UL << 4)
67// zig patch: check target glibc version
68#if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 44) || __GLIBC__ > 2
69/* Want/got supported mask flags */
70#define PIDFD_INFO_SUPPORTED_MASK (1UL << 5)
71/* Always returned if PIDFD_INFO_COREDUMP is requested. */
72#define PIDFD_INFO_COREDUMP_SIGNAL (1UL << 6)
73/* Always returned if PIDFD_INFO_COREDUMP is requested. */
74#define PIDFD_INFO_COREDUMP_CODE (1UL << 7)
75#endif /* (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 44) || __GLIBC__ > 2 */
6776
6877
6978/* Value for coredump_mask in pidfd_info. Only valid if PIDFD_INFO_COREDUMP
......@@ -95,11 +104,28 @@ struct pidfd_info
95104 __uint32_t fsgid;
96105 __int32_t exit_code;
97106 __uint32_t coredump_mask;
107// zig patch: check target glibc version
108#if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 44) || __GLIBC__ > 2
109 __uint32_t coredump_signal;
110 __uint32_t coredump_code;
111 __uint32_t coredump_pad;
112 __uint64_t supported_mask;
113#else
98114 __uint32_t __spare1;
115#endif /* (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 44) || __GLIBC__ > 2 */
99116};
100117
101118/* sizeof first published struct */
102119#define PIDFD_INFO_SIZE_VER0 64
120// zig patch: check target glibc version
121#if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 44) || __GLIBC__ > 2
122/* sizeof second published struct */
123#define PIDFD_INFO_SIZE_VER1 72
124/* sizeof third published struct */
125#define PIDFD_INFO_SIZE_VER2 80
126/* sizeof fourth published struct */
127#define PIDFD_INFO_SIZE_VER3 88
128#endif /* (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 44) || __GLIBC__ > 2 */
103129
104130#define PIDFD_GET_INFO _IOWR(PIDFS_IOCTL_MAGIC, 11, struct pidfd_info)
105131
lib/libc/include/generic-glibc/sys/platform/ppc.h deleted-146
......@@ -1,146 +0,0 @@
1/* Facilities specific to the PowerPC architecture
2 Copyright (C) 2012-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#ifndef _SYS_PLATFORM_PPC_H
20#define _SYS_PLATFORM_PPC_H 1
21
22#include <features.h>
23#include <stdint.h>
24#include <bits/ppc.h>
25
26/* Read the Time Base Register. */
27static __inline__ uint64_t
28__ppc_get_timebase (void)
29{
30#if __GNUC_PREREQ (4, 8)
31 return __builtin_ppc_get_timebase ();
32#else
33# ifdef __powerpc64__
34 uint64_t __tb;
35 /* "volatile" is necessary here, because the user expects this assembly
36 isn't moved after an optimization. */
37 __asm__ volatile ("mfspr %0, 268" : "=r" (__tb));
38 return __tb;
39# else /* not __powerpc64__ */
40 uint32_t __tbu, __tbl, __tmp; \
41 __asm__ volatile ("0:\n\t"
42 "mftbu %0\n\t"
43 "mftbl %1\n\t"
44 "mftbu %2\n\t"
45 "cmpw %0, %2\n\t"
46 "bne- 0b"
47 : "=r" (__tbu), "=r" (__tbl), "=r" (__tmp));
48 return (((uint64_t) __tbu << 32) | __tbl);
49# endif /* not __powerpc64__ */
50#endif
51}
52
53/* The following functions provide hints about the usage of shared processor
54 resources, as defined in ISA 2.06 and newer. */
55
56/* Provides a hint that performance will probably be improved if shared
57 resources dedicated to the executing processor are released for use by other
58 processors. */
59static __inline__ void
60__ppc_yield (void)
61{
62 __asm__ volatile ("or 27,27,27");
63}
64
65/* Provides a hint that performance will probably be improved if shared
66 resources dedicated to the executing processor are released until
67 all outstanding storage accesses to caching-inhibited storage have been
68 completed. */
69static __inline__ void
70__ppc_mdoio (void)
71{
72 __asm__ volatile ("or 29,29,29");
73}
74
75/* Provides a hint that performance will probably be improved if shared
76 resources dedicated to the executing processor are released until all
77 outstanding storage accesses to cacheable storage for which the data is not
78 in the cache have been completed. */
79static __inline__ void
80__ppc_mdoom (void)
81{
82 __asm__ volatile ("or 30,30,30");
83}
84
85
86/* ISA 2.05 and beyond support the Program Priority Register (PPR) to adjust
87 thread priorities based on lock acquisition, wait and release. The ISA
88 defines the use of form 'or Rx,Rx,Rx' as the way to modify the PRI field.
89 The unprivileged priorities are:
90 Rx = 1 (low)
91 Rx = 2 (medium)
92 Rx = 6 (medium-low/normal)
93 The 'or' instruction form is a nop in previous hardware, so it is safe to
94 use unguarded. The default value is 'medium'.
95 */
96
97static __inline__ void
98__ppc_set_ppr_med (void)
99{
100 __asm__ volatile ("or 2,2,2");
101}
102
103static __inline__ void
104__ppc_set_ppr_med_low (void)
105{
106 __asm__ volatile ("or 6,6,6");
107}
108
109static __inline__ void
110__ppc_set_ppr_low (void)
111{
112 __asm__ volatile ("or 1,1,1");
113}
114
115/* Power ISA 2.07 (Book II, Chapter 3) extends the priorities that can be set
116 to the Program Priority Register (PPR). The form 'or Rx,Rx,Rx' is used to
117 modify the PRI field of the PPR, the same way as described above.
118 The new priority levels are:
119 Rx = 31 (very low)
120 Rx = 5 (medium high)
121 Any program can set the priority to very low, low, medium low, and medium,
122 as these are unprivileged.
123 The medium high priority, on the other hand, is privileged, and may only be
124 set during certain time intervals by problem-state programs. If the program
125 priority is medium high when the time interval expires or if an attempt is
126 made to set the priority to medium high when it is not allowed, the PRI
127 field is set to medium.
128 */
129
130#ifdef _ARCH_PWR8
131
132static __inline__ void
133__ppc_set_ppr_very_low (void)
134{
135 __asm__ volatile ("or 31,31,31");
136}
137
138static __inline__ void
139__ppc_set_ppr_med_high (void)
140{
141 __asm__ volatile ("or 5,5,5");
142}
143
144#endif
145
146#endif /* sys/platform/ppc.h */
\ No newline at end of file
lib/libc/include/generic-netbsd/fcntl.h+4-1
......@@ -1,4 +1,4 @@
1/* $NetBSD: fcntl.h,v 1.57 2025/07/25 23:24:46 kre Exp $ */
1/* $NetBSD: fcntl.h,v 1.57.2.1 2026/06/16 09:06:50 martin Exp $ */
22
33/*-
44 * Copyright (c) 1983, 1990, 1993
......@@ -121,6 +121,9 @@
121121#if defined(_NETBSD_SOURCE)
122122#define O_NOSIGPIPE 0x01000000 /* don't deliver sigpipe */
123123#define O_REGULAR 0x02000000 /* fail if not a regular file */
124#endif
125#if (_POSIX_C_SOURCE - 0) >= 200809L || (_XOPEN_SOURCE - 0 >= 700) || \
126 defined(_NETBSD_SOURCE)
124127#define O_EXEC 0x04000000 /* open for executing only */
125128#endif
126129#if (_POSIX_C_SOURCE - 0) >= 202405L || (_XOPEN_SOURCE - 0 >= 800) || \
lib/libc/include/generic-netbsd/i386/mcontext.h+23-1
......@@ -1,4 +1,4 @@
1/* $NetBSD: mcontext.h,v 1.19 2024/11/30 01:04:10 christos Exp $ */
1/* $NetBSD: mcontext.h,v 1.19.2.1 2026/07/19 15:57:27 martin Exp $ */
22
33/*-
44 * Copyright (c) 1999 The NetBSD Foundation, Inc.
......@@ -40,6 +40,7 @@
4040#define _UC_CLRSTACK _UC_MD_BIT17
4141#define _UC_VM _UC_MD_BIT18
4242#define _UC_TLSBASE _UC_MD_BIT19
43#define _UC_XSAVE _UC_MD_BIT20
4344
4445/*
4546 * Layout of mcontext_t according to the System V Application Binary Interface,
......@@ -85,6 +86,27 @@ typedef struct {
8586 char __fp_xmm[512];
8687 } __fp_xmm_state; /* x87 and xmm regs in fxsave format */
8788 int __fp_fpregs[128];
89 struct {
90 /*
91 * `The XSAVE feature set does not use bytes
92 * 511:416; bytes 463:416 are reserved.'
93 *
94 * We take a part out of this to form a pointer
95 * to an external XSAVE area. This way, we can
96 * replicate the FXSAVE parts for the benefit
97 * of userland programs that aren't aware of
98 * the XSAVE pointer, have used the extended
99 * CPU registers (ymmN/zmmN/&c.), and want to
100 * examine the x87/SSE register state in a
101 * signal handler. The kernel does not use
102 * this part.
103 */
104 char __fxsave[416];
105 char __rsvd[48];
106 __greg_t __xsaveptr;
107 __greg_t __xsavelen;
108 char __pad[40];
109 } __xsave;
88110 } __fp_reg_set;
89111 int __fp_pad[33]; /* Historic padding */
90112} __fpregset_t;
lib/libc/include/generic-netbsd/i386/wchar_limits.h+1-1
......@@ -44,4 +44,4 @@
4444#define WINT_MIN (-0x7fffffff-1) /* wint_t */
4545#define WINT_MAX 0x7fffffff /* wint_t */
4646
47#endif /* !_I386_WCHAR_LIMITS_H_ */
47#endif /* !_I386_WCHAR_LIMITS_H_ */
\ No newline at end of file
lib/libc/include/generic-netbsd/machine/pte.h+32-19
......@@ -1,4 +1,4 @@
1/* $NetBSD: pte.h,v 1.14.2.2 2025/10/26 12:28:36 martin Exp $ */
1/* $NetBSD: pte.h,v 1.14.2.3 2026/06/03 18:17:02 martin Exp $ */
22
33/*
44 * Copyright (c) 2014, 2019, 2021 The NetBSD Foundation, Inc.
......@@ -139,6 +139,12 @@ pte_modified_p(pt_entry_t pte)
139139 return (pte & PTE_D) != 0;
140140}
141141
142static inline bool
143pte_referenced_p(pt_entry_t pte)
144{
145 return (pte & PTE_A) != 0;
146}
147
142148static inline bool
143149pte_cached_p(pt_entry_t pte)
144150{
......@@ -177,9 +183,15 @@ pte_nv_entry(bool kernel_p)
177183}
178184
179185static inline pt_entry_t
180pte_prot_nowrite(pt_entry_t pte)
186pte_clear_modify(pt_entry_t pte)
187{
188 return pte & ~PTE_D;
189}
190
191static inline pt_entry_t
192pte_clear_reference(pt_entry_t pte)
181193{
182 return pte & ~PTE_W;
194 return pte & ~PTE_A;
183195}
184196
185197static inline pt_entry_t
......@@ -237,28 +249,29 @@ pte_make_enter(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot,
237249 pte |= pte_prot_bits(mdpg, prot, kernel_p);
238250 pte |= pte_enter_flags_to_pbmt(flags);
239251
240 if (mdpg != NULL) {
252 /*
253 * pmap_enter should have checked flags and updated
254 * VM_PAGEMD_{REFERENCED,MODIFIED}_P, so there is no
255 * need here.
256 */
257 KASSERT(((flags & VM_PROT_ALL) == 0) || VM_PAGEMD_REFERENCED_P(mdpg));
258 KASSERT(((flags & VM_PROT_WRITE) == 0) || VM_PAGEMD_MODIFIED_P(mdpg));
241259
242 if ((prot & VM_PROT_WRITE) != 0 &&
243 ((flags & VM_PROT_WRITE) != 0 || VM_PAGEMD_MODIFIED_P(mdpg))) {
260 if (mdpg != NULL) {
261 if ((prot & VM_PROT_WRITE) != 0 && VM_PAGEMD_MODIFIED_P(mdpg)) {
244262 /*
245 * This is a writable mapping, and the page's mod state
246 * indicates it has already been modified. No need for
247 * modified emulation.
248 */
263 * This is a writable mapping, and the page's mod state
264 * indicates it has already been modified. No need for
265 * reference or modified emulation.
266 */
249267 pte |= PTE_A | PTE_D;
250 } else if ((flags & VM_PROT_ALL) || VM_PAGEMD_REFERENCED_P(mdpg)) {
268 } else if (VM_PAGEMD_REFERENCED_P(mdpg)) {
251269 /*
252 * - The access type indicates that we don't need to do
253 * referenced emulation.
254 * OR
255 * - The physical page has already been referenced so no need
256 * to re-do referenced emulation here.
257 */
270 * The physical page has already been referenced so no need
271 * to re-do referenced emulation here.
272 */
258273 pte |= PTE_A;
259274 }
260 } else {
261 pte |= PTE_A | PTE_D;
262275 }
263276
264277 return pte;
lib/libc/include/generic-netbsd/machine/vmparam.h+21-9
......@@ -1,4 +1,4 @@
1/* $NetBSD: vmparam.h,v 1.14 2023/05/07 12:41:48 skrll Exp $ */
1/* $NetBSD: vmparam.h,v 1.14.8.2 2026/06/03 18:17:02 martin Exp $ */
22
33/*-
44 * Copyright (c) 2014, 2020 The NetBSD Foundation, Inc.
......@@ -50,6 +50,25 @@
5050#define PAGE_SIZE (1 << PAGE_SHIFT)
5151#define PAGE_MASK (PAGE_SIZE - 1)
5252
53#ifdef _LP64
54/*
55 * Default pager_map of 16MB is awfully small. There is plenty
56 * of VA so use it.
57 */
58#define PAGER_MAP_DEFAULT_SIZE (512 * 1024 * 1024)
59
60/*
61 * Defaults for Unified Buffer Cache parameters.
62 */
63
64#ifndef UBC_WINSHIFT
65#define UBC_WINSHIFT 16 /* 64kB */
66#endif
67#ifndef UBC_NWINS
68#define UBC_NWINS 4096 /* 256MB */
69#endif
70#endif
71
5372/*
5473 * USRSTACK is the top (end) of the user stack.
5574 *
......@@ -125,12 +144,6 @@
125144#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)0xffffffd000000000)
126145
127146#else /* Sv32 */
128/*
129 * kernel virtual space layout:
130 * 0x8000_0000 - 64GiB KERNEL VM Space (inc. text/data/bss)
131 * (0x4000_0000 +1GiB) KERNEL VM start of KVA
132 * (0x0000_0000 64GiB) reserved
133 */
134147
135148/*
136149 * kernel virtual space layout without direct map (common case)
......@@ -154,13 +167,12 @@
154167 *
155168 */
156169
157
158
159170#define VM_MAXUSER_ADDRESS ((vaddr_t)-0x7fffffff-1)/* 0xffff_ffff_8000_0000 */
160171#define VM_MIN_KERNEL_ADDRESS ((vaddr_t)-0x7fffffff-1)/* 0xffff_ffff_8000_0000 */
161172#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)-0x10000000) /* 0xffff_ffff_f000_0000 */
162173
163174#endif
175
164176#define VM_KERNEL_BASE VM_MIN_KERNEL_ADDRESS
165177#define VM_KERNEL_SIZE 0x2000000 /* 32 MiB (8 / 16 megapages) */
166178#define VM_KERNEL_DTB_BASE (VM_KERNEL_BASE + VM_KERNEL_SIZE)
lib/libc/include/generic-netbsd/mips/pte.h+14-2
......@@ -1,4 +1,4 @@
1/* $NetBSD: pte.h,v 1.27 2020/08/22 15:34:51 skrll Exp $ */
1/* $NetBSD: pte.h,v 1.27.28.1 2026/06/03 18:17:03 martin Exp $ */
22
33/*-
44 * Copyright (c) 1997 The NetBSD Foundation, Inc.
......@@ -269,6 +269,12 @@ pte_modified_p(pt_entry_t pte)
269269 return (pte & MIPS_MMU(PG_D)) != 0;
270270}
271271
272static inline bool
273pte_referenced_p(pt_entry_t pte)
274{
275 return false;
276}
277
272278static inline bool
273279pte_global_p(pt_entry_t pte)
274280{
......@@ -340,11 +346,17 @@ pte_prot_downgrade(pt_entry_t pte, vm_prot_t prot)
340346}
341347
342348static inline pt_entry_t
343pte_prot_nowrite(pt_entry_t pte)
349pte_clear_modify(pt_entry_t pte)
344350{
345351 return pte & ~MIPS_MMU(PG_D);
346352}
347353
354static inline pt_entry_t
355pte_clear_reference(pt_entry_t pte)
356{
357 return pte;
358}
359
348360static inline pt_entry_t
349361pte_cached_change(pt_entry_t pte, bool cached)
350362{
lib/libc/include/generic-netbsd/netinet/tcp_timer.h+2-2
......@@ -1,4 +1,4 @@
1/* $NetBSD: tcp_timer.h,v 1.30 2019/08/06 15:48:18 riastradh Exp $ */
1/* $NetBSD: tcp_timer.h,v 1.30.34.1 2026/07/19 15:51:03 martin Exp $ */
22
33/*-
44 * Copyright (c) 2001, 2005 The NetBSD Foundation, Inc.
......@@ -119,7 +119,7 @@
119119#define TCPTV_MSL ( 30*PR_SLOWHZ) /* max seg lifetime (hah!) */
120120#define TCPTV_SRTTBASE 0 /* base roundtrip time;
121121 if 0, no idea yet */
122#define TCPTV_SRTTDFLT ( 3*PR_SLOWHZ) /* assumed RTT if no info */
122#define TCPTV_SRTTDFLT ( 1*PR_SLOWHZ) /* initial RTO; RFC 6298 (2.1) */
123123
124124#define TCPTV_PERSMIN ( 5*PR_SLOWHZ) /* retransmit persistance */
125125#define TCPTV_PERSMAX ( 60*PR_SLOWHZ) /* maximum persist interval */
lib/libc/include/generic-netbsd/nfs/nfs.h+3-1
......@@ -1,4 +1,4 @@
1/* $NetBSD: nfs.h,v 1.81 2024/12/07 02:05:55 riastradh Exp $ */
1/* $NetBSD: nfs.h,v 1.81.2.1 2026/06/27 09:46:05 martin Exp $ */
22/*
33 * Copyright (c) 1989, 1993, 1995
44 * The Regents of the University of California. All rights reserved.
......@@ -451,6 +451,8 @@ struct nfssvc_sock {
451451 int ns_sflags; /* b: */
452452 int ns_cc; /* b: */
453453 int ns_reclen; /* b: */
454 int ns_frag_count; /* b: */
455 int ns_streamlen; /* b: */
454456 int ns_numuids;
455457 u_int32_t ns_sref; /* g: */
456458 SIMPLEQ_HEAD(, nfsrv_descript) ns_sendq; /* s: send reply list */
lib/libc/include/generic-netbsd/nfs/nfsmount.h+4-2
......@@ -1,4 +1,4 @@
1/* $NetBSD: nfsmount.h,v 1.54 2024/12/07 02:05:55 riastradh Exp $ */
1/* $NetBSD: nfsmount.h,v 1.54.2.1 2026/06/03 18:46:36 martin Exp $ */
22
33/*
44 * Copyright (c) 1989, 1993
......@@ -92,13 +92,15 @@ struct nfs_args {
9292#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
9393#define NFSMNT_XLATECOOKIE 0x00040000 /* 32<->64 dir cookie xlation */
9494#define NFSMNT_NOAC 0x00080000 /* Turn off attribute cache */
95#define NFSMNT_NOWCCMSG 0x00100000 /* Turn off attribute wcc messages */
9596
9697#define NFSMNT_BITS "\177\20" \
9798 "b\00soft\0b\01wsize\0b\02rsize\0b\03timeo\0" \
9899 "b\04retrans\0b\05maxgrps\0b\06intr\0b\07noconn\0" \
99100 "b\10nqnfs\0b\11nfsv3\0b\12kerb\0b\13dumbtimr\0" \
100101 "b\14leaseterm\0b\15readahead\0b\16deadthresh\0b\17resvport\0" \
101 "b\20rdirplus\0b\21readdirsize\0b\22xlatecookie\0b\23noac\0"
102 "b\20rdirplus\0b\21readdirsize\0b\22xlatecookie\0b\23noac\0" \
103 "b\24nowccmsg\0"
102104
103105/*
104106 * NFS internal flags (nm_iflag) */
lib/libc/include/generic-netbsd/pthread.h+1-1
......@@ -461,4 +461,4 @@ __END_DECLS
461461
462462#endif /* __LIBPTHREAD_SOURCE__ */
463463
464#endif /* _LIB_PTHREAD_H */
464#endif /* _LIB_PTHREAD_H */
\ No newline at end of file
lib/libc/include/generic-netbsd/riscv/pte.h+32-19
......@@ -1,4 +1,4 @@
1/* $NetBSD: pte.h,v 1.14.2.2 2025/10/26 12:28:36 martin Exp $ */
1/* $NetBSD: pte.h,v 1.14.2.3 2026/06/03 18:17:02 martin Exp $ */
22
33/*
44 * Copyright (c) 2014, 2019, 2021 The NetBSD Foundation, Inc.
......@@ -139,6 +139,12 @@ pte_modified_p(pt_entry_t pte)
139139 return (pte & PTE_D) != 0;
140140}
141141
142static inline bool
143pte_referenced_p(pt_entry_t pte)
144{
145 return (pte & PTE_A) != 0;
146}
147
142148static inline bool
143149pte_cached_p(pt_entry_t pte)
144150{
......@@ -177,9 +183,15 @@ pte_nv_entry(bool kernel_p)
177183}
178184
179185static inline pt_entry_t
180pte_prot_nowrite(pt_entry_t pte)
186pte_clear_modify(pt_entry_t pte)
187{
188 return pte & ~PTE_D;
189}
190
191static inline pt_entry_t
192pte_clear_reference(pt_entry_t pte)
181193{
182 return pte & ~PTE_W;
194 return pte & ~PTE_A;
183195}
184196
185197static inline pt_entry_t
......@@ -237,28 +249,29 @@ pte_make_enter(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot,
237249 pte |= pte_prot_bits(mdpg, prot, kernel_p);
238250 pte |= pte_enter_flags_to_pbmt(flags);
239251
240 if (mdpg != NULL) {
252 /*
253 * pmap_enter should have checked flags and updated
254 * VM_PAGEMD_{REFERENCED,MODIFIED}_P, so there is no
255 * need here.
256 */
257 KASSERT(((flags & VM_PROT_ALL) == 0) || VM_PAGEMD_REFERENCED_P(mdpg));
258 KASSERT(((flags & VM_PROT_WRITE) == 0) || VM_PAGEMD_MODIFIED_P(mdpg));
241259
242 if ((prot & VM_PROT_WRITE) != 0 &&
243 ((flags & VM_PROT_WRITE) != 0 || VM_PAGEMD_MODIFIED_P(mdpg))) {
260 if (mdpg != NULL) {
261 if ((prot & VM_PROT_WRITE) != 0 && VM_PAGEMD_MODIFIED_P(mdpg)) {
244262 /*
245 * This is a writable mapping, and the page's mod state
246 * indicates it has already been modified. No need for
247 * modified emulation.
248 */
263 * This is a writable mapping, and the page's mod state
264 * indicates it has already been modified. No need for
265 * reference or modified emulation.
266 */
249267 pte |= PTE_A | PTE_D;
250 } else if ((flags & VM_PROT_ALL) || VM_PAGEMD_REFERENCED_P(mdpg)) {
268 } else if (VM_PAGEMD_REFERENCED_P(mdpg)) {
251269 /*
252 * - The access type indicates that we don't need to do
253 * referenced emulation.
254 * OR
255 * - The physical page has already been referenced so no need
256 * to re-do referenced emulation here.
257 */
270 * The physical page has already been referenced so no need
271 * to re-do referenced emulation here.
272 */
258273 pte |= PTE_A;
259274 }
260 } else {
261 pte |= PTE_A | PTE_D;
262275 }
263276
264277 return pte;
lib/libc/include/generic-netbsd/riscv/vmparam.h+21-9
......@@ -1,4 +1,4 @@
1/* $NetBSD: vmparam.h,v 1.14 2023/05/07 12:41:48 skrll Exp $ */
1/* $NetBSD: vmparam.h,v 1.14.8.2 2026/06/03 18:17:02 martin Exp $ */
22
33/*-
44 * Copyright (c) 2014, 2020 The NetBSD Foundation, Inc.
......@@ -50,6 +50,25 @@
5050#define PAGE_SIZE (1 << PAGE_SHIFT)
5151#define PAGE_MASK (PAGE_SIZE - 1)
5252
53#ifdef _LP64
54/*
55 * Default pager_map of 16MB is awfully small. There is plenty
56 * of VA so use it.
57 */
58#define PAGER_MAP_DEFAULT_SIZE (512 * 1024 * 1024)
59
60/*
61 * Defaults for Unified Buffer Cache parameters.
62 */
63
64#ifndef UBC_WINSHIFT
65#define UBC_WINSHIFT 16 /* 64kB */
66#endif
67#ifndef UBC_NWINS
68#define UBC_NWINS 4096 /* 256MB */
69#endif
70#endif
71
5372/*
5473 * USRSTACK is the top (end) of the user stack.
5574 *
......@@ -125,12 +144,6 @@
125144#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)0xffffffd000000000)
126145
127146#else /* Sv32 */
128/*
129 * kernel virtual space layout:
130 * 0x8000_0000 - 64GiB KERNEL VM Space (inc. text/data/bss)
131 * (0x4000_0000 +1GiB) KERNEL VM start of KVA
132 * (0x0000_0000 64GiB) reserved
133 */
134147
135148/*
136149 * kernel virtual space layout without direct map (common case)
......@@ -154,13 +167,12 @@
154167 *
155168 */
156169
157
158
159170#define VM_MAXUSER_ADDRESS ((vaddr_t)-0x7fffffff-1)/* 0xffff_ffff_8000_0000 */
160171#define VM_MIN_KERNEL_ADDRESS ((vaddr_t)-0x7fffffff-1)/* 0xffff_ffff_8000_0000 */
161172#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)-0x10000000) /* 0xffff_ffff_f000_0000 */
162173
163174#endif
175
164176#define VM_KERNEL_BASE VM_MIN_KERNEL_ADDRESS
165177#define VM_KERNEL_SIZE 0x2000000 /* 32 MiB (8 / 16 megapages) */
166178#define VM_KERNEL_DTB_BASE (VM_KERNEL_BASE + VM_KERNEL_SIZE)
lib/libc/include/generic-netbsd/sys/fcntl.h+4-1
......@@ -1,4 +1,4 @@
1/* $NetBSD: fcntl.h,v 1.57 2025/07/25 23:24:46 kre Exp $ */
1/* $NetBSD: fcntl.h,v 1.57.2.1 2026/06/16 09:06:50 martin Exp $ */
22
33/*-
44 * Copyright (c) 1983, 1990, 1993
......@@ -121,6 +121,9 @@
121121#if defined(_NETBSD_SOURCE)
122122#define O_NOSIGPIPE 0x01000000 /* don't deliver sigpipe */
123123#define O_REGULAR 0x02000000 /* fail if not a regular file */
124#endif
125#if (_POSIX_C_SOURCE - 0) >= 200809L || (_XOPEN_SOURCE - 0 >= 700) || \
126 defined(_NETBSD_SOURCE)
124127#define O_EXEC 0x04000000 /* open for executing only */
125128#endif
126129#if (_POSIX_C_SOURCE - 0) >= 202405L || (_XOPEN_SOURCE - 0 >= 800) || \
lib/libc/include/generic-netbsd/sys/lua.h+3-1
......@@ -1,4 +1,4 @@
1/* $NetBSD: lua.h,v 1.9 2023/07/11 14:57:21 martin Exp $ */
1/* $NetBSD: lua.h,v 1.9.8.1 2026/06/29 19:52:23 martin Exp $ */
22
33/*
44 * Copyright (c) 2014 by Lourival Vieira Neto <lneto@NetBSD.org>.
......@@ -33,7 +33,9 @@
3333#define _SYS_LUA_H_
3434
3535#include <sys/param.h>
36
3637#include <sys/ioccom.h>
38#include <sys/stdbool.h>
3739
3840#include <lua.h> /* for lua_State */
3941
lib/libc/include/generic-netbsd/sys/param.h+2-2
......@@ -1,4 +1,4 @@
1/* $NetBSD: param.h,v 1.738.2.5 2026/05/12 04:23:51 martin Exp $ */
1/* $NetBSD: param.h,v 1.738.2.9 2026/07/30 15:23:12 martin Exp $ */
22
33/*-
44 * Copyright (c) 1982, 1986, 1989, 1993
......@@ -566,4 +566,4 @@ extern size_t coherency_unit;
566566#endif
567567#endif /* !__ASSEMBLER__ */
568568
569#endif /* !_SYS_PARAM_H_ */
569#endif /* !_SYS_PARAM_H_ */
\ No newline at end of file
lib/libc/include/generic-netbsd/x86/cpu_extended_state.h+3-1
......@@ -1,4 +1,4 @@
1/* $NetBSD: cpu_extended_state.h,v 1.19 2025/04/24 01:50:39 riastradh Exp $ */
1/* $NetBSD: cpu_extended_state.h,v 1.19.2.1 2026/07/19 15:57:27 martin Exp $ */
22
33#ifndef _X86_CPU_EXTENDED_STATE_H_
44#define _X86_CPU_EXTENDED_STATE_H_
......@@ -142,6 +142,8 @@ struct xsave_header {
142142};
143143__CTASSERT(sizeof(struct xsave_header) == 512 + 64);
144144
145#define XSAVE_ALIGN 64
146
145147/*
146148 * The ymm save area actually follows the xsave_header.
147149 */
lib/libc/include/generic-netbsd/x86/fpu.h+7-1
......@@ -1,4 +1,4 @@
1/* $NetBSD: fpu.h,v 1.23 2020/10/24 07:14:29 mgorny Exp $ */
1/* $NetBSD: fpu.h,v 1.23.28.1 2026/07/19 15:57:27 martin Exp $ */
22
33#ifndef _X86_FPU_H_
44#define _X86_FPU_H_
......@@ -46,6 +46,12 @@ int process_read_xstate(struct lwp *, struct xstate *);
4646int process_verify_xstate(const struct xstate *);
4747int process_write_xstate(struct lwp *, const struct xstate *);
4848
49bool process_xsave_needed_p(struct lwp *);
50void process_read_xsave(struct lwp *, const struct xsave_header **, size_t *);
51int process_verify_xsavelen(struct lwp *, size_t);
52int process_verify_xsave(struct lwp *, const struct xsave_header *, size_t);
53void process_write_xsave(struct lwp *, const struct xsave_header *, size_t);
54
4955#endif
5056
5157#endif /* _X86_FPU_H_ */
\ No newline at end of file
lib/libc/include/generic-netbsd/x86/specialreg.h+71-5
......@@ -1,4 +1,4 @@
1/* $NetBSD: specialreg.h,v 1.219 2025/04/28 13:01:27 riastradh Exp $ */
1/* $NetBSD: specialreg.h,v 1.219.2.1 2026/07/19 15:57:27 martin Exp $ */
22
33/*
44 * Copyright (c) 2014-2020 The NetBSD Foundation, Inc.
......@@ -183,16 +183,82 @@
183183 "\0"
184184
185185/*
186 * Known FPU bits, only these get enabled. The save area is sized for all the
187 * fields below.
186 * XCR0_FPU: Known FPU bits, only these get enabled. The save area is
187 * sized for all the fields below.
188 *
189 * Any bits added to this will expand the extended CPU state that we
190 * may have to save and restore with XSAVE for userland processes,
191 * either in the kernel when preempting threads, or on the user's stack
192 * when delivering a signal.
193 *
194 * The kernel can dyanmically allocate larger sizes (on amd64, anyway,
195 * though not currently on i386 or Xen PV). But if the XSAVE area is
196 * expanded so much that it and mcontext_t exceed MINSIGSTKSZ
197 * (currently 8192), a userland ABI change and compatibility layer is
198 * required to accommodate that, because existing programs may use
199 * sigaltstack(2) with stacks sized for the old MINSIGSTKSZ.
200 *
201 * The current stack requirement is 3160 bytes of space plus up to
202 * 63+15+8=86 bytes of padding for alignment (could be reduced by
203 * around 512 bytes by having mcontext_t overlap with the XSAVE area a
204 * little in machdep.c cpu_getmcontext_xsave, but we don't do that
205 * right now):
206 *
207 * - mcontext_t (728 bytes: general registers and 512-byte FXSAVE area)
208 * - XSAVE header (576 bytes: 512 bytes of FXSAVE, 64 bytes of metadata)
209 * - AVX state: ymm0..ymm15 high 128-bit halves (256 bytes)
210 * - AVX-512 state:
211 * . k0..k7 opmask registers (64 bytes)
212 * . zmm0..zmm15 high 256-bit halves (512 bytes)
213 * . zmm16..zmm31 registers (1024 bytes)
214 *
215 * Likely future extensions that would expand the state beyond
216 * MINSIGSTKSZ:
217 *
218 * - AMX (Advanced Matrix Extensions) and ACE (AI Compute Extensions)
219 * state:
220 * . [AMX/ACE] TILECFG (64 bytes)
221 * . [AMX/ACE] TILEDATA (8192 bytes)
222 * . [ACE] SCALEDATA (128 bytes)
223 *
224 * As a precaution against ABI breakage, x86/identcpu.c will panic at
225 * boot if the XSAVE state size enabled in XCR0 exceeds MINSIGSTKSZ.
226 *
227 * References:
228 *
229 * - Intel 64 and IA-32 Architectures Software Developer's Manual,
230 * Volume 1: Basic Architecture, Intel, Order Number: 253665-092US,
231 * June 2026, Sec. 13.1 `XSAVE-Supported Features and State-Component
232 * Bitmaps', pp. 13-1 -- 13-2.
233 * https://web.archive.org/web/20260709150417/https://cdrdv2-public.intel.com/922477/253665-092-sdm-vol-1.pdf
234 *
235 * - AI Compute Extensions (ACE) Specification, x86 Ecosystem Advisory
236 * Group, Version 1.15, 2026-05-15, Sec 15.4.1 `XSAVE State
237 * Components', p. 86.
238 * https://web.archive.org/web/20260619062626/https://x86ecosystem.org/wp-content/uploads/2026/06/ACE_v1_Specification_public_1_15.pdf
188239 */
189240#if defined __i386__ || defined XENPV /* XXX XENPV PR kern/59371 */
190241#define XCR0_FPU (XCR0_X87 | XCR0_SSE | XCR0_YMM_Hi128 | \
191242 XCR0_Opmask | XCR0_ZMM_Hi256 | XCR0_Hi16_ZMM)
192243#else
193244#define XCR0_FPU (XCR0_X87 | XCR0_SSE | XCR0_YMM_Hi128 | \
194 XCR0_Opmask | XCR0_ZMM_Hi256 | XCR0_Hi16_ZMM | \
195 XCR0_TILECFG | XCR0_TILEDATA)
245 XCR0_Opmask | XCR0_ZMM_Hi256 | XCR0_Hi16_ZMM)
246#endif
247
248/*
249 * Maximum size of XSAVE state that we can handle without ABI changes
250 * to userland. Must match usage in cpu_getmcontext. Extra 8 is neeed
251 * on amd64 to have space for return address in 16-byte-aligned stack
252 * frame.
253 */
254#ifdef __x86_64__
255#define XSAVE_MAX_BYTES \
256 (MINSIGSTKSZ - (8 + STACK_ALIGNBYTES + \
257 sizeof(struct sigframe_siginfo) + (XSAVE_ALIGN - 1)))
258#else
259#define XSAVE_MAX_BYTES \
260 (MINSIGSTKSZ - (STACK_ALIGNBYTES + \
261 sizeof(struct sigframe_siginfo) + (XSAVE_ALIGN - 1)))
196262#endif
197263
198264/*
lib/libc/include/loongarch-linux-gnu/bits/hwcap.h+3-1
......@@ -36,4 +36,6 @@
3636#define HWCAP_LOONGARCH_LBT_ARM (1 << 11)
3737#define HWCAP_LOONGARCH_LBT_MIPS (1 << 12)
3838#define HWCAP_LOONGARCH_PTW (1 << 13)
39#define HWCAP_LOONGARCH_LSPW (1 << 14)
\ No newline at end of file
39#define HWCAP_LOONGARCH_LSPW (1 << 14)
40#define HWCAP_LOONGARCH_SCQ (1 << 15)
41#define HWCAP_LOONGARCH_LAM_BH (1 << 16)
\ No newline at end of file
lib/libc/include/loongarch-linux-gnu/bits/long-double.h deleted-21
......@@ -1,21 +0,0 @@
1/* Properties of long double type. ldbl-128 version.
2 Copyright (C) 2016-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19/* long double is distinct from double, so there is nothing to
20 define here. */
21#define __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI 0
\ No newline at end of file
lib/libc/include/loongarch-linux-gnu/bits/struct_stat.h deleted-127
......@@ -1,127 +0,0 @@
1/* Definition for struct stat.
2 Copyright (C) 2020-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library. If not, see
17 <https://www.gnu.org/licenses/>. */
18
19#if !defined _SYS_STAT_H && !defined _FCNTL_H
20# error "Never include <bits/struct_stat.h> directly; use <sys/stat.h> instead."
21#endif
22
23#ifndef _BITS_STRUCT_STAT_H
24#define _BITS_STRUCT_STAT_H 1
25
26#include <bits/endian.h>
27#include <bits/wordsize.h>
28
29#if defined __USE_FILE_OFFSET64
30# define __field64(type, type64, name) type64 name
31#elif __WORDSIZE == 64 || defined __INO_T_MATCHES_INO64_T
32# if defined __INO_T_MATCHES_INO64_T && !defined __OFF_T_MATCHES_OFF64_T
33# error "ino_t and off_t must both be the same type"
34# endif
35# define __field64(type, type64, name) type name
36#elif __BYTE_ORDER == __LITTLE_ENDIAN
37# define __field64(type, type64, name) \
38 type name __attribute__((__aligned__ (__alignof__ (type64)))); int __##name##_pad
39#else
40# define __field64(type, type64, name) \
41 int __##name##_pad __attribute__((__aligned__ (__alignof__ (type64)))); type name
42#endif
43
44struct stat
45 {
46 __dev_t st_dev; /* Device. */
47 __field64(__ino_t, __ino64_t, st_ino); /* File serial number. */
48 __mode_t st_mode; /* File mode. */
49 __nlink_t st_nlink; /* Link count. */
50 __uid_t st_uid; /* User ID of the file's owner. */
51 __gid_t st_gid; /* Group ID of the file's group.*/
52 __dev_t st_rdev; /* Device number, if device. */
53 __dev_t __pad1;
54 __field64(__off_t, __off64_t, st_size); /* Size of file, in bytes. */
55 __blksize_t st_blksize; /* Optimal block size for I/O. */
56 int __pad2;
57 __field64(__blkcnt_t, __blkcnt64_t, st_blocks); /* 512-byte blocks */
58#ifdef __USE_XOPEN2K8
59 /* Nanosecond resolution timestamps are stored in a format
60 equivalent to 'struct timespec'. This is the type used
61 whenever possible but the Unix namespace rules do not allow the
62 identifier 'timespec' to appear in the <sys/stat.h> header.
63 Therefore we have to handle the use of this header in strictly
64 standard-compliant sources special. */
65 struct timespec st_atim; /* Time of last access. */
66 struct timespec st_mtim; /* Time of last modification. */
67 struct timespec st_ctim; /* Time of last status change. */
68# define st_atime st_atim.tv_sec /* Backward compatibility. */
69# define st_mtime st_mtim.tv_sec
70# define st_ctime st_ctim.tv_sec
71#else
72 __time_t st_atime; /* Time of last access. */
73 unsigned long int st_atimensec; /* Nscecs of last access. */
74 __time_t st_mtime; /* Time of last modification. */
75 unsigned long int st_mtimensec; /* Nsecs of last modification. */
76 __time_t st_ctime; /* Time of last status change. */
77 unsigned long int st_ctimensec; /* Nsecs of last status change. */
78#endif
79 int __glibc_reserved[2];
80 };
81
82#undef __field64
83
84#ifdef __USE_LARGEFILE64
85struct stat64
86 {
87 __dev_t st_dev; /* Device. */
88 __ino64_t st_ino; /* File serial number. */
89 __mode_t st_mode; /* File mode. */
90 __nlink_t st_nlink; /* Link count. */
91 __uid_t st_uid; /* User ID of the file's owner. */
92 __gid_t st_gid; /* Group ID of the file's group.*/
93 __dev_t st_rdev; /* Device number, if device. */
94 __dev_t __pad1;
95 __off64_t st_size; /* Size of file, in bytes. */
96 __blksize_t st_blksize; /* Optimal block size for I/O. */
97 int __pad2;
98 __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */
99#ifdef __USE_XOPEN2K8
100 /* Nanosecond resolution timestamps are stored in a format
101 equivalent to 'struct timespec'. This is the type used
102 whenever possible but the Unix namespace rules do not allow the
103 identifier 'timespec' to appear in the <sys/stat.h> header.
104 Therefore we have to handle the use of this header in strictly
105 standard-compliant sources special. */
106 struct timespec st_atim; /* Time of last access. */
107 struct timespec st_mtim; /* Time of last modification. */
108 struct timespec st_ctim; /* Time of last status change. */
109#else
110 __time_t st_atime; /* Time of last access. */
111 unsigned long int st_atimensec; /* Nscecs of last access. */
112 __time_t st_mtime; /* Time of last modification. */
113 unsigned long int st_mtimensec; /* Nsecs of last modification. */
114 __time_t st_ctime; /* Time of last status change. */
115 unsigned long int st_ctimensec; /* Nsecs of last status change. */
116#endif
117 int __glibc_reserved[2];
118 };
119#endif
120
121/* Tell code we have these members. */
122#define _STATBUF_ST_BLKSIZE
123#define _STATBUF_ST_RDEV
124/* Nanosecond resolution time values are supported. */
125#define _STATBUF_ST_NSEC
126
127#endif /* _BITS_STRUCT_STAT_H */
\ No newline at end of file
lib/libc/include/loongarch-linux-gnu/bits/timesize.h deleted-20
......@@ -1,20 +0,0 @@
1/* Bit size of the time_t type at glibc build time, general case.
2 Copyright (C) 2018-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19/* Size in bits of the 'time_t' type of the default ABI. */
20#define __TIMESIZE 64
\ No newline at end of file
lib/libc/include/loongarch-linux-gnu/bits/wordsize.h+13-2
......@@ -15,5 +15,16 @@
1515 License along with the GNU C Library; if not, see
1616 <https://www.gnu.org/licenses/>. */
1717
18#define __WORDSIZE 64
19#define __WORDSIZE_TIME64_COMPAT32 0
\ No newline at end of file
18// zig patch: handle 32-bit and 64-bit in the same header
19#if __loongarch_grlen == (__SIZEOF_POINTER__ * 8)
20# define __WORDSIZE __loongarch_grlen
21#else
22# error unsupported ABI
23#endif
24
25#define __WORDSIZE_TIME64_COMPAT32 0
26
27#if __WORDSIZE == 32
28# define __WORDSIZE32_SIZE_ULONG 0
29# define __WORDSIZE32_PTRDIFF_LONG 0
30#endif
lib/libc/include/loongarch-linux-gnu/fpu_control.h+9
......@@ -94,6 +94,15 @@ extern void __loongarch_fpu_setcw (fpu_control_t) __THROW;
9494#define _FPU_GETCW(cw) __asm__ volatile ("movfcsr2gr %0,$fcsr0" : "=r"(cw))
9595#define _FPU_SETCW(cw) __asm__ volatile ("movgr2fcsr $fcsr0,%0" : : "r"(cw))
9696
97#define _FPU_GET_ENABLES(cw) __asm__ volatile ("movfcsr2gr %0,$fcsr1" : "=r"(cw))
98#define _FPU_SET_ENABLES(cw) __asm__ volatile ("movgr2fcsr $fcsr1,%0" : : "r"(cw))
99
100#define _FPU_GET_FLAGS_CAUSE(cw) __asm__ volatile ("movfcsr2gr %0,$fcsr2" : "=r"(cw))
101#define _FPU_SET_FLAGS_CAUSE(cw) __asm__ volatile ("movgr2fcsr $fcsr2,%0" : : "r"(cw))
102
103#define _FPU_GET_RM(cw) __asm__ volatile ("movfcsr2gr %0,$fcsr3" : "=r"(cw))
104#define _FPU_SET_RM(cw) __asm__ volatile ("movgr2fcsr $fcsr3,%0" : : "r"(cw))
105
97106/* Default control word set at startup. */
98107extern fpu_control_t __fpu_control;
99108
lib/libc/include/loongarch-linux-gnu/gnu/lib-names-ilp32d.h created+28
......@@ -0,0 +1,28 @@
1/* This file is automatically generated. */
2#ifndef __GNU_LIB_NAMES_H
3# error "Never use <gnu/lib-names-ilp32d.h> directly; include <gnu/lib-names.h> instead."
4#endif
5
6#define LD_LINUX_LOONGARCH_ILP32D_SO "ld-linux-loongarch-ilp32d.so.1"
7#define LD_SO "ld-linux-loongarch-ilp32d.so.1"
8#define LIBANL_SO "libanl.so.1"
9#define LIBBROKENLOCALE_SO "libBrokenLocale.so.1"
10#define LIBC_MALLOC_DEBUG_SO "libc_malloc_debug.so.0"
11#define LIBC_SO "libc.so.6"
12#define LIBDL_SO "libdl.so.2"
13#define LIBGCC_S_SO "libgcc_s.so.1"
14#define LIBMVEC_SO "libmvec.so.1"
15#define LIBM_SO "libm.so.6"
16#define LIBNSL_SO "libnsl.so.1"
17#define LIBNSS_COMPAT_SO "libnss_compat.so.2"
18#define LIBNSS_DB_SO "libnss_db.so.2"
19#define LIBNSS_DNS_SO "libnss_dns.so.2"
20#define LIBNSS_FILES_SO "libnss_files.so.2"
21#define LIBNSS_HESIOD_SO "libnss_hesiod.so.2"
22#define LIBNSS_LDAP_SO "libnss_ldap.so.2"
23#define LIBPTHREAD_SO "libpthread.so.0"
24#define LIBRESOLV_SO "libresolv.so.2"
25#define LIBRT_SO "librt.so.1"
26#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
28#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/loongarch-linux-gnu/gnu/lib-names-ilp32s.h created+28
......@@ -0,0 +1,28 @@
1/* This file is automatically generated. */
2#ifndef __GNU_LIB_NAMES_H
3# error "Never use <gnu/lib-names-ilp32s.h> directly; include <gnu/lib-names.h> instead."
4#endif
5
6#define LD_LINUX_LOONGARCH_ILP32S_SO "ld-linux-loongarch-ilp32s.so.1"
7#define LD_SO "ld-linux-loongarch-ilp32s.so.1"
8#define LIBANL_SO "libanl.so.1"
9#define LIBBROKENLOCALE_SO "libBrokenLocale.so.1"
10#define LIBC_MALLOC_DEBUG_SO "libc_malloc_debug.so.0"
11#define LIBC_SO "libc.so.6"
12#define LIBDL_SO "libdl.so.2"
13#define LIBGCC_S_SO "libgcc_s.so.1"
14#define LIBMVEC_SO "libmvec.so.1"
15#define LIBM_SO "libm.so.6"
16#define LIBNSL_SO "libnsl.so.1"
17#define LIBNSS_COMPAT_SO "libnss_compat.so.2"
18#define LIBNSS_DB_SO "libnss_db.so.2"
19#define LIBNSS_DNS_SO "libnss_dns.so.2"
20#define LIBNSS_FILES_SO "libnss_files.so.2"
21#define LIBNSS_HESIOD_SO "libnss_hesiod.so.2"
22#define LIBNSS_LDAP_SO "libnss_ldap.so.2"
23#define LIBPTHREAD_SO "libpthread.so.0"
24#define LIBRESOLV_SO "libresolv.so.2"
25#define LIBRT_SO "librt.so.1"
26#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
28#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/loongarch-linux-gnu/gnu/lib-names-lp64d.h+1
......@@ -24,4 +24,5 @@
2424#define LIBRESOLV_SO "libresolv.so.2"
2525#define LIBRT_SO "librt.so.1"
2626#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
2728#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/loongarch-linux-gnu/gnu/lib-names-lp64s.h+1
......@@ -24,4 +24,5 @@
2424#define LIBRESOLV_SO "libresolv.so.2"
2525#define LIBRT_SO "librt.so.1"
2626#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
2728#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/loongarch-linux-gnu/gnu/lib-names.h+6
......@@ -6,6 +6,12 @@
66
77#include <bits/wordsize.h>
88
9#if __WORDSIZE == 32 && defined __loongarch_soft_float
10# include <gnu/lib-names-ilp32s.h>
11#endif
12#if __WORDSIZE == 32 && defined __loongarch_double_float
13# include <gnu/lib-names-ilp32d.h>
14#endif
915#if __WORDSIZE == 64 && defined __loongarch_soft_float
1016# include <gnu/lib-names-lp64s.h>
1117#endif
lib/libc/include/loongarch-linux-gnu/gnu/stubs-ilp32d.h created+21
......@@ -0,0 +1,21 @@
1/* This file is automatically generated.
2 It defines a symbol `__stub_FUNCTION' for each function
3 in the C library which is a stub, meaning it will fail
4 every time called, usually setting errno to ENOSYS. */
5
6#ifdef _LIBC
7 #error Applications may not define the macro _LIBC
8#endif
9
10#define __stub___compat_bdflush
11#define __stub___compat_create_module
12#define __stub___compat_get_kernel_syms
13#define __stub___compat_query_module
14#define __stub___compat_uselib
15#define __stub_chflags
16#define __stub_fchflags
17#define __stub_gtty
18#define __stub_revoke
19#define __stub_setlogin
20#define __stub_sigreturn
21#define __stub_stty
\ No newline at end of file
lib/libc/include/loongarch-linux-gnu/gnu/stubs-ilp32s.h created+38
......@@ -0,0 +1,38 @@
1/* This file is automatically generated.
2 It defines a symbol `__stub_FUNCTION' for each function
3 in the C library which is a stub, meaning it will fail
4 every time called, usually setting errno to ENOSYS. */
5
6#ifdef _LIBC
7 #error Applications may not define the macro _LIBC
8#endif
9
10#define __stub___compat_bdflush
11#define __stub___compat_create_module
12#define __stub___compat_get_kernel_syms
13#define __stub___compat_query_module
14#define __stub___compat_uselib
15#define __stub_chflags
16#define __stub_fchflags
17#define __stub_feclearexcept
18#define __stub_fedisableexcept
19#define __stub_feenableexcept
20#define __stub_fegetenv
21#define __stub_fegetexcept
22#define __stub_fegetexceptflag
23#define __stub_fegetmode
24#define __stub_fegetround
25#define __stub_feholdexcept
26#define __stub_feraiseexcept
27#define __stub_fesetenv
28#define __stub_fesetexcept
29#define __stub_fesetexceptflag
30#define __stub_fesetmode
31#define __stub_fesetround
32#define __stub_fetestexcept
33#define __stub_feupdateenv
34#define __stub_gtty
35#define __stub_revoke
36#define __stub_setlogin
37#define __stub_sigreturn
38#define __stub_stty
\ No newline at end of file
lib/libc/include/loongarch-linux-gnu/gnu/stubs.h+6
......@@ -4,6 +4,12 @@
44
55#include <bits/wordsize.h>
66
7#if __WORDSIZE == 32 && defined __loongarch_soft_float
8# include <gnu/stubs-ilp32s.h>
9#endif
10#if __WORDSIZE == 32 && defined __loongarch_double_float
11# include <gnu/stubs-ilp32d.h>
12#endif
713#if __WORDSIZE == 64 && defined __loongarch_soft_float
814# include <gnu/stubs-lp64s.h>
915#endif
lib/libc/include/loongarch-linux-gnu/sys/asm.h+32-6
......@@ -23,10 +23,8 @@
2323#include <sysdeps/generic/sysdep.h>
2424
2525/* Macros to handle different pointer/register sizes for 32/64-bit code. */
26#if __loongarch_grlen == 64
2627#define SZREG 8
27#define SZFREG 8
28#define SZVREG 16
29#define SZXREG 32
3028#define REG_L ld.d
3129#define REG_S st.d
3230#define SRLI srli.d
......@@ -34,10 +32,38 @@
3432#define ADDI addi.d
3533#define ADD add.d
3634#define SUB sub.d
37#define BSTRINS bstrins.d
3835#define LI li.d
39#define FREG_L fld.d
40#define FREG_S fst.d
36#define BSTRINS bstrins.d
37
38#elif __loongarch_grlen == 32
39
40#define SZREG 4
41#define REG_L ld.w
42#define REG_S st.w
43#define SRLI srli.w
44#define SLLI slli.w
45#define ADDI addi.w
46#define ADD add.w
47#define SUB sub.w
48#define LI li.w
49#define BSTRINS bstrins.w
50
51#else
52#error __loongarch_grlen must equal 32 or 64
53#endif
54
55#if __loongarch_frlen == 64
56 #define SZFREG 8
57 #define FREG_L fld.d
58 #define FREG_S fst.d
59#elif __loongarch_frlen == 32
60 #define SZFREG 4
61 #define FREG_L fld.s
62 #define FREG_S fst.s
63#endif
64
65#define SZVREG 16
66#define SZXREG 32
4167
4268/* Declare leaf routine.
4369 The usage of macro LEAF/ENTRY is as follows:
lib/libc/include/m68k-linux-gnu/gnu/lib-names.h+1
......@@ -24,6 +24,7 @@
2424#define LIBRESOLV_SO "libresolv.so.2"
2525#define LIBRT_SO "librt.so.1"
2626#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
2728#define LIBUTIL_SO "libutil.so.1"
2829
2930#endif /* gnu/lib-names.h */
\ No newline at end of file
lib/libc/include/mips-linux-gnu/bits/long-double.h created+24
......@@ -0,0 +1,24 @@
1/* Properties of long double type. MIPS version.
2 Copyright (C) 2016-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#include <sgidefs.h>
20
21#if !defined __NO_LONG_DOUBLE_MATH && _MIPS_SIM == _ABIO32
22# define __NO_LONG_DOUBLE_MATH 1
23#endif
24#define __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI 0
\ No newline at end of file
lib/libc/include/mips-linux-gnu/bits/struct_stat.h created+237
......@@ -0,0 +1,237 @@
1/* Definition for struct stat.
2 Copyright (C) 2020-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library. If not, see
17 <https://www.gnu.org/licenses/>. */
18
19#if !defined _SYS_STAT_H && !defined _FCNTL_H
20# error "Never include <bits/struct_stat.h> directly; use <sys/stat.h> instead."
21#endif
22
23#ifndef _BITS_STRUCT_STAT_H
24#define _BITS_STRUCT_STAT_H 1
25
26#include <sgidefs.h>
27
28#if _MIPS_SIM == _ABIO32
29/* Structure describing file characteristics. */
30struct stat
31 {
32# ifdef __USE_TIME64_REDIRECTS
33# include <bits/struct_stat_time64_helper.h>
34# else
35 unsigned long int st_dev;
36 long int st_pad1[3];
37# ifndef __USE_FILE_OFFSET64
38 __ino_t st_ino; /* File serial number. */
39# else
40 __ino64_t st_ino; /* File serial number. */
41# endif
42 __mode_t st_mode; /* File mode. */
43 __nlink_t st_nlink; /* Link count. */
44 __uid_t st_uid; /* User ID of the file's owner. */
45 __gid_t st_gid; /* Group ID of the file's group.*/
46 unsigned long int st_rdev; /* Device number, if device. */
47# ifndef __USE_FILE_OFFSET64
48 long int st_pad2[2];
49 __off_t st_size; /* Size of file, in bytes. */
50 /* SVR4 added this extra long to allow for expansion of off_t. */
51 long int st_pad3;
52# else
53 long int st_pad2[3];
54 __off64_t st_size; /* Size of file, in bytes. */
55# endif
56# ifdef __USE_XOPEN2K8
57 /* Nanosecond resolution timestamps are stored in a format
58 equivalent to 'struct timespec'. This is the type used
59 whenever possible but the Unix namespace rules do not allow the
60 identifier 'timespec' to appear in the <sys/stat.h> header.
61 Therefore we have to handle the use of this header in strictly
62 standard-compliant sources special. */
63 struct timespec st_atim; /* Time of last access. */
64 struct timespec st_mtim; /* Time of last modification. */
65 struct timespec st_ctim; /* Time of last status change. */
66# define st_atime st_atim.tv_sec /* Backward compatibility. */
67# define st_mtime st_mtim.tv_sec
68# define st_ctime st_ctim.tv_sec
69# else
70 __time_t st_atime; /* Time of last access. */
71 unsigned long int st_atimensec; /* Nscecs of last access. */
72 __time_t st_mtime; /* Time of last modification. */
73 unsigned long int st_mtimensec; /* Nsecs of last modification. */
74 __time_t st_ctime; /* Time of last status change. */
75 unsigned long int st_ctimensec; /* Nsecs of last status change. */
76# endif
77 __blksize_t st_blksize; /* Optimal block size for I/O. */
78# ifndef __USE_FILE_OFFSET64
79 __blkcnt_t st_blocks; /* Number of 512-byte blocks allocated. */
80# else
81 long int st_pad4;
82 __blkcnt64_t st_blocks; /* Number of 512-byte blocks allocated. */
83# endif
84 long int st_pad5[14];
85# endif /* __USE_TIME64_REDIRECTS */
86 };
87
88# ifdef __USE_LARGEFILE64
89struct stat64
90 {
91# ifdef __USE_TIME64_REDIRECTS
92# include <bits/struct_stat_time64_helper.h>
93# else
94 unsigned long int st_dev;
95 long int st_pad1[3];
96 __ino64_t st_ino; /* File serial number. */
97 __mode_t st_mode; /* File mode. */
98 __nlink_t st_nlink; /* Link count. */
99 __uid_t st_uid; /* User ID of the file's owner. */
100 __gid_t st_gid; /* Group ID of the file's group.*/
101 unsigned long int st_rdev; /* Device number, if device. */
102 long int st_pad2[3];
103 __off64_t st_size; /* Size of file, in bytes. */
104# ifdef __USE_XOPEN2K8
105 /* Nanosecond resolution timestamps are stored in a format
106 equivalent to 'struct timespec'. This is the type used
107 whenever possible but the Unix namespace rules do not allow the
108 identifier 'timespec' to appear in the <sys/stat.h> header.
109 Therefore we have to handle the use of this header in strictly
110 standard-compliant sources special. */
111 struct timespec st_atim; /* Time of last access. */
112 struct timespec st_mtim; /* Time of last modification. */
113 struct timespec st_ctim; /* Time of last status change. */
114# else
115 __time_t st_atime; /* Time of last access. */
116 unsigned long int st_atimensec; /* Nscecs of last access. */
117 __time_t st_mtime; /* Time of last modification. */
118 unsigned long int st_mtimensec; /* Nsecs of last modification. */
119 __time_t st_ctime; /* Time of last status change. */
120 unsigned long int st_ctimensec; /* Nsecs of last status change. */
121# endif
122 __blksize_t st_blksize; /* Optimal block size for I/O. */
123 long int st_pad3;
124 __blkcnt64_t st_blocks; /* Number of 512-byte blocks allocated. */
125 long int st_pad4[14];
126# endif /* __USE_TIME64_REDIRECTS */
127 };
128# endif /* __USE_LARGEFILE64 */
129
130#else /* _MIPS_SIM != _ABIO32 */
131
132struct stat
133 {
134# ifdef __USE_TIME64_REDIRECTS
135# include <bits/struct_stat_time64_helper.h>
136# else
137 __dev_t st_dev;
138 int st_pad1[3]; /* Reserved for st_dev expansion */
139# ifndef __USE_FILE_OFFSET64
140 __ino_t st_ino;
141# else
142 __ino64_t st_ino;
143# endif
144 __mode_t st_mode;
145 __nlink_t st_nlink;
146 __uid_t st_uid;
147 __gid_t st_gid;
148 __dev_t st_rdev;
149# if !defined __USE_FILE_OFFSET64
150 unsigned int st_pad2[2]; /* Reserved for st_rdev expansion */
151 __off_t st_size;
152 int st_pad3;
153# else
154 unsigned int st_pad2[3]; /* Reserved for st_rdev expansion */
155 __off64_t st_size;
156# endif
157# ifdef __USE_XOPEN2K8
158 /* Nanosecond resolution timestamps are stored in a format
159 equivalent to 'struct timespec'. This is the type used
160 whenever possible but the Unix namespace rules do not allow the
161 identifier 'timespec' to appear in the <sys/stat.h> header.
162 Therefore we have to handle the use of this header in strictly
163 standard-compliant sources special. */
164 struct timespec st_atim; /* Time of last access. */
165 struct timespec st_mtim; /* Time of last modification. */
166 struct timespec st_ctim; /* Time of last status change. */
167# define st_atime st_atim.tv_sec /* Backward compatibility. */
168# define st_mtime st_mtim.tv_sec
169# define st_ctime st_ctim.tv_sec
170# else
171 __time_t st_atime; /* Time of last access. */
172 unsigned long int st_atimensec; /* Nscecs of last access. */
173 __time_t st_mtime; /* Time of last modification. */
174 unsigned long int st_mtimensec; /* Nsecs of last modification. */
175 __time_t st_ctime; /* Time of last status change. */
176 unsigned long int st_ctimensec; /* Nsecs of last status change. */
177# endif
178 __blksize_t st_blksize;
179 unsigned int st_pad4;
180# ifndef __USE_FILE_OFFSET64
181 __blkcnt_t st_blocks;
182# else
183 __blkcnt64_t st_blocks;
184# endif
185 int st_pad5[14];
186# endif
187 };
188
189#ifdef __USE_LARGEFILE64
190struct stat64
191 {
192# ifdef __USE_TIME64_REDIRECTS
193# include <bits/struct_stat_time64_helper.h>
194# else
195 __dev_t st_dev;
196 unsigned int st_pad1[3]; /* Reserved for st_dev expansion */
197 __ino64_t st_ino;
198 __mode_t st_mode;
199 __nlink_t st_nlink;
200 __uid_t st_uid;
201 __gid_t st_gid;
202 __dev_t st_rdev;
203 unsigned int st_pad2[3]; /* Reserved for st_rdev expansion */
204 __off64_t st_size;
205# ifdef __USE_XOPEN2K8
206 /* Nanosecond resolution timestamps are stored in a format
207 equivalent to 'struct timespec'. This is the type used
208 whenever possible but the Unix namespace rules do not allow the
209 identifier 'timespec' to appear in the <sys/stat.h> header.
210 Therefore we have to handle the use of this header in strictly
211 standard-compliant sources special. */
212 struct timespec st_atim; /* Time of last access. */
213 struct timespec st_mtim; /* Time of last modification. */
214 struct timespec st_ctim; /* Time of last status change. */
215# else
216 __time_t st_atime; /* Time of last access. */
217 unsigned long int st_atimensec; /* Nscecs of last access. */
218 __time_t st_mtime; /* Time of last modification. */
219 unsigned long int st_mtimensec; /* Nsecs of last modification. */
220 __time_t st_ctime; /* Time of last status change. */
221 unsigned long int st_ctimensec; /* Nsecs of last status change. */
222# endif
223 __blksize_t st_blksize;
224 unsigned int st_pad3;
225 __blkcnt64_t st_blocks;
226 int st_pad4[14];
227# endif /* __USE_TIME64_REDIRECTS */
228};
229#endif
230
231#endif
232
233/* Tell code we have these members. */
234#define _STATBUF_ST_BLKSIZE
235#define _STATBUF_ST_RDEV
236
237#endif /* _BITS_STRUCT_STAT_H */
\ No newline at end of file
lib/libc/include/mips-linux-gnu/bits/timesize.h created+22
......@@ -0,0 +1,22 @@
1/* Bit size of the time_t type at glibc build time, Linux/MIPS.
2 Copyright (C) 2021-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#include <bits/wordsize.h>
20
21/* Size in bits of the 'time_t' type of the default ABI. */
22#define __TIMESIZE __WORDSIZE
\ No newline at end of file
lib/libc/include/mips-linux-gnu/bits/waitstatus.h created+68
......@@ -0,0 +1,68 @@
1/* Definitions of status bits for `wait' et al.
2 MIPS version, based on the generic version (bits/waitstatus.h).
3
4 Copyright (C) 1992-2026 Free Software Foundation, Inc.
5 This file is part of the GNU C Library.
6
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with the GNU C Library; if not, see
19 <https://www.gnu.org/licenses/>. */
20
21#if !defined _SYS_WAIT_H && !defined _STDLIB_H
22# error "Never include <bits/waitstatus.h> directly; use <sys/wait.h> instead."
23#endif
24
25
26/* On MIPS SIGRTMAX is 127, so we need to handle the status code 127
27 which is impossible on other ports. */
28
29/* If WIFEXITED(STATUS), the low-order 8 bits of the status. */
30#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8)
31
32/* If WIFSIGNALED(STATUS), the terminating signal. */
33#define __WTERMSIG(status) ((status) & 0x7f)
34
35/* If WIFSTOPPED(STATUS), the signal that stopped the child. */
36#define __WSTOPSIG(status) __WEXITSTATUS(status)
37
38/* Nonzero if STATUS indicates normal termination. */
39#define __WIFEXITED(status) (__WTERMSIG(status) == 0)
40
41/* Nonzero if STATUS indicates termination by a signal. */
42static __inline int
43__WIFSIGNALED (int __status)
44{
45 return ((signed char) ((__status & 0x7f) + 1) >> 1) > 0 || __status == 0x7f;
46}
47
48/* Nonzero if STATUS indicates the child is stopped. */
49static __inline int
50__WIFSTOPPED (int __status)
51{
52 return (__status & 0xff) == 0x7f && __status != 0x7f;
53}
54
55/* Nonzero if STATUS indicates the child continued after a stop. We only
56 define this if <bits/waitflags.h> provides the WCONTINUED flag bit. */
57#ifdef WCONTINUED
58# define __WIFCONTINUED(status) ((status) == __W_CONTINUED)
59#endif
60
61/* Nonzero if STATUS indicates the child dumped core. */
62#define __WCOREDUMP(status) ((status) & __WCOREFLAG)
63
64/* Macros for constructing status values. */
65#define __W_EXITCODE(ret, sig) ((ret) << 8 | (sig))
66#define __W_STOPCODE(sig) ((sig) << 8 | 0x7f)
67#define __W_CONTINUED 0xffff
68#define __WCOREFLAG 0x80
\ No newline at end of file
lib/libc/include/powerpc-linux-gnu/bits/long-double.h+1-1
......@@ -1,5 +1,5 @@
11/* Properties of long double type. ldbl-opt version.
2 Copyright (C) 2016-2026 Free Software Foundation, Inc.
2 Copyright (C) 2019-2026 Free Software Foundation, Inc.
33 This file is part of the GNU C Library.
44
55 The GNU C Library is free software; you can redistribute it and/or
lib/libc/include/powerpc-linux-gnu/bits/ppc.h created+33
......@@ -0,0 +1,33 @@
1/* Facilities specific to the PowerPC architecture on Linux
2 Copyright (C) 2012-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#ifndef _BITS_PPC_H
20#define _BITS_PPC_H
21
22#ifndef _SYS_PLATFORM_PPC_H
23# error "Never include this file directly; use <sys/platform/ppc.h> instead."
24#endif
25
26__BEGIN_DECLS
27
28/* Read the time base frequency. */
29extern uint64_t __ppc_get_timebase_freq (void);
30
31__END_DECLS
32
33#endif
\ No newline at end of file
lib/libc/include/powerpc-linux-gnu/bits/struct_mutex.h+1-1
......@@ -59,4 +59,4 @@ struct __pthread_mutex_s
5959 0, 0, 0, __kind, 0, { { 0, 0 } }
6060#endif
6161
62#endif
62#endif
\ No newline at end of file
lib/libc/include/powerpc-linux-gnu/gnu/lib-names-32.h deleted-26
......@@ -1,26 +0,0 @@
1/* This file is automatically generated. */
2#ifndef __GNU_LIB_NAMES_H
3# error "Never use <gnu/lib-names-32.h> directly; include <gnu/lib-names.h> instead."
4#endif
5
6#define LD_SO "ld.so.1"
7#define LIBANL_SO "libanl.so.1"
8#define LIBBROKENLOCALE_SO "libBrokenLocale.so.1"
9#define LIBC_MALLOC_DEBUG_SO "libc_malloc_debug.so.0"
10#define LIBC_SO "libc.so.6"
11#define LIBDL_SO "libdl.so.2"
12#define LIBGCC_S_SO "libgcc_s.so.1"
13#define LIBMVEC_SO "libmvec.so.1"
14#define LIBM_SO "libm.so.6"
15#define LIBNSL_SO "libnsl.so.1"
16#define LIBNSS_COMPAT_SO "libnss_compat.so.2"
17#define LIBNSS_DB_SO "libnss_db.so.2"
18#define LIBNSS_DNS_SO "libnss_dns.so.2"
19#define LIBNSS_FILES_SO "libnss_files.so.2"
20#define LIBNSS_HESIOD_SO "libnss_hesiod.so.2"
21#define LIBNSS_LDAP_SO "libnss_ldap.so.2"
22#define LIBPTHREAD_SO "libpthread.so.0"
23#define LIBRESOLV_SO "libresolv.so.2"
24#define LIBRT_SO "librt.so.1"
25#define LIBTHREAD_DB_SO "libthread_db.so.1"
26#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/powerpc-linux-gnu/gnu/lib-names-64-v1.h deleted-27
......@@ -1,27 +0,0 @@
1/* This file is automatically generated. */
2#ifndef __GNU_LIB_NAMES_H
3# error "Never use <gnu/lib-names-64-v1.h> directly; include <gnu/lib-names.h> instead."
4#endif
5
6#define LD64_SO "ld64.so.1"
7#define LD_SO "ld64.so.1"
8#define LIBANL_SO "libanl.so.1"
9#define LIBBROKENLOCALE_SO "libBrokenLocale.so.1"
10#define LIBC_MALLOC_DEBUG_SO "libc_malloc_debug.so.0"
11#define LIBC_SO "libc.so.6"
12#define LIBDL_SO "libdl.so.2"
13#define LIBGCC_S_SO "libgcc_s.so.1"
14#define LIBMVEC_SO "libmvec.so.1"
15#define LIBM_SO "libm.so.6"
16#define LIBNSL_SO "libnsl.so.1"
17#define LIBNSS_COMPAT_SO "libnss_compat.so.2"
18#define LIBNSS_DB_SO "libnss_db.so.2"
19#define LIBNSS_DNS_SO "libnss_dns.so.2"
20#define LIBNSS_FILES_SO "libnss_files.so.2"
21#define LIBNSS_HESIOD_SO "libnss_hesiod.so.2"
22#define LIBNSS_LDAP_SO "libnss_ldap.so.2"
23#define LIBPTHREAD_SO "libpthread.so.0"
24#define LIBRESOLV_SO "libresolv.so.2"
25#define LIBRT_SO "librt.so.1"
26#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/powerpc-linux-gnu/gnu/lib-names-64-v2.h+1
......@@ -24,4 +24,5 @@
2424#define LIBRESOLV_SO "libresolv.so.2"
2525#define LIBRT_SO "librt.so.1"
2626#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
2728#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/powerpc-linux-gnu/gnu/stubs-64-v1.h deleted-16
......@@ -1,16 +0,0 @@
1/* This file is automatically generated.
2 It defines a symbol `__stub_FUNCTION' for each function
3 in the C library which is a stub, meaning it will fail
4 every time called, usually setting errno to ENOSYS. */
5
6#ifdef _LIBC
7 #error Applications may not define the macro _LIBC
8#endif
9
10#define __stub_chflags
11#define __stub_fchflags
12#define __stub_gtty
13#define __stub_revoke
14#define __stub_setlogin
15#define __stub_sigreturn
16#define __stub_stty
\ No newline at end of file
lib/libc/include/powerpc-linux-gnu/sys/platform/ppc.h created+146
......@@ -0,0 +1,146 @@
1/* Facilities specific to the PowerPC architecture
2 Copyright (C) 2012-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#ifndef _SYS_PLATFORM_PPC_H
20#define _SYS_PLATFORM_PPC_H 1
21
22#include <features.h>
23#include <stdint.h>
24#include <bits/ppc.h>
25
26/* Read the Time Base Register. */
27static __inline__ uint64_t
28__ppc_get_timebase (void)
29{
30#if __GNUC_PREREQ (4, 8)
31 return __builtin_ppc_get_timebase ();
32#else
33# ifdef __powerpc64__
34 uint64_t __tb;
35 /* "volatile" is necessary here, because the user expects this assembly
36 isn't moved after an optimization. */
37 __asm__ volatile ("mfspr %0, 268" : "=r" (__tb));
38 return __tb;
39# else /* not __powerpc64__ */
40 uint32_t __tbu, __tbl, __tmp; \
41 __asm__ volatile ("0:\n\t"
42 "mftbu %0\n\t"
43 "mftbl %1\n\t"
44 "mftbu %2\n\t"
45 "cmpw %0, %2\n\t"
46 "bne- 0b"
47 : "=r" (__tbu), "=r" (__tbl), "=r" (__tmp));
48 return (((uint64_t) __tbu << 32) | __tbl);
49# endif /* not __powerpc64__ */
50#endif
51}
52
53/* The following functions provide hints about the usage of shared processor
54 resources, as defined in ISA 2.06 and newer. */
55
56/* Provides a hint that performance will probably be improved if shared
57 resources dedicated to the executing processor are released for use by other
58 processors. */
59static __inline__ void
60__ppc_yield (void)
61{
62 __asm__ volatile ("or 27,27,27");
63}
64
65/* Provides a hint that performance will probably be improved if shared
66 resources dedicated to the executing processor are released until
67 all outstanding storage accesses to caching-inhibited storage have been
68 completed. */
69static __inline__ void
70__ppc_mdoio (void)
71{
72 __asm__ volatile ("or 29,29,29");
73}
74
75/* Provides a hint that performance will probably be improved if shared
76 resources dedicated to the executing processor are released until all
77 outstanding storage accesses to cacheable storage for which the data is not
78 in the cache have been completed. */
79static __inline__ void
80__ppc_mdoom (void)
81{
82 __asm__ volatile ("or 30,30,30");
83}
84
85
86/* ISA 2.05 and beyond support the Program Priority Register (PPR) to adjust
87 thread priorities based on lock acquisition, wait and release. The ISA
88 defines the use of form 'or Rx,Rx,Rx' as the way to modify the PRI field.
89 The unprivileged priorities are:
90 Rx = 1 (low)
91 Rx = 2 (medium)
92 Rx = 6 (medium-low/normal)
93 The 'or' instruction form is a nop in previous hardware, so it is safe to
94 use unguarded. The default value is 'medium'.
95 */
96
97static __inline__ void
98__ppc_set_ppr_med (void)
99{
100 __asm__ volatile ("or 2,2,2");
101}
102
103static __inline__ void
104__ppc_set_ppr_med_low (void)
105{
106 __asm__ volatile ("or 6,6,6");
107}
108
109static __inline__ void
110__ppc_set_ppr_low (void)
111{
112 __asm__ volatile ("or 1,1,1");
113}
114
115/* Power ISA 2.07 (Book II, Chapter 3) extends the priorities that can be set
116 to the Program Priority Register (PPR). The form 'or Rx,Rx,Rx' is used to
117 modify the PRI field of the PPR, the same way as described above.
118 The new priority levels are:
119 Rx = 31 (very low)
120 Rx = 5 (medium high)
121 Any program can set the priority to very low, low, medium low, and medium,
122 as these are unprivileged.
123 The medium high priority, on the other hand, is privileged, and may only be
124 set during certain time intervals by problem-state programs. If the program
125 priority is medium high when the time interval expires or if an attempt is
126 made to set the priority to medium high when it is not allowed, the PRI
127 field is set to medium.
128 */
129
130#ifdef _ARCH_PWR8
131
132static __inline__ void
133__ppc_set_ppr_very_low (void)
134{
135 __asm__ volatile ("or 31,31,31");
136}
137
138static __inline__ void
139__ppc_set_ppr_med_high (void)
140{
141 __asm__ volatile ("or 5,5,5");
142}
143
144#endif
145
146#endif /* sys/platform/ppc.h */
\ No newline at end of file
lib/libc/include/powerpc-netbsd-eabi/powerpc/oea/pmap.h+6-4
......@@ -1,4 +1,4 @@
1/* $NetBSD: pmap.h,v 1.39 2023/12/15 09:42:33 rin Exp $ */
1/* $NetBSD: pmap.h,v 1.39.4.1 2026/07/03 17:51:59 martin Exp $ */
22
33/*-
44 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
......@@ -122,11 +122,13 @@ __BEGIN_DECLS
122122#include <sys/systm.h>
123123
124124/*
125 * For OEA and OEA64_BRIDGE, we guarantee that pa below USER_ADDR
126 * (== 3GB < VM_MIN_KERNEL_ADDRESS) is direct-mapped.
125 * Physical memory below PMAP_DIRECT_MAPPED_LEN is direct-mapped
126 * (pa == va). Direct region covers the segments below BOTH
127 * the user copyin window (USER_SR) and the kernel HTAB window
128 * (KERNEL_SR), so it can never overlap.
127129 */
128130#if defined(PPC_OEA) || defined(PPC_OEA64_BRIDGE)
129#define PMAP_DIRECT_MAPPED_SR (USER_SR - 1)
131#define PMAP_DIRECT_MAPPED_SR (MIN(USER_SR, KERNEL_SR) - 1)
130132#define PMAP_DIRECT_MAPPED_LEN \
131133 ((vaddr_t)SEGMENT_LENGTH * (PMAP_DIRECT_MAPPED_SR + 1))
132134#endif
lib/libc/include/riscv-linux-gnu/bits/long-double.h deleted-21
......@@ -1,21 +0,0 @@
1/* Properties of long double type. ldbl-128 version.
2 Copyright (C) 2016-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19/* long double is distinct from double, so there is nothing to
20 define here. */
21#define __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI 0
\ No newline at end of file
lib/libc/include/riscv-linux-gnu/bits/struct_stat.h deleted-127
......@@ -1,127 +0,0 @@
1/* Definition for struct stat.
2 Copyright (C) 2020-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library. If not, see
17 <https://www.gnu.org/licenses/>. */
18
19#if !defined _SYS_STAT_H && !defined _FCNTL_H
20# error "Never include <bits/struct_stat.h> directly; use <sys/stat.h> instead."
21#endif
22
23#ifndef _BITS_STRUCT_STAT_H
24#define _BITS_STRUCT_STAT_H 1
25
26#include <bits/endian.h>
27#include <bits/wordsize.h>
28
29#if defined __USE_FILE_OFFSET64
30# define __field64(type, type64, name) type64 name
31#elif __WORDSIZE == 64 || defined __INO_T_MATCHES_INO64_T
32# if defined __INO_T_MATCHES_INO64_T && !defined __OFF_T_MATCHES_OFF64_T
33# error "ino_t and off_t must both be the same type"
34# endif
35# define __field64(type, type64, name) type name
36#elif __BYTE_ORDER == __LITTLE_ENDIAN
37# define __field64(type, type64, name) \
38 type name __attribute__((__aligned__ (__alignof__ (type64)))); int __##name##_pad
39#else
40# define __field64(type, type64, name) \
41 int __##name##_pad __attribute__((__aligned__ (__alignof__ (type64)))); type name
42#endif
43
44struct stat
45 {
46 __dev_t st_dev; /* Device. */
47 __field64(__ino_t, __ino64_t, st_ino); /* File serial number. */
48 __mode_t st_mode; /* File mode. */
49 __nlink_t st_nlink; /* Link count. */
50 __uid_t st_uid; /* User ID of the file's owner. */
51 __gid_t st_gid; /* Group ID of the file's group.*/
52 __dev_t st_rdev; /* Device number, if device. */
53 __dev_t __pad1;
54 __field64(__off_t, __off64_t, st_size); /* Size of file, in bytes. */
55 __blksize_t st_blksize; /* Optimal block size for I/O. */
56 int __pad2;
57 __field64(__blkcnt_t, __blkcnt64_t, st_blocks); /* 512-byte blocks */
58#ifdef __USE_XOPEN2K8
59 /* Nanosecond resolution timestamps are stored in a format
60 equivalent to 'struct timespec'. This is the type used
61 whenever possible but the Unix namespace rules do not allow the
62 identifier 'timespec' to appear in the <sys/stat.h> header.
63 Therefore we have to handle the use of this header in strictly
64 standard-compliant sources special. */
65 struct timespec st_atim; /* Time of last access. */
66 struct timespec st_mtim; /* Time of last modification. */
67 struct timespec st_ctim; /* Time of last status change. */
68# define st_atime st_atim.tv_sec /* Backward compatibility. */
69# define st_mtime st_mtim.tv_sec
70# define st_ctime st_ctim.tv_sec
71#else
72 __time_t st_atime; /* Time of last access. */
73 unsigned long int st_atimensec; /* Nscecs of last access. */
74 __time_t st_mtime; /* Time of last modification. */
75 unsigned long int st_mtimensec; /* Nsecs of last modification. */
76 __time_t st_ctime; /* Time of last status change. */
77 unsigned long int st_ctimensec; /* Nsecs of last status change. */
78#endif
79 int __glibc_reserved[2];
80 };
81
82#undef __field64
83
84#ifdef __USE_LARGEFILE64
85struct stat64
86 {
87 __dev_t st_dev; /* Device. */
88 __ino64_t st_ino; /* File serial number. */
89 __mode_t st_mode; /* File mode. */
90 __nlink_t st_nlink; /* Link count. */
91 __uid_t st_uid; /* User ID of the file's owner. */
92 __gid_t st_gid; /* Group ID of the file's group.*/
93 __dev_t st_rdev; /* Device number, if device. */
94 __dev_t __pad1;
95 __off64_t st_size; /* Size of file, in bytes. */
96 __blksize_t st_blksize; /* Optimal block size for I/O. */
97 int __pad2;
98 __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */
99#ifdef __USE_XOPEN2K8
100 /* Nanosecond resolution timestamps are stored in a format
101 equivalent to 'struct timespec'. This is the type used
102 whenever possible but the Unix namespace rules do not allow the
103 identifier 'timespec' to appear in the <sys/stat.h> header.
104 Therefore we have to handle the use of this header in strictly
105 standard-compliant sources special. */
106 struct timespec st_atim; /* Time of last access. */
107 struct timespec st_mtim; /* Time of last modification. */
108 struct timespec st_ctim; /* Time of last status change. */
109#else
110 __time_t st_atime; /* Time of last access. */
111 unsigned long int st_atimensec; /* Nscecs of last access. */
112 __time_t st_mtime; /* Time of last modification. */
113 unsigned long int st_mtimensec; /* Nsecs of last modification. */
114 __time_t st_ctime; /* Time of last status change. */
115 unsigned long int st_ctimensec; /* Nsecs of last status change. */
116#endif
117 int __glibc_reserved[2];
118 };
119#endif
120
121/* Tell code we have these members. */
122#define _STATBUF_ST_BLKSIZE
123#define _STATBUF_ST_RDEV
124/* Nanosecond resolution time values are supported. */
125#define _STATBUF_ST_NSEC
126
127#endif /* _BITS_STRUCT_STAT_H */
\ No newline at end of file
lib/libc/include/riscv-linux-gnu/bits/timesize.h deleted-20
......@@ -1,20 +0,0 @@
1/* Bit size of the time_t type at glibc build time, general case.
2 Copyright (C) 2018-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19/* Size in bits of the 'time_t' type of the default ABI. */
20#define __TIMESIZE 64
\ No newline at end of file
lib/libc/include/riscv-linux-gnu/gnu/lib-names-ilp32d.h+1
......@@ -24,4 +24,5 @@
2424#define LIBRESOLV_SO "libresolv.so.2"
2525#define LIBRT_SO "librt.so.1"
2626#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
2728#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/riscv-linux-gnu/gnu/lib-names-lp64d.h+1
......@@ -24,4 +24,5 @@
2424#define LIBRESOLV_SO "libresolv.so.2"
2525#define LIBRT_SO "librt.so.1"
2626#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
2728#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/s390x-linux-gnu/bits/elfclass.h+1-6
......@@ -27,11 +27,6 @@
2727
2828#define __ELF_NATIVE_CLASS __WORDSIZE
2929
30#if __WORDSIZE == 64
3130/* 64 bit Linux for S/390 is exceptional as it has .hash section with
3231 64 bit entries. */
33typedef uint64_t Elf_Symndx;
34#else
35/* 32 bit Linux for S/390 has normal .hash section entries with 32 bits. */
36typedef uint32_t Elf_Symndx;
37#endif
\ No newline at end of file
32typedef uint64_t Elf_Symndx;
\ No newline at end of file
lib/libc/include/s390x-linux-gnu/bits/environments.h deleted-96
......@@ -1,96 +0,0 @@
1/* Copyright (C) 1999-2026 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
17
18#ifndef _UNISTD_H
19# error "Never include this file directly. Use <unistd.h> instead"
20#endif
21
22#include <bits/wordsize.h>
23
24/* This header should define the following symbols under the described
25 situations. A value `1' means that the model is always supported,
26 `-1' means it is never supported. Undefined means it cannot be
27 statically decided.
28
29 _POSIX_V7_ILP32_OFF32 32bit int, long, pointers, and off_t type
30 _POSIX_V7_ILP32_OFFBIG 32bit int, long, and pointers and larger off_t type
31
32 _POSIX_V7_LP64_OFF32 64bit long and pointers and 32bit off_t type
33 _POSIX_V7_LPBIG_OFFBIG 64bit long and pointers and large off_t type
34
35 The macros _POSIX_V6_ILP32_OFF32, _POSIX_V6_ILP32_OFFBIG,
36 _POSIX_V6_LP64_OFF32, _POSIX_V6_LPBIG_OFFBIG, _XBS5_ILP32_OFF32,
37 _XBS5_ILP32_OFFBIG, _XBS5_LP64_OFF32, and _XBS5_LPBIG_OFFBIG were
38 used in previous versions of the Unix standard and are available
39 only for compatibility.
40*/
41
42#if __WORDSIZE == 64
43
44/* Environments with 32-bit wide pointers are optionally provided.
45 Therefore following macros aren't defined:
46 # undef _POSIX_V7_ILP32_OFF32
47 # undef _POSIX_V7_ILP32_OFFBIG
48 # undef _POSIX_V6_ILP32_OFF32
49 # undef _POSIX_V6_ILP32_OFFBIG
50 # undef _XBS5_ILP32_OFF32
51 # undef _XBS5_ILP32_OFFBIG
52 and users need to check at runtime. */
53
54/* We also have no use (for now) for an environment with bigger pointers
55 and offsets. */
56# define _POSIX_V7_LPBIG_OFFBIG -1
57# define _POSIX_V6_LPBIG_OFFBIG -1
58# define _XBS5_LPBIG_OFFBIG -1
59
60/* By default we have 64-bit wide `long int', pointers and `off_t'. */
61# define _POSIX_V7_LP64_OFF64 1
62# define _POSIX_V6_LP64_OFF64 1
63# define _XBS5_LP64_OFF64 1
64
65#else /* __WORDSIZE == 32 */
66
67/* By default we have 32-bit wide `int', `long int', pointers and `off_t'
68 and all platforms support LFS. */
69# define _POSIX_V7_ILP32_OFF32 1
70# define _POSIX_V7_ILP32_OFFBIG 1
71# define _POSIX_V6_ILP32_OFF32 1
72# define _POSIX_V6_ILP32_OFFBIG 1
73# define _XBS5_ILP32_OFF32 1
74# define _XBS5_ILP32_OFFBIG 1
75
76/* We optionally provide an environment with the above size but an 64-bit
77 side `off_t'. Therefore we don't define _POSIX_V7_ILP32_OFFBIG. */
78
79/* Environments with 64-bit wide pointers can be provided,
80 so these macros aren't defined:
81 # undef _POSIX_V7_LP64_OFF64
82 # undef _POSIX_V7_LPBIG_OFFBIG
83 # undef _POSIX_V6_LP64_OFF64
84 # undef _POSIX_V6_LPBIG_OFFBIG
85 # undef _XBS5_LP64_OFF64
86 # undef _XBS5_LPBIG_OFFBIG
87 and sysconf tests for it at runtime. */
88
89#endif /* __WORDSIZE == 32 */
90
91#define __ILP32_OFF32_CFLAGS "-m31"
92#define __ILP32_OFFBIG_CFLAGS "-m31 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
93#define __ILP32_OFF32_LDFLAGS "-m31"
94#define __ILP32_OFFBIG_LDFLAGS "-m31"
95#define __LP64_OFF64_CFLAGS "-m64"
96#define __LP64_OFF64_LDFLAGS "-m64"
\ No newline at end of file
lib/libc/include/s390x-linux-gnu/bits/fcntl.h+6-20
......@@ -22,29 +22,20 @@
2222
2323#include <bits/wordsize.h>
2424
25#if __WORDSIZE == 64
2625/* Not necessary, files are always with 64bit off_t. */
27# define __O_LARGEFILE 0
28#endif
26#define __O_LARGEFILE 0
2927
30#if __WORDSIZE == 64
3128/* Not necessary, we always have 64-bit offsets. */
32# define F_GETLK64 5 /* Get record locking info. */
33# define F_SETLK64 6 /* Set record locking info (non-blocking). */
34# define F_SETLKW64 7 /* Set record locking info (blocking). */
35#endif
29#define F_GETLK64 5 /* Get record locking info. */
30#define F_SETLK64 6 /* Set record locking info (non-blocking). */
31#define F_SETLKW64 7 /* Set record locking info (blocking). */
3632
3733struct flock
3834 {
3935 short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */
4036 short int l_whence; /* Where `l_start' is relative to (like `lseek'). */
41#if __WORDSIZE == 64 || !defined __USE_FILE_OFFSET64
4237 __off_t l_start; /* Offset where the lock begins. */
4338 __off_t l_len; /* Size of the locked area; zero means until EOF. */
44#else
45 __off64_t l_start; /* Offset where the lock begins. */
46 __off64_t l_len; /* Size of the locked area; zero means until EOF. */
47#endif
4839 __pid_t l_pid; /* Process holding the lock. */
4940 };
5041
......@@ -59,13 +50,8 @@ struct flock64
5950 };
6051#endif
6152
62#if __WORDSIZE == 64
63# define __POSIX_FADV_DONTNEED 6 /* Don't need these pages. */
64# define __POSIX_FADV_NOREUSE 7 /* Data will be accessed once. */
65#else
66# define __POSIX_FADV_DONTNEED 4 /* Don't need these pages. */
67# define __POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */
68#endif
53#define __POSIX_FADV_DONTNEED 6 /* Don't need these pages. */
54#define __POSIX_FADV_NOREUSE 7 /* Data will be accessed once. */
6955
7056/* Include generic Linux declarations. */
7157#include <bits/fcntl-linux.h>
\ No newline at end of file
lib/libc/include/s390x-linux-gnu/bits/fenv.h+4-4
......@@ -77,9 +77,9 @@ typedef struct
7777{
7878 fexcept_t __fpc;
7979 void *__glibc_reserved;
80 /* The field __unused (formerly __ieee_instruction_pointer) is a relict from
81 commit "Remove PTRACE_PEEKUSER" (87b9b50f0d4b92248905e95a06a13c513dc45e59)
82 and isn't used anymore. */
80 /* The field __glibc_reserved (formerly __ieee_instruction_pointer) is a
81 relict from commit "Remove PTRACE_PEEKUSER"
82 (87b9b50f0d4b92248905e95a06a13c513dc45e59) and isn't used anymore. */
8383} fenv_t;
8484
8585/* If the default argument is used we use this value. */
......@@ -96,4 +96,4 @@ typedef unsigned int femode_t;
9696
9797/* Default floating-point control modes. */
9898# define FE_DFL_MODE ((const femode_t *) -1L)
99#endif
99#endif
\ No newline at end of file
lib/libc/include/s390x-linux-gnu/bits/link.h+1-61
......@@ -23,64 +23,6 @@
2323typedef char La_s390_vr[16];
2424#endif
2525
26#if __ELF_NATIVE_CLASS == 32
27
28/* Registers for entry into PLT on s390-32. */
29typedef struct La_s390_32_regs
30{
31 uint32_t lr_r2;
32 uint32_t lr_r3;
33 uint32_t lr_r4;
34 uint32_t lr_r5;
35 uint32_t lr_r6;
36 double lr_fp0;
37 double lr_fp2;
38# if defined HAVE_S390_VX_ASM_SUPPORT
39 La_s390_vr lr_v24;
40 La_s390_vr lr_v25;
41 La_s390_vr lr_v26;
42 La_s390_vr lr_v27;
43 La_s390_vr lr_v28;
44 La_s390_vr lr_v29;
45 La_s390_vr lr_v30;
46 La_s390_vr lr_v31;
47# endif
48} La_s390_32_regs;
49
50/* Return values for calls from PLT on s390-32. */
51typedef struct La_s390_32_retval
52{
53 uint32_t lrv_r2;
54 uint32_t lrv_r3;
55 double lrv_fp0;
56# if defined HAVE_S390_VX_ASM_SUPPORT
57 La_s390_vr lrv_v24;
58# endif
59} La_s390_32_retval;
60
61
62__BEGIN_DECLS
63
64extern Elf32_Addr la_s390_32_gnu_pltenter (Elf32_Sym *__sym,
65 unsigned int __ndx,
66 uintptr_t *__refcook,
67 uintptr_t *__defcook,
68 La_s390_32_regs *__regs,
69 unsigned int *__flags,
70 const char *__symname,
71 long int *__framesizep);
72extern unsigned int la_s390_32_gnu_pltexit (Elf32_Sym *__sym,
73 unsigned int __ndx,
74 uintptr_t *__refcook,
75 uintptr_t *__defcook,
76 const La_s390_32_regs *__inregs,
77 La_s390_32_retval *__outregs,
78 const char *symname);
79
80__END_DECLS
81
82#else
83
8426/* Registers for entry into PLT on s390-64. */
8527typedef struct La_s390_64_regs
8628{
......@@ -134,6 +76,4 @@ extern unsigned int la_s390_64_gnu_pltexit (Elf64_Sym *__sym,
13476 La_s390_64_retval *__outregs,
13577 const char *__symname);
13678
137__END_DECLS
138
139#endif
\ No newline at end of file
79__END_DECLS
\ No newline at end of file
lib/libc/include/s390x-linux-gnu/bits/procfs-extra.h deleted-75
......@@ -1,75 +0,0 @@
1/* Extra sys/procfs.h definitions. S/390 version.
2 Copyright (C) 2000-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#ifndef _SYS_PROCFS_H
20# error "Never include <bits/procfs-extra.h> directly; use <sys/procfs.h> instead."
21#endif
22
23#if __WORDSIZE == 64
24
25/* Provide 32-bit variants so that BFD can read 32-bit
26 core files. */
27#define ELF_NGREG32 36
28typedef unsigned int elf_greg_t32;
29typedef elf_greg_t32
30 elf_gregset_t32[ELF_NGREG32] __attribute__ ((__aligned__ (8)));
31typedef elf_fpregset_t elf_fpregset_t32;
32
33struct elf_prstatus32
34 {
35 struct elf_siginfo pr_info; /* Info associated with signal. */
36 short int pr_cursig; /* Current signal. */
37 unsigned int pr_sigpend; /* Set of pending signals. */
38 unsigned int pr_sighold; /* Set of held signals. */
39 __pid_t pr_pid;
40 __pid_t pr_ppid;
41 __pid_t pr_pgrp;
42 __pid_t pr_sid;
43 struct
44 {
45 int tv_sec, tv_usec;
46 } pr_utime, /* User time. */
47 pr_stime, /* System time. */
48 pr_cutime, /* Cumulative user time. */
49 pr_cstime; /* Cumulative system time. */
50 elf_gregset_t32 pr_reg; /* GP registers. */
51 int pr_fpvalid; /* True if math copro being used. */
52 };
53
54struct elf_prpsinfo32
55 {
56 char pr_state; /* Numeric process state. */
57 char pr_sname; /* Char for pr_state. */
58 char pr_zomb; /* Zombie. */
59 char pr_nice; /* Nice val. */
60 unsigned int pr_flag; /* Flags. */
61 unsigned short int pr_uid;
62 unsigned short int pr_gid;
63 int pr_pid, pr_ppid, pr_pgrp, pr_sid;
64 /* Lots missing */
65 char pr_fname[16]; /* Filename of executable. */
66 char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */
67 };
68
69typedef elf_gregset_t32 prgregset32_t;
70typedef elf_fpregset_t32 prfpregset32_t;
71
72typedef struct elf_prstatus32 prstatus32_t;
73typedef struct elf_prpsinfo32 prpsinfo32_t;
74
75#endif
\ No newline at end of file
lib/libc/include/s390x-linux-gnu/bits/procfs-id.h deleted-30
......@@ -1,30 +0,0 @@
1/* Types of pr_uid and pr_gid in struct elf_prpsinfo. S/390 version.
2 Copyright (C) 2018-2026 Free Software Foundation, Inc.
3
4 This file is part of the GNU C Library.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <https://www.gnu.org/licenses/>. */
19
20#ifndef _SYS_PROCFS_H
21# error "Never include <bits/procfs-id.h> directly; use <sys/procfs.h> instead."
22#endif
23
24#if __WORDSIZE == 64
25typedef unsigned int __pr_uid_t;
26typedef unsigned int __pr_gid_t;
27#else
28typedef unsigned short int __pr_uid_t;
29typedef unsigned short int __pr_gid_t;
30#endif
\ No newline at end of file
lib/libc/include/s390x-linux-gnu/bits/setjmp.h-6
......@@ -33,13 +33,7 @@ typedef struct __s390_jmp_buf
3333 /* We save registers 6-15. */
3434 long int __gregs[10];
3535
36# if __WORDSIZE == 64
37 /* We save fpu registers f8 - f15. */
3836 long __fpregs[8];
39# else
40 /* We save fpu registers 4 and 6. */
41 long __fpregs[4];
42# endif
4337} __jmp_buf[1];
4438
4539#endif
lib/libc/include/s390x-linux-gnu/bits/sigaction.h+1-34
......@@ -1,4 +1,4 @@
1/* Definitions for 31 & 64 bit S/390 sigaction.
1/* Definitions for 64 bit S/390 sigaction.
22 Copyright (C) 2001-2026 Free Software Foundation, Inc.
33 This file is part of the GNU C Library.
44
......@@ -23,9 +23,6 @@
2323# error "Never include <bits/sigaction.h> directly; use <signal.h> instead."
2424#endif
2525
26#include <bits/wordsize.h>
27
28#if __WORDSIZE == 64
2926/* Structure describing the action to be taken when a signal arrives. */
3027struct sigaction
3128 {
......@@ -55,36 +52,6 @@ struct sigaction
5552 /* Additional set of signals to be blocked. */
5653 __sigset_t sa_mask;
5754 };
58#else
59/* Structure describing the action to be taken when a signal arrives. */
60struct sigaction
61 {
62 /* Signal handler. */
63#if defined __USE_POSIX199309 || defined __USE_XOPEN_EXTENDED
64 union
65 {
66 /* Used if SA_SIGINFO is not set. */
67 __sighandler_t sa_handler;
68 /* Used if SA_SIGINFO is set. */
69 void (*sa_sigaction) (int, siginfo_t *, void *);
70 }
71 __sigaction_handler;
72# define sa_handler __sigaction_handler.sa_handler
73# define sa_sigaction __sigaction_handler.sa_sigaction
74#else
75 __sighandler_t sa_handler;
76#endif
77
78 /* Additional set of signals to be blocked. */
79 __sigset_t sa_mask;
80
81 /* Special flags. */
82 int sa_flags;
83
84 /* Restore handler. */
85 void (*sa_restorer) (void);
86 };
87#endif
8855
8956/* Bits in `sa_flags'. */
9057#define SA_NOCLDSTOP 1 /* Don't send SIGCHLD when children stop. */
lib/libc/include/s390x-linux-gnu/bits/struct_mutex.h+2-24
......@@ -24,39 +24,17 @@ struct __pthread_mutex_s
2424 int __lock;
2525 unsigned int __count;
2626 int __owner;
27#if __WORDSIZE == 64
2827 unsigned int __nusers;
29#endif
3028 /* KIND must stay at this position in the structure to maintain
3129 binary compatibility with static initializers. */
3230 int __kind;
33#if __WORDSIZE == 64
3431 short __spins;
3532 short __glibc_reserved;
3633 __pthread_list_t __list;
3734# define __PTHREAD_MUTEX_HAVE_PREV 1
38#else
39 unsigned int __nusers;
40 __extension__ union
41 {
42 struct
43 {
44 short __data_spins;
45 short __data_unused;
46 } __data;
47# define __spins __data.__data_spins
48 __pthread_slist_t __list;
49 };
50# define __PTHREAD_MUTEX_HAVE_PREV 0
51#endif
5235};
5336
54#if __WORDSIZE == 64
55# define __PTHREAD_MUTEX_INITIALIZER(__kind) \
37#define __PTHREAD_MUTEX_INITIALIZER(__kind) \
5638 0, 0, 0, 0, __kind, 0, 0, { 0, 0 }
57#else
58# define __PTHREAD_MUTEX_INITIALIZER(__kind) \
59 0, 0, 0, __kind, 0, { { 0, 0 } }
60#endif
6139
62#endif
40#endif
\ No newline at end of file
lib/libc/include/s390x-linux-gnu/bits/struct_rwlock.h+1-16
......@@ -28,7 +28,6 @@ struct __pthread_rwlock_arch_t
2828 unsigned int __writers_futex;
2929 unsigned int __pad3;
3030 unsigned int __pad4;
31#if __WORDSIZE == 64
3231 int __cur_writer;
3332 int __shared;
3433 unsigned long int __pad1;
......@@ -36,23 +35,9 @@ struct __pthread_rwlock_arch_t
3635 /* FLAGS must stay at this position in the structure to maintain
3736 binary compatibility. */
3837 unsigned int __flags;
39# else
40 unsigned char __pad1;
41 unsigned char __pad2;
42 unsigned char __shared;
43 /* FLAGS must stay at this position in the structure to maintain
44 binary compatibility. */
45 unsigned char __flags;
46 int __cur_writer;
47#endif
4838};
4939
50#if __WORDSIZE == 64
51# define __PTHREAD_RWLOCK_INITIALIZER(__flags) \
40#define __PTHREAD_RWLOCK_INITIALIZER(__flags) \
5241 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, __flags
53#else
54# define __PTHREAD_RWLOCK_INITIALIZER(__flags) \
55 0, 0, 0, 0, 0, 0, 0, 0, 0, __flags, 0
56#endif
5742
5843#endif
\ No newline at end of file
lib/libc/include/s390x-linux-gnu/bits/struct_stat.h+6-114
......@@ -25,7 +25,6 @@
2525
2626#include <bits/wordsize.h>
2727
28#if __WORDSIZE == 64
2928struct stat
3029 {
3130 __dev_t st_dev; /* Device. */
......@@ -62,70 +61,8 @@ struct stat
6261 __blkcnt_t st_blocks; /* Nr. 512-byte blocks allocated. */
6362 long int __glibc_reserved[3];
6463 };
65#else
66struct stat
67 {
68# ifdef __USE_TIME64_REDIRECTS
69# include <bits/struct_stat_time64_helper.h>
70# else
71 __dev_t st_dev; /* Device. */
72 unsigned int __pad1;
73# ifndef __USE_FILE_OFFSET64
74 __ino_t st_ino; /* File serial number. */
75# else
76 __ino_t __st_ino; /* 32bit file serial number. */
77# endif
78 __mode_t st_mode; /* File mode. */
79 __nlink_t st_nlink; /* Link count. */
80 __uid_t st_uid; /* User ID of the file's owner. */
81 __gid_t st_gid; /* Group ID of the file's group.*/
82 __dev_t st_rdev; /* Device number, if device. */
83 unsigned int __pad2;
84# ifndef __USE_FILE_OFFSET64
85 __off_t st_size; /* Size of file, in bytes. */
86# else
87 __off64_t st_size; /* Size of file, in bytes. */
88# endif
89 __blksize_t st_blksize; /* Optimal block size for I/O. */
90
91# ifndef __USE_FILE_OFFSET64
92 __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */
93# else
94 __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */
95# endif
96# ifdef __USE_XOPEN2K8
97 /* Nanosecond resolution timestamps are stored in a format
98 equivalent to 'struct timespec'. This is the type used
99 whenever possible but the Unix namespace rules do not allow the
100 identifier 'timespec' to appear in the <sys/stat.h> header.
101 Therefore we have to handle the use of this header in strictly
102 standard-compliant sources special. */
103 struct timespec st_atim; /* Time of last access. */
104 struct timespec st_mtim; /* Time of last modification. */
105 struct timespec st_ctim; /* Time of last status change. */
106# define st_atime st_atim.tv_sec /* Backward compatibility. */
107# define st_mtime st_mtim.tv_sec
108# define st_ctime st_ctim.tv_sec
109# else
110 __time_t st_atime; /* Time of last access. */
111 unsigned long int st_atimensec; /* Nscecs of last access. */
112 __time_t st_mtime; /* Time of last modification. */
113 unsigned long int st_mtimensec; /* Nsecs of last modification. */
114 __time_t st_ctime; /* Time of last status change. */
115 unsigned long int st_ctimensec; /* Nsecs of last status change. */
116# endif
117# ifndef __USE_FILE_OFFSET64
118 unsigned long int __glibc_reserved4;
119 unsigned long int __glibc_reserved5;
120# else
121 __ino64_t st_ino; /* File serial number. */
122# endif
123# endif
124 };
125# endif
12664
12765#ifdef __USE_LARGEFILE64
128# if __WORDSIZE == 64
12966/* Note stat64 is the same shape as stat. */
13067struct stat64
13168 {
......@@ -138,7 +75,7 @@ struct stat64
13875 int __glibc_reserved0;
13976 __dev_t st_rdev; /* Device number, if device. */
14077 __off_t st_size; /* Size of file, in bytes. */
141# ifdef __USE_XOPEN2K8
78# ifdef __USE_XOPEN2K8
14279 /* Nanosecond resolution timestamps are stored in a format
14380 equivalent to 'struct timespec'. This is the type used
14481 whenever possible but the Unix namespace rules do not allow the
......@@ -148,66 +85,21 @@ struct stat64
14885 struct timespec st_atim; /* Time of last access. */
14986 struct timespec st_mtim; /* Time of last modification. */
15087 struct timespec st_ctim; /* Time of last status change. */
151# define st_atime st_atim.tv_sec /* Backward compatibility. */
152# define st_mtime st_mtim.tv_sec
153# define st_ctime st_ctim.tv_sec
154# else
88# define st_atime st_atim.tv_sec /* Backward compatibility. */
89# define st_mtime st_mtim.tv_sec
90# define st_ctime st_ctim.tv_sec
91# else
15592 __time_t st_atime; /* Time of last access. */
15693 unsigned long int st_atimensec; /* Nscecs of last access. */
15794 __time_t st_mtime; /* Time of last modification. */
15895 unsigned long int st_mtimensec; /* Nsecs of last modification. */
15996 __time_t st_ctime; /* Time of last status change. */
16097 unsigned long int st_ctimensec; /* Nsecs of last status change. */
161# endif
98# endif
16299 __blksize_t st_blksize; /* Optimal block size for I/O. */
163100 __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */
164101 long int __glibc_reserved[3];
165102 };
166# else
167struct stat64
168 {
169# ifdef __USE_TIME64_REDIRECTS
170# include <bits/struct_stat_time64_helper.h>
171# else
172 __dev_t st_dev; /* Device. */
173 unsigned int __pad1;
174
175 __ino_t __st_ino; /* 32bit file serial number. */
176 __mode_t st_mode; /* File mode. */
177 __nlink_t st_nlink; /* Link count. */
178 __uid_t st_uid; /* User ID of the file's owner. */
179 __gid_t st_gid; /* Group ID of the file's group.*/
180 __dev_t st_rdev; /* Device number, if device. */
181 unsigned int __pad2;
182 __off64_t st_size; /* Size of file, in bytes. */
183 __blksize_t st_blksize; /* Optimal block size for I/O. */
184
185 __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */
186# ifdef __USE_XOPEN2K8
187 /* Nanosecond resolution timestamps are stored in a format
188 equivalent to 'struct timespec'. This is the type used
189 whenever possible but the Unix namespace rules do not allow the
190 identifier 'timespec' to appear in the <sys/stat.h> header.
191 Therefore we have to handle the use of this header in strictly
192 standard-compliant sources special. */
193 struct timespec st_atim; /* Time of last access. */
194 struct timespec st_mtim; /* Time of last modification. */
195 struct timespec st_ctim; /* Time of last status change. */
196# define st_atime st_atim.tv_sec /* Backward compatibility. */
197# define st_mtime st_mtim.tv_sec
198# define st_ctime st_ctim.tv_sec
199# else
200 __time_t st_atime; /* Time of last access. */
201 unsigned long int st_atimensec; /* Nscecs of last access. */
202 __time_t st_mtime; /* Time of last modification. */
203 unsigned long int st_mtimensec; /* Nsecs of last modification. */
204 __time_t st_ctime; /* Time of last status change. */
205 unsigned long int st_ctimensec; /* Nsecs of last status change. */
206# endif
207 __ino64_t st_ino; /* File serial number. */
208# endif
209 };
210# endif
211103#endif
212104
213105/* Tell code we have these members. */
lib/libc/include/s390x-linux-gnu/bits/timesize.h deleted-22
......@@ -1,22 +0,0 @@
1/* Bit size of the time_t type at glibc build time, Linux/s390.
2 Copyright (C) 2021-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#include <bits/wordsize.h>
20
21/* Size in bits of the 'time_t' type of the default ABI. */
22#define __TIMESIZE __WORDSIZE
\ No newline at end of file
lib/libc/include/s390x-linux-gnu/bits/typesizes.h+14-22
......@@ -57,42 +57,34 @@
5757#define __TIMER_T_TYPE void *
5858#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE
5959#define __FSID_T_TYPE struct { int __val[2]; }
60#if defined __GNUC__ && __GNUC__ <= 2
61/* Compatibility with g++ 2.95.x. */
62#define __SSIZE_T_TYPE __SWORD_TYPE
63#else
64/* size_t is unsigned long int on s390 -m31. */
65#define __SSIZE_T_TYPE __SLONGWORD_TYPE
66#endif
60
61/* With s390-32, __SSIZE_T_TYPE was __SWORD_TYPE for compatibility with
62 g++ 2.95.x. Afterwards __SLONGWORD_TYPE was needed as size_t was
63 unsigned long int on s390-32.
64 Now as only s390-64 exists, __SWORD_TYPE can be used as also used in the
65 generic version as both types result in long int. */
66#define __SSIZE_T_TYPE __SWORD_TYPE
67
6768#define __SYSCALL_SLONG_TYPE __SLONGWORD_TYPE
6869#define __SYSCALL_ULONG_TYPE __ULONGWORD_TYPE
69#define __CPU_MASK_TYPE __ULONGWORD_TYPE
70#define __CPU_MASK_TYPE __ULONGWORD_TYPE
7071
71#ifdef __s390x__
7272/* Tell the libc code that off_t and off64_t are actually the same type
7373 for all ABI purposes, even if possibly expressed as different base types
7474 for C type-checking purposes. */
75# define __OFF_T_MATCHES_OFF64_T 1
75#define __OFF_T_MATCHES_OFF64_T 1
7676
7777/* Same for ino_t and ino64_t. */
78# define __INO_T_MATCHES_INO64_T 1
78#define __INO_T_MATCHES_INO64_T 1
7979
8080/* And for __rlim_t and __rlim64_t. */
81# define __RLIM_T_MATCHES_RLIM64_T 1
81#define __RLIM_T_MATCHES_RLIM64_T 1
8282
8383/* And for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t. */
84# define __STATFS_MATCHES_STATFS64 1
84#define __STATFS_MATCHES_STATFS64 1
8585
8686/* And for getitimer, setitimer and rusage */
87# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1
88#else
89# define __RLIM_T_MATCHES_RLIM64_T 0
90
91# define __STATFS_MATCHES_STATFS64 0
92
93/* And for getitimer, setitimer and rusage */
94# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 0
95#endif
87#define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1
9688
9789/* Number of descriptors that can fit in an `fd_set'. */
9890#define __FD_SETSIZE 1024
lib/libc/include/s390x-linux-gnu/bits/utmp.h deleted-127
......@@ -1,127 +0,0 @@
1/* The `struct utmp' type, describing entries in the utmp file. GNU version.
2 Copyright (C) 1993-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#ifndef _UTMP_H
20# error "Never include <bits/utmp.h> directly; use <utmp.h> instead."
21#endif
22
23#include <paths.h>
24#include <sys/time.h>
25#include <sys/types.h>
26#include <bits/wordsize.h>
27
28
29#define UT_LINESIZE 32
30#define UT_NAMESIZE 32
31#define UT_HOSTSIZE 256
32
33
34/* The structure describing an entry in the database of
35 previous logins. */
36struct lastlog
37 {
38#if __WORDSIZE == 32
39 int64_t ll_time;
40#else
41 __time_t ll_time;
42#endif
43 char ll_line[UT_LINESIZE];
44 char ll_host[UT_HOSTSIZE];
45 };
46
47
48/* The structure describing the status of a terminated process. This
49 type is used in `struct utmp' below. */
50struct exit_status
51 {
52 short int e_termination; /* Process termination status. */
53 short int e_exit; /* Process exit status. */
54 };
55
56
57/* The structure describing an entry in the user accounting database. */
58struct utmp
59{
60 short int ut_type; /* Type of login. */
61 pid_t ut_pid; /* Process ID of login process. */
62 char ut_line[UT_LINESIZE]
63 __attribute_nonstring__; /* Devicename. */
64 char ut_id[4]
65 __attribute_nonstring__; /* Inittab ID. */
66 char ut_user[UT_NAMESIZE]
67 __attribute_nonstring__; /* Username. */
68 char ut_host[UT_HOSTSIZE]
69 __attribute_nonstring__; /* Hostname for remote login. */
70 struct exit_status ut_exit; /* Exit status of a process marked
71 as DEAD_PROCESS. */
72/* The ut_session and ut_tv fields must be the same size when compiled
73 32- and 64-bit. This allows data files and shared memory to be
74 shared between 32- and 64-bit applications. */
75#if __WORDSIZE == 32
76 int64_t ut_session; /* Session ID, used for windowing. */
77 struct
78 {
79 int64_t tv_sec; /* Seconds. */
80 int64_t tv_usec; /* Microseconds. */
81 } ut_tv; /* Time entry was made. */
82#else
83 long int ut_session; /* Session ID, used for windowing. */
84 struct timeval ut_tv; /* Time entry was made. */
85#endif
86
87 int32_t ut_addr_v6[4]; /* Internet address of remote host. */
88 char __glibc_reserved[20]; /* Reserved for future use. */
89};
90
91/* Backwards compatibility hacks. */
92#define ut_name ut_user
93#ifndef _NO_UT_TIME
94/* We have a problem here: `ut_time' is also used otherwise. Define
95 _NO_UT_TIME if the compiler complains. */
96# define ut_time ut_tv.tv_sec
97#endif
98#define ut_xtime ut_tv.tv_sec
99#define ut_addr ut_addr_v6[0]
100
101
102/* Values for the `ut_type' field of a `struct utmp'. */
103#define EMPTY 0 /* No valid user accounting information. */
104
105#define RUN_LVL 1 /* The system's runlevel. */
106#define BOOT_TIME 2 /* Time of system boot. */
107#define NEW_TIME 3 /* Time after system clock changed. */
108#define OLD_TIME 4 /* Time when system clock changed. */
109
110#define INIT_PROCESS 5 /* Process spawned by the init process. */
111#define LOGIN_PROCESS 6 /* Session leader of a logged in user. */
112#define USER_PROCESS 7 /* Normal process. */
113#define DEAD_PROCESS 8 /* Terminated process. */
114
115#define ACCOUNTING 9
116
117/* Old Linux name for the EMPTY type. */
118#define UT_UNKNOWN EMPTY
119
120
121/* Tell the user that we have a modern system with UT_HOST, UT_PID,
122 UT_TYPE, UT_ID and UT_TV fields. */
123#define _HAVE_UT_TYPE 1
124#define _HAVE_UT_PID 1
125#define _HAVE_UT_ID 1
126#define _HAVE_UT_TV 1
127#define _HAVE_UT_HOST 1
\ No newline at end of file
lib/libc/include/s390x-linux-gnu/bits/utmpx.h deleted-106
......@@ -1,106 +0,0 @@
1/* Structures and definitions for the user accounting database. GNU version.
2 Copyright (C) 1997-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#ifndef _UTMPX_H
20# error "Never include <bits/utmpx.h> directly; use <utmpx.h> instead."
21#endif
22
23#include <bits/types.h>
24#include <sys/time.h>
25#include <bits/wordsize.h>
26
27
28#ifdef __USE_GNU
29# include <paths.h>
30# define _PATH_UTMPX _PATH_UTMP
31# define _PATH_WTMPX _PATH_WTMP
32#endif
33
34
35#define __UT_LINESIZE 32
36#define __UT_NAMESIZE 32
37#define __UT_HOSTSIZE 256
38
39
40/* The structure describing the status of a terminated process. This
41 type is used in `struct utmpx' below. */
42struct __exit_status
43 {
44#ifdef __USE_GNU
45 short int e_termination; /* Process termination status. */
46 short int e_exit; /* Process exit status. */
47#else
48 short int __e_termination; /* Process termination status. */
49 short int __e_exit; /* Process exit status. */
50#endif
51 };
52
53
54/* The structure describing an entry in the user accounting database. */
55struct utmpx
56{
57 short int ut_type; /* Type of login. */
58 __pid_t ut_pid; /* Process ID of login process. */
59 char ut_line[__UT_LINESIZE]
60 __attribute_nonstring__; /* Devicename. */
61 char ut_id[4]
62 __attribute_nonstring__; /* Inittab ID. */
63 char ut_user[__UT_NAMESIZE]
64 __attribute_nonstring__; /* Username. */
65 char ut_host[__UT_HOSTSIZE]
66 __attribute_nonstring__; /* Hostname for remote login. */
67 struct __exit_status ut_exit; /* Exit status of a process marked
68 as DEAD_PROCESS. */
69
70/* The fields ut_session and ut_tv must be the same size when compiled
71 32- and 64-bit. This allows files and shared memory to be shared
72 between 32- and 64-bit applications. */
73#if __WORDSIZE == 32
74 __int64_t ut_session; /* Session ID, used for windowing. */
75 struct
76 {
77 __int64_t tv_sec; /* Seconds. */
78 __int64_t tv_usec; /* Microseconds. */
79 } ut_tv; /* Time entry was made. */
80#else
81 long int ut_session; /* Session ID, used for windowing. */
82 struct timeval ut_tv; /* Time entry was made. */
83#endif
84 __int32_t ut_addr_v6[4]; /* Internet address of remote host. */
85 char __glibc_reserved[20]; /* Reserved for future use. */
86};
87
88
89/* Values for the `ut_type' field of a `struct utmpx'. */
90#define EMPTY 0 /* No valid user accounting information. */
91
92#ifdef __USE_GNU
93# define RUN_LVL 1 /* The system's runlevel. */
94#endif
95#define BOOT_TIME 2 /* Time of system boot. */
96#define NEW_TIME 3 /* Time after system clock changed. */
97#define OLD_TIME 4 /* Time when system clock changed. */
98
99#define INIT_PROCESS 5 /* Process spawned by the init process. */
100#define LOGIN_PROCESS 6 /* Session leader of a logged in user. */
101#define USER_PROCESS 7 /* Normal process. */
102#define DEAD_PROCESS 8 /* Terminated process. */
103
104#ifdef __USE_GNU
105# define ACCOUNTING 9 /* System accounting. */
106#endif
\ No newline at end of file
lib/libc/include/s390x-linux-gnu/bits/wordsize.h+17-9
......@@ -1,11 +1,19 @@
1/* Determine the wordsize from the preprocessor defines. */
1/* Copyright (C) 1999-2026 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
23
3#if defined __s390x__
4# define __WORDSIZE 64
5#else
6# define __WORDSIZE 32
7# define __WORDSIZE32_SIZE_ULONG 1
8# define __WORDSIZE32_PTRDIFF_LONG 0
9#endif
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
108
11#define __WORDSIZE_TIME64_COMPAT32 0
\ No newline at end of file
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
17
18#define __WORDSIZE 64
19#define __WORDSIZE_TIME64_COMPAT32 0
\ No newline at end of file
lib/libc/include/s390x-linux-gnu/gnu/lib-names-64.h deleted-27
......@@ -1,27 +0,0 @@
1/* This file is automatically generated. */
2#ifndef __GNU_LIB_NAMES_H
3# error "Never use <gnu/lib-names-64.h> directly; include <gnu/lib-names.h> instead."
4#endif
5
6#define LD64_SO "ld64.so.1"
7#define LD_SO "ld64.so.1"
8#define LIBANL_SO "libanl.so.1"
9#define LIBBROKENLOCALE_SO "libBrokenLocale.so.1"
10#define LIBC_MALLOC_DEBUG_SO "libc_malloc_debug.so.0"
11#define LIBC_SO "libc.so.6"
12#define LIBDL_SO "libdl.so.2"
13#define LIBGCC_S_SO "libgcc_s.so.1"
14#define LIBMVEC_SO "libmvec.so.1"
15#define LIBM_SO "libm.so.6"
16#define LIBNSL_SO "libnsl.so.1"
17#define LIBNSS_COMPAT_SO "libnss_compat.so.2"
18#define LIBNSS_DB_SO "libnss_db.so.2"
19#define LIBNSS_DNS_SO "libnss_dns.so.2"
20#define LIBNSS_FILES_SO "libnss_files.so.2"
21#define LIBNSS_HESIOD_SO "libnss_hesiod.so.2"
22#define LIBNSS_LDAP_SO "libnss_ldap.so.2"
23#define LIBPTHREAD_SO "libpthread.so.0"
24#define LIBRESOLV_SO "libresolv.so.2"
25#define LIBRT_SO "librt.so.1"
26#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/s390x-linux-gnu/gnu/lib-names.h+23-8
......@@ -4,13 +4,28 @@
44#ifndef __GNU_LIB_NAMES_H
55#define __GNU_LIB_NAMES_H 1
66
7#include <bits/wordsize.h>
8
9#if __WORDSIZE == 32
10# include <gnu/lib-names-32.h>
11#endif
12#if __WORDSIZE == 64
13# include <gnu/lib-names-64.h>
14#endif
7#define LD64_SO "ld64.so.1"
8#define LD_SO "ld64.so.1"
9#define LIBANL_SO "libanl.so.1"
10#define LIBBROKENLOCALE_SO "libBrokenLocale.so.1"
11#define LIBC_MALLOC_DEBUG_SO "libc_malloc_debug.so.0"
12#define LIBC_SO "libc.so.6"
13#define LIBDL_SO "libdl.so.2"
14#define LIBGCC_S_SO "libgcc_s.so.1"
15#define LIBMVEC_SO "libmvec.so.1"
16#define LIBM_SO "libm.so.6"
17#define LIBNSL_SO "libnsl.so.1"
18#define LIBNSS_COMPAT_SO "libnss_compat.so.2"
19#define LIBNSS_DB_SO "libnss_db.so.2"
20#define LIBNSS_DNS_SO "libnss_dns.so.2"
21#define LIBNSS_FILES_SO "libnss_files.so.2"
22#define LIBNSS_HESIOD_SO "libnss_hesiod.so.2"
23#define LIBNSS_LDAP_SO "libnss_ldap.so.2"
24#define LIBPTHREAD_SO "libpthread.so.0"
25#define LIBRESOLV_SO "libresolv.so.2"
26#define LIBRT_SO "librt.so.1"
27#define LIBTHREAD_DB_SO "libthread_db.so.1"
28#define LIBUNWIND_SO "libunwind.so.1"
29#define LIBUTIL_SO "libutil.so.1"
1530
1631#endif /* gnu/lib-names.h */
\ No newline at end of file
lib/libc/include/s390x-linux-gnu/gnu/stubs.h+13-9
......@@ -1,12 +1,16 @@
11/* This file is automatically generated.
2 This file selects the right generated file of `__stub_FUNCTION' macros
3 based on the architecture being compiled for. */
2 It defines a symbol `__stub_FUNCTION' for each function
3 in the C library which is a stub, meaning it will fail
4 every time called, usually setting errno to ENOSYS. */
45
5#include <bits/wordsize.h>
6
7#if __WORDSIZE == 32
8# include <gnu/stubs-32.h>
6#ifdef _LIBC
7 #error Applications may not define the macro _LIBC
98#endif
10#if __WORDSIZE == 64
11# include <gnu/stubs-64.h>
12#endif
\ No newline at end of file
9
10#define __stub_chflags
11#define __stub_fchflags
12#define __stub_gtty
13#define __stub_revoke
14#define __stub_setlogin
15#define __stub_sigreturn
16#define __stub_stty
\ No newline at end of file
lib/libc/include/s390x-linux-gnu/sys/ucontext.h+1-5
......@@ -45,11 +45,7 @@ typedef unsigned long greg_t;
4545 the register set is an array, we make gregset_t a simple array
4646 that has the same size as s390_regs. This is needed for the
4747 elf_prstatus structure. */
48#if __WORDSIZE == 64
49# define __NGREG 27
50#else
51# define __NGREG 36
52#endif
48#define __NGREG 27
5349#ifdef __USE_MISC
5450# define NGREG __NGREG
5551#endif
lib/libc/include/sparc-linux-gnu/bits/cloexec.h created+1
......@@ -0,0 +1 @@
1#define __O_CLOEXEC 0x400000
\ No newline at end of file
lib/libc/include/sparc-linux-gnu/gnu/lib-names-64.h+1
......@@ -24,4 +24,5 @@
2424#define LIBRESOLV_SO "libresolv.so.2"
2525#define LIBRT_SO "librt.so.1"
2626#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
2728#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/sparc-linux-gnu/gnu/stubs-64.h created+16
......@@ -0,0 +1,16 @@
1/* This file is automatically generated.
2 It defines a symbol `__stub_FUNCTION' for each function
3 in the C library which is a stub, meaning it will fail
4 every time called, usually setting errno to ENOSYS. */
5
6#ifdef _LIBC
7 #error Applications may not define the macro _LIBC
8#endif
9
10#define __stub_chflags
11#define __stub_fchflags
12#define __stub_gtty
13#define __stub_revoke
14#define __stub_setlogin
15#define __stub_sigreturn
16#define __stub_stty
\ No newline at end of file
lib/libc/include/x86-linux-gnu/bits/struct_mutex.h+1-1
......@@ -59,4 +59,4 @@ struct __pthread_mutex_s
5959 0, 0, 0, __kind, 0, { { 0, 0 } }
6060#endif
6161
62#endif
62#endif
\ No newline at end of file
lib/libc/include/x86-linux-gnu/gnu/lib-names-64.h+1
......@@ -24,4 +24,5 @@
2424#define LIBRESOLV_SO "libresolv.so.2"
2525#define LIBRT_SO "librt.so.1"
2626#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
2728#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/x86-linux-gnu/gnu/lib-names-x32.h+1
......@@ -24,4 +24,5 @@
2424#define LIBRESOLV_SO "libresolv.so.2"
2525#define LIBRT_SO "librt.so.1"
2626#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
2728#define LIBUTIL_SO "libutil.so.1"
\ No newline at end of file
lib/libc/include/x86-netbsd-none/machine/mcontext.h+23-1
......@@ -1,4 +1,4 @@
1/* $NetBSD: mcontext.h,v 1.19 2024/11/30 01:04:10 christos Exp $ */
1/* $NetBSD: mcontext.h,v 1.19.2.1 2026/07/19 15:57:27 martin Exp $ */
22
33/*-
44 * Copyright (c) 1999 The NetBSD Foundation, Inc.
......@@ -40,6 +40,7 @@
4040#define _UC_CLRSTACK _UC_MD_BIT17
4141#define _UC_VM _UC_MD_BIT18
4242#define _UC_TLSBASE _UC_MD_BIT19
43#define _UC_XSAVE _UC_MD_BIT20
4344
4445/*
4546 * Layout of mcontext_t according to the System V Application Binary Interface,
......@@ -85,6 +86,27 @@ typedef struct {
8586 char __fp_xmm[512];
8687 } __fp_xmm_state; /* x87 and xmm regs in fxsave format */
8788 int __fp_fpregs[128];
89 struct {
90 /*
91 * `The XSAVE feature set does not use bytes
92 * 511:416; bytes 463:416 are reserved.'
93 *
94 * We take a part out of this to form a pointer
95 * to an external XSAVE area. This way, we can
96 * replicate the FXSAVE parts for the benefit
97 * of userland programs that aren't aware of
98 * the XSAVE pointer, have used the extended
99 * CPU registers (ymmN/zmmN/&c.), and want to
100 * examine the x87/SSE register state in a
101 * signal handler. The kernel does not use
102 * this part.
103 */
104 char __fxsave[416];
105 char __rsvd[48];
106 __greg_t __xsaveptr;
107 __greg_t __xsavelen;
108 char __pad[40];
109 } __xsave;
88110 } __fp_reg_set;
89111 int __fp_pad[33]; /* Historic padding */
90112} __fpregset_t;
lib/libc/include/x86_64-netbsd-none/amd64/mcontext.h+31-2
......@@ -1,4 +1,4 @@
1/* $NetBSD: mcontext.h,v 1.24 2024/11/30 01:04:06 christos Exp $ */
1/* $NetBSD: mcontext.h,v 1.24.2.1 2026/07/19 15:57:26 martin Exp $ */
22
33/*-
44 * Copyright (c) 1999 The NetBSD Foundation, Inc.
......@@ -56,7 +56,28 @@ typedef __greg_t __gregset_t[_NGREG];
5656 * which requires 16 byte alignment. However the mcontext version
5757 * is never directly accessed.
5858 */
59typedef char __fpregset_t[512] __aligned(8);
59typedef union {
60 char __fxsave[512] __aligned(8);
61 struct {
62 /*
63 * `The XSAVE feature set does not use bytes 511:416;
64 * bytes 463:416 are reserved.'
65 *
66 * We take a part out of this to form a pointer to an
67 * external XSAVE area. This way, we can replicate the
68 * FXSAVE parts for the benefit of userland programs
69 * that aren't aware of the XSAVE pointer, have used
70 * the extended CPU registers (ymmN/zmmN/&c.), and want
71 * to examine the x87/SSE register state in a signal
72 * handler. The kernel does not use this part.
73 */
74 char __fxsave[416];
75 char __rsvd[48];
76 __greg_t __xsaveptr;
77 __greg_t __xsavelen;
78 char __pad[32];
79 } __xsave;
80} __fpregset_t;
6081
6182typedef struct {
6283 __gregset_t __gregs;
......@@ -75,6 +96,7 @@ typedef struct {
7596#define _UC_MACHINE_SET_PC(uc, pc) _UC_MACHINE_PC(uc) = (pc)
7697
7798#define _UC_TLSBASE _UC_MD_BIT19
99#define _UC_XSAVE _UC_MD_BIT20
78100
79101/*
80102 * mcontext extensions to handle signal delivery.
......@@ -127,6 +149,13 @@ typedef struct {
127149 struct {
128150 char __fp_xmm[512];
129151 } __fp_xmm_state;
152 struct {
153 char __fxsave[416];
154 char __rsvd[48];
155 __greg32_t __xsaveptr;
156 __greg32_t __xsavelen;
157 char __pad[40];
158 } __xsave;
130159 } __fp_reg_set;
131160 int __fp_pad[33]; /* Historic padding */
132161} __fpregset32_t;
lib/libc/include/x86_64-netbsd-none/machine/mcontext.h+31-2
......@@ -1,4 +1,4 @@
1/* $NetBSD: mcontext.h,v 1.24 2024/11/30 01:04:06 christos Exp $ */
1/* $NetBSD: mcontext.h,v 1.24.2.1 2026/07/19 15:57:26 martin Exp $ */
22
33/*-
44 * Copyright (c) 1999 The NetBSD Foundation, Inc.
......@@ -56,7 +56,28 @@ typedef __greg_t __gregset_t[_NGREG];
5656 * which requires 16 byte alignment. However the mcontext version
5757 * is never directly accessed.
5858 */
59typedef char __fpregset_t[512] __aligned(8);
59typedef union {
60 char __fxsave[512] __aligned(8);
61 struct {
62 /*
63 * `The XSAVE feature set does not use bytes 511:416;
64 * bytes 463:416 are reserved.'
65 *
66 * We take a part out of this to form a pointer to an
67 * external XSAVE area. This way, we can replicate the
68 * FXSAVE parts for the benefit of userland programs
69 * that aren't aware of the XSAVE pointer, have used
70 * the extended CPU registers (ymmN/zmmN/&c.), and want
71 * to examine the x87/SSE register state in a signal
72 * handler. The kernel does not use this part.
73 */
74 char __fxsave[416];
75 char __rsvd[48];
76 __greg_t __xsaveptr;
77 __greg_t __xsavelen;
78 char __pad[32];
79 } __xsave;
80} __fpregset_t;
6081
6182typedef struct {
6283 __gregset_t __gregs;
......@@ -75,6 +96,7 @@ typedef struct {
7596#define _UC_MACHINE_SET_PC(uc, pc) _UC_MACHINE_PC(uc) = (pc)
7697
7798#define _UC_TLSBASE _UC_MD_BIT19
99#define _UC_XSAVE _UC_MD_BIT20
78100
79101/*
80102 * mcontext extensions to handle signal delivery.
......@@ -127,6 +149,13 @@ typedef struct {
127149 struct {
128150 char __fp_xmm[512];
129151 } __fp_xmm_state;
152 struct {
153 char __fxsave[416];
154 char __rsvd[48];
155 __greg32_t __xsaveptr;
156 __greg32_t __xsavelen;
157 char __pad[40];
158 } __xsave;
130159 } __fp_reg_set;
131160 int __fp_pad[33]; /* Historic padding */
132161} __fpregset32_t;
lib/std/Build.zig+48-44
......@@ -45,17 +45,6 @@ debug_log_scopes: []const []const u8 = &.{},
4545/// Set to 0 to disable stack collection.
4646debug_stack_frames_count: u8 = 8,
4747
48/// Experimental. Use system Darling installation to run cross compiled macOS build artifacts.
49enable_darling: bool = false,
50/// Use system QEMU installation to run cross compiled foreign architecture build artifacts.
51enable_qemu: bool = false,
52/// Darwin. Use Rosetta to run x86_64 macOS build artifacts on arm64 macOS.
53enable_rosetta: bool = false,
54/// Use system Wasmtime installation to run cross compiled wasm/wasi build artifacts.
55enable_wasmtime: bool = false,
56/// Use system Wine installation to run cross compiled Windows build artifacts.
57enable_wine: bool = false,
58
5948dep_prefix: []const u8 = "",
6049
6150modules: std.array_hash_map.String(*Module),
......@@ -388,11 +377,6 @@ fn createChild(
388377 .default_step = undefined,
389378 .top_level_steps = .{},
390379 .debug_log_scopes = parent.debug_log_scopes,
391 .enable_darling = parent.enable_darling,
392 .enable_qemu = parent.enable_qemu,
393 .enable_rosetta = parent.enable_rosetta,
394 .enable_wasmtime = parent.enable_wasmtime,
395 .enable_wine = parent.enable_wine,
396380 .dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }),
397381 .modules = .empty,
398382 .named_writefiles = .empty,
......@@ -830,7 +814,7 @@ pub fn addTest(b: *Build, options: TestOptions) *Step.Compile {
830814 .kind = if (options.emit_object) .test_obj else .@"test",
831815 .root_module = options.root_module,
832816 .max_rss = options.max_rss,
833 .filters = b.dupeStrings(options.filters),
817 .filters = b.graph.dupeStrings(options.filters),
834818 .test_runner = options.test_runner,
835819 .use_llvm = options.use_llvm,
836820 .use_lld = options.use_lld,
......@@ -1125,7 +1109,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw
11251109 const type_id = comptime typeToEnum(T);
11261110 const enum_options = if (type_id == .@"enum" or type_id == .enum_list) blk: {
11271111 const EnumType = if (type_id == .enum_list) @typeInfo(T).pointer.child else T;
1128 const field_names = comptime std.meta.fieldNames(EnumType);
1112 const field_names = @typeInfo(EnumType).@"enum".field_names;
11291113 var options = std.array_list.Managed([]const u8).initCapacity(b.allocator, field_names.len) catch @panic("OOM");
11301114
11311115 inline for (field_names) |field_name| {
......@@ -1210,13 +1194,16 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw
12101194 return null;
12111195 },
12121196 .scalar => |s| {
1213 if (std.meta.stringToEnum(T, s)) |enum_lit| {
1214 return enum_lit;
1215 } else {
1216 log.err("expected -D{s} to be of type {s}", .{ name, @typeName(T) });
1217 b.markInvalidUserInput();
1218 return null;
1197 if (T == std.lang.Optimize) {
1198 if (std.lang.Optimize.fromString(s)) |tag| {
1199 return tag;
1200 }
1201 } else if (std.meta.stringToEnum(T, s)) |tag| {
1202 return tag;
12191203 }
1204 log.err("expected -D{s} to be of type {q}", .{ name, @typeName(T) });
1205 b.markInvalidUserInput();
1206 return null;
12201207 },
12211208 },
12221209 .string => switch (option_ptr.value) {
......@@ -1262,23 +1249,36 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw
12621249 },
12631250 .scalar => |s| {
12641251 const Child = @typeInfo(T).pointer.child;
1265 const value = std.meta.stringToEnum(Child, s) orelse {
1266 log.err("expected -D{s} to be of type {s}", .{ name, @typeName(Child) });
1267 b.markInvalidUserInput();
1268 return null;
1269 };
1270 return arena.dupe(Child, &[_]Child{value}) catch @panic("OOM");
1252 if (Child == std.lang.Optimize) {
1253 if (std.lang.Optimize.fromString(s)) |tag| {
1254 return arena.dupe(Child, &.{tag}) catch @panic("OOM");
1255 }
1256 } else {
1257 if (std.meta.stringToEnum(Child, s)) |tag| {
1258 return arena.dupe(Child, &.{tag}) catch @panic("OOM");
1259 }
1260 }
1261 log.err("expected -D{s} to be of type {q}", .{ name, @typeName(Child) });
1262 b.markInvalidUserInput();
1263 return null;
12711264 },
12721265 .list => |lst| {
12731266 const Child = @typeInfo(T).pointer.child;
12741267 const new_list = graph.alloc(Child, lst.items.len);
12751268 for (new_list, lst.items) |*new_item, str| {
1276 new_item.* = std.meta.stringToEnum(Child, str) orelse {
1277 log.err("expected -D{s} to be of type {s}", .{ name, @typeName(Child) });
1278 b.markInvalidUserInput();
1279 arena.free(new_list);
1280 return null;
1281 };
1269 if (Child == std.lang.Optimize) {
1270 if (std.lang.Optimize.fromString(str)) |tag| {
1271 new_item.* = tag;
1272 continue;
1273 }
1274 }
1275 if (std.meta.stringToEnum(Child, str)) |tag| {
1276 new_item.* = tag;
1277 continue;
1278 }
1279 log.err("expected -D{s} to be of type {q}", .{ name, @typeName(Child) });
1280 b.markInvalidUserInput();
1281 return null;
12821282 }
12831283 return new_list;
12841284 },
......@@ -1359,14 +1359,14 @@ pub fn standardOptimizeOption(b: *Build, options: StandardOptimizeOptionOptions)
13591359 }
13601360
13611361 return switch (graph.release_mode) {
1362 .off => .Debug,
1362 .off => .debug,
13631363 .any => {
13641364 std.debug.print("the project does not declare a preferred optimization mode. choose: --release=fast, --release=safe, or --release=small\n", .{});
13651365 process.exit(1);
13661366 },
1367 .fast => .ReleaseFast,
1368 .safe => .ReleaseSafe,
1369 .small => .ReleaseSmall,
1367 .fast => .fast,
1368 .safe => .safe,
1369 .small => .small,
13701370 };
13711371}
13721372
......@@ -1420,7 +1420,7 @@ pub fn parseTargetQuery(options: std.Target.Query.ParseOptions) error{ParseFaile
14201420 \\available operating systems:
14211421 \\
14221422 , .{diags.os_name.?});
1423 inline for (comptime std.meta.fieldNames(Target.Os.Tag)) |field_name| {
1423 inline for (@typeInfo(Target.Os.Tag).@"enum".field_names) |field_name| {
14241424 std.debug.print(" {s}\n", .{field_name});
14251425 }
14261426 return error.ParseFailed;
......@@ -2144,7 +2144,7 @@ pub fn dependencyLazy(b: *Build, name: []const u8, args: anytype) error{LazyDepe
21442144 return dependencyResolved(b, name, entry, userInputOptionsFromArgs(b.graph.arena, args));
21452145}
21462146
2147const PackageEntry = struct {
2147pub const PackageEntry = struct {
21482148 hash: []const u8,
21492149 available: bool,
21502150 build_root: []const u8,
......@@ -2152,7 +2152,8 @@ const PackageEntry = struct {
21522152 run_build: ?*const fn (*Build) void,
21532153};
21542154
2155const package_map: std.StaticStringMap(PackageEntry) = blk: {
2155/// Build system implementation detail.
2156pub const package_map: std.StaticStringMap(PackageEntry) = blk: {
21562157 const deps = @import("root").dependencies;
21572158 const decl_names = @typeInfo(deps.packages).@"struct".decl_names;
21582159 var kvs: [decl_names.len]struct { []const u8, PackageEntry } = undefined;
......@@ -2632,7 +2633,10 @@ pub const LazyPath = union(enum) {
26322633
26332634 fn dupeInner(lazy_path: LazyPath, arena: Allocator) LazyPath {
26342635 return switch (lazy_path) {
2635 .src_path => |sp| .{ .src_path = .{ .owner = sp.owner, .sub_path = sp.owner.dupePath(sp.sub_path) } },
2636 .src_path => |sp| .{ .src_path = .{
2637 .owner = sp.owner,
2638 .sub_path = sp.owner.graph.dupePath(sp.sub_path),
2639 } },
26362640 .cwd_relative => |p| .{ .cwd_relative = Graph.dupePathInner(arena, p) },
26372641 .relative => |r| .{ .relative = r },
26382642 .generated => |gen| .{ .generated = .{
lib/std/Build/Configuration.zig+77-334
......@@ -15,6 +15,8 @@ unlazy_deps: []String,
1515system_integrations: []SystemIntegration,
1616available_options: []AvailableOption,
1717search_prefixes: []String,
18/// Index 0 always exists and is the root package.
19packages: []Package,
1820extra: []u32,
1921default_step: Step.Index,
2022generated_files_len: u32,
......@@ -30,6 +32,7 @@ pub const Header = extern struct {
3032 system_integrations_len: u32,
3133 available_options_len: u32,
3234 search_prefixes_len: u32,
35 packages_len: u32,
3336 extra_len: u32,
3437
3538 default_step: Step.Index,
......@@ -58,6 +61,7 @@ pub const Wip = struct {
5861 steps: std.ArrayList(Step) = .empty,
5962 path_deps: std.ArrayList(PathDep) = .empty,
6063 search_prefixes: std.ArrayList(String) = .empty,
64 packages: std.ArrayList(Package) = .empty,
6165 extra: std.ArrayList(u32) = .empty,
6266 next_generated_file_index: u32 = 0,
6367 cache_poison: bool = false,
......@@ -121,7 +125,7 @@ pub const Wip = struct {
121125 }
122126
123127 pub fn hash(_: @This(), adapted_key: []const u8) u64 {
124 assert(std.mem.indexOfScalar(u8, adapted_key, 0) == null);
128 assert(std.mem.findScalar(u8, adapted_key, 0) == null);
125129 return std.hash_map.hashString(adapted_key);
126130 }
127131 };
......@@ -139,6 +143,7 @@ pub const Wip = struct {
139143 wip.steps.deinit(gpa);
140144 wip.path_deps.deinit(gpa);
141145 wip.search_prefixes.deinit(gpa);
146 wip.packages.deinit(gpa);
142147 wip.extra.deinit(gpa);
143148 wip.* = undefined;
144149 }
......@@ -158,6 +163,7 @@ pub const Wip = struct {
158163 .system_integrations_len = @intCast(wip.system_integrations.items.len),
159164 .available_options_len = @intCast(wip.available_options.items.len),
160165 .search_prefixes_len = @intCast(wip.search_prefixes.items.len),
166 .packages_len = @intCast(wip.packages.items.len),
161167 .extra_len = @intCast(wip.extra.items.len),
162168
163169 .default_step = static.default_step,
......@@ -175,6 +181,7 @@ pub const Wip = struct {
175181 @ptrCast(wip.system_integrations.items),
176182 @ptrCast(wip.available_options.items),
177183 @ptrCast(wip.search_prefixes.items),
184 @ptrCast(wip.packages.items),
178185 @ptrCast(wip.extra.items),
179186 };
180187 try w.writeVecAll(&buffers);
......@@ -182,7 +189,7 @@ pub const Wip = struct {
182189
183190 pub fn addString(wip: *Wip, bytes: []const u8) Allocator.Error!String {
184191 const gpa = wip.gpa;
185 assert(std.mem.indexOfScalar(u8, bytes, 0) == null);
192 assert(std.mem.findScalar(u8, bytes, 0) == null);
186193 const gop = try wip.string_table.getOrPutContextAdapted(
187194 gpa,
188195 @as([]const u8, bytes),
......@@ -439,7 +446,7 @@ pub const Wip = struct {
439446 /// Returned slice expires upon next append to the configuration.
440447 pub fn stringSlice(wip: *const Wip, s: String) [:0]const u8 {
441448 const start_slice = wip.string_bytes.items[@backingInt(s)..];
442 return start_slice[0..std.mem.indexOfScalar(u8, start_slice, 0).? :0];
449 return start_slice[0..std.mem.findScalar(u8, start_slice, 0).? :0];
443450 }
444451};
445452
......@@ -569,8 +576,7 @@ pub const Step = extern struct {
569576 flags2: Flags2,
570577 args: Storage.LengthPrefixedList(Arg.Index),
571578 cwd: Storage.FlagOptional(.flags, .cwd, LazyPath.Index),
572 preopen_names: Storage.LengthPrefixedList(String),
573 preopen_paths: Storage.LengthPrefixedList(LazyPath.Index),
579 preopens: Storage.FlagLengthPrefixedList(.flags, .preopens, Preopen),
574580 captured_stdout: Storage.FlagOptional(.flags, .captured_stdout, CapturedStream),
575581 captured_stderr: Storage.FlagOptional(.flags, .captured_stderr, CapturedStream),
576582 file_inputs: Storage.LengthPrefixedList(LazyPath.Index),
......@@ -627,6 +633,13 @@ pub const Step = extern struct {
627633 output_file,
628634 output_directory,
629635 passthru,
636 /// `prefix` contains the enabled string.
637 /// `suffix` contains the disabled string.
638 enable_darling,
639 enable_qemu,
640 enable_rosetta,
641 enable_wasmtime,
642 enable_wine,
630643 };
631644
632645 pub const Index = IndexType(@This());
......@@ -646,6 +659,11 @@ pub const Step = extern struct {
646659 manual,
647660 };
648661
662 pub const Preopen = extern struct {
663 name: String,
664 path: LazyPath.Index,
665 };
666
649667 pub const StdIn = union(@This().Tag) {
650668 none: void,
651669 bytes: Bytes,
......@@ -676,7 +694,8 @@ pub const Step = extern struct {
676694 captured_stdout: bool,
677695 captured_stderr: bool,
678696 environ_map: bool,
679 _: u4 = 0,
697 preopens: bool,
698 _: u3 = 0,
680699 };
681700
682701 pub const Flags2 = packed struct(u32) {
......@@ -979,8 +998,6 @@ pub const Step = extern struct {
979998 };
980999
9811000 pub const Flags3 = packed struct(u32) {
982 is_linking_libc: bool,
983 is_linking_libcpp: bool,
9841001 version: bool,
9851002 initial_memory: bool,
9861003 max_memory: bool,
......@@ -998,6 +1015,7 @@ pub const Step = extern struct {
9981015 entry: Entry,
9991016 lto: Lto,
10001017 subsystem: Subsystem,
1018 _: u2 = 0,
10011019 };
10021020
10031021 pub const Flags4 = packed struct(u32) {
......@@ -1076,6 +1094,7 @@ pub const Step = extern struct {
10761094 autoconf_undef,
10771095 autoconf_at,
10781096 cmake,
1097 meson,
10791098 blank,
10801099 nasm,
10811100
......@@ -1084,6 +1103,7 @@ pub const Step = extern struct {
10841103 .autoconf_undef => .autoconf_undef,
10851104 .autoconf_at => .autoconf_at,
10861105 .cmake => .cmake,
1106 .meson => .meson,
10871107 .blank => .blank,
10881108 .nasm => .nasm,
10891109 };
......@@ -1589,30 +1609,28 @@ pub const OptionalGeneratedFileIndex = enum(u32) {
15891609 }
15901610};
15911611
1592pub const Package = struct {
1612pub const Package = extern struct {
15931613 dep_prefix: String,
15941614 hash: String,
15951615 root_path: String,
1616 deps: Dep.List.Index,
15961617
15971618 pub const Index = enum(u32) {
1598 root = max_u32,
1619 root,
15991620 _,
16001621
1601 /// Returns `null` for root package.
1602 pub fn get(i: @This(), c: *const Configuration) ?Package {
1603 if (i == .root) return null;
1604 return extraData(c, Package, @backingInt(i));
1622 pub fn ptr(i: @This(), c: *const Configuration) *const Package {
1623 return &c.packages[@backingInt(i)];
16051624 }
16061625
16071626 pub fn depPrefixSlice(i: @This(), c: *const Configuration) [:0]const u8 {
1608 const package = get(i, c) orelse return "";
1609 return package.dep_prefix.slice(c);
1627 return ptr(i, c).dep_prefix.slice(c);
16101628 }
16111629 };
16121630
16131631 pub const OptionalIndex = enum(u32) {
1614 none = max_u32 - 1,
1615 root = max_u32,
1632 root,
1633 none = max_u32,
16161634 _,
16171635
16181636 pub fn init(i: Index) OptionalIndex {
......@@ -1629,6 +1647,28 @@ pub const Package = struct {
16291647 };
16301648 }
16311649 };
1650
1651 pub const Dep = extern struct {
1652 name: String,
1653 /// Must not be `.root`.
1654 package: Package.Index,
1655
1656 pub const List = struct {
1657 deps: Storage.LengthPrefixedList(Dep),
1658
1659 pub const Index = enum(u32) {
1660 _,
1661
1662 pub fn get(this: @This(), c: *const Configuration) List {
1663 return extraData(c, List, @backingInt(this));
1664 }
1665
1666 pub fn slice(this: @This(), c: *const Configuration) []const Dep {
1667 return get(this, c).deps.slice;
1668 }
1669 };
1670 };
1671 };
16321672};
16331673
16341674pub const Module = struct {
......@@ -1655,10 +1695,10 @@ pub const Module = struct {
16551695
16561696 pub fn init(o: ?std.builtin.OptimizeMode) Optimize {
16571697 return switch (o orelse return .default) {
1658 .Debug => .debug,
1659 .ReleaseSafe => .safe,
1660 .ReleaseFast => .fast,
1661 .ReleaseSmall => .small,
1698 .debug => .debug,
1699 .safe => .safe,
1700 .fast => .fast,
1701 .small => .small,
16621702 };
16631703 }
16641704 };
......@@ -1946,7 +1986,7 @@ pub const String = enum(u32) {
19461986
19471987 pub fn slice(index: String, c: *const Configuration) [:0]const u8 {
19481988 const start_slice = c.string_bytes[@backingInt(index)..];
1949 return start_slice[0..std.mem.indexOfScalar(u8, start_slice, 0).? :0];
1989 return start_slice[0..std.mem.findScalar(u8, start_slice, 0).? :0];
19501990 }
19511991};
19521992
......@@ -2113,27 +2153,18 @@ pub const OptionalCSourceLanguage = enum(u3) {
21132153 objective_cpp,
21142154 assembly,
21152155 assembly_with_preprocessor,
2156
21162157 default,
21172158
21182159 pub fn init(x: ?std.Build.Module.CSourceLanguage) @This() {
21192160 return switch (x orelse return .default) {
2120 .c => .c,
2121 .cpp => .cpp,
2122 .objective_c => .objective_c,
2123 .objective_cpp => .objective_cpp,
2124 .assembly => .assembly,
2125 .assembly_with_preprocessor => .assembly_with_preprocessor,
2161 inline else => |tag| @field(@This(), @tagName(tag)),
21262162 };
21272163 }
21282164
21292165 pub fn get(this: @This()) ?std.Build.Module.CSourceLanguage {
21302166 return switch (this) {
2131 .c => .c,
2132 .cpp => .cpp,
2133 .objective_c => .objective_c,
2134 .objective_cpp => .objective_cpp,
2135 .assembly => .assembly,
2136 .assembly_with_preprocessor => .assembly_with_preprocessor,
2167 inline else => |tag| @field(std.Build.Module.CSourceLanguage, @tagName(tag)),
21372168 .default => null,
21382169 };
21392170 }
......@@ -2261,10 +2292,7 @@ pub const TargetQuery = struct {
22612292
22622293 pub fn init(x: std.Target.Query.CpuModel) @This() {
22632294 return switch (x) {
2264 .native => .native,
2265 .baseline => .baseline,
2266 .determined_by_arch_os => .determined_by_arch_os,
2267 .explicit => .explicit,
2295 inline else => |_, tag| @field(@This(), @tagName(tag)),
22682296 };
22692297 }
22702298 };
......@@ -2322,71 +2350,13 @@ pub const TargetQuery = struct {
23222350
23232351 pub fn init(x: ?std.Target.Abi) @This() {
23242352 return switch (x orelse return .default) {
2325 .none => .none,
2326 .gnu => .gnu,
2327 .gnuabin32 => .gnuabin32,
2328 .gnuabi64 => .gnuabi64,
2329 .gnueabi => .gnueabi,
2330 .gnueabihf => .gnueabihf,
2331 .gnuf32 => .gnuf32,
2332 .gnusf => .gnusf,
2333 .gnux32 => .gnux32,
2334 .eabi => .eabi,
2335 .eabihf => .eabihf,
2336 .abin32 => .abin32,
2337 .x32 => .x32,
2338 .ilp32 => .ilp32,
2339 .android => .android,
2340 .androideabi => .androideabi,
2341 .musl => .musl,
2342 .muslabin32 => .muslabin32,
2343 .muslabi64 => .muslabi64,
2344 .musleabi => .musleabi,
2345 .musleabihf => .musleabihf,
2346 .muslf32 => .muslf32,
2347 .muslsf => .muslsf,
2348 .muslx32 => .muslx32,
2349 .msvc => .msvc,
2350 .itanium => .itanium,
2351 .simulator => .simulator,
2352 .ohos => .ohos,
2353 .ohoseabi => .ohoseabi,
2354 .call0 => .call0,
2353 inline else => |tag| @field(@This(), @tagName(tag)),
23552354 };
23562355 }
23572356
23582357 pub fn unwrap(this: @This()) ?std.Target.Abi {
23592358 return switch (this) {
2360 .none => .none,
2361 .gnu => .gnu,
2362 .gnuabin32 => .gnuabin32,
2363 .gnuabi64 => .gnuabi64,
2364 .gnueabi => .gnueabi,
2365 .gnueabihf => .gnueabihf,
2366 .gnuf32 => .gnuf32,
2367 .gnusf => .gnusf,
2368 .gnux32 => .gnux32,
2369 .eabi => .eabi,
2370 .eabihf => .eabihf,
2371 .abin32 => .abin32,
2372 .x32 => .x32,
2373 .ilp32 => .ilp32,
2374 .android => .android,
2375 .androideabi => .androideabi,
2376 .musl => .musl,
2377 .muslabin32 => .muslabin32,
2378 .muslabi64 => .muslabi64,
2379 .musleabi => .musleabi,
2380 .musleabihf => .musleabihf,
2381 .muslf32 => .muslf32,
2382 .muslsf => .muslsf,
2383 .muslx32 => .muslx32,
2384 .msvc => .msvc,
2385 .itanium => .itanium,
2386 .simulator => .simulator,
2387 .ohos => .ohos,
2388 .ohoseabi => .ohoseabi,
2389 .call0 => .call0,
2359 inline else => |tag| @field(std.Target.Abi, @tagName(tag)),
23902360 .default => null,
23912361 };
23922362 }
......@@ -2458,132 +2428,13 @@ pub const TargetQuery = struct {
24582428
24592429 pub fn init(x: ?std.Target.Cpu.Arch) @This() {
24602430 return switch (x orelse return .default) {
2461 .aarch64 => .aarch64,
2462 .aarch64_be => .aarch64_be,
2463 .alpha => .alpha,
2464 .amdgcn => .amdgcn,
2465 .arc => .arc,
2466 .arceb => .arceb,
2467 .arm => .arm,
2468 .armeb => .armeb,
2469 .avr => .avr,
2470 .bpfeb => .bpfeb,
2471 .bpfel => .bpfel,
2472 .csky => .csky,
2473 .ez80 => .ez80,
2474 .hexagon => .hexagon,
2475 .hppa => .hppa,
2476 .hppa64 => .hppa64,
2477 .kalimba => .kalimba,
2478 .kvx => .kvx,
2479 .lanai => .lanai,
2480 .loongarch32 => .loongarch32,
2481 .loongarch64 => .loongarch64,
2482 .m68k => .m68k,
2483 .m88k => .m88k,
2484 .microblaze => .microblaze,
2485 .microblazeel => .microblazeel,
2486 .mips => .mips,
2487 .mipsel => .mipsel,
2488 .mips64 => .mips64,
2489 .mips64el => .mips64el,
2490 .msp430 => .msp430,
2491 .nvptx => .nvptx,
2492 .nvptx64 => .nvptx64,
2493 .or1k => .or1k,
2494 .powerpc => .powerpc,
2495 .powerpcle => .powerpcle,
2496 .powerpc64 => .powerpc64,
2497 .powerpc64le => .powerpc64le,
2498 .propeller => .propeller,
2499 .riscv32 => .riscv32,
2500 .riscv32be => .riscv32be,
2501 .riscv64 => .riscv64,
2502 .riscv64be => .riscv64be,
2503 .s390x => .s390x,
2504 .sh => .sh,
2505 .sheb => .sheb,
2506 .sparc => .sparc,
2507 .sparc64 => .sparc64,
2508 .spirv32 => .spirv32,
2509 .spirv64 => .spirv64,
2510 .thumb => .thumb,
2511 .thumbeb => .thumbeb,
2512 .ve => .ve,
2513 .wasm32 => .wasm32,
2514 .wasm64 => .wasm64,
2515 .x86_16 => .x86_16,
2516 .x86 => .x86,
2517 .x86_64 => .x86_64,
2518 .xcore => .xcore,
2519 .xtensa => .xtensa,
2520 .xtensaeb => .xtensaeb,
2431 inline else => |tag| @field(@This(), @tagName(tag)),
25212432 };
25222433 }
25232434
25242435 pub fn unwrap(this: @This()) ?std.Target.Cpu.Arch {
25252436 return switch (this) {
2526 .aarch64 => .aarch64,
2527 .aarch64_be => .aarch64_be,
2528 .alpha => .alpha,
2529 .amdgcn => .amdgcn,
2530 .arc => .arc,
2531 .arceb => .arceb,
2532 .arm => .arm,
2533 .armeb => .armeb,
2534 .avr => .avr,
2535 .bpfeb => .bpfeb,
2536 .bpfel => .bpfel,
2537 .csky => .csky,
2538 .ez80 => .ez80,
2539 .hexagon => .hexagon,
2540 .hppa => .hppa,
2541 .hppa64 => .hppa64,
2542 .kalimba => .kalimba,
2543 .kvx => .kvx,
2544 .lanai => .lanai,
2545 .loongarch32 => .loongarch32,
2546 .loongarch64 => .loongarch64,
2547 .m68k => .m68k,
2548 .m88k => .m88k,
2549 .microblaze => .microblaze,
2550 .microblazeel => .microblazeel,
2551 .mips => .mips,
2552 .mipsel => .mipsel,
2553 .mips64 => .mips64,
2554 .mips64el => .mips64el,
2555 .msp430 => .msp430,
2556 .nvptx => .nvptx,
2557 .nvptx64 => .nvptx64,
2558 .or1k => .or1k,
2559 .powerpc => .powerpc,
2560 .powerpcle => .powerpcle,
2561 .powerpc64 => .powerpc64,
2562 .powerpc64le => .powerpc64le,
2563 .propeller => .propeller,
2564 .riscv32 => .riscv32,
2565 .riscv32be => .riscv32be,
2566 .riscv64 => .riscv64,
2567 .riscv64be => .riscv64be,
2568 .s390x => .s390x,
2569 .sh => .sh,
2570 .sheb => .sheb,
2571 .sparc => .sparc,
2572 .sparc64 => .sparc64,
2573 .spirv32 => .spirv32,
2574 .spirv64 => .spirv64,
2575 .thumb => .thumb,
2576 .thumbeb => .thumbeb,
2577 .ve => .ve,
2578 .wasm32 => .wasm32,
2579 .wasm64 => .wasm64,
2580 .x86_16 => .x86_16,
2581 .x86 => .x86,
2582 .x86_64 => .x86_64,
2583 .xcore => .xcore,
2584 .xtensa => .xtensa,
2585 .xtensaeb => .xtensaeb,
2586
2437 inline else => |tag| @field(std.Target.Cpu.Arch, @tagName(tag)),
25872438 .default => null,
25882439 };
25892440 }
......@@ -2642,106 +2493,13 @@ pub const TargetQuery = struct {
26422493
26432494 pub fn init(x: ?std.Target.Os.Tag) @This() {
26442495 return switch (x orelse return .default) {
2645 .freestanding => .freestanding,
2646 .other => .other,
2647 .contiki => .contiki,
2648 .fuchsia => .fuchsia,
2649 .hermit => .hermit,
2650 .managarm => .managarm,
2651 .haiku => .haiku,
2652 .hurd => .hurd,
2653 .illumos => .illumos,
2654 .linux => .linux,
2655 .plan9 => .plan9,
2656 .rtems => .rtems,
2657 .serenity => .serenity,
2658 .dragonfly => .dragonfly,
2659 .freebsd => .freebsd,
2660 .netbsd => .netbsd,
2661 .openbsd => .openbsd,
2662 .driverkit => .driverkit,
2663 .ios => .ios,
2664 .maccatalyst => .maccatalyst,
2665 .macos => .macos,
2666 .tvos => .tvos,
2667 .visionos => .visionos,
2668 .watchos => .watchos,
2669 .windows => .windows,
2670 .uefi => .uefi,
2671 .@"3ds" => .@"3ds",
2672 .wiiu => .wiiu,
2673 .@"switch" => .@"switch",
2674 .psx => .psx,
2675 .ps3 => .ps3,
2676 .ps4 => .ps4,
2677 .ps5 => .ps5,
2678 .psp => .psp,
2679 .vita => .vita,
2680 .emscripten => .emscripten,
2681 .wasi => .wasi,
2682 .amdhsa => .amdhsa,
2683 .amdpal => .amdpal,
2684 .cuda => .cuda,
2685 .mesa3d => .mesa3d,
2686 .nvcl => .nvcl,
2687 .opencl => .opencl,
2688 .opengl => .opengl,
2689 .vulkan => .vulkan,
2690 .tios => .tios,
2691 .ashetos => .ashetos,
2496 inline else => |tag| @field(@This(), @tagName(tag)),
26922497 };
26932498 }
26942499
26952500 pub fn unwrap(this: @This()) ?std.Target.Os.Tag {
26962501 return switch (this) {
2697 .freestanding => .freestanding,
2698 .other => .other,
2699 .contiki => .contiki,
2700 .fuchsia => .fuchsia,
2701 .hermit => .hermit,
2702 .managarm => .managarm,
2703 .haiku => .haiku,
2704 .hurd => .hurd,
2705 .illumos => .illumos,
2706 .linux => .linux,
2707 .plan9 => .plan9,
2708 .rtems => .rtems,
2709 .serenity => .serenity,
2710 .dragonfly => .dragonfly,
2711 .freebsd => .freebsd,
2712 .netbsd => .netbsd,
2713 .openbsd => .openbsd,
2714 .driverkit => .driverkit,
2715 .ios => .ios,
2716 .maccatalyst => .maccatalyst,
2717 .macos => .macos,
2718 .tvos => .tvos,
2719 .visionos => .visionos,
2720 .watchos => .watchos,
2721 .windows => .windows,
2722 .uefi => .uefi,
2723 .@"3ds" => .@"3ds",
2724 .wiiu => .wiiu,
2725 .@"switch" => .@"switch",
2726 .psx => .psx,
2727 .ps3 => .ps3,
2728 .ps4 => .ps4,
2729 .ps5 => .ps5,
2730 .psp => .psp,
2731 .vita => .vita,
2732 .emscripten => .emscripten,
2733 .wasi => .wasi,
2734 .amdhsa => .amdhsa,
2735 .amdpal => .amdpal,
2736 .cuda => .cuda,
2737 .mesa3d => .mesa3d,
2738 .nvcl => .nvcl,
2739 .opencl => .opencl,
2740 .opengl => .opengl,
2741 .vulkan => .vulkan,
2742 .tios => .tios,
2743 .ashetos => .ashetos,
2744
2502 inline else => |tag| @field(std.Target.Os.Tag, @tagName(tag)),
27452503 .default => null,
27462504 };
27472505 }
......@@ -2762,30 +2520,13 @@ pub const TargetQuery = struct {
27622520
27632521 pub fn init(x: ?std.Target.ObjectFormat) @This() {
27642522 return switch (x orelse return .default) {
2765 .c => .c,
2766 .coff => .coff,
2767 .elf => .elf,
2768 .hex => .hex,
2769 .macho => .macho,
2770 .plan9 => .plan9,
2771 .raw => .raw,
2772 .spirv => .spirv,
2773 .wasm => .wasm,
2523 inline else => |tag| @field(@This(), @tagName(tag)),
27742524 };
27752525 }
27762526
27772527 pub fn unwrap(this: @This()) ?std.Target.ObjectFormat {
27782528 return switch (this) {
2779 .c => .c,
2780 .coff => .coff,
2781 .elf => .elf,
2782 .hex => .hex,
2783 .macho => .macho,
2784 .plan9 => .plan9,
2785 .raw => .raw,
2786 .spirv => .spirv,
2787 .wasm => .wasm,
2788
2529 inline else => |tag| @field(std.Target.ObjectFormat, @tagName(tag)),
27892530 .default => null,
27902531 };
27912532 }
......@@ -3462,6 +3203,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {
34623203 .system_integrations = try arena.alloc(SystemIntegration, header.system_integrations_len),
34633204 .available_options = try arena.alloc(AvailableOption, header.available_options_len),
34643205 .search_prefixes = try arena.alloc(String, header.search_prefixes_len),
3206 .packages = try arena.alloc(Package, header.packages_len),
34653207 .extra = try arena.alloc(u32, header.extra_len),
34663208 .default_step = header.default_step,
34673209 .generated_files_len = header.generated_files_len,
......@@ -3475,6 +3217,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {
34753217 @ptrCast(result.system_integrations),
34763218 @ptrCast(result.available_options),
34773219 @ptrCast(result.search_prefixes),
3220 @ptrCast(result.packages),
34783221 @ptrCast(result.extra),
34793222 };
34803223 try reader.readVecAll(&vecs);
lib/std/Build/Module.zig+2-2
......@@ -402,8 +402,8 @@ pub fn addCSourceFiles(m: *Module, options: AddCSourceFilesOptions) void {
402402 const c_source_files = arena.create(CSourceFiles) catch @panic("OOM");
403403 c_source_files.* = .{
404404 .root = options.root orelse b.path(""),
405 .files = b.dupeStrings(options.files),
406 .flags = b.dupeStrings(options.flags),
405 .files = b.graph.dupeStrings(options.files),
406 .flags = b.graph.dupeStrings(options.flags),
407407 .language = options.language,
408408 };
409409 m.link_objects.append(arena, .{ .c_source_files = c_source_files }) catch @panic("OOM");
lib/std/Build/Serialize.zig+172-22
......@@ -10,7 +10,8 @@ const log = std.log;
1010arena: Allocator,
1111wc: *Configuration.Wip,
1212module_map: std.array_hash_map.Auto(*std.Build.Module, Configuration.Module.Index) = .empty,
13package_map: std.array_hash_map.Auto(*std.Build, Configuration.Package.Index) = .empty,
13/// Keyed by package hash.
14package_map: std.array_hash_map.String(Configuration.Package.Index) = .empty,
1415/// Index corresponds to `Configuration.steps` index.
1516step_map: std.array_hash_map.Auto(*Step, void) = .empty,
1617
......@@ -21,6 +22,10 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
2122
2223 var s: Serialize = .{ .wc = wc, .arena = arena };
2324
25 // Serialize all of the packages first to seed the package_map, which is
26 // later used in calls to packageFromHash.
27 try s.addRootPackage(b);
28
2429 try wc.path_deps.ensureTotalCapacityPrecise(gpa, graph.configure_dependencies.items.len);
2530 for (
2631 graph.configure_dependencies.items,
......@@ -44,10 +49,10 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
4449 .relative => |r| try wc.addString(r.sub_path),
4550 },
4651 .pkg = switch (src.lazy_path) {
47 .src_path => |sp| .init(try s.builderToPackage(sp.owner)),
52 .src_path => |sp| .init(s.packageFromHash(sp.owner.pkg_hash)),
4853 .generated => unreachable,
4954 .cwd_relative, .relative => .none,
50 .dependency => |d| .init(try s.builderToPackage(d.dependency.builder)),
55 .dependency => |d| .init(s.packageFromHash(d.dependency.builder.pkg_hash)),
5156 },
5257 };
5358 }
......@@ -84,7 +89,7 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
8489 try wc.steps.ensureTotalCapacity(gpa, s.step_map.entries.capacity);
8590 wc.steps.appendAssumeCapacity(.{
8691 .name = try wc.addString(step.name),
87 .owner = try s.builderToPackage(step.owner),
92 .owner = s.packageFromHash(step.owner.pkg_hash),
8893 .deps = deps,
8994 .max_rss = .fromBytes(step.max_rss),
9095 .extended = @fromBackingInt(@intCast(switch (step.tag) {
......@@ -168,8 +173,6 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
168173 .linkage = .init(c.linkage),
169174 },
170175 .flags3 = .{
171 .is_linking_libc = c.is_linking_libc,
172 .is_linking_libcpp = c.is_linking_libcpp,
173176 .version = c.version != null,
174177 .compress_debug_sections = c.compress_debug_sections,
175178 .initial_memory = c.initial_memory != null,
......@@ -454,6 +457,13 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
454457 },
455458 else => {},
456459 }
460 const preopens = try arena.alloc(
461 Configuration.Step.Run.Preopen,
462 run.preopens.count(),
463 );
464 for (preopens, run.preopens.keys(), run.preopens.values()) |*dest, name, path| {
465 dest.* = .{ .name = name, .path = try s.addLazyPath(path) };
466 }
457467
458468 break :e try wc.addExtraErased(Configuration.Step.Run, .{
459469 .flags = .{
......@@ -482,6 +492,7 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
482492 .captured_stdout = run.captured_stdout != null,
483493 .captured_stderr = run.captured_stderr != null,
484494 .environ_map = run.environ_map != null,
495 .preopens = run.preopens.count() > 0,
485496 },
486497 .flags2 = .{
487498 .expect_stderr_exact = expect_stderr_exact != null,
......@@ -496,8 +507,7 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
496507 .file_inputs = .{ .slice = try s.initLazyPathList(run.file_inputs.items) },
497508 .args = .{ .slice = try s.initArgsList(run.argv.items) },
498509 .cwd = .{ .value = try s.addOptionalLazyPath(run.cwd) },
499 .preopen_names = .{ .slice = try s.initStringList(run.preopens.keys()) },
500 .preopen_paths = .{ .slice = try s.initLazyPathList(run.preopens.values()) },
510 .preopens = .{ .slice = preopens },
501511 .captured_stdout = .{ .value = if (run.captured_stdout) |cs| .{
502512 .basename = try wc.addString(cs.basename),
503513 .generated_file = cs.generated_file,
......@@ -717,19 +727,64 @@ pub fn packageOptions(b: *std.Build, wc: *Configuration.Wip) Allocator.Error!voi
717727 }
718728}
719729
720fn builderToPackage(s: *Serialize, b: *std.Build) !Configuration.Package.Index {
721 if (b.pkg_hash.len == 0) return .root;
730fn addRootPackage(s: *Serialize, b: *std.Build) Allocator.Error!void {
722731 const arena = s.arena;
723732 const wc = s.wc;
724 const gop = try s.package_map.getOrPut(arena, b);
725 if (!gop.found_existing) {
726 gop.value_ptr.* = try wc.addExtra(Configuration.Package, .{
727 .hash = try wc.addString(b.pkg_hash),
728 .dep_prefix = try wc.addString(b.dep_prefix),
729 .root_path = try wc.addString(try b.root.toString(arena)),
730 });
731 }
732 return gop.value_ptr.*;
733
734 try wc.packages.append(wc.gpa, .{
735 .dep_prefix = .empty,
736 .hash = .empty,
737 .root_path = try wc.addString(try b.root.toString(arena)),
738 .deps = undefined,
739 });
740
741 const deps = try arena.alloc(Configuration.Package.Dep, b.available_deps.len);
742 for (deps, b.available_deps) |*dest, src| dest.* = try s.makePackageDep("", src[0], src[1]);
743
744 wc.packages.items[0].deps = try wc.addExtra(Configuration.Package.Dep.List, .{
745 .deps = .{ .slice = deps },
746 });
747}
748
749fn makePackageDep(s: *Serialize, parent_dep_prefix: []const u8, name: []const u8, hash: []const u8) Allocator.Error!Configuration.Package.Dep {
750 const arena = s.arena;
751 const wc = s.wc;
752
753 if (s.package_map.get(hash)) |index| return .{
754 .name = try wc.addString(name),
755 .package = index,
756 };
757
758 const entry = std.Build.package_map.get(hash) orelse unreachable;
759
760 const dep_prefix = try arena.print("{s}{s}.", .{ parent_dep_prefix, name });
761
762 const index: Configuration.Package.Index = @fromBackingInt(@intCast(wc.packages.items.len));
763 try s.package_map.put(arena, hash, index);
764
765 try wc.packages.append(wc.gpa, .{
766 .dep_prefix = try wc.addString(dep_prefix),
767 .hash = try wc.addString(hash),
768 .root_path = try wc.addString(entry.build_root),
769 .deps = undefined,
770 });
771
772 const deps = try arena.alloc(Configuration.Package.Dep, entry.deps.len);
773 for (deps, entry.deps) |*dest, src| dest.* = try s.makePackageDep(dep_prefix, src[0], src[1]);
774
775 wc.packages.items[@backingInt(index)].deps = try wc.addExtra(Configuration.Package.Dep.List, .{
776 .deps = .{ .slice = deps },
777 });
778
779 return .{
780 .name = try wc.addString(name),
781 .package = index,
782 };
783}
784
785fn packageFromHash(s: *Serialize, pkg_hash: []const u8) Configuration.Package.Index {
786 if (pkg_hash.len == 0) return .root;
787 return s.package_map.get(pkg_hash) orelse std.debug.panic("unrecognized package hash: {q}", .{pkg_hash});
733788}
734789
735790fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuration.LazyPath.OptionalIndex {
......@@ -738,7 +793,7 @@ fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuratio
738793 .src_path => |src_path| i: {
739794 const sub_path = try wc.addString(src_path.sub_path);
740795 break :i try wc.addExtraErased(Configuration.LazyPath.SourcePath, .{
741 .owner = try s.builderToPackage(src_path.owner),
796 .owner = s.packageFromHash(src_path.owner.pkg_hash),
742797 .sub_path = sub_path,
743798 });
744799 },
......@@ -766,7 +821,7 @@ fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuratio
766821 .dependency => |dependency| i: {
767822 const sub_path = try wc.addString(dependency.sub_path);
768823 break :i try wc.addExtraErased(Configuration.LazyPath.SourcePath, .{
769 .owner = try s.builderToPackage(dependency.dependency.builder),
824 .owner = s.packageFromHash(dependency.dependency.builder.pkg_hash),
770825 .sub_path = sub_path,
771826 });
772827 },
......@@ -1012,6 +1067,101 @@ fn initArgsList(s: *Serialize, args: []const Step.Run.Arg) ![]const Configuratio
10121067 .producer = .{ .value = null },
10131068 .generated = .{ .value = null },
10141069 },
1070 .enable_darling => |a| .{
1071 .flags = .{
1072 .tag = .enable_darling,
1073 .prefix = a.enabled != null,
1074 .suffix = a.disabled != null,
1075 .basename = false,
1076 .path = false,
1077 .producer = false,
1078 .generated = false,
1079 .dep_file = false,
1080 .make_absolute = false,
1081 },
1082 .prefix = .{ .value = try s.addOptionalString(a.enabled) },
1083 .suffix = .{ .value = try s.addOptionalString(a.disabled) },
1084 .basename = .{ .value = null },
1085 .path = .{ .value = null },
1086 .producer = .{ .value = null },
1087 .generated = .{ .value = null },
1088 },
1089 .enable_qemu => |a| .{
1090 .flags = .{
1091 .tag = .enable_qemu,
1092 .prefix = a.enabled != null,
1093 .suffix = a.disabled != null,
1094 .basename = false,
1095 .path = false,
1096 .producer = false,
1097 .generated = false,
1098 .dep_file = false,
1099 .make_absolute = false,
1100 },
1101 .prefix = .{ .value = try s.addOptionalString(a.enabled) },
1102 .suffix = .{ .value = try s.addOptionalString(a.disabled) },
1103 .basename = .{ .value = null },
1104 .path = .{ .value = null },
1105 .producer = .{ .value = null },
1106 .generated = .{ .value = null },
1107 },
1108 .enable_rosetta => |a| .{
1109 .flags = .{
1110 .tag = .enable_rosetta,
1111 .prefix = a.enabled != null,
1112 .suffix = a.disabled != null,
1113 .basename = false,
1114 .path = false,
1115 .producer = false,
1116 .generated = false,
1117 .dep_file = false,
1118 .make_absolute = false,
1119 },
1120 .prefix = .{ .value = try s.addOptionalString(a.enabled) },
1121 .suffix = .{ .value = try s.addOptionalString(a.disabled) },
1122 .basename = .{ .value = null },
1123 .path = .{ .value = null },
1124 .producer = .{ .value = null },
1125 .generated = .{ .value = null },
1126 },
1127 .enable_wasmtime => |a| .{
1128 .flags = .{
1129 .tag = .enable_wasmtime,
1130 .prefix = a.enabled != null,
1131 .suffix = a.disabled != null,
1132 .basename = false,
1133 .path = false,
1134 .producer = false,
1135 .generated = false,
1136 .dep_file = false,
1137 .make_absolute = false,
1138 },
1139 .prefix = .{ .value = try s.addOptionalString(a.enabled) },
1140 .suffix = .{ .value = try s.addOptionalString(a.disabled) },
1141 .basename = .{ .value = null },
1142 .path = .{ .value = null },
1143 .producer = .{ .value = null },
1144 .generated = .{ .value = null },
1145 },
1146 .enable_wine => |a| .{
1147 .flags = .{
1148 .tag = .enable_wine,
1149 .prefix = a.enabled != null,
1150 .suffix = a.disabled != null,
1151 .basename = false,
1152 .path = false,
1153 .producer = false,
1154 .generated = false,
1155 .dep_file = false,
1156 .make_absolute = false,
1157 },
1158 .prefix = .{ .value = try s.addOptionalString(a.enabled) },
1159 .suffix = .{ .value = try s.addOptionalString(a.disabled) },
1160 .basename = .{ .value = null },
1161 .path = .{ .value = null },
1162 .producer = .{ .value = null },
1163 .generated = .{ .value = null },
1164 },
10151165 });
10161166 }
10171167 return result;
......@@ -1131,7 +1281,7 @@ fn addModule(s: *Serialize, m: *std.Build.Module) !Configuration.Module.Index {
11311281 .link_libcpp = .init(m.link_libcpp),
11321282 .no_builtin = .init(m.no_builtin),
11331283 },
1134 .owner = try s.builderToPackage(m.owner),
1284 .owner = s.packageFromHash(m.owner.pkg_hash),
11351285 .root_source_file = try s.addOptionalLazyPathEnum(m.root_source_file),
11361286 .import_table = .invalid,
11371287 .resolved_target = try addOptionalResolvedTarget(wc, m.resolved_target),
lib/std/Build/Step/Compile.zig+4-9
......@@ -101,7 +101,7 @@ each_lib_rpath: ?bool = null,
101101/// This option overrides the CLI argument passed to `zig build`.
102102build_id: ?std.zig.BuildId = null,
103103
104/// Create a .eh_frame_hdr section and a PT_GNU_EH_FRAME segment in the ELF
104/// Create a .eh_frame_hdr section and a PT.GNU_EH_FRAME segment in the ELF
105105/// file.
106106link_eh_frame_hdr: bool = false,
107107link_emit_relocs: bool = false,
......@@ -220,11 +220,6 @@ expect_errors: ?ExpectedCompileErrors = null,
220220/// `std.math.maxInt(u16)`. Overrides the argument passed to `zig build`.
221221error_limit: ?u32 = null,
222222
223/// Computed during make().
224is_linking_libc: bool = false,
225/// Computed during make().
226is_linking_libcpp: bool = false,
227
228223/// Enables coverage instrumentation that is only useful if you are using third
229224/// party fuzzers that depend on it. Otherwise, slows down the instrumented
230225/// binary with unnecessary function calls.
......@@ -375,7 +370,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
375370 const graph = owner.graph;
376371 const arena = graph.arena;
377372
378 const name = owner.dupe(options.name);
373 const name = owner.graph.dupeString(options.name);
379374 if (mem.find(u8, name, "/") != null or mem.find(u8, name, "\\") != null) {
380375 panic("invalid name: '{s}'. It looks like a file path, but it is supposed to be the library or application name.", .{name});
381376 }
......@@ -390,7 +385,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
390385 @tagName(options.kind)
391386 else
392387 owner.fmt("{t} {s}", .{ options.kind, name }),
393 @tagName(options.root_module.optimize orelse .Debug),
388 @tagName(options.root_module.optimize orelse .debug),
394389 resolved_target.query.zigTriple(arena) catch @panic("OOM"),
395390 });
396391
......@@ -645,7 +640,7 @@ pub fn producesPdbFile(compile: *Compile) bool {
645640 if (target.ofmt == .c) return false;
646641 if (compile.use_llvm == false) return false;
647642 if (compile.root_module.strip == true or
648 (compile.root_module.strip == null and compile.root_module.optimize == .ReleaseSmall))
643 (compile.root_module.strip == null and compile.root_module.optimize == .small))
649644 {
650645 return false;
651646 }
lib/std/Build/Step/ConfigHeader.zig+4-1
......@@ -27,6 +27,9 @@ pub const Style = union(enum) {
2727 /// The configure format supported by CMake. It uses `@FOO@`, `${}` and
2828 /// `#cmakedefine` for template substitution.
2929 cmake: std.Build.LazyPath,
30 /// The configure format supported by Meson. It uses `@FOO@`, and
31 /// `#mesondefine` for template substitution.
32 meson: std.Build.LazyPath,
3033 /// Instead of starting with an input file, start with nothing.
3134 blank,
3235 /// Start with nothing, like blank, and output a nasm .asm file.
......@@ -34,7 +37,7 @@ pub const Style = union(enum) {
3437
3538 pub fn getPath(style: Style) ?std.Build.LazyPath {
3639 switch (style) {
37 .autoconf_undef, .autoconf_at, .cmake => |s| return s,
40 .autoconf_undef, .autoconf_at, .cmake, .meson => |s| return s,
3841 .blank, .nasm => return null,
3942 }
4043 }
lib/std/Build/Step/Run.zig+58-2
......@@ -28,7 +28,7 @@ environ_map: ?*EnvMap,
2828
2929/// Named files that will be provided to the parent process.
3030/// See `std.process.Preopens`.
31preopens: std.array_hash_map.String(Build.LazyPath),
31preopens: std.array_hash_map.Auto(Configuration.String, Build.LazyPath),
3232
3333/// Controls the `NO_COLOR` and `CLICOLOR_FORCE` environment variables.
3434color: Color = .auto,
......@@ -68,9 +68,11 @@ rename_step_with_output_arg: bool,
6868/// executed binary will not fail the build if the binary cannot be executed
6969/// due to being for a foreign binary to the host system which is running the
7070/// build graph.
71///
7172/// Command-line arguments such as -fqemu and -fwasmtime may affect whether a
7273/// binary is detected as foreign, as well as system configuration such as
7374/// Rosetta (macOS) and binfmt_misc (Linux).
75///
7476/// If this Run step is considered to have side-effects, then this flag does
7577/// nothing.
7678skip_foreign_checks: bool,
......@@ -149,6 +151,19 @@ pub const Arg = union(enum) {
149151 output_directory: *Output,
150152 /// The arguments passed after "--" on the "zig build" CLI.
151153 passthru,
154
155 enable_darling: ToggleFlags,
156 enable_qemu: ToggleFlags,
157 enable_rosetta: ToggleFlags,
158 enable_wasmtime: ToggleFlags,
159 enable_wine: ToggleFlags,
160};
161
162pub const ToggleFlags = struct {
163 /// The string to pass when enabled, or null to omit the arg.
164 enabled: ?[]const u8 = null,
165 /// The string to pass when disabled, or null to omit the arg.
166 disabled: ?[]const u8 = null,
152167};
153168
154169pub const DecoratedArtifact = struct {
......@@ -576,6 +591,46 @@ pub fn addPassthruArgs(run: *Run) void {
576591 run.argv.append(arena, .passthru) catch @panic("OOM");
577592}
578593
594/// Appends a custom string to the command line depending on the `-fdarling`
595/// value passed to `zig build`.
596pub fn addThirdPartyEnabledArgDarling(run: *Run, toggle_flags: ToggleFlags) void {
597 const graph = run.step.owner.graph;
598 const arena = graph.arena;
599 run.argv.append(arena, .{ .enable_darling = toggle_flags }) catch @panic("OOM");
600}
601
602/// Appends a custom string to the command line depending on the `-fqemu`
603/// value passed to `zig build`.
604pub fn addThirdPartyEnabledArgQemu(run: *Run, toggle_flags: ToggleFlags) void {
605 const graph = run.step.owner.graph;
606 const arena = graph.arena;
607 run.argv.append(arena, .{ .enable_qemu = toggle_flags }) catch @panic("OOM");
608}
609
610/// Appends a custom string to the command line depending on the `-frosetta`
611/// value passed to `zig build`.
612pub fn addThirdPartyEnabledArgRosetta(run: *Run, toggle_flags: ToggleFlags) void {
613 const graph = run.step.owner.graph;
614 const arena = graph.arena;
615 run.argv.append(arena, .{ .enable_rosetta = toggle_flags }) catch @panic("OOM");
616}
617
618/// Appends a custom string to the command line depending on the `-fwasmtime`
619/// value passed to `zig build`.
620pub fn addThirdPartyEnabledArgWasmtime(run: *Run, toggle_flags: ToggleFlags) void {
621 const graph = run.step.owner.graph;
622 const arena = graph.arena;
623 run.argv.append(arena, .{ .enable_wasmtime = toggle_flags }) catch @panic("OOM");
624}
625
626/// Appends a custom string to the command line depending on the `-fwine`
627/// value passed to `zig build`.
628pub fn addThirdPartyEnabledArgWine(run: *Run, toggle_flags: ToggleFlags) void {
629 const graph = run.step.owner.graph;
630 const arena = graph.arena;
631 run.argv.append(arena, .{ .enable_wine = toggle_flags }) catch @panic("OOM");
632}
633
579634pub fn setStdIn(run: *Run, stdin: StdIn) void {
580635 switch (stdin) {
581636 .lazy_path => |lazy_path| lazy_path.addStepDependencies(&run.step),
......@@ -624,11 +679,12 @@ pub fn removeEnvironmentVariable(run: *Run, key: []const u8) void {
624679
625680pub fn setPreopen(run: *Run, name: []const u8, resource: Build.LazyPath) void {
626681 const graph = run.step.owner.graph;
682 const wc = &graph.wip_configuration;
627683 const arena = graph.arena;
628684 resource.addStepDependencies(&run.step);
629685 run.preopens.put(
630686 arena,
631 graph.dupeString(name),
687 wc.addString(name) catch @panic("OOM"),
632688 resource.dupe(graph),
633689 ) catch @panic("OOM");
634690}
lib/std/Io.zig+12-6
......@@ -238,7 +238,7 @@ pub const VTable = struct {
238238 netSend: *const fn (?*anyopaque, net.Socket.Handle, []net.OutgoingMessage, net.SendFlags) struct { ?net.Socket.SendError, usize },
239239 netWrite: *const fn (?*anyopaque, dest: net.Socket.Handle, header: []const u8, data: []const []const u8, splat: usize) net.Stream.Writer.Error!usize,
240240 netWriteFile: *const fn (?*anyopaque, net.Socket.Handle, header: []const u8, *Io.File.Reader, Io.Limit) net.Stream.Writer.WriteFileError!usize,
241 netClose: *const fn (?*anyopaque, handle: []const net.Socket.Handle) void,
241 netClose: *const fn (?*anyopaque, sockets: []const net.Socket) void,
242242 netShutdown: *const fn (?*anyopaque, handle: net.Socket.Handle, how: net.ShutdownHow) net.ShutdownError!void,
243243 netInterfaceNameResolve: *const fn (?*anyopaque, *const net.Interface.Name) net.Interface.Name.ResolveError!net.Interface,
244244 netInterfaceName: *const fn (?*anyopaque, net.Interface) net.Interface.NameError!net.Interface.Name,
......@@ -467,6 +467,7 @@ pub const OperateTimeoutError = Cancelable || Timeout.Error || ConcurrentError;
467467
468468/// Performs one `Operation` with provided `timeout`.
469469pub fn operateTimeout(io: Io, operation: Operation, timeout: Timeout) OperateTimeoutError!Operation.Result {
470 if (timeout == .none) return io.vtable.operate(io.userdata, operation);
470471 var storage: [1]Operation.Storage = undefined;
471472 var batch: Batch = .init(&storage);
472473 batch.addAt(0, operation);
......@@ -778,10 +779,10 @@ pub const Clock = enum {
778779 /// * On Linux, corresponds `CLOCK_BOOTTIME`.
779780 /// * On macOS, corresponds to `CLOCK_MONOTONIC_RAW`.
780781 boot,
781 /// Tracks the amount of CPU in user or kernel mode used by the calling
782 /// Tracks the amount of CPU time in user or kernel mode used by the calling
782783 /// process.
783784 cpu_process,
784 /// Tracks the amount of CPU in user or kernel mode used by the calling
785 /// Tracks the amount of CPU time in user or kernel mode used by the calling
785786 /// thread.
786787 cpu_thread,
787788
......@@ -980,6 +981,10 @@ pub const Timestamp = struct {
980981 const now_ts = clock.now(io);
981982 return t.durationTo(now_ts);
982983 }
984
985 pub fn compare(lhs: Timestamp, op: math.CompareOperator, rhs: Timestamp) bool {
986 return math.compare(lhs.nanoseconds, op, rhs.nanoseconds);
987 }
983988};
984989
985990pub const Duration = struct {
......@@ -1147,6 +1152,7 @@ pub const Duration = struct {
11471152
11481153/// Declares under what conditions an operation should return `error.Timeout`.
11491154pub const Timeout = union(enum) {
1155 /// `.none` will wait forever
11501156 none,
11511157 duration: Clock.Duration,
11521158 deadline: Clock.Timestamp,
......@@ -2525,7 +2531,7 @@ pub fn lockStderr(io: Io, buffer: []u8, terminal_mode: ?Terminal.Mode) Cancelabl
25252531
25262532/// Same as `lockStderr` but non-blocking.
25272533pub fn tryLockStderr(io: Io, buffer: []u8, terminal_mode: ?Terminal.Mode) Cancelable!?LockedStderr {
2528 const ls = (try io.vtable.tryLockStderr(io.userdata, buffer, terminal_mode)) orelse return null;
2534 const ls = (try io.vtable.tryLockStderr(io.userdata, terminal_mode)) orelse return null;
25292535 try ls.clear(buffer);
25302536 return ls;
25312537}
......@@ -3476,9 +3482,9 @@ pub fn failingNetWriteFile(userdata: ?*anyopaque, handle: net.Socket.Handle, hea
34763482 return error.NetworkDown;
34773483}
34783484
3479pub fn unreachableNetClose(userdata: ?*anyopaque, handle: []const net.Socket.Handle) void {
3485pub fn unreachableNetClose(userdata: ?*anyopaque, sockets: []const net.Socket) void {
34803486 _ = userdata;
3481 _ = handle;
3487 _ = sockets;
34823488 unreachable;
34833489}
34843490
lib/std/Io/Dispatch.zig+9-8
......@@ -580,6 +580,7 @@ pub fn deinit(ev: *Evented) void {
580580 ev.stderr_mutex.deinit();
581581 for (&ev.futexes) |*futex| futex.deinit();
582582 ev.exit_semaphore.as_object().release();
583 ev.backing_allocator_mutex.deinit();
583584 ev.backing_allocator.free(ev.main_loop_stack[0..main_loop_stack_size]);
584585 ev.queue.as_object().release();
585586}
......@@ -825,7 +826,7 @@ const Mutex = struct {
825826 sleeper: Sleeper = undefined,
826827 cancelable: Cancelable,
827828 mutex: *Mutex,
828 node: std.DoublyLinkedList.Node = undefined,
829 node: std.DoublyLinkedList.Node = .{},
829830
830831 fn add(context: ?*anyopaque) callconv(.c) void {
831832 const waiter: *Waiter = @ptrCast(@alignCast(context));
......@@ -2781,7 +2782,7 @@ fn realPath(ev: *Evented, fd: c.fd_t, out_buffer: []u8) File.RealPathError!usize
27812782 else => |err| return unexpectedErrno(err),
27822783 }
27832784 }
2784 const n = std.mem.indexOfScalar(u8, &buffer, 0) orelse buffer.len;
2785 const n = std.mem.findScalar(u8, &buffer, 0) orelse buffer.len;
27852786 if (n > out_buffer.len) return error.NameTooLong;
27862787 @memcpy(out_buffer[0..n], buffer[0..n]);
27872788 return n;
......@@ -2803,7 +2804,7 @@ fn dirRealPathFile(
28032804 while (true) {
28042805 if (c.realpath(sub_path_posix, out_buffer.ptr)) |redundant_pointer| {
28052806 assert(redundant_pointer == out_buffer.ptr);
2806 return std.mem.indexOfScalar(u8, out_buffer, 0) orelse out_buffer.len;
2807 return std.mem.findScalar(u8, out_buffer, 0) orelse out_buffer.len;
28072808 }
28082809 const err: c.E = @fromBackingInt(@intCast(c._errno().*));
28092810 switch (err) {
......@@ -3791,7 +3792,7 @@ fn fileRealPath(userdata: ?*anyopaque, file: File, out_buffer: []u8) File.RealPa
37913792 else => |err| return unexpectedErrno(err),
37923793 }
37933794 }
3794 const n = std.mem.indexOfScalar(u8, &buffer, 0) orelse buffer.len;
3795 const n = std.mem.findScalar(u8, &buffer, 0) orelse buffer.len;
37953796 if (n > out_buffer.len) return error.NameTooLong;
37963797 @memcpy(out_buffer[0..n], buffer[0..n]);
37973798 return n;
......@@ -3897,7 +3898,7 @@ fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void {
38973898 if (memory.len == 0) return;
38983899 switch (c.errno(c.munmap(memory.ptr, memory.len))) {
38993900 .SUCCESS => {},
3900 else => |err| if (builtin.mode == .Debug)
3901 else => |err| if (builtin.mode == .debug)
39013902 std.log.err("failed to unmap {d} bytes at {*}: {t}", .{ memory.len, memory.ptr, err }),
39023903 }
39033904 mm.* = undefined;
......@@ -4714,7 +4715,7 @@ fn sleep(userdata: ?*anyopaque, timeout: Io.Timeout) Io.Cancelable!void {
47144715 return ev.yield(.{ .after = ev.timeFromTimeout(timeout) });
47154716 };
47164717 var waiter: SleepWaiter = .{
4717 .cancelable = .{ .queue = queue, .cancel = &Futex.Waiter.canceled },
4718 .cancelable = .{ .queue = queue, .cancel = &SleepWaiter.canceled },
47184719 .timer = timer,
47194720 };
47204721 timer.as_object().set_context(&waiter);
......@@ -4911,10 +4912,10 @@ fn netWriteFileUnavailable(
49114912 return error.Unimplemented;
49124913}
49134914
4914fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void {
4915fn netClose(userdata: ?*anyopaque, sockets: []const net.Socket) void {
49154916 const ev: *Evented = @ptrCast(@alignCast(userdata));
49164917 _ = ev;
4917 for (handles) |handle| closeFd(handle);
4918 for (sockets) |socket| closeFd(socket.handle);
49184919}
49194920
49204921fn netShutdownUnavailable(
lib/std/Io/Kqueue.zig+3-2
......@@ -1280,10 +1280,10 @@ fn netWrite(userdata: ?*anyopaque, dest: net.Socket.Handle, header: []const u8,
12801280 @panic("TODO");
12811281}
12821282
1283fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void {
1283fn netClose(userdata: ?*anyopaque, sockets: []const net.Socket) void {
12841284 const k: *Kqueue = @ptrCast(@alignCast(userdata));
12851285 _ = k;
1286 _ = handles;
1286 _ = sockets;
12871287 @panic("TODO");
12881288}
12891289
......@@ -1422,6 +1422,7 @@ fn posixBind(
14221422 .INTR => continue,
14231423 .CANCELED => return error.Canceled,
14241424
1425 .ACCES => return error.AccessDenied,
14251426 .ADDRINUSE => return error.AddressInUse,
14261427 .BADF => |err| return errnoBug(err), // File descriptor used after closed.
14271428 .INVAL => |err| return errnoBug(err), // invalid parameters
lib/std/Io/Reader.zig+3-5
......@@ -718,7 +718,7 @@ pub inline fn readSliceEndian(
718718 endian: std.builtin.Endian,
719719) Error!void {
720720 try readSliceAll(r, @ptrCast(buffer));
721 if (native_endian != endian) for (buffer) |*elem| std.mem.byteSwapAllFields(Elem, elem);
721 if (native_endian != endian) std.mem.byteSwapAllElements(Elem, buffer);
722722}
723723
724724pub const ReadAllocError = Error || Allocator.Error;
......@@ -734,8 +734,7 @@ pub inline fn readSliceEndianAlloc(
734734) ReadAllocError![]Elem {
735735 const dest = try allocator.alloc(Elem, len);
736736 errdefer allocator.free(dest);
737 try readSliceAll(r, @ptrCast(dest));
738 if (native_endian != endian) for (dest) |*elem| std.mem.byteSwapAllFields(Elem, elem);
737 try r.readSliceEndian(Elem, dest, endian);
739738 return dest;
740739}
741740
......@@ -1227,8 +1226,7 @@ pub inline fn takeStruct(r: *Reader, comptime T: type, endian: std.builtin.Endia
12271226 .auto => @compileError("ill-defined memory layout"),
12281227 .@"extern" => {
12291228 var res: T = undefined;
1230 try r.readSliceAll(std.mem.asBytes(&res));
1231 if (native_endian != endian) std.mem.byteSwapAllFields(T, &res);
1229 try r.readSliceEndian(T, (&res)[0..1], endian);
12321230 return res;
12331231 },
12341232 .@"packed" => {
lib/std/Io/RwLock.zig-2
......@@ -284,8 +284,6 @@ test "concurrent access" {
284284}
285285
286286test "lock canceling" {
287 if (builtin.cpu.arch.isSPARC() and builtin.os.tag == .linux) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35347
288
289287 const io = testing.io;
290288
291289 var rl: Io.RwLock = .init;
lib/std/Io/Semaphore.zig-2
......@@ -4,8 +4,6 @@
44//! This API supports static initialization and does not require deinitialization.
55const Semaphore = @This();
66
7const builtin = @import("builtin");
8
97const std = @import("../std.zig");
108const Io = std.Io;
119const testing = std.testing;
lib/std/Io/Threaded.zig+156-38
......@@ -4,7 +4,7 @@ const builtin = @import("builtin");
44const native_os = builtin.os.tag;
55const is_windows = native_os == .windows;
66const is_darwin = native_os.isDarwin();
7const is_debug = builtin.mode == .Debug;
7const is_debug = builtin.mode == .debug;
88
99const std = @import("../std.zig");
1010const Io = std.Io;
......@@ -440,12 +440,12 @@ pub const UseFchmodat2 = if (have_fchmodat2 and !have_fchmodat_flags) enum {
440440pub const apc_align = @max(default_fn_align, 2);
441441
442442const default_fn_align = switch (builtin.mode) {
443 .Debug, .ReleaseSafe, .ReleaseFast => switch (builtin.cpu.arch) {
443 .debug, .safe, .fast => switch (builtin.cpu.arch) {
444444 else => |arch| @compileError("Unsupported architecture: " ++ @tagName(arch)),
445445 .arm, .thumb => 4,
446446 .aarch64, .x86, .x86_64 => 16,
447447 },
448 .ReleaseSmall => 1,
448 .small => 1,
449449};
450450
451451const Runnable = struct {
......@@ -829,6 +829,7 @@ const Thread = struct {
829829 /// Always released when `Status.cancelation` is set to `.parked`.
830830 futex_waiter: if (use_parking_futex) ?*parking_futex.Waiter else ?noreturn,
831831 unpark_flag: UnparkFlag,
832 park_tid: if (ParkTid == std.Thread.Id) void else ParkTid,
832833
833834 csprng: Csprng,
834835
......@@ -1220,7 +1221,7 @@ const Thread = struct {
12201221 parking_futex.removeCanceledWaiter(futex_waiter);
12211222 }
12221223 if (need_unpark_flag) setUnparkFlag(&thread.unpark_flag);
1223 unpark(&.{thread.id}, null);
1224 unpark(&.{if (ParkTid == std.Thread.Id) thread.id else thread.park_tid}, null);
12241225 return false;
12251226 },
12261227
......@@ -1749,6 +1750,7 @@ fn worker(t: *Threaded) void {
17491750 .cancel_protection = .unblocked,
17501751 .futex_waiter = undefined,
17511752 .unpark_flag = unpark_flag_init,
1753 .park_tid = if (ParkTid == std.Thread.Id) {} else getParkTid(),
17521754 .csprng = .uninitialized,
17531755 };
17541756 Thread.current = &thread;
......@@ -3858,7 +3860,26 @@ fn fileLength(userdata: ?*anyopaque, file: File) File.LengthError!u64 {
38583860 }
38593861 }
38603862 } else if (is_windows) {
3861 // TODO call NtQueryInformationFile and ask for only the size instead of "all"
3863 var io_status_block: windows.IO_STATUS_BLOCK = undefined;
3864 var info: windows.FILE.STANDARD_INFORMATION = undefined;
3865 const syscall: Syscall = try .start();
3866 while (true) switch (windows.ntdll.NtQueryInformationFile(
3867 file.handle,
3868 &io_status_block,
3869 &info,
3870 @sizeOf(windows.FILE.STANDARD_INFORMATION),
3871 .Standard,
3872 )) {
3873 .SUCCESS => break syscall.finish(),
3874 .INVALID_PARAMETER => |err| return syscall.ntstatusBug(err),
3875 .ACCESS_DENIED => return syscall.fail(error.AccessDenied),
3876 .CANCELLED => {
3877 try syscall.checkCancel();
3878 continue;
3879 },
3880 else => |s| return syscall.unexpectedNtstatus(s),
3881 };
3882 return @as(u64, @bitCast(info.EndOfFile));
38623883 }
38633884
38643885 const stat = try fileStat(t, file);
......@@ -4382,7 +4403,7 @@ fn dirCreateFilePosix(
43824403 }
43834404 };
43844405
4385 fl_flags |= @as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK"));
4406 fl_flags &= ~@as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK"));
43864407
43874408 const syscall: Syscall = try .start();
43884409 while (true) {
......@@ -4978,7 +4999,7 @@ fn dirOpenFilePosix(
49784999 }
49795000 };
49805001
4981 fl_flags |= @as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK"));
5002 fl_flags &= ~@as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK"));
49825003
49835004 const syscall: Syscall = try .start();
49845005 while (true) {
......@@ -5053,7 +5074,7 @@ pub fn dirOpenFileWtf16(
50535074 .VALID_FLAGS,
50545075 .OPEN,
50555076 .{
5056 .IO = if (flags.follow_symlinks) .SYNCHRONOUS_NONALERT else .ASYNCHRONOUS,
5077 .IO = .SYNCHRONOUS_NONALERT,
50575078 .NON_DIRECTORY_FILE = !allow_directory,
50585079 .OPEN_REPARSE_POINT = !flags.follow_symlinks,
50595080 },
......@@ -6817,7 +6838,7 @@ fn dirRealPathFilePosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, o
68176838 if (std.c.realpath(sub_path_posix, out_buffer.ptr)) |redundant_pointer| {
68186839 syscall.finish();
68196840 assert(redundant_pointer == out_buffer.ptr);
6820 return std.mem.indexOfScalar(u8, out_buffer, 0) orelse out_buffer.len;
6841 return std.mem.findScalar(u8, out_buffer, 0) orelse out_buffer.len;
68216842 }
68226843 const err: posix.E = @fromBackingInt(@intCast(std.c._errno().*));
68236844 if (err == .INTR) {
......@@ -6961,7 +6982,7 @@ fn realPathPosix(fd: posix.fd_t, out_buffer: []u8) File.RealPathError!usize {
69616982 },
69626983 }
69636984 }
6964 const n = std.mem.indexOfScalar(u8, &sufficient_buffer, 0) orelse sufficient_buffer.len;
6985 const n = std.mem.findScalar(u8, &sufficient_buffer, 0) orelse sufficient_buffer.len;
69656986 if (n > out_buffer.len) return error.NameTooLong;
69666987 @memcpy(out_buffer[0..n], sufficient_buffer[0..n]);
69676988 return n;
......@@ -7119,9 +7140,10 @@ fn dirDeleteFileWasi(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8) Dir.
71197140 if (builtin.link_libc) return dirDeleteFilePosix(userdata, dir, sub_path);
71207141 const t: *Threaded = @ptrCast(@alignCast(userdata));
71217142 _ = t;
7143 const wasi = std.os.wasi;
71227144 const syscall: Syscall = try .start();
71237145 while (true) {
7124 const res = std.os.wasi.path_unlink_file(dir.handle, sub_path.ptr, sub_path.len);
7146 const res = wasi.path_unlink_file(dir.handle, sub_path.ptr, sub_path.len);
71257147 switch (res) {
71267148 .SUCCESS => {
71277149 syscall.finish();
......@@ -7131,11 +7153,35 @@ fn dirDeleteFileWasi(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8) Dir.
71317153 try syscall.checkCancel();
71327154 continue;
71337155 },
7156 .ACCES, .PERM => |e| {
7157 const original_error: Dir.DeleteFileError = switch (e) {
7158 .ACCES => error.AccessDenied,
7159 .PERM => error.PermissionDenied,
7160 else => unreachable,
7161 };
7162 var stat: wasi.filestat_t = undefined;
7163 while (true) {
7164 try syscall.checkCancel();
7165 switch (wasi.path_filestat_get(dir.handle, .{}, sub_path.ptr, sub_path.len, &stat)) {
7166 .SUCCESS => {
7167 syscall.finish();
7168 break;
7169 },
7170 .INTR => continue,
7171 else => {
7172 syscall.finish();
7173 return original_error;
7174 },
7175 }
7176 }
7177 if (stat.filetype == .DIRECTORY)
7178 return error.IsDir
7179 else
7180 return original_error;
7181 },
71347182 else => |e| {
71357183 syscall.finish();
71367184 switch (e) {
7137 .ACCES => return error.AccessDenied,
7138 .PERM => return error.PermissionDenied,
71397185 .BUSY => return error.FileBusy,
71407186 .FAULT => |err| return errnoBug(err),
71417187 .IO => return error.FileSystem,
......@@ -8111,7 +8157,7 @@ fn dirReadLinkWindows(dir: Dir, sub_path: []const u8, buffer: []u8) Dir.ReadLink
81118157 .{
81128158 .DIRECTORY_FILE = false,
81138159 .NON_DIRECTORY_FILE = false,
8114 .IO = .ASYNCHRONOUS,
8160 .IO = .SYNCHRONOUS_NONALERT,
81158161 .OPEN_REPARSE_POINT = true,
81168162 },
81178163 null,
......@@ -8177,7 +8223,7 @@ fn dirReadLinkWindows(dir: Dir, sub_path: []const u8, buffer: []u8) Dir.ReadLink
81778223
81788224 var reparse_buf: [windows.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 align(@alignOf(windows.REPARSE_DATA_BUFFER)) = undefined;
81798225 switch ((try deviceIoControl(&.{
8180 .file = .{ .handle = result_handle, .flags = .{ .nonblocking = true } },
8226 .file = .{ .handle = result_handle, .flags = .{ .nonblocking = false } },
81818227 .code = .GET_REPARSE_POINT,
81828228 .out = &reparse_buf,
81838229 })).u.Status) {
......@@ -8955,7 +9001,7 @@ fn isCygwinPty(file: File) Io.Cancelable!bool {
89559001 // The name we get from NtQueryInformationFile will be prefixed with a '\', e.g. \msys-1888ae32e00d56aa-pty0-to-master
89569002 return (std.mem.startsWith(u16, name_wide, &[_]u16{ '\\', 'm', 's', 'y', 's', '-' }) or
89579003 std.mem.startsWith(u16, name_wide, &[_]u16{ '\\', 'c', 'y', 'g', 'w', 'i', 'n', '-' })) and
8958 std.mem.indexOf(u16, name_wide, &[_]u16{ '-', 'p', 't', 'y' }) != null;
9004 std.mem.find(u16, name_wide, &[_]u16{ '-', 'p', 't', 'y' }) != null;
89599005}
89609006
89619007fn fileSetLength(userdata: ?*anyopaque, file: File, length: u64) File.SetLengthError!void {
......@@ -11184,7 +11230,10 @@ fn fileWriteFileStreaming(
1118411230 var off: std.os.linux.off_t = undefined;
1118511231 const off_ptr: ?*std.os.linux.off_t, const count: usize = switch (file_reader.mode) {
1118611232 .positional => o: {
11187 const size = file_reader.getSize() catch return 0;
11233 const size = file_reader.getSize() catch |err| switch (err) {
11234 error.Canceled => |e| return e,
11235 else => break :sf,
11236 };
1118811237 off = std.math.cast(std.os.linux.off_t, file_reader.pos) orelse return error.ReadFailed;
1118911238 break :o .{ &off, @min(@backingInt(limit), size - file_reader.pos, max_count) };
1119011239 },
......@@ -11533,7 +11582,10 @@ fn fileWriteFilePositional(
1153311582 if (file_reader.pos != 0) break :fcf;
1153411583 if (offset != 0) break :fcf;
1153511584 if (limit != .unlimited) break :fcf;
11536 const size = file_reader.getSize() catch break :fcf;
11585 const size = file_reader.getSize() catch |err| switch (err) {
11586 error.Canceled => |e| return e,
11587 else => break :fcf,
11588 };
1153711589 if (header.len != 0 or reader_buffered.len != 0) {
1153811590 const n = try fileWritePositional(t, file, header, &.{limit.slice(reader_buffered)}, 1, offset);
1153911591 file_reader.interface.toss(n -| header.len);
......@@ -11725,7 +11777,6 @@ fn nowWasi(clock: Io.Clock) Io.Timestamp {
1172511777
1172611778fn sleep(userdata: ?*anyopaque, timeout: Io.Timeout) Io.Cancelable!void {
1172711779 const t: *Threaded = @ptrCast(@alignCast(userdata));
11728 if (timeout == .none) return;
1172911780 if (use_parking_sleep) return parking_sleep.sleep(timeout);
1173011781 if (native_os == .wasi) return sleepWasi(t, timeout);
1173111782 if (@TypeOf(posix.system.clock_nanosleep) != void) return sleepPosix(timeout);
......@@ -12042,6 +12093,7 @@ fn posixBind(
1204212093 else => |e| {
1204312094 syscall.finish();
1204412095 switch (e) {
12096 .ACCES => return error.AccessDenied,
1204512097 .ADDRINUSE => return error.AddressInUse,
1204612098 .BADF => |err| return errnoBug(err), // File descriptor used after closed.
1204712099 .INVAL => |err| return errnoBug(err), // invalid parameters
......@@ -12124,6 +12176,7 @@ fn posixConnectUnix(
1212412176 .NOTDIR => return error.NotDir,
1212512177 .ROFS => return error.ReadOnlyFileSystem,
1212612178 .PERM => return error.PermissionDenied,
12179 .CONNREFUSED => return error.ConnectionRefused,
1212712180
1212812181 .BADF => |err| return errnoBug(err), // File descriptor used after closed.
1212912182 .CONNABORTED => |err| return errnoBug(err),
......@@ -13362,13 +13415,13 @@ fn addBuf(v: []posix.iovec_const, i: *iovlen_t, bytes: []const u8) void {
1336213415 i.* += 1;
1336313416}
1336413417
13365fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void {
13418fn netClose(userdata: ?*anyopaque, sockets: []const net.Socket) void {
1336613419 if (!have_networking) unreachable;
1336713420 const t: *Threaded = @ptrCast(@alignCast(userdata));
1336813421 _ = t;
13369 for (handles) |handle| switch (native_os) {
13370 .windows => windows.CloseHandle(handle),
13371 else => closeFd(handle),
13422 for (sockets) |socket| switch (native_os) {
13423 .windows => windows.CloseHandle(socket.handle),
13424 else => closeFd(socket.handle),
1337213425 };
1337313426}
1337413427
......@@ -13870,9 +13923,14 @@ fn netLookupFallible(
1387013923 var port_buffer: [8]u8 = undefined;
1387113924 const port_c = std.fmt.bufPrintSentinel(&port_buffer, "{d}", .{options.port}, 0) catch unreachable;
1387213925
13926 const family: i32 = if (options.family) |f| switch (f) {
13927 .ip4 => posix.AF.INET,
13928 .ip6 => posix.AF.INET6,
13929 } else posix.AF.UNSPEC;
13930
1387313931 const hints: posix.addrinfo = .{
1387413932 .flags = .{ .CANONNAME = options.canonical_name_buffer != null, .NUMERICSERV = true },
13875 .family = posix.AF.UNSPEC,
13933 .family = family,
1387613934 .socktype = posix.SOCK.STREAM,
1387713935 .protocol = posix.IPPROTO.TCP,
1387813936 .canonname = null,
......@@ -15302,8 +15360,7 @@ fn childKillWindows(t: *Threaded, child: *process.Child, exit_code: windows.UINT
1530215360 _ = windows.ntdll.RtlReportSilentProcessExit(handle, @fromBackingInt(@intCast(exit_code)));
1530315361 switch (windows.ntdll.NtTerminateProcess(handle, @fromBackingInt(@intCast(exit_code)))) {
1530415362 .SUCCESS, .PROCESS_IS_TERMINATING => {
15305 const infinite_timeout: windows.LARGE_INTEGER = std.math.minInt(windows.LARGE_INTEGER);
15306 _ = windows.ntdll.NtWaitForSingleObject(handle, .FALSE, &infinite_timeout);
15363 _ = windows.ntdll.NtWaitForSingleObject(handle, .FALSE, null);
1530715364 childCleanupWindows(child);
1530815365 },
1530915366 .ACCESS_DENIED => {
......@@ -15326,8 +15383,7 @@ fn childWaitWindows(child: *process.Child) process.Child.WaitError!process.Child
1532615383 const handle = child.id.?;
1532715384
1532815385 const alertable_syscall: AlertableSyscall = try .start();
15329 const infinite_timeout: windows.LARGE_INTEGER = std.math.minInt(windows.LARGE_INTEGER);
15330 while (true) switch (windows.ntdll.NtWaitForSingleObject(handle, .TRUE, &infinite_timeout)) {
15386 while (true) switch (windows.ntdll.NtWaitForSingleObject(handle, .TRUE, null)) {
1533115387 windows.NTSTATUS.WAIT_0 => break alertable_syscall.finish(),
1533215388 .USER_APC, .ALERTED, .TIMEOUT => {
1533315389 try alertable_syscall.checkCancel();
......@@ -16272,7 +16328,7 @@ fn windowsCreateProcessPathExt(
1627216328
1627316329 const is_bat_or_cmd = bat_or_cmd: {
1627416330 const app_name = app_buf.items[0..app_name_len];
16275 const ext_start = std.mem.lastIndexOfScalar(u16, app_name, '.') orelse break :bat_or_cmd false;
16331 const ext_start = std.mem.findScalarLast(u16, app_name, '.') orelse break :bat_or_cmd false;
1627616332 const ext = app_name[ext_start..];
1627716333 const ext_enum = windowsCreateProcessSupportsExtension(ext) orelse break :bat_or_cmd false;
1627816334 switch (ext_enum) {
......@@ -16308,7 +16364,7 @@ fn windowsCreateProcessPathExt(
1630816364 // it's treated as an unrecoverable error. Otherwise, it'll be
1630916365 // skipped as normal.
1631016366 const app_name = app_buf.items[0..app_name_len];
16311 const ext_start = std.mem.lastIndexOfScalar(u16, app_name, '.') orelse break :unappended err;
16367 const ext_start = std.mem.findScalarLast(u16, app_name, '.') orelse break :unappended err;
1631216368 const ext = app_name[ext_start..];
1631316369 if (windows.eqlIgnoreCaseWtf16(ext, std.unicode.utf8ToUtf16LeStringLiteral(".EXE"))) {
1631416370 return error.UnrecoverableInvalidExe;
......@@ -17387,6 +17443,7 @@ const use_parking_futex = switch (native_os) {
1738717443 .windows => true, // RtlWaitOnAddress is a userland implementation anyway
1738817444 .netbsd => true, // NetBSD has `futex(2)`, but it's historically been quite buggy. TODO: evaluate whether it's okay to use now.
1738917445 .illumos => true, // Illumos has no futex mechanism
17446 .haiku => true, // Haiku has no futex mechanism
1739017447 else => false,
1739117448};
1739217449const use_parking_sleep = switch (native_os) {
......@@ -17432,7 +17489,7 @@ const parking_futex = struct {
1743217489 const Waiter = struct {
1743317490 node: std.DoublyLinkedList.Node,
1743417491 address: usize,
17435 tid: std.Thread.Id,
17492 tid: ParkTid,
1743617493 /// `thread_status.cancelation` is `.parked` while the thread is waiting. The single thread
1743717494 /// which atomically updates it (to `.none` or `.canceling`) is responsible for:
1743817495 ///
......@@ -17473,7 +17530,7 @@ const parking_futex = struct {
1747317530
1747417531 // Put the threadlocal access outside of the critical section.
1747517532 const opt_thread = Thread.current;
17476 const self_tid = if (opt_thread) |thread| thread.id else std.Thread.getCurrentId();
17533 const self_tid = getParkTid();
1747717534
1747817535 var waiter: Waiter = .{
1747917536 .node = undefined, // populated by list append
......@@ -17721,7 +17778,12 @@ const parking_sleep = struct {
1772117778 },
1772217779 }
1772317780 }
17781
1772417782 // Uncancelable sleep; we expect not to be manually unparked.
17783
17784 // On systems where parking the thread requires a one-time setup operation (e.g. creating a
17785 // semaphore), we need to ensure that setup is done before we call `park`.
17786 _ = getParkTid();
1772517787 var dummy_flag: UnparkFlag = unpark_flag_init;
1772617788 if (park(timeout, null, if (need_unpark_flag) &dummy_flag)) {
1772717789 unreachable; // unexpected unpark
......@@ -17760,7 +17822,7 @@ const ParkingMutex = struct {
1776017822 /// Never modified once the `Waiter` is in the linked list.
1776117823 next: ?*Waiter,
1776217824 /// Never modified once the `Waiter` is in the linked list.
17763 tid: std.Thread.Id,
17825 tid: ParkTid,
1776417826 };
1776517827 fn lock(m: *ParkingMutex) void {
1776617828 state: switch (State.unlocked) { // assume 'unlocked' to optimize for uncontended case
......@@ -17776,7 +17838,7 @@ const ParkingMutex = struct {
1777617838
1777717839 .locked_once, _ => |last_state| {
1777817840 const old_waiter = last_state.waiter();
17779 const self_tid = if (Thread.current) |t| t.id else std.Thread.getCurrentId();
17841 const self_tid = getParkTid();
1778017842 var waiter: Waiter = .{
1778117843 .next = old_waiter,
1778217844 .unpark_flag = unpark_flag_init,
......@@ -17904,9 +17966,36 @@ fn setUnparkFlag(f: *UnparkFlag) void {
1790417966/// but it seems that someone at Microsoft forgot how big their TIDs are supposed to be.
1790517967const UnparkTid = switch (native_os) {
1790617968 .windows => usize,
17969 else => ParkTid,
17970};
17971
17972const ParkTid = switch (native_os) {
17973 .haiku => std.c.sem_id,
1790717974 else => std.Thread.Id,
1790817975};
1790917976
17977threadlocal var park_sem: std.c.sem_id = -1;
17978
17979fn getParkTid() ParkTid {
17980 switch (native_os) {
17981 .haiku => {
17982 if (park_sem == -1) {
17983 park_sem = std.c._kern_create_sem(0, null);
17984 if (park_sem < 0) @panic("_kern_create_sem failed");
17985 _ = std.c.on_exit_thread(destroyParkSem, null);
17986 }
17987 return park_sem;
17988 },
17989 else => {
17990 return if (Thread.current) |thread| thread.id else std.Thread.getCurrentId();
17991 },
17992 }
17993}
17994
17995fn destroyParkSem(_: ?*anyopaque) callconv(.c) void {
17996 _ = std.c._kern_delete_sem(park_sem);
17997}
17998
1791017999fn park(
1791118000 timeout: Io.Timeout,
1791218001 /// This value has no semantic effect, but may allow the OS to optimize the operation.
......@@ -17972,6 +18061,27 @@ fn park(
1797218061 }
1797318062 },
1797418063 .illumos => @panic("TODO: illumos lwp_park"),
18064 .haiku => {
18065 const timeout_flags: u32, const timeout_us = switch (timeout) {
18066 .none => .{ 0, 0 },
18067 .deadline => |deadline| .{
18068 if (deadline.clock == .real) std.c.B_ABSOLUTE_TIMEOUT | std.c.B_TIMEOUT_REAL_TIME_BASE else std.c.B_ABSOLUTE_TIMEOUT,
18069 deadline.raw.toMicroseconds(),
18070 },
18071 .duration => |duration| .{
18072 if (duration.clock == .real) std.c.B_ABSOLUTE_TIMEOUT | std.c.B_TIMEOUT_REAL_TIME_BASE else std.c.B_ABSOLUTE_TIMEOUT,
18073 nowPosix(duration.clock).addDuration(duration.raw).toMicroseconds(),
18074 },
18075 };
18076 while (true) {
18077 switch (std.c._kern_acquire_sem_etc(park_sem, 1, timeout_flags, timeout_us)) {
18078 0 => return,
18079 std.c.E.B_TIMED_OUT => return error.Timeout,
18080 std.c.E.B_INTERRUPTED => {},
18081 else => unreachable,
18082 }
18083 }
18084 },
1797518085 else => comptime unreachable,
1797618086 }
1797718087}
......@@ -18014,6 +18124,14 @@ fn unpark(tids: []const UnparkTid, addr_hint: ?*const anyopaque) void {
1801418124 }
1801518125 },
1801618126 .illumos => @panic("TODO: illumos lwp_unpark"),
18127 .haiku => {
18128 for (tids) |tid| {
18129 switch (std.c._kern_release_sem_etc(tid, 1, 0)) {
18130 0 => {},
18131 else => recoverableOsBugDetected(),
18132 }
18133 }
18134 },
1801718135 else => comptime unreachable,
1801818136 }
1801918137}
......@@ -18171,7 +18289,7 @@ fn fileMemoryMapCreate(
1817118289 error.Unseekable, error.Canceled, error.AccessDenied => |e| return e,
1817218290 error.OperationUnsupported => {},
1817318291 else => {
18174 if (builtin.mode == .Debug)
18292 if (builtin.mode == .debug)
1817518293 std.log.warn("memory mapping failed with {t}, falling back to file operations", .{err});
1817618294 },
1817718295 }
......@@ -18278,7 +18396,7 @@ fn createFileMap(
1827818396 .INVALID_VIEW_SIZE => |status| return windows.statusBug(status),
1827918397 else => |status| return windows.unexpectedStatus(status),
1828018398 }
18281 if (builtin.mode == .Debug) {
18399 if (builtin.mode == .debug) {
1828218400 const page_size = std.heap.pageSize();
1828318401 const alignment: Alignment = .fromByteUnits(page_size);
1828418402 assert(contents_len == alignment.forward(len));
......@@ -18369,7 +18487,7 @@ fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void {
1836918487 switch (posix.errno(posix.system.munmap(memory.ptr, memory.len))) {
1837018488 .SUCCESS => {},
1837118489 else => |e| {
18372 if (builtin.mode == .Debug)
18490 if (builtin.mode == .debug)
1837318491 std.log.err("failed to unmap {d} bytes at {*}: {t}", .{ memory.len, memory.ptr, e });
1837418492 },
1837518493 }
......@@ -18969,7 +19087,7 @@ fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!windows
1896919087 .{
1897019088 .DIRECTORY_FILE = options.filter == .dir_only,
1897119089 .NON_DIRECTORY_FILE = options.filter == .non_directory_only,
18972 .IO = if (options.follow_symlinks) .SYNCHRONOUS_NONALERT else .ASYNCHRONOUS,
19090 .IO = .SYNCHRONOUS_NONALERT,
1897319091 .OPEN_REPARSE_POINT = !options.follow_symlinks,
1897419092 },
1897519093 null,
lib/std/Io/Threaded/test.zig-2
......@@ -149,8 +149,6 @@ test "async with array return type" {
149149}
150150
151151test "cancel blocked read from pipe" {
152 if (builtin.cpu.arch.isSPARC() and builtin.os.tag == .linux) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35347
153
154152 const global = struct {
155153 fn readFromPipe(io: Io, pipe: Io.File) !void {
156154 var buf: [1]u8 = undefined;
lib/std/Io/Uring.zig+14-8
......@@ -1135,8 +1135,9 @@ fn mainIdleEntry() callconv(.naked) void {
11351135
11361136fn mainIdle(
11371137 ev: *Evented,
1138 message: *const SwitchMessage,
1138 contexts: *const Io.fiber.Switch,
11391139) callconv(.withStackAlign(.c, @max(@alignOf(Thread), @alignOf(Io.fiber.Context)))) noreturn {
1140 const message: *const SwitchMessage = @fieldParentPtr("contexts", contexts);
11401141 message.handle(ev);
11411142 ev.idle(&ev.threads.allocated[0]);
11421143 ev.yield(@ptrCast(&ev.main_fiber_buffer), .nothing);
......@@ -1414,8 +1415,9 @@ const AsyncClosure = struct {
14141415
14151416 fn call(
14161417 closure: *AsyncClosure,
1417 message: *const SwitchMessage,
1418 contexts: *const Io.fiber.Switch,
14181419 ) callconv(.withStackAlign(.c, @alignOf(AsyncClosure))) noreturn {
1420 const message: *const SwitchMessage = @fieldParentPtr("contexts", contexts);
14191421 const ev = closure.evented;
14201422 const fiber = closure.fiber;
14211423 message.handle(ev);
......@@ -1779,8 +1781,9 @@ const Group = struct {
17791781
17801782 fn call(
17811783 closure: *Group.AsyncClosure,
1782 message: *const SwitchMessage,
1784 contexts: *const Io.fiber.Switch,
17831785 ) callconv(.withStackAlign(.c, @alignOf(Group.AsyncClosure))) noreturn {
1786 const message: *const SwitchMessage = @fieldParentPtr("contexts", contexts);
17841787 const ev = closure.evented;
17851788 const fiber = closure.fiber;
17861789 message.handle(ev);
......@@ -3558,7 +3561,7 @@ fn dirHardLink(
35583561 old_sub_path_posix,
35593562 new_dir.handle,
35603563 new_sub_path_posix,
3561 if (options.follow_symlinks) 0 else linux.AT.SYMLINK_NOFOLLOW,
3564 if (options.follow_symlinks) linux.AT.SYMLINK_FOLLOW else 0,
35623565 );
35633566}
35643567
......@@ -3990,7 +3993,7 @@ fn fileHardLink(
39903993 "",
39913994 new_dir.handle,
39923995 new_sub_path_posix,
3993 linux.AT.EMPTY_PATH | @as(u32, if (options.follow_symlinks) 0 else linux.AT.SYMLINK_NOFOLLOW),
3996 linux.AT.EMPTY_PATH | @as(u32, if (options.follow_symlinks) linux.AT.SYMLINK_FOLLOW else 0),
39943997 );
39953998}
39963999
......@@ -4050,7 +4053,7 @@ fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void {
40504053 if (memory.len == 0) return;
40514054 switch (linux.errno(linux.munmap(memory.ptr, memory.len))) {
40524055 .SUCCESS => {},
4053 else => |err| if (builtin.mode == .Debug)
4056 else => |err| if (builtin.mode == .debug)
40544057 std.log.err("failed to unmap {d} bytes at {*}: {t}", .{ memory.len, memory.ptr, err }),
40554058 }
40564059 mm.* = undefined;
......@@ -5186,9 +5189,9 @@ fn netWriteFileUnavailable(
51865189 return error.Unimplemented;
51875190}
51885191
5189fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void {
5192fn netClose(userdata: ?*anyopaque, sockets: []const net.Socket) void {
51905193 const ev: *Evented = @ptrCast(@alignCast(userdata));
5191 for (handles) |handle| ev.close(handle);
5194 for (sockets) |sock| ev.close(sock.handle);
51925195}
51935196
51945197fn netShutdown(
......@@ -5295,6 +5298,7 @@ fn bind(
52955298 switch (cancel_region.errno()) {
52965299 .SUCCESS => return,
52975300 .INTR, .CANCELED => {},
5301 .ACCES => return error.AccessDenied,
52985302 .ADDRINUSE => return error.AddressInUse,
52995303 .BADF => |err| return errnoBug(err), // File descriptor used after closed.
53005304 .INVAL => |err| return errnoBug(err), // invalid parameters
......@@ -5542,6 +5546,8 @@ fn linkat(
55425546 new_path: [*:0]const u8,
55435547 flags: u32,
55445548) File.HardLinkError!void {
5549 // allowed flags: https://man7.org/linux/man-pages/man2/linkat.2.html
5550 assert(flags & ~(@as(u32, linux.AT.SYMLINK_FOLLOW | linux.AT.EMPTY_PATH)) == 0);
55455551 while (true) {
55465552 const thread = try cancel_region.awaitIoUring();
55475553 thread.enqueue().* = .{
lib/std/Io/Writer.zig+21-21
......@@ -874,7 +874,7 @@ pub fn splatBytes(w: *Writer, bytes: []const u8, n: usize) Error!usize {
874874}
875875
876876/// Asserts the `buffer` was initialized with a capacity of at least `@sizeOf(T)` bytes.
877pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.builtin.Endian) Error!void {
877pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.lang.Endian) Error!void {
878878 var bytes: [@divExact(@typeInfo(T).int.bits, 8)]u8 = undefined;
879879 std.mem.writeInt(std.math.ByteAlignedInt(@TypeOf(value)), &bytes, value, endian);
880880 return w.writeAll(&bytes);
......@@ -882,7 +882,7 @@ pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.built
882882
883883/// The function is inline to avoid the dead code in case `endian` is
884884/// comptime-known and matches host endianness.
885pub inline fn writeStruct(w: *Writer, value: anytype, endian: std.builtin.Endian) Error!void {
885pub inline fn writeStruct(w: *Writer, value: anytype, endian: std.lang.Endian) Error!void {
886886 switch (@typeInfo(@TypeOf(value))) {
887887 .@"struct" => |info| switch (info.layout) {
888888 .auto => @compileError("ill-defined memory layout"),
......@@ -907,7 +907,7 @@ pub inline fn writeSliceEndian(
907907 w: *Writer,
908908 Elem: type,
909909 slice: []const Elem,
910 endian: std.builtin.Endian,
910 endian: std.lang.Endian,
911911) Error!void {
912912 switch (@typeInfo(Elem)) {
913913 .@"struct" => |info| comptime assert(info.layout != .auto),
......@@ -2387,6 +2387,7 @@ pub fn unreachableRebase(w: *Writer, preserve: usize, capacity: usize) Error!voi
23872387
23882388pub fn fromArrayList(array_list: *ArrayList(u8)) Writer {
23892389 defer array_list.* = .empty;
2390 array_list.pointer_stability.assertUnlocked();
23902391 return .{
23912392 .vtable = &.{
23922393 .drain = fixedDrain,
......@@ -2402,6 +2403,7 @@ pub fn toArrayList(w: *Writer) ArrayList(u8) {
24022403 const result: ArrayList(u8) = .{
24032404 .items = w.buffer[0..w.end],
24042405 .capacity = w.buffer.len,
2406 .pointer_stability = .{},
24052407 };
24062408 w.buffer = &.{};
24072409 w.end = 0;
......@@ -2651,6 +2653,7 @@ pub const Allocating = struct {
26512653 const result: std.array_list.Aligned(u8, alignment) = .{
26522654 .items = @alignCast(w.buffer[0..w.end]),
26532655 .capacity = w.buffer.len,
2656 .pointer_stability = .{},
26542657 };
26552658 w.buffer = &.{};
26562659 w.end = 0;
......@@ -2742,29 +2745,26 @@ pub const Allocating = struct {
27422745
27432746 fn drain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
27442747 const a: *Allocating = @fieldParentPtr("writer", w);
2745 const pattern = data[data.len - 1];
2746 const splat_len = pattern.len * splat;
2747 const start_len = a.writer.end;
27482748 assert(data.len != 0);
2749 for (data) |bytes| {
2750 a.ensureUnusedCapacity(bytes.len + splat_len + 1) catch return error.WriteFailed;
2749 const count = countSplat(data, splat);
2750 a.ensureUnusedCapacity(count + 1) catch return error.WriteFailed;
2751 for (data[0 .. data.len - 1]) |bytes| {
27512752 @memcpy(a.writer.buffer[a.writer.end..][0..bytes.len], bytes);
27522753 a.writer.end += bytes.len;
27532754 }
2754 if (splat == 0) {
2755 a.writer.end -= pattern.len;
2756 } else switch (pattern.len) {
2755 const pattern = data[data.len - 1];
2756 switch (pattern.len) {
27572757 0 => {},
27582758 1 => {
2759 @memset(a.writer.buffer[a.writer.end..][0 .. splat - 1], pattern[0]);
2760 a.writer.end += splat - 1;
2759 @memset(a.writer.buffer[a.writer.end..][0..splat], pattern[0]);
2760 a.writer.end += splat;
27612761 },
2762 else => for (0..splat - 1) |_| {
2762 else => for (0..splat) |_| {
27632763 @memcpy(a.writer.buffer[a.writer.end..][0..pattern.len], pattern);
27642764 a.writer.end += pattern.len;
27652765 },
27662766 }
2767 return a.writer.end - start_len;
2767 return count;
27682768 }
27692769
27702770 fn sendFile(w: *Writer, file_reader: *File.Reader, limit: Limit) FileError!usize {
......@@ -2817,12 +2817,12 @@ pub const Allocating = struct {
28172817 }
28182818
28192819 test Allocating {
2820 try testAllocating(.fromByteUnits(1));
2821 try testAllocating(.fromByteUnits(4));
2822 try testAllocating(.fromByteUnits(8));
2823 try testAllocating(.fromByteUnits(16));
2824 try testAllocating(.fromByteUnits(32));
2825 try testAllocating(.fromByteUnits(64));
2820 try testAllocating(.@"1");
2821 try testAllocating(.@"4");
2822 try testAllocating(.@"8");
2823 try testAllocating(.@"16");
2824 try testAllocating(.@"32");
2825 try testAllocating(.@"64");
28262826 }
28272827};
28282828
lib/std/Io/net.zig+7-2
......@@ -198,6 +198,8 @@ pub const IpAddress = union(enum) {
198198 }
199199
200200 pub const ListenError = error{
201 /// The address is protected and the current user does not have permission to bind it.
202 AccessDenied,
201203 /// The address is already taken. Can occur when bound port is 0 but
202204 /// all ephemeral ports are already in use.
203205 AddressInUse,
......@@ -254,6 +256,8 @@ pub const IpAddress = union(enum) {
254256 }
255257
256258 pub const BindError = error{
259 /// The address is protected and the current user does not have permission to bind it.
260 AccessDenied,
257261 /// The address is already taken. Can occur when bound port is 0 but
258262 /// all ephemeral ports are already in use.
259263 AddressInUse,
......@@ -901,6 +905,7 @@ pub const UnixAddress = struct {
901905 ReadOnlyFileSystem,
902906 WouldBlock,
903907 NetworkDown,
908 ConnectionRefused,
904909 } || Io.Cancelable || Io.UnexpectedError;
905910
906911 pub fn connect(ua: *const UnixAddress, io: Io) ConnectError!Stream {
......@@ -1076,7 +1081,7 @@ pub const Socket = struct {
10761081
10771082 /// Leaves `address` in a valid state.
10781083 pub fn close(s: *const Socket, io: Io) void {
1079 io.vtable.netClose(io.userdata, (&s.handle)[0..1]);
1084 io.vtable.netClose(io.userdata, s[0..1]);
10801085 }
10811086
10821087 pub fn closeMany(io: Io, sockets: []const Socket) void {
......@@ -1253,7 +1258,7 @@ pub const Stream = struct {
12531258 }
12541259
12551260 pub fn close(s: *const Stream, io: Io) void {
1256 io.vtable.netClose(io.userdata, (&s.socket.handle)[0..1]);
1261 io.vtable.netClose(io.userdata, (&s.socket)[0..1]);
12571262 }
12581263
12591264 pub fn shutdown(s: *const Stream, io: Io, how: ShutdownHow) ShutdownError!void {
lib/std/Io/net/test.zig-2
......@@ -356,8 +356,6 @@ test "decompress compressed DNS name" {
356356}
357357
358358test "cancel accept" {
359 if (builtin.cpu.arch.isSPARC() and builtin.os.tag == .linux) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35347
360
361359 const io = testing.io;
362360 const localhost: net.IpAddress = .{ .ip4 = .loopback(0) };
363361
lib/std/Io/test.zig-4
......@@ -232,8 +232,6 @@ fn count(a: usize, b: usize, result: *usize) void {
232232}
233233
234234test "Group.cancel" {
235 if (builtin.cpu.arch.isSPARC() and builtin.os.tag == .linux) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35347
236
237235 const global = struct {
238236 fn sleep(io: Io, result: *usize) Io.Cancelable!void {
239237 defer result.* = 1;
......@@ -326,8 +324,6 @@ test "Group materializes error.Cancel" {
326324}
327325
328326test "Group task receives cancelation unknowingly" {
329 if (builtin.cpu.arch.isSPARC() and builtin.os.tag == .linux) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35347
330
331327 const S = struct {
332328 io: Io,
333329 err: ?Io.Cancelable!void,
lib/std/Progress.zig+14-2
......@@ -442,7 +442,15 @@ pub const Node = struct {
442442 global_progress.ipc_files[slot] = file;
443443 storageByIndex(index).setIpcIndex(.{ .slot = slot, .generation = generation });
444444 break;
445 } else file.close(io);
445 } else {
446 // There was no IPC slot available, so we'll drop this node's IPC info and just close
447 // the fd. To avoid an old `estimated_total_items` or `completed_count` value still
448 // being rendered for the node, we'll zero that field out (and the user is not allowed
449 // to change it because they think we're doing IPC).
450 file.close(io);
451 @atomicStore(u32, &storageByIndex(index).completed_count, 0, .monotonic);
452 @atomicStore(u32, &storageByIndex(index).estimated_total_count, 0, .monotonic);
453 }
446454 }
447455
448456 pub fn setIpcIndex(node: Node, ipc_index: Ipc.Index) void {
......@@ -452,7 +460,11 @@ pub const Node = struct {
452460 /// Not thread-safe.
453461 pub fn takeIpcIndex(node: Node) ?Ipc.Index {
454462 const storage = storageByIndex(node.index.unwrap() orelse return null);
455 assert(storage.estimated_total_count == std.math.maxInt(u32));
463 switch (storage.estimated_total_count) {
464 std.math.maxInt(u32) => {}, // indicates that there is an IPC index in `completed_count`
465 0 => return null, // `setIpcFile` failed so we don't have an IPC index for this node
466 else => unreachable, // not an IPC node
467 }
456468 @atomicStore(u32, &storage.estimated_total_count, 0, .monotonic);
457469 return @bitCast(storage.completed_count);
458470 }
lib/std/Random/RomuTrio.zig-1
......@@ -122,7 +122,6 @@ test fill {
122122}
123123
124124test "buf seeding test" {
125 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
126125 const buf0: [24]u8 = @bitCast([3]u64{ 16294208416658607535, 13964609475759908645, 4703697494102998476 });
127126 const resulting_state = .{ .x = 16294208416658607535, .y = 13964609475759908645, .z = 4703697494102998476 };
128127 var r = RomuTrio.init(0);
lib/std/Random/Xoshiro256.zig-2
......@@ -89,8 +89,6 @@ pub fn fill(self: *Xoshiro256, buf: []u8) void {
8989}
9090
9191test "sequence" {
92 if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest;
93
9492 var r = Xoshiro256.init(0);
9593
9694 const seq1 = [_]u64{
lib/std/Random/benchmark.zig+1-1
......@@ -122,7 +122,7 @@ fn usage() void {
122122}
123123
124124fn mode(comptime x: comptime_int) comptime_int {
125 return if (builtin.mode == .Debug) x / 64 else x;
125 return if (builtin.mode == .debug) x / 64 else x;
126126}
127127
128128pub fn main(init: std.process.Init) !void {
lib/std/Target.zig+49-140
......@@ -1194,9 +1194,6 @@ pub fn toCoffMachine(target: *const Target) std.coff.IMAGE.FILE.MACHINE {
11941194 };
11951195}
11961196
1197/// Deprecated; use 'std.zig.Subsystem' instead. To be removed after 0.16.0 is tagged.
1198pub const SubSystem = std.zig.Subsystem;
1199
12001197pub const Cpu = struct {
12011198 /// Architecture
12021199 arch: Arch,
......@@ -1796,10 +1793,12 @@ pub const Cpu = struct {
17961793 .x86_64_regcall_v4_win,
17971794 .x86_64_vectorcall,
17981795 .x86_64_interrupt,
1796 .x86_64_preserve_none,
17991797 => &.{.x86_64},
18001798
18011799 .x86_sysv,
18021800 .x86_win,
1801 .x86_mingw,
18031802 .x86_stdcall,
18041803 .x86_fastcall,
18051804 .x86_thiscall,
......@@ -1821,6 +1820,7 @@ pub const Cpu = struct {
18211820 .aarch64_aapcs_win,
18221821 .aarch64_vfabi,
18231822 .aarch64_vfabi_sve,
1823 .aarch64_preserve_none,
18241824 => &.{ .aarch64, .aarch64_be },
18251825
18261826 .alpha_osf,
......@@ -2081,6 +2081,7 @@ pub const Cpu = struct {
20812081 else => generic(arch),
20822082 },
20832083 .powerpc64 => switch (os.tag) {
2084 .linux, .freebsd => &powerpc.cpu.pwr8,
20842085 .openbsd => &powerpc.cpu.pwr9,
20852086 else => generic(arch),
20862087 },
......@@ -2660,12 +2661,26 @@ pub const DynamicLinker = struct {
26602661 else => return none,
26612662 }}),
26622663
2663 .loongarch64 => initFmt("/lib64/ld-linux-loongarch-{s}.so.1", .{switch (abi) {
2664 .gnu => "lp64d",
2665 .gnuf32 => "lp64f",
2666 .gnusf => "lp64s",
2667 else => return none,
2668 }}),
2664 .loongarch32,
2665 .loongarch64,
2666 => |arch| initFmt("/lib{s}/ld-linux-{s}{s}.so.1", .{
2667 switch (arch) {
2668 .loongarch32 => "32",
2669 .loongarch64 => "64",
2670 else => unreachable,
2671 },
2672 switch (arch) {
2673 .loongarch32 => "loongarch-ilp32",
2674 .loongarch64 => "loongarch-lp64",
2675 else => unreachable,
2676 },
2677 switch (abi) {
2678 .gnu => "d",
2679 .gnuf32 => "f",
2680 .gnusf => "s",
2681 else => return none,
2682 },
2683 }),
26692684
26702685 .hppa,
26712686 .m68k,
......@@ -3069,9 +3084,13 @@ pub fn stackGrowth(target: *const Target) StackGrowth {
30693084/// Default signedness of `char` for the native C compiler for this target
30703085/// Note that char signedness is implementation-defined and many compilers provide
30713086/// an option to override the default signedness e.g. GCC's -funsigned-char / -fsigned-char
3072pub fn cCharSignedness(target: *const Target) std.builtin.Signedness {
3087/// Returns `null` if no C ABI is defined for this target.
3088pub fn cCharSignedness(target: *const Target) ?std.builtin.Signedness {
3089 switch (target.os.tag) {
3090 .opengl => return null,
3091 else => {},
3092 }
30733093 if (target.os.tag.isDarwin() or target.os.tag == .windows or target.os.tag == .uefi) return .signed;
3074
30753094 return switch (target.cpu.arch) {
30763095 .aarch64,
30773096 .aarch64_be,
......@@ -3117,7 +3136,8 @@ pub const CType = enum {
31173136 longdouble,
31183137};
31193138
3120pub fn cTypeByteSize(t: *const Target, c_type: CType) u16 {
3139/// Returns `null` if no C ABI is defined for this target.
3140pub fn cTypeByteSize(t: *const Target, c_type: CType) ?u16 {
31213141 return switch (c_type) {
31223142 .char,
31233143 .short,
......@@ -3130,18 +3150,19 @@ pub fn cTypeByteSize(t: *const Target, c_type: CType) u16 {
31303150 .ulonglong,
31313151 .float,
31323152 .double,
3133 => @divExact(cTypeBitSize(t, c_type), 8),
3153 => @divExact(cTypeBitSize(t, c_type) orelse return null, 8),
31343154
3135 .longdouble => switch (cTypeBitSize(t, c_type)) {
3155 .longdouble => switch (cTypeBitSize(t, c_type) orelse return null) {
31363156 64 => 8,
3137 80 => @intCast(std.mem.alignForward(usize, 10, cTypeAlignment(t, .longdouble))),
3157 80 => @intCast(std.mem.alignForward(usize, 10, cTypeAlignment(t, c_type).?)),
31383158 128 => 16,
31393159 else => unreachable,
31403160 },
31413161 };
31423162}
31433163
3144pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
3164/// Returns `null` if no C ABI is defined for this target.
3165pub fn cTypeBitSize(target: *const Target, c_type: CType) ?u16 {
31453166 switch (target.os.tag) {
31463167 .freestanding,
31473168 .other,
......@@ -3462,15 +3483,17 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
34623483 .longlong, .ulonglong, .longdouble => return 64,
34633484 },
34643485
3486 .opengl => return null,
3487
34653488 .ps3,
34663489 .contiki,
34673490 .managarm,
3468 .opengl,
34693491 => @panic("specify the C integer and float type sizes for this OS"),
34703492 }
34713493}
34723494
3473pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 {
3495/// Returns `null` if no C ABI is defined for this target.
3496pub fn cTypeAlignment(target: *const Target, c_type: CType) ?u16 {
34743497 // Overrides for unusual alignments
34753498 switch (target.cpu.arch) {
34763499 .avr,
......@@ -3503,7 +3526,7 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 {
35033526
35043527 // Next-power-of-two-aligned, up to a maximum.
35053528 return @min(
3506 std.math.ceilPowerOfTwoAssert(u16, (cTypeBitSize(target, c_type) + 7) / 8),
3529 std.math.ceilPowerOfTwoAssert(u16, ((cTypeBitSize(target, c_type) orelse return null) + 7) / 8),
35073530 @as(u16, switch (target.cpu.arch) {
35083531 .msp430,
35093532 .x86_16,
......@@ -3578,120 +3601,6 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 {
35783601 );
35793602}
35803603
3581pub fn cTypePreferredAlignment(target: *const Target, c_type: CType) u16 {
3582 // Overrides for unusual alignments
3583 switch (target.cpu.arch) {
3584 .arc, .arceb => switch (c_type) {
3585 .longdouble => return 4,
3586 else => {},
3587 },
3588 .avr,
3589 .ez80,
3590 => return 1,
3591 .x86 => switch (target.os.tag) {
3592 .windows, .uefi => switch (c_type) {
3593 .longdouble => switch (target.abi) {
3594 .gnu => return 4,
3595 else => return 8,
3596 },
3597 else => {},
3598 },
3599 else => switch (c_type) {
3600 .longdouble => return 4,
3601 else => {},
3602 },
3603 },
3604 .m68k => switch (c_type) {
3605 .int, .uint, .long, .ulong => return 2,
3606 else => {},
3607 },
3608 .wasm32, .wasm64 => switch (target.os.tag) {
3609 .emscripten => switch (c_type) {
3610 .longdouble => return 8,
3611 else => {},
3612 },
3613 else => {},
3614 },
3615 else => {},
3616 }
3617
3618 // Next-power-of-two-aligned, up to a maximum.
3619 return @min(
3620 std.math.ceilPowerOfTwoAssert(u16, (cTypeBitSize(target, c_type) + 7) / 8),
3621 @as(u16, switch (target.cpu.arch) {
3622 .x86_16,
3623 .msp430,
3624 => 2,
3625
3626 .arc,
3627 .arceb,
3628 .csky,
3629 .kalimba,
3630 .microblaze,
3631 .microblazeel,
3632 .or1k,
3633 .propeller,
3634 .sh,
3635 .sheb,
3636 .xcore,
3637 .xtensa,
3638 .xtensaeb,
3639 => 4,
3640
3641 .amdgcn,
3642 .arm,
3643 .armeb,
3644 .bpfeb,
3645 .bpfel,
3646 .hexagon,
3647 .hppa,
3648 .lanai,
3649 .m68k,
3650 .m88k,
3651 .mips,
3652 .mipsel,
3653 .nvptx,
3654 .nvptx64,
3655 .s390x,
3656 .sparc,
3657 .thumb,
3658 .thumbeb,
3659 .x86,
3660 => 8,
3661
3662 .aarch64,
3663 .aarch64_be,
3664 .alpha,
3665 .hppa64,
3666 .kvx,
3667 .loongarch32,
3668 .loongarch64,
3669 .mips64,
3670 .mips64el,
3671 .powerpc,
3672 .powerpcle,
3673 .powerpc64,
3674 .powerpc64le,
3675 .riscv32,
3676 .riscv32be,
3677 .riscv64,
3678 .riscv64be,
3679 .sparc64,
3680 .spirv32,
3681 .spirv64,
3682 .ve,
3683 .wasm32,
3684 .wasm64,
3685 .x86_64,
3686 => 16,
3687
3688 .avr,
3689 .ez80,
3690 => unreachable, // Handled above.
3691 }),
3692 );
3693}
3694
36953604pub fn cMaxIntAlignment(target: *const Target) u16 {
36963605 return switch (target.cpu.arch) {
36973606 .avr,
......@@ -3715,6 +3624,11 @@ pub fn cMaxIntAlignment(target: *const Target) u16 {
37153624 .xcore,
37163625 => 4,
37173626
3627 .x86 => switch (target.os.tag) {
3628 else => 4,
3629 .uefi, .windows => 8,
3630 },
3631
37183632 .arm,
37193633 .armeb,
37203634 .hexagon,
......@@ -3733,7 +3647,6 @@ pub fn cMaxIntAlignment(target: *const Target) u16 {
37333647 .sparc,
37343648 .thumb,
37353649 .thumbeb,
3736 .x86,
37373650 .xtensa,
37383651 .xtensaeb,
37393652 => 8,
......@@ -3769,18 +3682,14 @@ pub fn cMaxIntAlignment(target: *const Target) u16 {
37693682pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention {
37703683 return switch (target.cpu.arch) {
37713684 .x86_64 => switch (target.os.tag) {
3772 .windows,
3773 .uefi,
3774 => .{ .x86_64_win = .{} },
3685 .windows, .uefi => .{ .x86_64_win = .{} },
37753686 else => switch (target.abi) {
37763687 .gnux32, .muslx32, .x32 => .{ .x86_64_x32 = .{} },
37773688 else => .{ .x86_64_sysv = .{} },
37783689 },
37793690 },
37803691 .x86 => switch (target.os.tag) {
3781 .windows,
3782 .uefi,
3783 => .{ .x86_win = .{} },
3692 .windows, .uefi => if (target.isMinGW()) .{ .x86_mingw = .{} } else .{ .x86_win = .{} },
37843693 else => .{ .x86_sysv = .{} },
37853694 },
37863695 .x86_16 => .{ .x86_16_cdecl = .{} },
lib/std/Thread.zig+36-43
......@@ -639,8 +639,7 @@ const WindowsThreadImpl = struct {
639639 }
640640
641641 fn join(self: Impl) void {
642 const infinite_timeout: windows.LARGE_INTEGER = std.math.minInt(windows.LARGE_INTEGER);
643 switch (windows.ntdll.NtWaitForSingleObject(self.thread.thread_handle, .FALSE, &infinite_timeout)) {
642 switch (windows.ntdll.NtWaitForSingleObject(self.thread.thread_handle, .FALSE, null)) {
644643 windows.NTSTATUS.WAIT_0 => {},
645644 else => |status| windows.unexpectedStatus(status) catch unreachable,
646645 }
......@@ -720,10 +719,9 @@ const PosixThreadImpl = struct {
720719 },
721720 .haiku => {
722721 var system_info: std.c.system_info = undefined;
723 const rc = std.c.get_system_info(&system_info); // always returns B_OK
724 return switch (posix.errno(rc)) {
725 .SUCCESS => @as(usize, @intCast(system_info.cpu_count)),
726 else => |err| posix.unexpectedErrno(err),
722 return switch (std.c.get_system_info(&system_info)) {
723 0 => @as(usize, @intCast(system_info.cpu_count)),
724 else => error.Unexpected,
727725 };
728726 },
729727 else => {
......@@ -1146,6 +1144,13 @@ const LinuxThreadImpl = struct {
11461144 parent_tid: i32 = undefined,
11471145 mapped: []align(std.heap.page_size_min) u8,
11481146
1147 // On SPARC, the kernel needs to be able to restore the current register window from the
1148 // stack when returning from a syscall. That presents a bit of a problem in `freeAndExit`
1149 // since we're deallocating the stack! The good news is that, since we do not care about
1150 // the contents of the incoming and local registers at that point, we can just tell the
1151 // kernel that our stack is this undefined global buffer.
1152 var sparc_exit_stack: [192]u8 align(16) = undefined;
1153
11491154 /// Calls `munmap(mapped.ptr, mapped.len)` then `exit(1)` without touching the stack (which lives in `mapped.ptr`).
11501155 /// Ported over from musl libc's pthread detached implementation:
11511156 /// https://github.com/ifduyue/musl/search?q=__unmapself
......@@ -1365,51 +1370,39 @@ const LinuxThreadImpl = struct {
13651370 [len] "{r5}" (self.mapped.len),
13661371 ),
13671372 .sparc => asm volatile (
1368 \\ # See sparc64 comments below.
1369 \\ 1:
1370 \\ cmp %%fp, 0
1371 \\ beq 2f
1372 \\ nop
1373 \\ ba 1b
1374 \\ restore
1375 \\ 2:
1376 \\ mov %%g1, %%o0 // ptr
1377 \\ mov %%g2, %%o1 // len
1378 \\ mov 73, %%g1 // SYS_munmap
1379 \\ t 0x3 // ST_FLUSH_WINDOWS
1380 \\ t 0x10
1381 \\ mov 1, %%g1 // SYS_exit
1382 \\ mov 0, %%o0
1383 \\ t 0x10
1373 \\ // See sparc64 comments below.
1374 \\ t 0x3 // ST_FLUSH_WINDOWS
1375 \\ mov %%g3, %%sp
1376 \\ mov %%g1, %%o0
1377 \\ mov %%g2, %%o1
1378 \\ mov 73, %%g1 // SYS_munmap
1379 \\ t 0x10
1380 \\ mov 1, %%g1 // SYS_exit
1381 \\ mov 0, %%o0
1382 \\ t 0x10
13841383 :
13851384 : [ptr] "{g1}" (@intFromPtr(self.mapped.ptr)),
13861385 [len] "{g2}" (self.mapped.len),
1386 [stack] "{g3}" (&sparc_exit_stack),
13871387 : .{ .memory = true }),
13881388 .sparc64 => asm volatile (
1389 \\ # SPARCs really don't like it when active stack frames
1390 \\ # is unmapped (it will result in a segfault), so we
1391 \\ # force-deactivate it by running `restore` until
1392 \\ # all frames are cleared.
1393 \\ 1:
1394 \\ cmp %%fp, 0
1395 \\ beq 2f
1396 \\ nop
1397 \\ ba 1b
1398 \\ restore
1399 \\ 2:
1400 \\ mov %%g1, %%o0 // ptr
1401 \\ mov %%g2, %%o1 // len
1402 \\ mov 73, %%g1 // SYS_munmap
1403 \\ # Flush register window contents to prevent background
1404 \\ # memory access before unmapping the stack.
1405 \\ flushw
1406 \\ t 0x6d
1407 \\ mov 1, %%g1 // SYS_exit
1408 \\ mov 0, %%o0
1409 \\ t 0x6d
1389 \\ // Ensure that the kernel only has to flush the current register window.
1390 \\ flushw
1391 \\ // Set up a fake stack for the syscall to restore l/i registers from. Local
1392 \\ // and incoming registers must be treated as effectively garbage past this
1393 \\ // instruction!
1394 \\ sub %%g3, 2047, %%sp
1395 \\ mov %%g1, %%o0
1396 \\ mov %%g2, %%o1
1397 \\ mov 73, %%g1 // SYS_munmap
1398 \\ t 0x6d
1399 \\ mov 1, %%g1 // SYS_exit
1400 \\ mov 0, %%o0
1401 \\ t 0x6d
14101402 :
14111403 : [ptr] "{g1}" (@intFromPtr(self.mapped.ptr)),
14121404 [len] "{g2}" (self.mapped.len),
1405 [stack] "{g3}" (&sparc_exit_stack),
14131406 : .{ .memory = true }),
14141407 .loongarch32, .loongarch64 => asm volatile (
14151408 \\ ori $a7, $zero, 215 # SYS_munmap
lib/std/Uri.zig+4-4
......@@ -221,16 +221,16 @@ pub fn parseAfterScheme(scheme: []const u8, text: []const u8) ParseError!Uri {
221221 }
222222
223223 if (authority.len > start_of_host and authority[start_of_host] == '[') { // IPv6
224 end_of_host = std.mem.lastIndexOf(u8, authority, "]") orelse return error.InvalidFormat;
224 end_of_host = std.mem.findLast(u8, authority, "]") orelse return error.InvalidFormat;
225225 end_of_host += 1;
226226
227 if (std.mem.lastIndexOf(u8, authority, ":")) |index| {
227 if (std.mem.findLast(u8, authority, ":")) |index| {
228228 if (index >= end_of_host) { // if not part of the V6 address field
229229 end_of_host = @min(end_of_host, index);
230230 uri.port = std.fmt.parseInt(u16, authority[index + 1 ..], 10) catch return error.InvalidPort;
231231 }
232232 }
233 } else if (std.mem.lastIndexOf(u8, authority, ":")) |index| {
233 } else if (std.mem.findLast(u8, authority, ":")) |index| {
234234 if (index >= start_of_host) { // if not part of the userinfo field
235235 end_of_host = @min(end_of_host, index);
236236 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
475475 var aux: Writer = .fixed(aux_buf.*);
476476 if (!base.isEmpty()) {
477477 base.formatPath(&aux) catch return error.NoSpaceLeft;
478 aux.end = std.mem.lastIndexOfScalar(u8, aux.buffered(), '/') orelse return remove_dot_segments(new);
478 aux.end = std.mem.findScalarLast(u8, aux.buffered(), '/') orelse return remove_dot_segments(new);
479479 }
480480 aux.print("/{s}", .{new}) catch return error.NoSpaceLeft;
481481 const merged_path = remove_dot_segments(aux.buffered());
lib/std/array_hash_map.zig+7-7
......@@ -13,12 +13,12 @@ const hash_map = @This();
1313///
1414/// See `AutoContext` for a description of the hash and equal implementations.
1515pub fn Auto(comptime K: type, comptime V: type) type {
16 return ArrayHashMap(K, V, AutoContext(K), !autoEqlIsCheap(K));
16 return Custom(K, V, AutoContext(K), !autoEqlIsCheap(K));
1717}
1818
1919/// An `ArrayHashMap` with strings as keys.
2020pub fn String(comptime V: type) type {
21 return ArrayHashMap([]const u8, V, StringContext, true);
21 return Custom([]const u8, V, StringContext, true);
2222}
2323
2424pub const StringContext = struct {
......@@ -2130,7 +2130,7 @@ test "0 sized key and 0 sized value" {
21302130test "setKey storehash true" {
21312131 const gpa = std.testing.allocator;
21322132
2133 var map: ArrayHashMap(i32, i32, AutoContext(i32), true) = .empty;
2133 var map: Custom(i32, i32, AutoContext(i32), true) = .empty;
21342134 defer map.deinit(gpa);
21352135
21362136 try map.put(gpa, 12, 34);
......@@ -2146,7 +2146,7 @@ test "setKey storehash true" {
21462146test "setKey storehash false" {
21472147 const gpa = std.testing.allocator;
21482148
2149 var map: ArrayHashMap(i32, i32, AutoContext(i32), false) = .empty;
2149 var map: Custom(i32, i32, AutoContext(i32), false) = .empty;
21502150 defer map.deinit(gpa);
21512151
21522152 try map.put(gpa, 12, 34);
......@@ -2162,7 +2162,7 @@ test "setKey storehash false" {
21622162test "setKey storehash false with index" {
21632163 const gpa = std.testing.allocator;
21642164
2165 const T = ArrayHashMap(usize, usize, AutoContext(usize), false);
2165 const T = Custom(usize, usize, AutoContext(usize), false);
21662166
21672167 var map: T = .empty;
21682168 defer map.deinit(gpa);
......@@ -2180,9 +2180,9 @@ test "setKey storehash false with index" {
21802180test "setKey storehash true with index" {
21812181 const gpa = std.testing.allocator;
21822182
2183 const T = ArrayHashMap(usize, usize, AutoContext(usize), false);
2183 const T = Custom(usize, usize, AutoContext(usize), false);
21842184
2185 var map: ArrayHashMap(usize, usize, AutoContext(usize), true) = .empty;
2185 var map: Custom(usize, usize, AutoContext(usize), true) = .empty;
21862186 defer map.deinit(gpa);
21872187
21882188 for (0..T.linear_scan_max + 1) |i| try map.put(gpa, i, i);
lib/std/array_list.zig+201-145
......@@ -26,8 +26,8 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
2626 ///
2727 /// Pointers to elements in this slice are invalidated by various
2828 /// functions of this ArrayList in accordance with the respective
29 /// documentation. In all cases, "invalidated" means that the memory
30 /// has been passed to this allocator's resize or free function.
29 /// documentation.
30 /// An invalidated pointer may point either to valid or freed memory.
3131 items: Slice,
3232 /// How many T values this list can hold without allocating
3333 /// additional memory.
......@@ -35,7 +35,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
3535 allocator: Allocator,
3636
3737 /// Used to detect memory safety violations.
38 pointer_stability: debug.SafetyLock = .{},
38 pointer_stability: debug.SafetyLock,
3939
4040 pub const Slice = if (alignment) |a| ([]align(a.toByteUnits()) T) else []T;
4141
......@@ -49,6 +49,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
4949 .items = &[_]T{},
5050 .capacity = 0,
5151 .allocator = gpa,
52 .pointer_stability = .{},
5253 };
5354 }
5455
......@@ -94,6 +95,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
9495 .items = slice,
9596 .capacity = slice.len,
9697 .allocator = gpa,
98 .pointer_stability = .{},
9799 };
98100 }
99101
......@@ -105,22 +107,28 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
105107 .items = slice,
106108 .capacity = slice.len + 1,
107109 .allocator = gpa,
110 .pointer_stability = .{},
108111 };
109112 }
110113
111114 /// Initializes an ArrayList with the `items` and `capacity` fields
112115 /// of this ArrayList. Empties this ArrayList.
113116 pub fn moveToUnmanaged(self: *Self) Aligned(T, alignment) {
114 self.pointer_stability.assertUnlocked();
115117 const allocator = self.allocator;
116 const result: Aligned(T, alignment) = .{ .items = self.items, .capacity = self.capacity };
118 const result: Aligned(T, alignment) = .{
119 .items = self.items,
120 .capacity = self.capacity,
121 .pointer_stability = self.pointer_stability,
122 };
117123 self.* = init(allocator);
118124 return result;
119125 }
120126
121127 /// The caller owns the returned memory. Empties this ArrayList.
122128 /// Its capacity is cleared, making `deinit` safe but unnecessary to call.
129 /// May invalidate element pointers if remapping memory cannot be done in place.
123130 pub fn toOwnedSlice(self: *Self) Allocator.Error!Slice {
131 self.pointer_stability.assertUnlocked();
124132 const allocator = self.allocator;
125133
126134 const old_memory = self.allocatedSlice();
......@@ -136,6 +144,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
136144 }
137145
138146 /// The caller owns the returned memory. Empties this ArrayList.
147 /// May invalidate element pointers if remapping memory cannot be done in place.
139148 pub fn toOwnedSliceSentinel(self: *Self, comptime sentinel: T) Allocator.Error!SentinelSlice(sentinel) {
140149 // This addition can never overflow because `self.items` can never occupy the whole address space
141150 try self.ensureTotalCapacityPrecise(self.items.len + 1);
......@@ -151,31 +160,31 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
151160 return cloned;
152161 }
153162
154 /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room.
155 /// If `i` is equal to the length of the list this operation is equivalent to append.
163 /// Insert `item` at index `index`. Moves `list[index .. list.len]` to higher indices to make room.
164 /// If `index` is equal to the length of the list this operation is equivalent to append.
156165 /// This operation is O(N).
157166 /// Invalidates element pointers if additional memory is needed.
167 /// Invalidates pre-existing pointers to elements at and after `index`.
158168 /// Asserts that the index is in bounds or equal to the length.
159 pub fn insert(self: *Self, i: usize, item: T) Allocator.Error!void {
160 const dst = try self.addManyAt(i, 1);
169 pub fn insert(self: *Self, index: usize, item: T) Allocator.Error!void {
170 self.pointer_stability.assertUnlocked();
171 const dst = try self.addManyAt(index, 1);
161172 dst[0] = item;
162173 }
163174
164 /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room.
165 /// If `i` is equal to the length of the list this operation is
175 /// Insert `item` at index `index`. Moves `list[index .. list.len]` to higher indices to make room.
176 /// If `index` is equal to the length of the list this operation is
166177 /// equivalent to appendAssumeCapacity.
167178 /// This operation is O(N).
179 /// Invalidates pre-existing pointers to elements at and after `index`.
168180 /// Asserts that there is enough capacity for the new item.
169181 /// Asserts that the index is in bounds or equal to the length.
170 pub fn insertAssumeCapacity(self: *Self, i: usize, item: T) void {
171 self.pointer_stability.lock();
172 defer self.pointer_stability.unlock();
173
182 pub fn insertAssumeCapacity(self: *Self, index: usize, item: T) void {
183 self.pointer_stability.assertUnlocked();
174184 assert(self.items.len < self.capacity);
175185 self.items.len += 1;
176
177 @memmove(self.items[i + 1 .. self.items.len], self.items[i .. self.items.len - 1]);
178 self.items[i] = item;
186 @memmove(self.items[index + 1 .. self.items.len], self.items[index .. self.items.len - 1]);
187 self.items[index] = item;
179188 }
180189
181190 /// Add `count` new elements at position `index`, which have
......@@ -188,12 +197,11 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
188197 /// Asserts that the index is in bounds or equal to the length.
189198 pub fn addManyAt(self: *Self, index: usize, count: usize) Allocator.Error![]T {
190199 const new_len = try addOrOom(self.items.len, count);
200 self.pointer_stability.assertUnlocked();
191201
192202 if (self.capacity >= new_len)
193203 return addManyAtAssumeCapacity(self, index, count);
194204
195 self.pointer_stability.lock();
196 defer self.pointer_stability.unlock();
197205 // Here we avoid copying allocated but unused bytes by
198206 // attempting a resize in place, and falling back to allocating
199207 // a new buffer and doing our own copy. With a realloc() call,
......@@ -225,9 +233,11 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
225233 /// `undefined` values. Returns a slice pointing to the newly allocated
226234 /// elements, which becomes invalid after various `ArrayList`
227235 /// operations.
236 /// Invalidates pre-existing pointers to elements at and after `index`.
228237 /// Asserts that there is enough capacity for the new elements.
229238 /// Asserts that the index is in bounds or equal to the length.
230239 pub fn addManyAtAssumeCapacity(self: *Self, index: usize, count: usize) []T {
240 self.pointer_stability.assertUnlocked();
231241 const new_len = self.items.len + count;
232242 assert(self.capacity >= new_len);
233243 const to_move = self.items[index..];
......@@ -238,7 +248,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
238248 return result;
239249 }
240250
241 /// Insert slice `items` at index `i` by moving `list[i .. list.len]` to make room.
251 /// Insert slice `items` at index `index` by moving `list[index .. list.len]` to make room.
242252 /// This operation is O(N).
243253 /// Invalidates pre-existing pointers to elements at and after `index`.
244254 /// Invalidates all pre-existing element pointers if capacity must be
......@@ -254,7 +264,9 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
254264 }
255265
256266 /// Grows or shrinks the list as necessary.
257 /// Invalidates element pointers if additional capacity is allocated.
267 /// Invalidates element pointers if additional capacity is allocated,
268 /// Invalidates pointers to elements at and above index `start + len`
269 /// when `len` and `new_items.len` are unequal.
258270 /// Asserts that the range is in bounds.
259271 pub fn replaceRange(self: *Self, start: usize, len: usize, new_items: []const T) Allocator.Error!void {
260272 var unmanaged = self.moveToUnmanaged();
......@@ -263,7 +275,8 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
263275 }
264276
265277 /// Grows or shrinks the list as necessary.
266 /// Never invalidates element pointers.
278 /// Invalidates pointers to elements at and above index `start + len`
279 /// when `len` and `new_items.len` are unequal.
267280 /// Asserts the capacity is enough for additional items.
268281 pub fn replaceRangeAssumeCapacity(self: *Self, start: usize, len: usize, new_items: []const T) void {
269282 var unmanaged = self.moveToUnmanaged();
......@@ -300,10 +313,12 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
300313
301314 /// Removes the element at the specified index and returns it.
302315 /// The empty slot is filled from the end of the list.
316 /// Invalidates pointers to the end of the list.
303317 /// This operation is O(1).
304318 /// This may not preserve item order. Use `orderedRemove` if you need to preserve order.
305319 /// Asserts that the index is in bounds.
306320 pub fn swapRemove(self: *Self, i: usize) T {
321 self.pointer_stability.assertUnlocked();
307322 const val = self.items[i];
308323 self.items[i] = self.items[self.items.len - 1];
309324 self.items[self.items.len - 1] = undefined;
......@@ -353,6 +368,8 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
353368 @memcpy(self.items[old_len..][0..items.len], items);
354369 }
355370
371 /// Prints a formatted string into this list.
372 /// Invalidates element pointers if additional memory is needed.
356373 pub fn print(self: *Self, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void {
357374 const gpa = self.allocator;
358375 var unmanaged = self.moveToUnmanaged();
......@@ -404,9 +421,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
404421 /// Invalidates element pointers for the elements `items[new_len..]`.
405422 /// Asserts that the new length is less than or equal to the previous length.
406423 pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void {
407 self.pointer_stability.lock();
408 defer self.pointer_stability.unlock();
409
424 self.pointer_stability.assertUnlocked();
410425 assert(new_len <= self.items.len);
411426 @memset(self.items[new_len..], undefined);
412427 self.items.len = new_len;
......@@ -415,8 +430,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
415430 /// Reduce length to 0.
416431 /// Invalidates all element pointers.
417432 pub fn clearRetainingCapacity(self: *Self) void {
418 self.pointer_stability.lock();
419 defer self.pointer_stability.unlock();
433 self.pointer_stability.assertUnlocked();
420434 @memset(self.items, undefined);
421435 self.items.len = 0;
422436 }
......@@ -449,18 +463,15 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
449463 /// modify the array so that it can hold exactly `new_capacity` items.
450464 /// Invalidates element pointers if additional memory is needed.
451465 pub fn ensureTotalCapacityPrecise(self: *Self, new_capacity: usize) Allocator.Error!void {
452 self.pointer_stability.lock();
453 defer self.pointer_stability.unlock();
454
455466 if (@sizeOf(T) == 0) {
456467 self.capacity = math.maxInt(usize);
457468 return;
458469 }
459470
460471 if (self.capacity >= new_capacity) return;
461
472 self.pointer_stability.assertUnlocked();
462473 // Here we avoid copying allocated but unused bytes by
463 // attempting a resize in place, and falling back to allocating
474 // attempting a remap, and falling back to allocating
464475 // a new buffer and doing our own copy. With a realloc() call,
465476 // the allocator implementation would pointlessly copy our
466477 // extra capacity.
......@@ -491,7 +502,8 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
491502 }
492503
493504 /// Increase length by 1, returning pointer to the new item.
494 /// The returned pointer becomes invalid when the list resized.
505 /// Invalidates element pointers if additional memory is needed.
506 /// The returned pointer may be invalidated by further operations to this list.
495507 pub fn addOne(self: *Self) Allocator.Error!*T {
496508 // This can never overflow because `self.items` can never occupy the whole address space
497509 const newlen = self.items.len + 1;
......@@ -500,7 +512,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
500512 }
501513
502514 /// Increase length by 1, returning pointer to the new item.
503 /// The returned pointer becomes invalid when the list is resized.
515 /// The returned pointer may be invalidated by further operations to this list.
504516 /// Never invalidates element pointers.
505517 /// Asserts that the list can hold one additional item.
506518 pub fn addOneAssumeCapacity(self: *Self) *T {
......@@ -511,8 +523,9 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
511523
512524 /// Resize the array, adding `n` new elements, which have `undefined` values.
513525 /// The return value is an array pointing to the newly allocated elements.
514 /// The returned pointer becomes invalid when the list is resized.
526 /// The returned pointer may be invalidated by further operations to this list.
515527 /// Resizes list if `self.capacity` is not large enough.
528 /// Invalidates element pointers if additional memory is needed.
516529 pub fn addManyAsArray(self: *Self, comptime n: usize) Allocator.Error!*[n]T {
517530 const prev_len = self.items.len;
518531 try self.resize(try addOrOom(self.items.len, n));
......@@ -522,7 +535,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
522535 /// Resize the array, adding `n` new elements, which have `undefined` values.
523536 /// The return value is an array pointing to the newly allocated elements.
524537 /// Never invalidates element pointers.
525 /// The returned pointer becomes invalid when the list is resized.
538 /// The returned pointer may be invalidated by further operations to this list.
526539 /// Asserts that the list can hold the additional items.
527540 pub fn addManyAsArrayAssumeCapacity(self: *Self, comptime n: usize) *[n]T {
528541 assert(self.items.len + n <= self.capacity);
......@@ -533,8 +546,9 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
533546
534547 /// Resize the array, adding `n` new elements, which have `undefined` values.
535548 /// The return value is a slice pointing to the newly allocated elements.
536 /// The returned pointer becomes invalid when the list is resized.
549 /// The returned pointer may be invalidated by further operations to this list.
537550 /// Resizes list if `self.capacity` is not large enough.
551 /// Invalidates element pointers if additional memory is needed.
538552 pub fn addManyAsSlice(self: *Self, n: usize) Allocator.Error![]T {
539553 const prev_len = self.items.len;
540554 try self.resize(try addOrOom(self.items.len, n));
......@@ -544,7 +558,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
544558 /// Resize the array, adding `n` new elements, which have `undefined` values.
545559 /// The return value is a slice pointing to the newly allocated elements.
546560 /// Never invalidates element pointers.
547 /// The returned pointer becomes invalid when the list is resized.
561 /// The returned pointer may be invalidated by further operations to this list.
548562 /// Asserts that the list can hold the additional items.
549563 pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T {
550564 assert(self.items.len + n <= self.capacity);
......@@ -554,11 +568,10 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
554568 }
555569
556570 /// Remove and return the last element from the list, or return `null` if list is empty.
557 /// Invalidates element pointers to the removed element, if any.
571 /// Invalidates element pointers to the removed element.
558572 pub fn pop(self: *Self) ?T {
559573 if (self.items.len == 0) return null;
560 self.pointer_stability.lock();
561 defer self.pointer_stability.unlock();
574 self.pointer_stability.assertUnlocked();
562575 const val = self.items[self.items.len - 1];
563576 self.items[self.items.len - 1] = undefined;
564577 self.items.len -= 1;
......@@ -567,6 +580,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
567580
568581 /// Returns a slice of all the items plus the extra capacity, whose memory
569582 /// contents are `undefined`.
583 /// The returned pointer may be invalidated by further operations to this list.
570584 pub fn allocatedSlice(self: Self) Slice {
571585 // `items.len` is the length, not the capacity.
572586 return self.items.ptr[0..self.capacity];
......@@ -576,18 +590,29 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
576590 /// This can be useful for writing directly into an ArrayList.
577591 /// Note that such an operation must be followed up with a direct
578592 /// modification of `self.items.len`.
593 /// The returned pointer may be invalidated by further operations to this list.
579594 pub fn unusedCapacitySlice(self: Self) []T {
580595 return self.allocatedSlice()[self.items.len..];
581596 }
582597
583 /// Deprecated in favor of `getLast`
584 pub const getLastOrNull = getLast;
598 /// Deprecated in favor of `last`
599 pub const getLastOrNull = last;
585600
586 /// Returns the last element from the list, or `null` if the list is empty.
587 pub fn getLast(self: Self) ?T {
601 /// Returns the last element from the list, or `null` if the list is
602 /// empty.
603 /// Never invalidates element pointers.
604 pub fn last(self: Self) ?T {
588605 if (self.items.len == 0) return null;
589606 return self.items[self.items.len - 1];
590607 }
608
609 /// Returns a pointer to the last element from the list, or `null` if
610 /// the list is empty.
611 /// The returned pointer may be invalidated by further operations to this list.
612 pub fn lastPtr(self: Self) ?*T {
613 if (self.items.len == 0) return null;
614 return &self.items[self.items.len - 1];
615 }
591616 };
592617}
593618
......@@ -613,20 +638,21 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
613638 ///
614639 /// Pointers to elements in this slice are invalidated by various
615640 /// functions of this ArrayList in accordance with the respective
616 /// documentation. In all cases, "invalidated" means that the memory
617 /// has been passed to an allocator's resize or free function.
641 /// documentation.
642 /// An invalidated pointer may point either to valid or freed memory.
618643 items: Slice,
619644 /// How many T values this list can hold without allocating
620645 /// additional memory.
621646 capacity: usize,
622647
623648 /// Used to detect memory safety violations.
624 pointer_stability: debug.SafetyLock = .{},
649 pointer_stability: debug.SafetyLock,
625650
626651 /// An ArrayList containing no elements.
627652 pub const empty: Self = .{
628653 .items = &.{},
629654 .capacity = 0,
655 .pointer_stability = .{},
630656 };
631657
632658 pub const Slice = if (alignment) |a| ([]align(a.toByteUnits()) T) else []T;
......@@ -652,6 +678,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
652678 return .{
653679 .items = buffer[0..0],
654680 .capacity = buffer.len,
681 .pointer_stability = .{},
655682 };
656683 }
657684
......@@ -682,7 +709,12 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
682709 /// Convert this list into an analogous memory-managed one.
683710 /// The returned list has ownership of the underlying memory.
684711 pub fn toManaged(self: *Self, gpa: Allocator) AlignedManaged(T, alignment) {
685 return .{ .items = self.items, .capacity = self.capacity, .allocator = gpa };
712 return .{
713 .items = self.items,
714 .capacity = self.capacity,
715 .allocator = gpa,
716 .pointer_stability = self.pointer_stability,
717 };
686718 }
687719
688720 /// ArrayList takes ownership of the passed in slice.
......@@ -691,6 +723,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
691723 return Self{
692724 .items = slice,
693725 .capacity = slice.len,
726 .pointer_stability = .{},
694727 };
695728 }
696729
......@@ -700,13 +733,16 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
700733 return Self{
701734 .items = slice,
702735 .capacity = slice.len + 1,
736 .pointer_stability = .{},
703737 };
704738 }
705739
706740 /// The caller owns the returned memory. Empties this ArrayList.
707741 /// Its capacity is cleared, making deinit() safe but unnecessary to call.
742 /// May invalidate element pointers.
708743 pub fn toOwnedSlice(self: *Self, gpa: Allocator) Allocator.Error!Slice {
709744 const old_memory = self.allocatedSlice();
745 self.pointer_stability.assertUnlocked();
710746 if (gpa.remap(old_memory, self.items.len)) |new_items| {
711747 self.* = .empty;
712748 return new_items;
......@@ -719,7 +755,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
719755 }
720756
721757 /// The caller owns the returned memory. ArrayList becomes empty.
758 /// May invalidate element pointers.
722759 pub fn toOwnedSliceSentinel(self: *Self, gpa: Allocator, comptime sentinel: T) Allocator.Error!SentinelSlice(sentinel) {
760 self.pointer_stability.assertUnlocked();
723761 // This addition can never overflow because `self.items` can never occupy the whole address space.
724762 try self.ensureTotalCapacityPrecise(gpa, self.items.len + 1);
725763 self.appendAssumeCapacity(sentinel);
......@@ -732,6 +770,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
732770 /// Its capacity is cleared, making deinit() safe but unnecessary to call.
733771 ///
734772 /// Asserts what the capacity is equal to the length.
773 /// Never invalidates element pointers.
735774 pub fn toOwnedSliceAssert(self: *Self) Slice {
736775 assert(self.items.len == self.capacity);
737776 const items = self.items;
......@@ -741,6 +780,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
741780
742781 /// The caller owns the returned memory. ArrayList becomes empty.
743782 /// Asserts what the capacity is equal to the length + 1.
783 /// Never invalidates element pointers.
744784 pub fn toOwnedSliceSentinelAssert(self: *Self, comptime sentinel: T) SentinelSlice(sentinel) {
745785 std.debug.assert(self.items.len + 1 == self.capacity);
746786 self.appendAssumeCapacity(sentinel);
......@@ -755,46 +795,41 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
755795 return cloned;
756796 }
757797
758 /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room.
759 /// If `i` is equal to the length of the list this operation is equivalent to append.
798 /// Insert `item` at index `index`. Moves `list[index .. list.len]` to higher indices to make room.
799 /// If `index` is equal to the length of the list this operation is equivalent to append.
760800 /// This operation is O(N).
761801 /// Invalidates element pointers if additional memory is needed.
802 /// Invalidates pre-existing pointers to elements at and after `index`.
762803 /// Asserts that the index is in bounds or equal to the length.
763 pub fn insert(self: *Self, gpa: Allocator, i: usize, item: T) Allocator.Error!void {
764 const dst = try self.addManyAt(gpa, i, 1);
804 pub fn insert(self: *Self, gpa: Allocator, index: usize, item: T) Allocator.Error!void {
805 self.pointer_stability.assertUnlocked();
806 const dst = try self.addManyAt(gpa, index, 1);
765807 dst[0] = item;
766808 }
767809
768 /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room.
769 ///
770 /// If `i` is equal to the length of the list this operation is equivalent to append.
771 ///
810 /// Insert `item` at index `index`. Moves `list[index .. list.len]` to higher indices to make room.
811 /// If `index` is equal to the length of the list this operation is
812 /// equivalent to appendAssumeCapacity.
772813 /// This operation is O(N).
773 ///
814 /// Invalidates pre-existing pointers to elements at and after `index`.
774815 /// Asserts that the list has capacity for one additional item.
775 ///
776816 /// Asserts that the index is in bounds or equal to the length.
777 pub fn insertAssumeCapacity(self: *Self, i: usize, item: T) void {
778 self.pointer_stability.lock();
779 defer self.pointer_stability.unlock();
780
817 pub fn insertAssumeCapacity(self: *Self, index: usize, item: T) void {
818 self.pointer_stability.assertUnlocked();
781819 assert(self.items.len < self.capacity);
782820 self.items.len += 1;
783
784 @memmove(self.items[i + 1 .. self.items.len], self.items[i .. self.items.len - 1]);
785 self.items[i] = item;
821 @memmove(self.items[index + 1 .. self.items.len], self.items[index .. self.items.len - 1]);
822 self.items[index] = item;
786823 }
787824
788 /// Insert `item` at index `i`, moving `list[i .. list.len]` to higher indices to make room.
789 ///
790 /// If `i` is equal to the length of the list this operation is equivalent to append.
791 ///
825 /// Insert `item` at index `index`. Moves `list[index .. list.len]` to higher indices to make room.
826 /// If `index` is equal to the length of the list this operation is
827 /// equivalent to appendAssumeCapacity.
792828 /// This operation is O(N).
793 ///
829 /// Invalidates pre-existing pointers to elements at and after `index`.
830 /// Asserts that the index is in bounds or equal to the length.
794831 /// If the list lacks unused capacity for the additional item, returns
795832 /// `error.OutOfMemory`.
796 ///
797 /// Asserts that the index is in bounds or equal to the length.
798833 pub fn insertBounded(self: *Self, i: usize, item: T) error{OutOfMemory}!void {
799834 if (self.capacity - self.items.len == 0) return error.OutOfMemory;
800835 return insertAssumeCapacity(self, i, item);
......@@ -814,21 +849,48 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
814849 index: usize,
815850 count: usize,
816851 ) Allocator.Error![]T {
817 var managed = self.toManaged(gpa);
818 defer self.* = managed.moveToUnmanaged();
819 return managed.addManyAt(index, count);
852 const new_len = try addOrOom(self.items.len, count);
853 self.pointer_stability.assertUnlocked();
854
855 if (self.capacity >= new_len)
856 return addManyAtAssumeCapacity(self, index, count);
857
858 // Here we avoid copying allocated but unused bytes by
859 // attempting a resize in place, and falling back to allocating
860 // a new buffer and doing our own copy. With a realloc() call,
861 // the allocator implementation would pointlessly copy our
862 // extra capacity.
863 const new_capacity = Aligned(T, alignment).growCapacity(new_len);
864 const old_memory = self.allocatedSlice();
865 if (gpa.remap(old_memory, new_capacity)) |new_memory| {
866 self.items.ptr = new_memory.ptr;
867 self.capacity = new_memory.len;
868 return addManyAtAssumeCapacity(self, index, count);
869 }
870
871 // Make a new allocation, avoiding `ensureTotalCapacity` in order
872 // to avoid extra memory copies.
873 const new_memory = try gpa.alignedAlloc(T, alignment, new_capacity);
874 const to_move = self.items[index..];
875 @memcpy(new_memory[0..index], self.items[0..index]);
876 @memcpy(new_memory[index + count ..][0..to_move.len], to_move);
877 gpa.free(old_memory);
878 self.items = new_memory[0..new_len];
879 self.capacity = new_memory.len;
880 // The inserted elements at `new_memory[index..][0..count]` have
881 // already been set to `undefined` by memory allocation.
882 return new_memory[index..][0..count];
820883 }
821884
822885 /// Add `count` new elements at position `index`, which have
823886 /// `undefined` values. Returns a slice pointing to the newly allocated
824887 /// elements, which becomes invalid after various `ArrayList`
825888 /// operations.
889 /// Invalidates pre-existing pointers to elements at and after `index`.
826890 /// Asserts that the list has capacity for the additional items.
827891 /// Asserts that the index is in bounds or equal to the length.
828892 pub fn addManyAtAssumeCapacity(self: *Self, index: usize, count: usize) []T {
829 self.pointer_stability.lock();
830 defer self.pointer_stability.unlock();
831
893 self.pointer_stability.assertUnlocked();
832894 const new_len = self.items.len + count;
833895 assert(self.capacity >= new_len);
834896 const to_move = self.items[index..];
......@@ -843,17 +905,16 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
843905 /// `undefined` values, returning a slice pointing to the newly
844906 /// allocated elements, which becomes invalid after various `ArrayList`
845907 /// operations.
846 ///
908 /// Invalidates pre-existing pointers to elements at and after `index`.
847909 /// If the list lacks unused capacity for the additional items, returns
848910 /// `error.OutOfMemory`.
849 ///
850911 /// Asserts that the index is in bounds or equal to the length.
851912 pub fn addManyAtBounded(self: *Self, index: usize, count: usize) error{OutOfMemory}![]T {
852913 if (self.capacity - self.items.len < count) return error.OutOfMemory;
853914 return addManyAtAssumeCapacity(self, index, count);
854915 }
855916
856 /// Insert slice `items` at index `i` by moving `list[i .. list.len]` to make room.
917 /// Insert slice `items` at index `index` by moving `list[index .. list.len]` to make room.
857918 /// This operation is O(N).
858919 /// Invalidates pre-existing pointers to elements at and after `index`.
859920 /// Invalidates all pre-existing element pointers if capacity must be
......@@ -873,7 +934,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
873934 @memcpy(dst, items);
874935 }
875936
876 /// Insert slice `items` at index `i` by moving `list[i .. list.len]` to make room.
937 /// Insert slice `items` at index `index` by moving `list[index .. list.len]` to make room.
877938 /// This operation is O(N).
878939 /// Invalidates pre-existing pointers to elements at and after `index`.
879940 /// Asserts that the list has capacity for the additional items.
......@@ -887,7 +948,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
887948 @memcpy(dst, items);
888949 }
889950
890 /// Insert slice `items` at index `i` by moving `list[i .. list.len]` to make room.
951 /// Insert slice `items` at index `index` by moving `list[index .. list.len]` to make room.
891952 /// This operation is O(N).
892953 /// Invalidates pre-existing pointers to elements at and after `index`.
893954 /// If the list lacks unused capacity for the additional items, returns
......@@ -903,7 +964,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
903964 }
904965
905966 /// Grows or shrinks the list as necessary.
906 /// Invalidates element pointers if additional capacity is allocated.
967 /// Invalidates element pointers if additional capacity is allocated,
968 /// Invalidates pointers to elements at and above index `start + len`
969 /// when `len` and `new_items.len` are unequal.
907970 /// Asserts that the range is in bounds.
908971 pub fn replaceRange(
909972 self: *Self,
......@@ -917,9 +980,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
917980 }
918981
919982 /// Grows or shrinks the list as necessary.
920 ///
921 /// Never invalidates element pointers.
922 ///
983 /// Invalidates pointers to elements at and above index `start + len`
984 /// when `len` and `new_items.len` are unequal.
923985 /// Asserts the capacity is enough for additional items.
924986 pub fn replaceRangeAssumeCapacity(
925987 self: *Self,
......@@ -928,7 +990,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
928990 new_items: []const T,
929991 ) void {
930992 std.debug.assert(self.capacity - self.items.len >= new_items.len -| len);
931
993 self.pointer_stability.assertUnlocked();
932994 const tail = self.items[start + len ..];
933995 const vacated = self.items[self.items.len - (len -| new_items.len) ..];
934996 self.items.len = self.items.len - len + new_items.len;
......@@ -937,10 +999,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
937999 @memset(vacated, undefined);
9381000 }
9391001
940 /// Grows or shrinks the list as necessary.
941 ///
942 /// Never invalidates element pointers.
943 ///
1002 /// Invalidates pointers to elements at and above index `start + len`
1003 /// when `len` and `new_items.len` are unequal.
9441004 /// If the unused capacity is insufficient for additional items,
9451005 /// returns `error.OutOfMemory`.
9461006 pub fn replaceRangeBounded(
......@@ -1003,6 +1063,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
10031063 ///
10041064 /// Invalidates element pointers beyond the first deleted index.
10051065 pub fn orderedRemoveMany(self: *Self, sorted_indexes: []const usize) void {
1066 self.pointer_stability.assertUnlocked();
10061067 if (sorted_indexes.len == 0) return;
10071068 var shift: usize = 1;
10081069 for (sorted_indexes[0 .. sorted_indexes.len - 1], sorted_indexes[1..]) |removed, end| {
......@@ -1025,8 +1086,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
10251086 /// This operation is O(1).
10261087 /// Asserts that the index is in bounds.
10271088 pub fn swapRemove(self: *Self, i: usize) T {
1028 self.pointer_stability.lock();
1029 defer self.pointer_stability.unlock();
1089 self.pointer_stability.assertUnlocked();
10301090 const val = self.items[i];
10311091 self.items[i] = self.items[self.items.len - 1];
10321092 self.items[self.items.len - 1] = undefined;
......@@ -1043,7 +1103,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
10431103 }
10441104
10451105 /// Append the slice of items to the list.
1046 ///
1106 /// Never invalidates element pointers.
10471107 /// Asserts that the list can hold the additional items.
10481108 pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void {
10491109 const old_len = self.items.len;
......@@ -1054,7 +1114,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
10541114 }
10551115
10561116 /// Append the slice of items to the list.
1057 ///
1117 /// Never invalidates element pointers.
10581118 /// If the list lacks unused capacity for the additional items, returns `error.OutOfMemory`.
10591119 pub fn appendSliceBounded(self: *Self, items: []const T) error{OutOfMemory}!void {
10601120 if (self.capacity - self.items.len < items.len) return error.OutOfMemory;
......@@ -1074,7 +1134,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
10741134 ///
10751135 /// Intended to be used only when `appendSliceAssumeCapacity` would be
10761136 /// a compile error.
1077 ///
1137 /// Never invalidates element pointers.
10781138 /// Asserts that the list can hold the additional items.
10791139 pub fn appendUnalignedSliceAssumeCapacity(self: *Self, items: []align(1) const T) void {
10801140 const old_len = self.items.len;
......@@ -1088,7 +1148,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
10881148 ///
10891149 /// Intended to be used only when `appendSliceAssumeCapacity` would be
10901150 /// a compile error.
1091 ///
1151 /// Never invalidates element pointers.
10921152 /// If the list lacks unused capacity for the additional items, returns
10931153 /// `error.OutOfMemory`.
10941154 pub fn appendUnalignedSliceBounded(self: *Self, items: []align(1) const T) error{OutOfMemory}!void {
......@@ -1096,6 +1156,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
10961156 return appendUnalignedSliceAssumeCapacity(self, items);
10971157 }
10981158
1159 /// Prints a formatted string into this list.
1160 /// Invalidates element pointers if additional memory is needed.
10991161 pub fn print(self: *Self, gpa: Allocator, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void {
11001162 comptime assert(T == u8);
11011163 try self.ensureUnusedCapacity(gpa, fmt.len);
......@@ -1106,6 +1168,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
11061168 };
11071169 }
11081170
1171 /// Prints a formatted string into this list.
1172 /// Asserts that there is enough capacity for the write.
1173 /// Never invalidates element pointers.
11091174 pub fn printAssumeCapacity(self: *Self, comptime fmt: []const u8, args: anytype) void {
11101175 comptime assert(T == u8);
11111176 var w: std.Io.Writer = .fixed(self.unusedCapacitySlice());
......@@ -1113,6 +1178,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
11131178 self.items.len += w.end;
11141179 }
11151180
1181 /// Prints a formatted string into this list.
1182 /// Returns error.OutOfMemory if additional capacity is needed for the write.
1183 /// Never invalidates element pointers.
11161184 pub fn printBounded(self: *Self, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void {
11171185 comptime assert(T == u8);
11181186 var w: std.Io.Writer = .fixed(self.unusedCapacitySlice());
......@@ -1188,8 +1256,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
11881256 /// Asserts that the new length is less than or equal to the previous length.
11891257 /// If succeds capacity is guaranteed to be equal to the length.
11901258 pub fn shrinkAndFreePrecise(self: *Self, gpa: Allocator, new_len: usize) Allocator.Error!void {
1191 self.pointer_stability.lock();
1192 defer self.pointer_stability.unlock();
1259 self.pointer_stability.assertUnlocked();
11931260 assert(new_len <= self.items.len);
11941261
11951262 if (@sizeOf(T) == 0) {
......@@ -1243,8 +1310,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
12431310 /// Keeps capacity the same.
12441311 /// Asserts that the new length is less than or equal to the previous length.
12451312 pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void {
1246 self.pointer_stability.lock();
1247 defer self.pointer_stability.unlock();
1313 self.pointer_stability.assertUnlocked();
12481314
12491315 assert(new_len <= self.items.len);
12501316 @memset(self.items[new_len..], undefined);
......@@ -1254,16 +1320,14 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
12541320 /// Reduce length to 0.
12551321 /// Invalidates all element pointers.
12561322 pub fn clearRetainingCapacity(self: *Self) void {
1257 self.pointer_stability.lock();
1258 defer self.pointer_stability.unlock();
1323 self.pointer_stability.assertUnlocked();
12591324 @memset(self.items, undefined);
12601325 self.items.len = 0;
12611326 }
12621327
12631328 /// Invalidates all element pointers.
12641329 pub fn clearAndFree(self: *Self, gpa: Allocator) void {
1265 self.pointer_stability.lock();
1266 defer self.pointer_stability.unlock();
1330 self.pointer_stability.assertUnlocked();
12671331 gpa.free(self.allocatedSlice());
12681332 self.items.len = 0;
12691333 self.capacity = 0;
......@@ -1281,8 +1345,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
12811345 /// modify the array so that it can hold exactly `new_capacity` items.
12821346 /// Invalidates element pointers if additional memory is needed.
12831347 pub fn ensureTotalCapacityPrecise(self: *Self, gpa: Allocator, new_capacity: usize) Allocator.Error!void {
1284 self.pointer_stability.lock();
1285 defer self.pointer_stability.unlock();
1348 self.pointer_stability.assertUnlocked();
12861349
12871350 if (@sizeOf(T) == 0) {
12881351 self.capacity = math.maxInt(usize);
......@@ -1327,7 +1390,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
13271390 }
13281391
13291392 /// Increase length by 1, returning pointer to the new item.
1330 /// The returned element pointer becomes invalid when the list is resized.
1393 /// Invalidates element pointers if additional memory is needed.
1394 /// The returned pointer may be invalidated by further operations to this list.
13311395 pub fn addOne(self: *Self, gpa: Allocator) Allocator.Error!*T {
13321396 // This can never overflow because `self.items` can never occupy the whole address space
13331397 const newlen = self.items.len + 1;
......@@ -1336,11 +1400,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
13361400 }
13371401
13381402 /// Increase length by 1, returning pointer to the new item.
1339 ///
13401403 /// Never invalidates element pointers.
1341 ///
1342 /// The returned element pointer becomes invalid when the list is resized.
1343 ///
1404 /// The returned pointer may be invalidated by further operations to this list.
13441405 /// Asserts that the list can hold one additional item.
13451406 pub fn addOneAssumeCapacity(self: *Self) *T {
13461407 assert(self.items.len < self.capacity);
......@@ -1350,11 +1411,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
13501411 }
13511412
13521413 /// Increase length by 1, returning pointer to the new item.
1353 ///
13541414 /// Never invalidates element pointers.
1355 ///
1356 /// The returned element pointer becomes invalid when the list is resized.
1357 ///
1415 /// The returned pointer may be invalidated by further operations to this list.
13581416 /// If the list lacks unused capacity for the additional item, returns `error.OutOfMemory`.
13591417 pub fn addOneBounded(self: *Self) error{OutOfMemory}!*T {
13601418 if (self.capacity - self.items.len < 1) return error.OutOfMemory;
......@@ -1362,8 +1420,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
13621420 }
13631421
13641422 /// Resize the array, adding `n` new elements, which have `undefined` values.
1423 /// Invalidates element pointers if additional memory is required.
13651424 /// The return value is an array pointing to the newly allocated elements.
1366 /// The returned pointer becomes invalid when the list is resized.
1425 /// The returned pointer may be invalidated by further operations to this list.
13671426 pub fn addManyAsArray(self: *Self, gpa: Allocator, comptime n: usize) Allocator.Error!*[n]T {
13681427 const prev_len = self.items.len;
13691428 try self.resize(gpa, try addOrOom(self.items.len, n));
......@@ -1371,13 +1430,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
13711430 }
13721431
13731432 /// Resize the array, adding `n` new elements, which have `undefined` values.
1374 ///
13751433 /// The return value is an array pointing to the newly allocated elements.
1376 ///
13771434 /// Never invalidates element pointers.
1378 ///
1379 /// The returned pointer becomes invalid when the list is resized.
1380 ///
1435 /// The returned pointer may be invalidated by further operations to this list.
13811436 /// Asserts that the list can hold the additional items.
13821437 pub fn addManyAsArrayAssumeCapacity(self: *Self, comptime n: usize) *[n]T {
13831438 assert(self.items.len + n <= self.capacity);
......@@ -1387,13 +1442,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
13871442 }
13881443
13891444 /// Resize the array, adding `n` new elements, which have `undefined` values.
1390 ///
13911445 /// The return value is an array pointing to the newly allocated elements.
1392 ///
13931446 /// Never invalidates element pointers.
1394 ///
1395 /// The returned pointer becomes invalid when the list is resized.
1396 ///
1447 /// The returned pointer may be invalidated by further operations to this list.
13971448 /// If the list lacks unused capacity for the additional items, returns
13981449 /// `error.OutOfMemory`.
13991450 pub fn addManyAsArrayBounded(self: *Self, comptime n: usize) error{OutOfMemory}!*[n]T {
......@@ -1403,7 +1454,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
14031454
14041455 /// Resize the array, adding `n` new elements, which have `undefined` values.
14051456 /// The return value is a slice pointing to the newly allocated elements.
1406 /// The returned pointer becomes invalid when the list is resized.
1457 /// The returned pointer may be invalidated by further operations to this list.
14071458 /// Resizes list if `self.capacity` is not large enough.
14081459 pub fn addManyAsSlice(self: *Self, gpa: Allocator, n: usize) Allocator.Error![]T {
14091460 const prev_len = self.items.len;
......@@ -1413,10 +1464,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
14131464
14141465 /// Resizes the array, adding `n` new elements, which have `undefined`
14151466 /// values, returning a slice pointing to the newly allocated elements.
1416 ///
1417 /// Never invalidates element pointers. The returned pointer becomes
1418 /// invalid when the list is resized.
1419 ///
1467 /// Never invalidates element pointers.
1468 /// The returned pointer may be invalidated by further operations to this list.
14201469 /// Asserts that the list can hold the additional items.
14211470 pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T {
14221471 assert(self.items.len + n <= self.capacity);
......@@ -1427,10 +1476,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
14271476
14281477 /// Resizes the array, adding `n` new elements, which have `undefined`
14291478 /// values, returning a slice pointing to the newly allocated elements.
1430 ///
1431 /// Never invalidates element pointers. The returned pointer becomes
1432 /// invalid when the list is resized.
1433 ///
1479 /// Never invalidates element pointers.
1480 /// The returned pointer may be invalidated by further operations to this list.
14341481 /// If the list lacks unused capacity for the additional items, returns
14351482 /// `error.OutOfMemory`.
14361483 pub fn addManyAsSliceBounded(self: *Self, n: usize) error{OutOfMemory}![]T {
......@@ -1443,8 +1490,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
14431490 /// Invalidates pointers to last element.
14441491 pub fn pop(self: *Self) ?T {
14451492 if (self.items.len == 0) return null;
1446 self.pointer_stability.lock();
1447 defer self.pointer_stability.unlock();
1493 self.pointer_stability.assertUnlocked();
14481494
14491495 const val = self.items[self.items.len - 1];
14501496 self.items[self.items.len - 1] = undefined;
......@@ -1454,6 +1500,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
14541500
14551501 /// Returns a slice of all the items plus the extra capacity, whose memory
14561502 /// contents are `undefined`.
1503 /// The returned pointer may be invalidated by further operations to this list.
14571504 pub fn allocatedSlice(self: Self) Slice {
14581505 return self.items.ptr[0..self.capacity];
14591506 }
......@@ -1462,19 +1509,22 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
14621509 /// This can be useful for writing directly into an ArrayList.
14631510 /// Note that such an operation must be followed up with a direct
14641511 /// modification of `self.items.len`.
1512 /// The returned pointer may be invalidated by further operations to this list.
14651513 pub fn unusedCapacitySlice(self: Self) []T {
14661514 return self.allocatedSlice()[self.items.len..];
14671515 }
14681516
1469 /// Deprecated in favor of `last`.
1470 pub fn getLast(self: Self) ?T {
1517 /// Returns the last element from the list, or `null` if the list is
1518 /// empty.
1519 pub fn last(self: Self) ?T {
14711520 if (self.items.len == 0) return null;
14721521 return self.items[self.items.len - 1];
14731522 }
14741523
14751524 /// Returns a pointer to the last element from the list, or `null` if
14761525 /// the list is empty.
1477 pub fn last(self: Self) ?*T {
1526 /// The returned pointer may be invalidated by further operations to this list.
1527 pub fn lastPtr(self: Self) ?*T {
14781528 if (self.items.len == 0) return null;
14791529 return &self.items[self.items.len - 1];
14801530 }
......@@ -2441,6 +2491,10 @@ test "Managed(u0)" {
24412491 count += 1;
24422492 }
24432493 try testing.expectEqual(count, 3);
2494
2495 const ownedSlice = try list.toOwnedSlice();
2496 defer a.free(ownedSlice);
2497 try testing.expectEqualSlices(u0, ownedSlice, &.{ 0, 0, 0 });
24442498}
24452499
24462500test "Managed(?u32).pop()" {
......@@ -2469,7 +2523,7 @@ test "last" {
24692523 try testing.expectEqual(list.last(), null);
24702524
24712525 try list.append(a, 2);
2472 try testing.expectEqual(list.last().?.*, 2);
2526 try testing.expectEqual(list.last().?, 2);
24732527}
24742528
24752529test "return OutOfMemory when capacity would exceed maximum usize integer value" {
......@@ -2481,6 +2535,7 @@ test "return OutOfMemory when capacity would exceed maximum usize integer value"
24812535 var list: ArrayList(u32) = .{
24822536 .items = undefined,
24832537 .capacity = math.maxInt(usize) - 1,
2538 .pointer_stability = .{},
24842539 };
24852540 list.items.len = math.maxInt(usize) - 1;
24862541
......@@ -2499,6 +2554,7 @@ test "return OutOfMemory when capacity would exceed maximum usize integer value"
24992554 .items = undefined,
25002555 .capacity = math.maxInt(usize) - 1,
25012556 .allocator = a,
2557 .pointer_stability = .{},
25022558 };
25032559 list.items.len = math.maxInt(usize) - 1;
25042560
lib/std/ascii.zig+3-3
......@@ -511,11 +511,11 @@ pub const HexEscape = struct {
511511};
512512
513513/// Replaces non-ASCII bytes with hex escapes.
514pub fn hexEscape(bytes: []const u8, case: std.fmt.Case) std.fmt.Alt(HexEscape, HexEscape.format) {
515 return .{ .data = .{ .bytes = bytes, .charset = switch (case) {
514pub fn hexEscape(bytes: []const u8, case: std.fmt.Case) HexEscape {
515 return .{ .bytes = bytes, .charset = switch (case) {
516516 .lower => HexEscape.lower_charset,
517517 .upper => HexEscape.upper_charset,
518 } } };
518 } };
519519}
520520
521521test hexEscape {
lib/std/bit_set.zig-2
......@@ -1707,8 +1707,6 @@ fn testStaticBitSet(comptime Set: type) !void {
17071707}
17081708
17091709test Integer {
1710 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1711
17121710 try testStaticBitSet(Integer(0));
17131711 try testStaticBitSet(Integer(1));
17141712 try testStaticBitSet(Integer(2));
lib/std/c.zig+52-22
......@@ -2821,13 +2821,14 @@ pub const SIG = switch (native_os) {
28212821 }
28222822
28232823 pub const POLL: SIG = .IO;
2824 pub const IOT: SIG = .ABRT;
2825 pub const CLD: SIG = .CHLD;
28242826
28252827 HUP = 1,
28262828 INT = 2,
28272829 QUIT = 3,
28282830 ILL = 4,
28292831 TRAP = 5,
2830 IOT = 6,
28312832 ABRT = 6,
28322833 EMT = 7,
28332834 FPE = 8,
......@@ -2840,7 +2841,6 @@ pub const SIG = switch (native_os) {
28402841 TERM = 15,
28412842 USR1 = 16,
28422843 USR2 = 17,
2843 CLD = 18,
28442844 CHLD = 18,
28452845 PWR = 19,
28462846 WINCH = 20,
......@@ -2991,6 +2991,7 @@ pub const SIG = switch (native_os) {
29912991 pub const UNBLOCK = 2;
29922992 pub const SETMASK = 3;
29932993
2994 pub const IO: SIG = .POLL;
29942995 pub const IOT: SIG = .ABRT;
29952996
29962997 HUP = 1,
......@@ -9736,6 +9737,7 @@ pub const SS = switch (native_os) {
97369737
97379738pub const EV = switch (native_os) {
97389739 .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => struct {
9740 // https://github.com/apple-oss-distributions/xnu/blob/main/bsd/sys/event.h
97399741 /// add event to kq (implies enable)
97409742 pub const ADD = 0x0001;
97419743 /// delete event from kq
......@@ -9771,11 +9773,14 @@ pub const EV = switch (native_os) {
97719773 pub const FLAG0 = 0x1000;
97729774 /// filter-specific flag
97739775 pub const FLAG1 = 0x2000;
9774 /// EOF detected
9776 /// EOF detected (return value)
97759777 pub const EOF = 0x8000;
9776 /// error, data contains errno
9778 /// error, data contains errno (return value)
97779779 pub const ERROR = 0x4000;
9780 /// use poll(2) semantics for EVFILT.READ
97789781 pub const POLL = FLAG0;
9782 /// on input, filter should actively return in the presence of OOB on the descriptor
9783 /// on output, indicates the presence of OOB data on the descriptor
97799784 pub const OOBAND = FLAG1;
97809785 },
97819786 .dragonfly => struct {
......@@ -9818,6 +9823,7 @@ pub const EV = switch (native_os) {
98189823 pub const EOF = 0x8000;
98199824 },
98209825 .freebsd => struct {
9826 // https://cgit.freebsd.org/src/tree/sys/sys/event.h
98219827 /// add event to kq (implies enable)
98229828 pub const ADD = 0x0001;
98239829 /// delete event from kq
......@@ -9826,12 +9832,14 @@ pub const EV = switch (native_os) {
98269832 pub const ENABLE = 0x0004;
98279833 /// disable event (not reported)
98289834 pub const DISABLE = 0x0008;
9835 /// enable _ONESHOT and force trigger
9836 pub const FORCEONESHOT = 0x0100;
9837 /// do not update the udata field
9838 pub const KEEPUDATA = 0x0200;
98299839 /// only report one occurrence
98309840 pub const ONESHOT = 0x0010;
98319841 /// clear event state after reporting
98329842 pub const CLEAR = 0x0020;
9833 /// error, event data contains errno
9834 pub const ERROR = 0x4000;
98359843 /// force immediate event output
98369844 /// ... with or without ERROR
98379845 /// ... use KEVENT_FLAG_ERROR_EVENTS
......@@ -9839,6 +9847,18 @@ pub const EV = switch (native_os) {
98399847 pub const RECEIPT = 0x0040;
98409848 /// disable event after reporting
98419849 pub const DISPATCH = 0x0080;
9850 /// reserved by system
9851 pub const SYSFLAGS = 0xF000;
9852 /// note should be dropped
9853 pub const DROP = 0x1000;
9854 /// filter-specific flag 1
9855 pub const FLAG1 = 0x2000;
9856 /// filter-specific flag 2
9857 pub const FLAG2 = 0x4000;
9858 /// EOF detected (return value)
9859 pub const EOF = 0x8000;
9860 /// error, event data contains errno (return value)
9861 pub const ERROR = 0x4000;
98429862 },
98439863 .openbsd => struct {
98449864 pub const ADD = 0x0001;
......@@ -9962,6 +9982,7 @@ pub const EVFILT = switch (native_os) {
99629982 pub const EMPTY = 9;
99639983 },
99649984 .freebsd => struct {
9985 // https://cgit.freebsd.org/src/tree/sys/sys/event.h
99659986 pub const READ = -1;
99669987 pub const WRITE = -2;
99679988 /// attached to aio requests
......@@ -9978,12 +9999,18 @@ pub const EVFILT = switch (native_os) {
99789999 pub const PROCDESC = -8;
997910000 /// Filesystem events
998010001 pub const FS = -9;
10002 /// attached to lio requests
998110003 pub const LIO = -10;
998210004 /// User events
998310005 pub const USER = -11;
998410006 /// Sendfile events
998510007 pub const SENDFILE = -12;
10008 /// empty send socket buf
998610009 pub const EMPTY = -13;
10010 /// attached to struct prison
10011 pub const JAIL = -14;
10012 /// attached to jail descriptors
10013 pub const JAILDESC = -15;
998710014 },
998810015 .openbsd => struct {
998910016 pub const READ = -1;
......@@ -10002,6 +10029,7 @@ pub const EVFILT = switch (native_os) {
1000210029
1000310030pub const NOTE = switch (native_os) {
1000410031 .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => struct {
10032 // https://github.com/apple-oss-distributions/xnu/blob/main/bsd/sys/event.h
1000510033 /// On input, TRIGGER causes the event to be triggered for output.
1000610034 pub const TRIGGER = 0x01000000;
1000710035 /// ignore input fflags
......@@ -10033,7 +10061,7 @@ pub const NOTE = switch (native_os) {
1003310061 pub const RENAME = 0x00000020;
1003410062 /// vnode access was revoked
1003510063 pub const REVOKE = 0x00000040;
10036 /// No specific vnode event: to test for EVFILT_READ activation
10064 /// No specific vnode event: to test for EVFILT_READ activation
1003710065 pub const NONE = 0x00000080;
1003810066 /// vnode was unlocked by flock(2)
1003910067 pub const FUNLOCK = 0x00000100;
......@@ -10045,7 +10073,7 @@ pub const NOTE = switch (native_os) {
1004510073 pub const EXEC = 0x20000000;
1004610074 /// shared with EVFILT_SIGNAL
1004710075 pub const SIGNAL = 0x08000000;
10048 /// exit status to be returned, valid for child process only
10076 /// exit status to be returned, valid for child process only
1004910077 pub const EXITSTATUS = 0x04000000;
1005010078 /// provide details on reasons for exit
1005110079 pub const EXIT_DETAIL = 0x02000000;
......@@ -10056,11 +10084,11 @@ pub const NOTE = switch (native_os) {
1005610084 pub const EXIT_DECRYPTFAIL = 0x00010000;
1005710085 pub const EXIT_MEMORY = 0x00020000;
1005810086 pub const EXIT_CSERROR = 0x00040000;
10059 /// will react on memory pressure
10087 /// will react on memory pressure
1006010088 pub const VM_PRESSURE = 0x80000000;
10061 /// will quit on memory pressure, possibly after cleaning up dirty state
10089 /// will quit on memory pressure, possibly after cleaning up dirty state
1006210090 pub const VM_PRESSURE_TERMINATE = 0x40000000;
10063 /// will quit immediately on memory pressure
10091 /// will quit immediately on memory pressure
1006410092 pub const VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000;
1006510093 /// there was an error
1006610094 pub const VM_ERROR = 0x10000000;
......@@ -10078,6 +10106,9 @@ pub const NOTE = switch (native_os) {
1007810106 pub const CRITICAL = 0x00000020;
1007910107 /// system does maximum timer coalescing
1008010108 pub const BACKGROUND = 0x00000040;
10109 /// with ABSOLUTE: causes the timer to continue to tick across sleep, still uses gettimeofday epoch
10110 /// with MACHTIME and ABSOLUTE: uses mach continuous time epoch
10111 /// without ABSOLUTE: continues to tick across sleep
1008110112 pub const MACH_CONTINUOUS_TIME = 0x00000080;
1008210113 /// data is mach absolute time units
1008310114 pub const MACHTIME = 0x00000100;
......@@ -11237,31 +11268,30 @@ pub const signalfd_siginfo = illumos.signalfd_siginfo;
1123711268pub const taskid_t = illumos.taskid_t;
1123811269pub const zoneid_t = illumos.zoneid_t;
1123911270
11271pub const B_ABSOLUTE_TIMEOUT = haiku.B_ABSOLUTE_TIMEOUT;
11272pub const B_OS_NAME_LENGTH = haiku.B_OS_NAME_LENGTH;
11273pub const B_TIMEOUT_REAL_TIME_BASE = haiku.B_TIMEOUT_REAL_TIME_BASE;
1124011274pub const DirEnt = haiku.DirEnt;
11241pub const _get_next_area_info = haiku._get_next_area_info;
11242pub const _get_next_image_info = haiku._get_next_image_info;
11243pub const _get_team_info = haiku._get_team_info;
11244pub const _kern_get_current_team = haiku._kern_get_current_team;
11275pub const _kern_acquire_sem_etc = haiku._kern_acquire_sem_etc;
11276pub const _kern_create_sem = haiku._kern_create_sem;
11277pub const _kern_delete_sem = haiku._kern_delete_sem;
1124511278pub const _kern_open_dir = haiku._kern_open_dir;
1124611279pub const _kern_read_dir = haiku._kern_read_dir;
1124711280pub const _kern_read_stat = haiku._kern_read_stat;
11281pub const _kern_release_sem_etc = haiku._kern_release_sem_etc;
1124811282pub const _kern_rewind_dir = haiku._kern_rewind_dir;
11249pub const readv_pos = haiku.readv_pos;
11250pub const writev_pos = haiku.writev_pos;
1125111283pub const area_id = haiku.area_id;
11252pub const area_info = haiku.area_info;
11253pub const directory_which = haiku.directory_which;
11254pub const find_directory = haiku.find_directory;
1125511284pub const find_thread = haiku.find_thread;
1125611285pub const get_system_info = haiku.get_system_info;
11257pub const image_info = haiku.image_info;
11286pub const on_exit_thread = haiku.on_exit_thread;
1125811287pub const port_id = haiku.port_id;
11288pub const readv_pos = haiku.readv_pos;
1125911289pub const sem_id = haiku.sem_id;
1126011290pub const status_t = haiku.status_t;
1126111291pub const system_info = haiku.system_info;
1126211292pub const team_id = haiku.team_id;
11263pub const team_info = haiku.team_info;
1126411293pub const thread_id = haiku.thread_id;
11294pub const writev_pos = haiku.writev_pos;
1126511295
1126611296pub const AUTH = openbsd.AUTH;
1126711297pub const BI = openbsd.BI;
lib/std/c/darwin/dispatch.zig+2-2
......@@ -44,8 +44,8 @@ pub const once_t = enum(isize) {
4444 once_f(predicate, context, function);
4545 } else asm volatile ("" ::: .{ .memory = true });
4646 switch (builtin.mode) {
47 .Debug, .ReleaseSafe => {},
48 .ReleaseFast, .ReleaseSmall => if (predicate.* != .done) unreachable,
47 .debug, .safe => {},
48 .fast, .small => if (predicate.* != .done) unreachable,
4949 }
5050 }
5151};
lib/std/c/haiku.zig+18-69
......@@ -1,15 +1,8 @@
11const std = @import("../std.zig");
2const assert = std.debug.assert;
32const builtin = @import("builtin");
4const maxInt = std.math.maxInt;
5const iovec = std.posix.iovec;
6const iovec_const = std.posix.iovec_const;
7const socklen_t = std.c.socklen_t;
3const assert = std.debug.assert;
84const fd_t = std.c.fd_t;
95const off_t = std.c.off_t;
10const PATH_MAX = std.c.PATH_MAX;
11const uid_t = std.c.uid_t;
12const gid_t = std.c.gid_t;
136const dev_t = std.c.dev_t;
147const ino_t = std.c.ino_t;
158
......@@ -17,52 +10,27 @@ comptime {
1710 assert(builtin.os.tag == .haiku); // Prevent access of std.c symbols on wrong OS.
1811}
1912
20pub extern "root" fn _errnop() *i32;
21pub extern "root" fn find_directory(which: directory_which, volume: i32, createIt: bool, path_ptr: [*]u8, length: i32) u64;
22pub extern "root" fn find_thread(thread_name: ?*anyopaque) i32;
23pub extern "root" fn get_system_info(system_info: *system_info) usize;
24pub extern "root" fn _get_team_info(team: i32, team_info: *team_info, size: usize) i32;
25pub extern "root" fn _get_next_area_info(team: i32, cookie: *i64, area_info: *area_info, size: usize) i32;
26pub extern "root" fn _get_next_image_info(team: i32, cookie: *i32, image_info: *image_info, size: usize) i32;
27pub extern "root" fn _kern_get_current_team() team_id;
13pub const B_OS_NAME_LENGTH = 32;
14pub const B_ABSOLUTE_TIMEOUT = 0x10;
15pub const B_TIMEOUT_REAL_TIME_BASE = 0x40;
16
17pub extern "root" fn _kern_create_sem(count: c_int, name: ?[*:0]const u8) sem_id;
18pub extern "root" fn _kern_delete_sem(id: sem_id) status_t;
19pub extern "root" fn _kern_acquire_sem_etc(id: sem_id, count: u32, flags: u32, timeout: i64) status_t;
20pub extern "root" fn _kern_release_sem_etc(id: sem_id, count: u32, flags: u32) status_t;
2821pub extern "root" fn _kern_open_dir(fd: fd_t, path: [*:0]const u8) fd_t;
2922pub extern "root" fn _kern_read_dir(fd: fd_t, buffer: [*]u8, bufferSize: usize, maxCount: u32) isize;
3023pub extern "root" fn _kern_rewind_dir(fd: fd_t) status_t;
3124pub extern "root" fn _kern_read_stat(fd: fd_t, path: [*:0]const u8, traverseLink: bool, stat: *std.c.Stat, statSize: usize) status_t;
32pub extern "root" fn readv_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec, count: i32) isize;
33pub extern "root" fn writev_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec_const, count: i32) isize;
3425
35pub const area_info = extern struct {
36 area: u32,
37 name: [32]u8,
38 size: usize,
39 lock: u32,
40 protection: u32,
41 team_id: i32,
42 ram_size: u32,
43 copy_count: u32,
44 in_count: u32,
45 out_count: u32,
46 address: *anyopaque,
47};
26pub extern "root" fn on_exit_thread(callback: *const fn (?*anyopaque) callconv(.c) void, data: ?*anyopaque) status_t;
27pub extern "root" fn find_thread(name: ?[*:0]const u8) thread_id;
28pub extern "root" fn get_system_info(info: *system_info) status_t;
4829
49pub const image_info = extern struct {
50 id: u32,
51 image_type: u32,
52 sequence: i32,
53 init_order: i32,
54 init_routine: *anyopaque,
55 term_routine: *anyopaque,
56 device: i32,
57 node: i64,
58 name: [PATH_MAX]u8,
59 text: *anyopaque,
60 data: *anyopaque,
61 text_size: i32,
62 data_size: i32,
63 api_version: i32,
64 abi: i32,
65};
30pub extern "root" fn _errnop() *i32;
31
32pub extern "root" fn readv_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec, count: i32) isize;
33pub extern "root" fn writev_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec_const, count: i32) isize;
6634
6735pub const system_info = extern struct {
6836 boot_time: i64,
......@@ -86,31 +54,12 @@ pub const system_info = extern struct {
8654 max_teams: u32,
8755 used_teams: u32,
8856 kernel_name: [256]u8,
89 kernel_build_date: [32]u8,
90 kernel_build_time: [32]u8,
57 kernel_build_date: [B_OS_NAME_LENGTH]u8,
58 kernel_build_time: [B_OS_NAME_LENGTH]u8,
9159 kernel_version: i64,
9260 abi: u32,
9361};
9462
95pub const team_info = extern struct {
96 team_id: i32,
97 thread_count: i32,
98 image_count: i32,
99 area_count: i32,
100 debugger_nub_thread: i32,
101 debugger_nub_port: i32,
102 argc: i32,
103 args: [64]u8,
104 uid: uid_t,
105 gid: gid_t,
106};
107
108pub const directory_which = enum(i32) {
109 B_USER_SETTINGS_DIRECTORY = 0xbbe,
110
111 _,
112};
113
11463pub const area_id = i32;
11564pub const port_id = i32;
11665pub const sem_id = i32;
lib/std/compress/flate/Compress.zig+1-1
......@@ -738,7 +738,7 @@ fn matchAndAddHash(c: *Compress, i: usize, h: Hash, gt: u16, max_chain: u16, goo
738738
739739fn clenHlen(freqs: [19]u16) u4 {
740740 // Note that the first four codes (16, 17, 18, and 0) are always present.
741 if (builtin.mode != .ReleaseSmall and (std.simd.suggestVectorLength(u16) orelse 1) >= 8) {
741 if (builtin.mode != .small and (std.simd.suggestVectorLength(u16) orelse 1) >= 8) {
742742 const V = @Vector(16, u16);
743743 const hlen_mul: V = comptime m: {
744744 var hlen_mul: [16]u16 = undefined;
lib/std/compress/flate/token.zig+3-3
......@@ -57,9 +57,9 @@ const fixed_dist = blk: {
5757};
5858
5959// All paramters of codes can be derived matchematically, however some are faster to
60// do via lookup table. For ReleaseSmall, we do all mathematically to save space.
61pub const LenCode = if (builtin.mode != .ReleaseSmall) LookupLenCode else ShortLenCode;
62pub const DistCode = if (builtin.mode != .ReleaseSmall) LookupDistCode else ShortDistCode;
60// do via lookup table. For -Osmall, we do all mathematically to save space.
61pub const LenCode = if (builtin.mode != .small) LookupLenCode else ShortLenCode;
62pub const DistCode = if (builtin.mode != .small) LookupDistCode else ShortDistCode;
6363const ShortLenCode = ShortCode(u8, u2, u3, true);
6464const ShortDistCode = ShortCode(u15, u1, u4, false);
6565/// For length and distance codes, they having this format.
lib/std/crypto/25519/field.zig+2-2
......@@ -7,8 +7,8 @@ const NotSquareError = crypto.errors.NotSquareError;
77
88// Inline conditionally, when it can result in large code generation.
99const bloaty_inline: std.builtin.CallingConvention = switch (builtin.mode) {
10 .ReleaseSafe, .ReleaseFast => .@"inline",
11 .Debug, .ReleaseSmall => .auto,
10 .safe, .fast => .@"inline",
11 .debug, .small => .auto,
1212};
1313
1414pub const Fe = struct {
lib/std/crypto/Certificate.zig+81-10
......@@ -175,6 +175,8 @@ pub const GeneralNameTag = enum(u5) {
175175 _,
176176};
177177
178const net = @import("../Io/net.zig");
179
178180pub const Parsed = struct {
179181 certificate: Certificate,
180182 issuer_slice: Slice,
......@@ -315,6 +317,7 @@ pub const Parsed = struct {
315317 // what to check. Otherwise, only the common name is checked.
316318 const subject_alt_name = parsed_subject.subjectAltName();
317319 if (subject_alt_name.len == 0) {
320 // note: checkIpAddress is intentionally omitted, as it is not permitted in the common name field anyway.
318321 if (checkHostName(host_name, parsed_subject.commonName())) {
319322 return;
320323 } else {
......@@ -332,6 +335,10 @@ pub const Parsed = struct {
332335 const dns_name = subject_alt_name[general_name.slice.start..general_name.slice.end];
333336 if (checkHostName(host_name, dns_name)) return;
334337 },
338 .iPAddress => {
339 const ip_address = subject_alt_name[general_name.slice.start..general_name.slice.end];
340 if (checkIpAddress(host_name, ip_address)) return;
341 },
335342 else => {},
336343 }
337344 }
......@@ -376,6 +383,22 @@ pub const Parsed = struct {
376383
377384 return false;
378385 }
386
387 // Check IP address according to RFC 5280 §4.2.1.6.
388 fn checkIpAddress(host_name: []const u8, ip_address: []const u8) bool {
389 switch (ip_address.len) {
390 4 => {
391 // port is irrelevant to SAN matching, so 0 is a harmless placeholder.
392 const address = net.Ip4Address.parse(host_name, 0) catch return false;
393 return mem.eql(u8, &address.bytes, ip_address);
394 },
395 16 => {
396 const address = net.Ip6Address.parse(host_name, 0) catch return false;
397 return mem.eql(u8, &address.bytes, ip_address);
398 },
399 else => return false, // a malformed certificate, neither 4 nor 16 octets
400 }
401 }
379402};
380403
381404test "Parsed.checkHostName RFC 6125 compliance" {
......@@ -417,6 +440,39 @@ test "Parsed.checkHostName RFC 6125 compliance" {
417440 try expectEqual(false, Parsed.checkHostName("example.com", "*."));
418441}
419442
443test "Parsed.checkIpAddress RFC 5280 4.2.1.6 compliance" {
444 const expectEqual = std.testing.expectEqual;
445
446 // Exact match positive tests
447 try expectEqual(true, Parsed.checkIpAddress("127.0.0.1", &[4]u8{ 127, 0, 0, 1 }));
448 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 }));
449
450 // Mismatches should not pass
451 try expectEqual(false, Parsed.checkIpAddress("1.2.3.4", &[4]u8{ 5, 6, 7, 8 }));
452 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 }));
453
454 // IPv6: the hostname may be in short-form and should match the exact 16 octets specified in the SAN
455 try expectEqual(true, Parsed.checkIpAddress("::1", &[16]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }));
456
457 // IPv6: do not match when using DNS64 / NAT64 (i.e. 64:ff9b::/96)
458 // 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.
459 // The test assertions are included not to harden on this behavior, but to show that this use-case was considered.
460 // This check may become more lenient in the future if a valid use-case is found.
461 try expectEqual(false, Parsed.checkIpAddress("64:ff9b::192.0.2.10", &[4]u8{ 192, 0, 2, 10 }));
462 try expectEqual(false, Parsed.checkIpAddress("::ffff:127.0.0.1", &[4]u8{ 127, 0, 0, 1 }));
463
464 // Malformed SAN lengths (not 4 or 16 octets) never match.
465 try expectEqual(false, Parsed.checkIpAddress("127.0.0", &[_]u8{ 127, 0, 0 }));
466 try expectEqual(false, Parsed.checkIpAddress("127.0.0.1.0", &[_]u8{ 127, 0, 0, 1, 0 }));
467
468 // A non-parseable host_name never matches.
469 try expectEqual(false, Parsed.checkIpAddress("not-an-ip", &[4]u8{ 127, 0, 0, 1 }));
470
471 // Edge cases - empty strings
472 try expectEqual(false, Parsed.checkIpAddress("", ""));
473 try expectEqual(false, Parsed.checkIpAddress("127.0.0.1", ""));
474}
475
420476pub const ParseError = der.Element.ParseError || ParseVersionError || ParseTimeError || ParseEnumError || ParseBitStringError;
421477
422478pub fn parse(cert: Certificate) ParseError!Parsed {
......@@ -793,7 +849,7 @@ fn verifyRsa(
793849 inline 128, 256, 384, 512 => |modulus_len| {
794850 const public_key = rsa.PublicKey.fromBytes(exponent, modulus) catch
795851 return error.CertificateSignatureInvalid;
796 rsa.PKCS1v1_5Signature.verify(modulus_len, sig[0..modulus_len].*, msg, public_key, Hash) catch
852 rsa.PKCS1v1_5Signature.verify(modulus_len, sig[0..modulus_len], msg, public_key, Hash) catch
797853 return error.CertificateSignatureInvalid;
798854 },
799855 else => return error.CertificateSignatureUnsupportedBitCount,
......@@ -983,7 +1039,7 @@ pub const rsa = struct {
9831039
9841040 pub fn concatVerify(
9851041 comptime modulus_len: usize,
986 sig: [modulus_len]u8,
1042 sig: *const [modulus_len]u8,
9871043 msg: []const []const u8,
9881044 public_key: PublicKey,
9891045 comptime Hash: type,
......@@ -1092,9 +1148,9 @@ pub const rsa = struct {
10921148 }
10931149 var m_p_buf: [8 + Hash.digest_length + Hash.digest_length]u8 = undefined;
10941150 var m_p = m_p_buf[0 .. 8 + Hash.digest_length + sLen];
1095 std.mem.copyForwards(u8, m_p, @as(*const [8]u8, &@splat(0)));
1096 std.mem.copyForwards(u8, m_p[8..], &mHash);
1097 std.mem.copyForwards(u8, m_p[(8 + Hash.digest_length)..], salt);
1151 @memmove(m_p[0..8], @as(*const [8]u8, &@splat(0)));
1152 @memmove(m_p[8..][0..Hash.digest_length], &mHash);
1153 @memmove(m_p[(8 + Hash.digest_length)..], salt);
10981154
10991155 // 13. Let H' = Hash(M'), an octet string of length hLen.
11001156 var h_p: [Hash.digest_length]u8 = undefined;
......@@ -1136,7 +1192,7 @@ pub const rsa = struct {
11361192
11371193 pub fn verify(
11381194 comptime modulus_len: usize,
1139 sig: [modulus_len]u8,
1195 sig: *const [modulus_len]u8,
11401196 msg: []const u8,
11411197 public_key: PublicKey,
11421198 comptime Hash: type,
......@@ -1146,7 +1202,7 @@ pub const rsa = struct {
11461202
11471203 pub fn concatVerify(
11481204 comptime modulus_len: usize,
1149 sig: [modulus_len]u8,
1205 sig: *const [modulus_len]u8,
11501206 msg: []const []const u8,
11511207 public_key: PublicKey,
11521208 comptime Hash: type,
......@@ -1187,6 +1243,11 @@ pub const rsa = struct {
11871243 // DigestInfo value (see the notes below) and let tLen be the length
11881244 // in octets of T.
11891245 const hash_der: []const u8 = &switch (Hash) {
1246 crypto.hash.Md5 => .{
1247 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86,
1248 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00,
1249 0x04, 0x10,
1250 },
11901251 crypto.hash.Sha1 => .{
11911252 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
11921253 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14,
......@@ -1211,7 +1272,17 @@ pub const rsa = struct {
12111272 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
12121273 0x00, 0x04, 0x40,
12131274 },
1214 else => @compileError("unreachable"),
1275 crypto.hash.sha3.Sha3_256 => .{
1276 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86,
1277 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x08, 0x05,
1278 0x00, 0x04, 0x20,
1279 },
1280 crypto.hash.sha3.Sha3_512 => .{
1281 0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86,
1282 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0a, 0x05,
1283 0x00, 0x04, 0x40,
1284 },
1285 else => comptime unreachable,
12151286 };
12161287 em_index -= hash_der.len;
12171288 @memcpy(em[em_index..][0..hash_der.len], hash_der);
......@@ -1292,8 +1363,8 @@ pub const rsa = struct {
12921363
12931364 const EncryptError = error{MessageTooLong};
12941365
1295 fn encrypt(comptime modulus_len: usize, msg: [modulus_len]u8, public_key: PublicKey) EncryptError![modulus_len]u8 {
1296 const m = Fe.fromBytes(public_key.n, &msg, .big) catch return error.MessageTooLong;
1366 fn encrypt(comptime modulus_len: usize, msg: *const [modulus_len]u8, public_key: PublicKey) EncryptError![modulus_len]u8 {
1367 const m = Fe.fromBytes(public_key.n, msg, .big) catch return error.MessageTooLong;
12971368 const e = public_key.n.powPublic(m, public_key.e) catch unreachable;
12981369 var res: [modulus_len]u8 = undefined;
12991370 e.toBytes(&res, .big) catch unreachable;
lib/std/crypto/aes.zig+2-2
......@@ -6,9 +6,9 @@ const has_aesni = builtin.cpu.has(.x86, .aes);
66const has_avx = builtin.cpu.has(.x86, .avx);
77const has_armaes = builtin.cpu.has(.aarch64, .aes);
88// C backend doesn't currently support passing vectors to inline asm.
9const impl = if (builtin.cpu.arch == .x86_64 and builtin.zig_backend != .stage2_c and has_aesni and has_avx) impl: {
9const impl = if (builtin.cpu.arch == .x86_64 and has_aesni and has_avx) impl: {
1010 break :impl @import("aes/aesni.zig");
11} else if (builtin.cpu.arch == .aarch64 and builtin.zig_backend != .stage2_c and has_armaes) impl: {
11} else if (builtin.cpu.arch == .aarch64 and (builtin.zig_backend != .stage2_c or !builtin.os.tag.isDarwin()) and has_armaes) impl: {
1212 break :impl @import("aes/armcrypto.zig");
1313} else impl: {
1414 break :impl @import("aes/soft.zig");
lib/std/crypto/aes_ocb.zig-10
......@@ -262,8 +262,6 @@ const hexToBytes = std.fmt.hexToBytes;
262262const testing = std.testing;
263263
264264test "AesOcb test vector 1" {
265 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
266
267265 var k: [Aes128Ocb.key_length]u8 = undefined;
268266 var nonce: [Aes128Ocb.nonce_length]u8 = undefined;
269267 var tag: [Aes128Ocb.tag_length]u8 = undefined;
......@@ -281,8 +279,6 @@ test "AesOcb test vector 1" {
281279}
282280
283281test "AesOcb test vector 2" {
284 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
285
286282 var k: [Aes128Ocb.key_length]u8 = undefined;
287283 var nonce: [Aes128Ocb.nonce_length]u8 = undefined;
288284 var tag: [Aes128Ocb.tag_length]u8 = undefined;
......@@ -303,8 +299,6 @@ test "AesOcb test vector 2" {
303299}
304300
305301test "AesOcb test vector 3" {
306 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
307
308302 var k: [Aes128Ocb.key_length]u8 = undefined;
309303 var nonce: [Aes128Ocb.nonce_length]u8 = undefined;
310304 var tag: [Aes128Ocb.tag_length]u8 = undefined;
......@@ -329,8 +323,6 @@ test "AesOcb test vector 3" {
329323}
330324
331325test "AesOcb test vector 4" {
332 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
333
334326 var k: [Aes128Ocb.key_length]u8 = undefined;
335327 var nonce: [Aes128Ocb.nonce_length]u8 = undefined;
336328 var tag: [Aes128Ocb.tag_length]u8 = undefined;
......@@ -356,8 +348,6 @@ test "AesOcb test vector 4" {
356348}
357349
358350test "AesOcb in-place encryption-decryption" {
359 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
360
361351 var k: [Aes128Ocb.key_length]u8 = undefined;
362352 var nonce: [Aes128Ocb.nonce_length]u8 = undefined;
363353 var tag: [Aes128Ocb.tag_length]u8 = undefined;
lib/std/crypto/benchmark.zig+3-3
......@@ -454,8 +454,8 @@ fn benchmarkPwhash(
454454
455455 const strHash = ty.strHash;
456456 const strHashFnInfo = @typeInfo(@TypeOf(strHash)).@"fn";
457 const needs_io = strHashFnInfo.params.len == 4 and strHashFnInfo.params[3].type == std.Io;
458 const needs_salt = strHashFnInfo.params.len == 4 and strHashFnInfo.params[3].type != std.Io;
457 const needs_io = strHashFnInfo.param_types.len == 4 and strHashFnInfo.param_types[3].? == std.Io;
458 const needs_salt = strHashFnInfo.param_types.len == 4 and strHashFnInfo.param_types[3].? != std.Io;
459459 const salt: [16]u8 = @splat(0);
460460
461461 const start = benchTime(io);
......@@ -493,7 +493,7 @@ fn usage() void {
493493}
494494
495495fn mode(comptime x: comptime_int) comptime_int {
496 return if (builtin.mode == .Debug) x / 64 else x;
496 return if (builtin.mode == .debug) x / 64 else x;
497497}
498498
499499pub fn main(init: std.process.Init) !void {
lib/std/crypto/ecdsa.zig+6-24
......@@ -1,4 +1,3 @@
1const builtin = @import("builtin");
21const std = @import("std");
32const crypto = std.crypto;
43const fmt = std.fmt;
......@@ -25,14 +24,17 @@ pub const EcdsaSecp256k1Sha256 = Ecdsa(crypto.ecc.Secp256k1, crypto.hash.sha2.Sh
2524pub const EcdsaSecp256k1Sha256oSha256 = Ecdsa(crypto.ecc.Secp256k1, crypto.hash.composition.Sha256oSha256);
2625
2726/// Elliptic Curve Digital Signature Algorithm (ECDSA).
28pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type {
29 const Prf = switch (Hash) {
27pub fn Ecdsa(comptime C: type, comptime H: type) type {
28 const Prf = switch (H) {
3029 sha3.Shake128 => sha3.KMac128,
3130 sha3.Shake256 => sha3.KMac256,
32 else => crypto.auth.hmac.Hmac(Hash),
31 else => crypto.auth.hmac.Hmac(H),
3332 };
3433
3534 return struct {
35 pub const Curve = C;
36 pub const Hash = H;
37
3638 /// Length (in bytes) of optional random bytes, for non-deterministic signatures.
3739 pub const noise_length = Curve.scalar.encoded_length;
3840
......@@ -415,8 +417,6 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type {
415417}
416418
417419test "Basic operations over EcdsaP384Sha384" {
418 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
419
420420 const io = testing.io;
421421 const Scheme = EcdsaP384Sha384;
422422 const kp = Scheme.KeyPair.generate(io);
......@@ -432,8 +432,6 @@ test "Basic operations over EcdsaP384Sha384" {
432432}
433433
434434test "Basic operations over Secp256k1" {
435 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
436
437435 const io = testing.io;
438436 const Scheme = EcdsaSecp256k1Sha256oSha256;
439437 const kp = Scheme.KeyPair.generate(io);
......@@ -449,8 +447,6 @@ test "Basic operations over Secp256k1" {
449447}
450448
451449test "Basic operations over EcdsaP384Sha256" {
452 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
453
454450 const io = testing.io;
455451 const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256);
456452 const kp = Scheme.KeyPair.generate(io);
......@@ -466,8 +462,6 @@ test "Basic operations over EcdsaP384Sha256" {
466462}
467463
468464test "Verifying a existing signature with EcdsaP384Sha256" {
469 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
470
471465 const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256);
472466 // zig fmt: off
473467 const sk_bytes = [_]u8{
......@@ -503,8 +497,6 @@ test "Verifying a existing signature with EcdsaP384Sha256" {
503497}
504498
505499test "Prehashed message operations" {
506 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
507
508500 const io = testing.io;
509501
510502 const Scheme = EcdsaP256Sha256;
......@@ -539,8 +531,6 @@ const TestVector = struct {
539531};
540532
541533test "Test vectors from Project Wycheproof - EcdsaP256Sha256 valid" {
542 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
543
544534 const vectors: []const TestVector = &.{
545535 // well-formed DER encoding -> expected valid
546536 .{ .key = "042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", .msg = "313233343030", .sig = "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1802204cd60b855d442f5b3c7b11eb6c4e0ae7525fe710fab9aa7c77a67f79e6fadd76" },
......@@ -711,8 +701,6 @@ test "Test vectors from Project Wycheproof - EcdsaP256Sha256 valid" {
711701}
712702
713703test "Test vectors from Project Wycheproof - EcdsaP256Sha256 invalid" {
714 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
715
716704 const vectors: []const TestVector = &.{
717705 // S encoded with negative sign -> expected invalid
718706 .{ .key = "042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", .msg = "313233343030", .sig = "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180220b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db" },
......@@ -1026,8 +1014,6 @@ test "Test vectors from Project Wycheproof - EcdsaP256Sha256 invalid" {
10261014}
10271015
10281016test "Test vectors from Project Wycheproof - EcdsaP384Sha384 valid" {
1029 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1030
10311017 const vectors: []const TestVector = &.{
10321018 // canonical sign-bit padding on R; canonical sign-bit padding on S -> expected valid
10331019 .{ .key = "0429bdb76d5fa741bfd70233cb3a66cc7d44beb3b0663d92a8136650478bcefb61ef182e155a54345a5e8e5e88f064e5bc9a525ab7f764dad3dae1468c2b419f3b62b9ba917d5e8c4fb1ec47404a3fc76474b2713081be9db4c00e043ada9fc4a3", .msg = "4d7367", .sig = "3066023100d7143a836608b25599a7f28dec6635494c2992ad1e2bbeecb7ef601a9c01746e710ce0d9c48accb38a79ede5b9638f3402310080f9e165e8c61035bf8aa7b5533960e46dd0e211c904a064edb6de41f797c0eae4e327612ee3f816f4157272bb4fabc9" },
......@@ -1243,8 +1229,6 @@ test "Test vectors from Project Wycheproof - EcdsaP384Sha384 valid" {
12431229}
12441230
12451231test "Test vectors from Project Wycheproof - EcdsaP384Sha384 invalid" {
1246 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1247
12481232 const vectors: []const TestVector = &.{
12491233 // S encoded with negative sign -> expected invalid
12501234 .{ .key = "042da57dda1089276a543f9ffdac0bff0d976cad71eb7280e7d9bfd9fee4bdb2f20f47ff888274389772d98cc5752138aa4b6d054d69dcf3e25ec49df870715e34883b1836197d76f8ad962e78f6571bbc7407b0d6091f9e4d88f014274406174f", .msg = "313233343030", .sig = "3064023012b30abef6b5476fe6b612ae557c0425661e26b44b1bfe19daf2ca28e3113083ba8e4ae4cc45a0320abd3394f1c548d70230e7bf25603e2d07076ff30b7a2abec473da8b11c572b35fc631991d5de62ddca7525aaba89325dfd04fecc47bff426f82" },
......@@ -1631,8 +1615,6 @@ fn tvTry(comptime Scheme: type, vector: TestVector) !void {
16311615}
16321616
16331617test "Sec1 encoding/decoding" {
1634 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1635
16361618 const io = testing.io;
16371619 const Scheme = EcdsaP384Sha384;
16381620 const kp = Scheme.KeyPair.generate(io);
lib/std/crypto/ff.zig-4
......@@ -966,8 +966,6 @@ const ct_unprotected = struct {
966966};
967967
968968test "finite field arithmetic" {
969 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
970
971969 const M = Modulus(256);
972970 const m = try M.fromPrimitive(u256, 3429938563481314093726330772853735541133072814650493833233);
973971 var x = try M.Fe.fromPrimitive(u256, m, 80169837251094269539116136208111827396136208141182357733);
......@@ -1066,8 +1064,6 @@ test "finite field arithmetic" {
10661064}
10671065
10681066fn testCt(ct_: anytype) !void {
1069 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1070
10711067 const l0: Limb = 0;
10721068 const l1: Limb = 1;
10731069 try testing.expectEqual(l1, ct_.select(true, l1, l0));
lib/std/crypto/ghash_polyval.zig+5-5
......@@ -30,7 +30,7 @@ fn Hash(comptime endian: std.builtin.Endian, comptime shift_key: bool) type {
3030 pub const mac_length = 16;
3131 pub const key_length = 16;
3232
33 const pc_count = if (builtin.mode != .ReleaseSmall) 16 else 2;
33 const pc_count = if (builtin.mode != .small) 16 else 2;
3434 const agg_4_threshold = 22;
3535 const agg_8_threshold = 84;
3636 const agg_16_threshold = 328;
......@@ -61,7 +61,7 @@ fn Hash(comptime endian: std.builtin.Endian, comptime shift_key: bool) type {
6161 hx[0] = h;
6262 hx[1] = reduce(clsq128(hx[0])); // h^2
6363
64 if (builtin.mode != .ReleaseSmall) {
64 if (builtin.mode != .small) {
6565 hx[2] = reduce(clmul128(hx[1], h)); // h^3
6666 hx[3] = reduce(clsq128(hx[1])); // h^4 = h^2^2
6767 if (block_count >= agg_8_threshold) {
......@@ -303,7 +303,7 @@ fn Hash(comptime endian: std.builtin.Endian, comptime shift_key: bool) type {
303303
304304 var i: usize = 0;
305305
306 if (builtin.mode != .ReleaseSmall and msg.len >= agg_16_threshold * block_length) {
306 if (builtin.mode != .small and msg.len >= agg_16_threshold * block_length) {
307307 // 16-blocks aggregated reduction
308308 while (i + 256 <= msg.len) : (i += 256) {
309309 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 {
313313 }
314314 acc = reduce(u);
315315 }
316 } else if (builtin.mode != .ReleaseSmall and msg.len >= agg_8_threshold * block_length) {
316 } else if (builtin.mode != .small and msg.len >= agg_8_threshold * block_length) {
317317 // 8-blocks aggregated reduction
318318 while (i + 128 <= msg.len) : (i += 128) {
319319 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 {
323323 }
324324 acc = reduce(u);
325325 }
326 } else if (builtin.mode != .ReleaseSmall and msg.len >= agg_4_threshold * block_length) {
326 } else if (builtin.mode != .small and msg.len >= agg_4_threshold * block_length) {
327327 // 4-blocks aggregated reduction
328328 while (i + 64 <= msg.len) : (i += 64) {
329329 var u = clmul128(acc ^ mem.readInt(u128, msg[i..][0..16], endian), st.hx[3 - 0]);
lib/std/crypto/kangarootwelve.zig+2-2
......@@ -885,7 +885,7 @@ fn ktMultiThreaded(
885885
886886 var select_outstanding: usize = 0;
887887 var select: Select = .init(io, select_buf);
888 defer select.cancel();
888 defer select.cancelDiscard();
889889 var batches_spawned: usize = 0;
890890 var next_to_process: usize = 0;
891891
......@@ -1398,7 +1398,7 @@ test "KT128 sequential and parallel produce same output for many random lengths"
13981398 var prng = std.Random.DefaultPrng.init(std.testing.random_seed);
13991399 const random = prng.random();
14001400
1401 const num_tests = if (builtin.mode == .Debug) 10 else 1000;
1401 const num_tests = if (builtin.mode == .debug) 10 else 1000;
14021402 const max_length = 250000;
14031403
14041404 for (0..num_tests) |_| {
lib/std/crypto/keccak_p.zig+2-2
......@@ -202,7 +202,7 @@ pub fn State(comptime f: u11, comptime capacity: u11, comptime rounds: u5) type
202202
203203 // In debug mode, track transitions to prevent insecure ones.
204204 const Op = enum { uninitialized, initialized, updated, absorb, squeeze };
205 const TransitionTracker = if (mode == .Debug) struct {
205 const TransitionTracker = if (mode == .debug) struct {
206206 op: Op = .uninitialized,
207207
208208 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
294294
295295 /// Permute the state
296296 pub fn permute(self: *Self) void {
297 if (mode == .Debug) {
297 if (mode == .debug) {
298298 if (self.transition.op == .absorb and self.offset > 0) {
299299 @panic("cannot permute with pending input - call fillBlock() or pad() instead");
300300 }
lib/std/crypto/pcurves/p256/p256_64.zig+17-17
......@@ -110,7 +110,7 @@ fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
110110/// out1: [0x0 ~> 0xffffffffffffffff]
111111/// out2: [0x0 ~> 0xffffffffffffffff]
112112fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
113 @setRuntimeSafety(mode == .Debug);
113 @setRuntimeSafety(mode == .debug);
114114
115115 const x = @as(u128, arg1) * @as(u128, arg2);
116116 out1.* = @as(u64, @truncate(x));
......@@ -129,7 +129,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
129129/// Output Bounds:
130130/// out1: [0x0 ~> 0xffffffffffffffff]
131131fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
132 @setRuntimeSafety(mode == .Debug);
132 @setRuntimeSafety(mode == .debug);
133133
134134 const mask = 0 -% @as(u64, arg1);
135135 out1.* = (mask & arg3) | ((~mask) & arg2);
......@@ -145,7 +145,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
145145/// 0 ≤ eval out1 < m
146146///
147147pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
148 @setRuntimeSafety(mode == .Debug);
148 @setRuntimeSafety(mode == .debug);
149149
150150 const x1 = (arg1[1]);
151151 const x2 = (arg1[2]);
......@@ -437,7 +437,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
437437/// 0 ≤ eval out1 < m
438438///
439439pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
440 @setRuntimeSafety(mode == .Debug);
440 @setRuntimeSafety(mode == .debug);
441441
442442 const x1 = (arg1[1]);
443443 const x2 = (arg1[2]);
......@@ -730,7 +730,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl
730730/// 0 ≤ eval out1 < m
731731///
732732pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
733 @setRuntimeSafety(mode == .Debug);
733 @setRuntimeSafety(mode == .debug);
734734
735735 var x1: u64 = undefined;
736736 var x2: u1 = undefined;
......@@ -783,7 +783,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
783783/// 0 ≤ eval out1 < m
784784///
785785pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
786 @setRuntimeSafety(mode == .Debug);
786 @setRuntimeSafety(mode == .debug);
787787
788788 var x1: u64 = undefined;
789789 var x2: u1 = undefined;
......@@ -826,7 +826,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
826826/// 0 ≤ eval out1 < m
827827///
828828pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
829 @setRuntimeSafety(mode == .Debug);
829 @setRuntimeSafety(mode == .debug);
830830
831831 var x1: u64 = undefined;
832832 var x2: u1 = undefined;
......@@ -869,7 +869,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
869869/// 0 ≤ eval out1 < m
870870///
871871pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
872 @setRuntimeSafety(mode == .Debug);
872 @setRuntimeSafety(mode == .debug);
873873
874874 const x1 = (arg1[0]);
875875 var x2: u64 = undefined;
......@@ -1022,7 +1022,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo
10221022/// 0 ≤ eval out1 < m
10231023///
10241024pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void {
1025 @setRuntimeSafety(mode == .Debug);
1025 @setRuntimeSafety(mode == .debug);
10261026
10271027 const x1 = (arg1[1]);
10281028 const x2 = (arg1[2]);
......@@ -1297,7 +1297,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma
12971297/// Output Bounds:
12981298/// out1: [0x0 ~> 0xffffffffffffffff]
12991299pub fn nonzero(out1: *u64, arg1: [4]u64) void {
1300 @setRuntimeSafety(mode == .Debug);
1300 @setRuntimeSafety(mode == .debug);
13011301
13021302 const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3]))));
13031303 out1.* = x1;
......@@ -1315,7 +1315,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void {
13151315/// Output Bounds:
13161316/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
13171317pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void {
1318 @setRuntimeSafety(mode == .Debug);
1318 @setRuntimeSafety(mode == .debug);
13191319
13201320 var x1: u64 = undefined;
13211321 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 {
13431343/// Output Bounds:
13441344/// 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]]
13451345pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {
1346 @setRuntimeSafety(mode == .Debug);
1346 @setRuntimeSafety(mode == .debug);
13471347
13481348 const x1 = (arg1[3]);
13491349 const x2 = (arg1[2]);
......@@ -1452,7 +1452,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {
14521452/// Output Bounds:
14531453/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
14541454pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {
1455 @setRuntimeSafety(mode == .Debug);
1455 @setRuntimeSafety(mode == .debug);
14561456
14571457 const x1 = (@as(u64, (arg1[31])) << 56);
14581458 const x2 = (@as(u64, (arg1[30])) << 48);
......@@ -1527,7 +1527,7 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {
15271527/// 0 ≤ eval out1 < m
15281528///
15291529pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
1530 @setRuntimeSafety(mode == .Debug);
1530 @setRuntimeSafety(mode == .debug);
15311531
15321532 out1[0] = @as(u64, 0x1);
15331533 out1[1] = 0xffffffff00000000;
......@@ -1544,7 +1544,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
15441544/// Output Bounds:
15451545/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
15461546pub fn msat(out1: *[5]u64) void {
1547 @setRuntimeSafety(mode == .Debug);
1547 @setRuntimeSafety(mode == .debug);
15481548
15491549 out1[0] = 0xffffffffffffffff;
15501550 out1[1] = 0xffffffff;
......@@ -1582,7 +1582,7 @@ pub fn msat(out1: *[5]u64) void {
15821582/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
15831583/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
15841584pub 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 {
1585 @setRuntimeSafety(mode == .Debug);
1585 @setRuntimeSafety(mode == .debug);
15861586
15871587 var x1: u64 = undefined;
15881588 var x2: u1 = undefined;
......@@ -1816,7 +1816,7 @@ pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[
18161816/// Output Bounds:
18171817/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
18181818pub fn divstepPrecomp(out1: *[4]u64) void {
1819 @setRuntimeSafety(mode == .Debug);
1819 @setRuntimeSafety(mode == .debug);
18201820
18211821 out1[0] = 0x67ffffffb8000000;
18221822 out1[1] = 0xc000000038000000;
lib/std/crypto/pcurves/p256/p256_scalar_64.zig+17-17
......@@ -110,7 +110,7 @@ fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
110110/// out1: [0x0 ~> 0xffffffffffffffff]
111111/// out2: [0x0 ~> 0xffffffffffffffff]
112112fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
113 @setRuntimeSafety(mode == .Debug);
113 @setRuntimeSafety(mode == .debug);
114114
115115 const x = @as(u128, arg1) * @as(u128, arg2);
116116 out1.* = @as(u64, @truncate(x));
......@@ -129,7 +129,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
129129/// Output Bounds:
130130/// out1: [0x0 ~> 0xffffffffffffffff]
131131fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
132 @setRuntimeSafety(mode == .Debug);
132 @setRuntimeSafety(mode == .debug);
133133
134134 const mask = 0 -% @as(u64, arg1);
135135 out1.* = (mask & arg3) | ((~mask) & arg2);
......@@ -145,7 +145,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
145145/// 0 ≤ eval out1 < m
146146///
147147pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
148 @setRuntimeSafety(mode == .Debug);
148 @setRuntimeSafety(mode == .debug);
149149
150150 const x1 = (arg1[1]);
151151 const x2 = (arg1[2]);
......@@ -485,7 +485,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
485485/// 0 ≤ eval out1 < m
486486///
487487pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
488 @setRuntimeSafety(mode == .Debug);
488 @setRuntimeSafety(mode == .debug);
489489
490490 const x1 = (arg1[1]);
491491 const x2 = (arg1[2]);
......@@ -826,7 +826,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl
826826/// 0 ≤ eval out1 < m
827827///
828828pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
829 @setRuntimeSafety(mode == .Debug);
829 @setRuntimeSafety(mode == .debug);
830830
831831 var x1: u64 = undefined;
832832 var x2: u1 = undefined;
......@@ -879,7 +879,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
879879/// 0 ≤ eval out1 < m
880880///
881881pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
882 @setRuntimeSafety(mode == .Debug);
882 @setRuntimeSafety(mode == .debug);
883883
884884 var x1: u64 = undefined;
885885 var x2: u1 = undefined;
......@@ -922,7 +922,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
922922/// 0 ≤ eval out1 < m
923923///
924924pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
925 @setRuntimeSafety(mode == .Debug);
925 @setRuntimeSafety(mode == .debug);
926926
927927 var x1: u64 = undefined;
928928 var x2: u1 = undefined;
......@@ -965,7 +965,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
965965/// 0 ≤ eval out1 < m
966966///
967967pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
968 @setRuntimeSafety(mode == .Debug);
968 @setRuntimeSafety(mode == .debug);
969969
970970 const x1 = (arg1[0]);
971971 var x2: u64 = undefined;
......@@ -1178,7 +1178,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo
11781178/// 0 ≤ eval out1 < m
11791179///
11801180pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void {
1181 @setRuntimeSafety(mode == .Debug);
1181 @setRuntimeSafety(mode == .debug);
11821182
11831183 const x1 = (arg1[1]);
11841184 const x2 = (arg1[2]);
......@@ -1501,7 +1501,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma
15011501/// Output Bounds:
15021502/// out1: [0x0 ~> 0xffffffffffffffff]
15031503pub fn nonzero(out1: *u64, arg1: [4]u64) void {
1504 @setRuntimeSafety(mode == .Debug);
1504 @setRuntimeSafety(mode == .debug);
15051505
15061506 const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3]))));
15071507 out1.* = x1;
......@@ -1519,7 +1519,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void {
15191519/// Output Bounds:
15201520/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
15211521pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void {
1522 @setRuntimeSafety(mode == .Debug);
1522 @setRuntimeSafety(mode == .debug);
15231523
15241524 var x1: u64 = undefined;
15251525 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 {
15471547/// Output Bounds:
15481548/// 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]]
15491549pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {
1550 @setRuntimeSafety(mode == .Debug);
1550 @setRuntimeSafety(mode == .debug);
15511551
15521552 const x1 = (arg1[3]);
15531553 const x2 = (arg1[2]);
......@@ -1656,7 +1656,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {
16561656/// Output Bounds:
16571657/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
16581658pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {
1659 @setRuntimeSafety(mode == .Debug);
1659 @setRuntimeSafety(mode == .debug);
16601660
16611661 const x1 = (@as(u64, (arg1[31])) << 56);
16621662 const x2 = (@as(u64, (arg1[30])) << 48);
......@@ -1731,7 +1731,7 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {
17311731/// 0 ≤ eval out1 < m
17321732///
17331733pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
1734 @setRuntimeSafety(mode == .Debug);
1734 @setRuntimeSafety(mode == .debug);
17351735
17361736 out1[0] = 0xc46353d039cdaaf;
17371737 out1[1] = 0x4319055258e8617b;
......@@ -1748,7 +1748,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
17481748/// Output Bounds:
17491749/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
17501750pub fn msat(out1: *[5]u64) void {
1751 @setRuntimeSafety(mode == .Debug);
1751 @setRuntimeSafety(mode == .debug);
17521752
17531753 out1[0] = 0xf3b9cac2fc632551;
17541754 out1[1] = 0xbce6faada7179e84;
......@@ -1786,7 +1786,7 @@ pub fn msat(out1: *[5]u64) void {
17861786/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
17871787/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
17881788pub 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 {
1789 @setRuntimeSafety(mode == .Debug);
1789 @setRuntimeSafety(mode == .debug);
17901790
17911791 var x1: u64 = undefined;
17921792 var x2: u1 = undefined;
......@@ -2020,7 +2020,7 @@ pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[
20202020/// Output Bounds:
20212021/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
20222022pub fn divstepPrecomp(out1: *[4]u64) void {
2023 @setRuntimeSafety(mode == .Debug);
2023 @setRuntimeSafety(mode == .debug);
20242024
20252025 out1[0] = 0xd739262fb7fcfbb5;
20262026 out1[1] = 0x8ac6f75d20074414;
lib/std/crypto/pcurves/p384.zig+4-6
......@@ -56,7 +56,7 @@ pub const P384 = struct {
5656 }
5757
5858 /// Create a point from serialized affine coordinates.
59 pub fn fromSerializedAffineCoordinates(xs: [48]u8, ys: [48]u8, endian: std.builtin.Endian) (NonCanonicalError || EncodingError)!P384 {
59 pub fn fromSerializedAffineCoordinates(xs: [48]u8, ys: [48]u8, endian: std.lang.Endian) (NonCanonicalError || EncodingError)!P384 {
6060 const x = try Fe.fromBytes(xs, endian);
6161 const y = try Fe.fromBytes(ys, endian);
6262 return fromAffineCoordinates(.{ .x = x, .y = y });
......@@ -395,7 +395,7 @@ pub const P384 = struct {
395395
396396 /// Multiply an elliptic curve point by a scalar.
397397 /// Return error.IdentityElement if the result is the identity element.
398 pub fn mul(p: P384, s_: [48]u8, endian: std.builtin.Endian) IdentityElementError!P384 {
398 pub fn mul(p: P384, s_: [48]u8, endian: std.lang.Endian) IdentityElementError!P384 {
399399 const s = if (endian == .little) s_ else Fe.orderSwap(s_);
400400 if (p.is_base) {
401401 return pcMul16(&basePointPc, s, false);
......@@ -407,7 +407,7 @@ pub const P384 = struct {
407407
408408 /// Multiply an elliptic curve point by a *PUBLIC* scalar *IN VARIABLE TIME*
409409 /// This can be used for signature verification.
410 pub fn mulPublic(p: P384, s_: [48]u8, endian: std.builtin.Endian) IdentityElementError!P384 {
410 pub fn mulPublic(p: P384, s_: [48]u8, endian: std.lang.Endian) IdentityElementError!P384 {
411411 const s = if (endian == .little) s_ else Fe.orderSwap(s_);
412412 if (p.is_base) {
413413 return pcMul16(&basePointPc, s, true);
......@@ -419,7 +419,7 @@ pub const P384 = struct {
419419
420420 /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME*
421421 /// This can be used for signature verification.
422 pub fn mulDoubleBasePublic(p1: P384, s1_: [48]u8, p2: P384, s2_: [48]u8, endian: std.builtin.Endian) IdentityElementError!P384 {
422 pub fn mulDoubleBasePublic(p1: P384, s1_: [48]u8, p2: P384, s2_: [48]u8, endian: std.lang.Endian) IdentityElementError!P384 {
423423 const s1 = if (endian == .little) s1_ else Fe.orderSwap(s1_);
424424 const s2 = if (endian == .little) s2_ else Fe.orderSwap(s2_);
425425 try p1.rejectIdentity();
......@@ -478,7 +478,5 @@ pub const AffineCoordinates = struct {
478478};
479479
480480test {
481 if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest;
482
483481 _ = @import("tests/p384.zig");
484482}
lib/std/crypto/pcurves/p384/p384_64.zig+17-17
......@@ -79,7 +79,7 @@ fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
7979/// out1: [0x0 ~> 0xffffffffffffffff]
8080/// out2: [0x0 ~> 0xffffffffffffffff]
8181fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
82 @setRuntimeSafety(mode == .Debug);
82 @setRuntimeSafety(mode == .debug);
8383
8484 const x = @as(u128, arg1) * @as(u128, arg2);
8585 out1.* = @as(u64, @truncate(x));
......@@ -98,7 +98,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
9898/// Output Bounds:
9999/// out1: [0x0 ~> 0xffffffffffffffff]
100100fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
101 @setRuntimeSafety(mode == .Debug);
101 @setRuntimeSafety(mode == .debug);
102102
103103 const mask = 0 -% @as(u64, arg1);
104104 out1.* = (mask & arg3) | ((~mask) & arg2);
......@@ -114,7 +114,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
114114/// 0 ≤ eval out1 < m
115115///
116116pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
117 @setRuntimeSafety(mode == .Debug);
117 @setRuntimeSafety(mode == .debug);
118118
119119 const x1 = (arg1[1]);
120120 const x2 = (arg1[2]);
......@@ -834,7 +834,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
834834/// 0 ≤ eval out1 < m
835835///
836836pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
837 @setRuntimeSafety(mode == .Debug);
837 @setRuntimeSafety(mode == .debug);
838838
839839 const x1 = (arg1[1]);
840840 const x2 = (arg1[2]);
......@@ -1555,7 +1555,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl
15551555/// 0 ≤ eval out1 < m
15561556///
15571557pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
1558 @setRuntimeSafety(mode == .Debug);
1558 @setRuntimeSafety(mode == .debug);
15591559
15601560 var x1: u64 = undefined;
15611561 var x2: u1 = undefined;
......@@ -1626,7 +1626,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
16261626/// 0 ≤ eval out1 < m
16271627///
16281628pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
1629 @setRuntimeSafety(mode == .Debug);
1629 @setRuntimeSafety(mode == .debug);
16301630
16311631 var x1: u64 = undefined;
16321632 var x2: u1 = undefined;
......@@ -1683,7 +1683,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
16831683/// 0 ≤ eval out1 < m
16841684///
16851685pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
1686 @setRuntimeSafety(mode == .Debug);
1686 @setRuntimeSafety(mode == .debug);
16871687
16881688 var x1: u64 = undefined;
16891689 var x2: u1 = undefined;
......@@ -1740,7 +1740,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
17401740/// 0 ≤ eval out1 < m
17411741///
17421742pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
1743 @setRuntimeSafety(mode == .Debug);
1743 @setRuntimeSafety(mode == .debug);
17441744
17451745 const x1 = (arg1[0]);
17461746 var x2: u64 = undefined;
......@@ -2225,7 +2225,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo
22252225/// 0 ≤ eval out1 < m
22262226///
22272227pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void {
2228 @setRuntimeSafety(mode == .Debug);
2228 @setRuntimeSafety(mode == .debug);
22292229
22302230 const x1 = (arg1[1]);
22312231 const x2 = (arg1[2]);
......@@ -2862,7 +2862,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma
28622862/// Output Bounds:
28632863/// out1: [0x0 ~> 0xffffffffffffffff]
28642864pub fn nonzero(out1: *u64, arg1: [6]u64) void {
2865 @setRuntimeSafety(mode == .Debug);
2865 @setRuntimeSafety(mode == .debug);
28662866
28672867 const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | ((arg1[3]) | ((arg1[4]) | (arg1[5]))))));
28682868 out1.* = x1;
......@@ -2880,7 +2880,7 @@ pub fn nonzero(out1: *u64, arg1: [6]u64) void {
28802880/// Output Bounds:
28812881/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
28822882pub fn selectznz(out1: *[6]u64, arg1: u1, arg2: [6]u64, arg3: [6]u64) void {
2883 @setRuntimeSafety(mode == .Debug);
2883 @setRuntimeSafety(mode == .debug);
28842884
28852885 var x1: u64 = undefined;
28862886 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 {
29142914/// Output Bounds:
29152915/// 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]]
29162916pub fn toBytes(out1: *[48]u8, arg1: [6]u64) void {
2917 @setRuntimeSafety(mode == .Debug);
2917 @setRuntimeSafety(mode == .debug);
29182918
29192919 const x1 = (arg1[5]);
29202920 const x2 = (arg1[4]);
......@@ -3069,7 +3069,7 @@ pub fn toBytes(out1: *[48]u8, arg1: [6]u64) void {
30693069/// Output Bounds:
30703070/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
30713071pub fn fromBytes(out1: *[6]u64, arg1: [48]u8) void {
3072 @setRuntimeSafety(mode == .Debug);
3072 @setRuntimeSafety(mode == .debug);
30733073
30743074 const x1 = (@as(u64, (arg1[47])) << 56);
30753075 const x2 = (@as(u64, (arg1[46])) << 48);
......@@ -3176,7 +3176,7 @@ pub fn fromBytes(out1: *[6]u64, arg1: [48]u8) void {
31763176/// 0 ≤ eval out1 < m
31773177///
31783178pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
3179 @setRuntimeSafety(mode == .Debug);
3179 @setRuntimeSafety(mode == .debug);
31803180
31813181 out1[0] = 0xffffffff00000001;
31823182 out1[1] = 0xffffffff;
......@@ -3195,7 +3195,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
31953195/// Output Bounds:
31963196/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
31973197pub fn msat(out1: *[7]u64) void {
3198 @setRuntimeSafety(mode == .Debug);
3198 @setRuntimeSafety(mode == .debug);
31993199
32003200 out1[0] = 0xffffffff;
32013201 out1[1] = 0xffffffff00000000;
......@@ -3235,7 +3235,7 @@ pub fn msat(out1: *[7]u64) void {
32353235/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
32363236/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
32373237pub 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 {
3238 @setRuntimeSafety(mode == .Debug);
3238 @setRuntimeSafety(mode == .debug);
32393239
32403240 var x1: u64 = undefined;
32413241 var x2: u1 = undefined;
......@@ -3561,7 +3561,7 @@ pub fn divstep(out1: *u64, out2: *[7]u64, out3: *[7]u64, out4: *[6]u64, out5: *[
35613561/// Output Bounds:
35623562/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
35633563pub fn divstepPrecomp(out1: *[6]u64) void {
3564 @setRuntimeSafety(mode == .Debug);
3564 @setRuntimeSafety(mode == .debug);
35653565
35663566 out1[0] = 0xfff69400fff18fff;
35673567 out1[1] = 0x2b7feffffd3ff;
lib/std/crypto/pcurves/p384/p384_scalar_64.zig+17-17
......@@ -79,7 +79,7 @@ fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
7979/// out1: [0x0 ~> 0xffffffffffffffff]
8080/// out2: [0x0 ~> 0xffffffffffffffff]
8181fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
82 @setRuntimeSafety(mode == .Debug);
82 @setRuntimeSafety(mode == .debug);
8383
8484 const x = @as(u128, arg1) * @as(u128, arg2);
8585 out1.* = @as(u64, @truncate(x));
......@@ -98,7 +98,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
9898/// Output Bounds:
9999/// out1: [0x0 ~> 0xffffffffffffffff]
100100fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
101 @setRuntimeSafety(mode == .Debug);
101 @setRuntimeSafety(mode == .debug);
102102
103103 const mask = 0 -% @as(u64, arg1);
104104 out1.* = (mask & arg3) | ((~mask) & arg2);
......@@ -114,7 +114,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
114114/// 0 ≤ eval out1 < m
115115///
116116pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
117 @setRuntimeSafety(mode == .Debug);
117 @setRuntimeSafety(mode == .debug);
118118
119119 const x1 = (arg1[1]);
120120 const x2 = (arg1[2]);
......@@ -834,7 +834,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
834834/// 0 ≤ eval out1 < m
835835///
836836pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
837 @setRuntimeSafety(mode == .Debug);
837 @setRuntimeSafety(mode == .debug);
838838
839839 const x1 = (arg1[1]);
840840 const x2 = (arg1[2]);
......@@ -1555,7 +1555,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl
15551555/// 0 ≤ eval out1 < m
15561556///
15571557pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
1558 @setRuntimeSafety(mode == .Debug);
1558 @setRuntimeSafety(mode == .debug);
15591559
15601560 var x1: u64 = undefined;
15611561 var x2: u1 = undefined;
......@@ -1626,7 +1626,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
16261626/// 0 ≤ eval out1 < m
16271627///
16281628pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
1629 @setRuntimeSafety(mode == .Debug);
1629 @setRuntimeSafety(mode == .debug);
16301630
16311631 var x1: u64 = undefined;
16321632 var x2: u1 = undefined;
......@@ -1683,7 +1683,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
16831683/// 0 ≤ eval out1 < m
16841684///
16851685pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
1686 @setRuntimeSafety(mode == .Debug);
1686 @setRuntimeSafety(mode == .debug);
16871687
16881688 var x1: u64 = undefined;
16891689 var x2: u1 = undefined;
......@@ -1740,7 +1740,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
17401740/// 0 ≤ eval out1 < m
17411741///
17421742pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
1743 @setRuntimeSafety(mode == .Debug);
1743 @setRuntimeSafety(mode == .debug);
17441744
17451745 const x1 = (arg1[0]);
17461746 var x2: u64 = undefined;
......@@ -2225,7 +2225,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo
22252225/// 0 ≤ eval out1 < m
22262226///
22272227pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void {
2228 @setRuntimeSafety(mode == .Debug);
2228 @setRuntimeSafety(mode == .debug);
22292229
22302230 const x1 = (arg1[1]);
22312231 const x2 = (arg1[2]);
......@@ -2916,7 +2916,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma
29162916/// Output Bounds:
29172917/// out1: [0x0 ~> 0xffffffffffffffff]
29182918pub fn nonzero(out1: *u64, arg1: [6]u64) void {
2919 @setRuntimeSafety(mode == .Debug);
2919 @setRuntimeSafety(mode == .debug);
29202920
29212921 const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | ((arg1[3]) | ((arg1[4]) | (arg1[5]))))));
29222922 out1.* = x1;
......@@ -2934,7 +2934,7 @@ pub fn nonzero(out1: *u64, arg1: [6]u64) void {
29342934/// Output Bounds:
29352935/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
29362936pub fn selectznz(out1: *[6]u64, arg1: u1, arg2: [6]u64, arg3: [6]u64) void {
2937 @setRuntimeSafety(mode == .Debug);
2937 @setRuntimeSafety(mode == .debug);
29382938
29392939 var x1: u64 = undefined;
29402940 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 {
29682968/// Output Bounds:
29692969/// 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]]
29702970pub fn toBytes(out1: *[48]u8, arg1: [6]u64) void {
2971 @setRuntimeSafety(mode == .Debug);
2971 @setRuntimeSafety(mode == .debug);
29722972
29732973 const x1 = (arg1[5]);
29742974 const x2 = (arg1[4]);
......@@ -3123,7 +3123,7 @@ pub fn toBytes(out1: *[48]u8, arg1: [6]u64) void {
31233123/// Output Bounds:
31243124/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
31253125pub fn fromBytes(out1: *[6]u64, arg1: [48]u8) void {
3126 @setRuntimeSafety(mode == .Debug);
3126 @setRuntimeSafety(mode == .debug);
31273127
31283128 const x1 = (@as(u64, (arg1[47])) << 56);
31293129 const x2 = (@as(u64, (arg1[46])) << 48);
......@@ -3230,7 +3230,7 @@ pub fn fromBytes(out1: *[6]u64, arg1: [48]u8) void {
32303230/// 0 ≤ eval out1 < m
32313231///
32323232pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
3233 @setRuntimeSafety(mode == .Debug);
3233 @setRuntimeSafety(mode == .debug);
32343234
32353235 out1[0] = 0x1313e695333ad68d;
32363236 out1[1] = 0xa7e5f24db74f5885;
......@@ -3249,7 +3249,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
32493249/// Output Bounds:
32503250/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
32513251pub fn msat(out1: *[7]u64) void {
3252 @setRuntimeSafety(mode == .Debug);
3252 @setRuntimeSafety(mode == .debug);
32533253
32543254 out1[0] = 0xecec196accc52973;
32553255 out1[1] = 0x581a0db248b0a77a;
......@@ -3289,7 +3289,7 @@ pub fn msat(out1: *[7]u64) void {
32893289/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
32903290/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
32913291pub 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 {
3292 @setRuntimeSafety(mode == .Debug);
3292 @setRuntimeSafety(mode == .debug);
32933293
32943294 var x1: u64 = undefined;
32953295 var x2: u1 = undefined;
......@@ -3615,7 +3615,7 @@ pub fn divstep(out1: *u64, out2: *[7]u64, out3: *[7]u64, out4: *[6]u64, out5: *[
36153615/// Output Bounds:
36163616/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
36173617pub fn divstepPrecomp(out1: *[6]u64) void {
3618 @setRuntimeSafety(mode == .Debug);
3618 @setRuntimeSafety(mode == .debug);
36193619
36203620 out1[0] = 0x49589ae0e6045b6a;
36213621 out1[1] = 0x3c9a5352870040ed;
lib/std/crypto/pcurves/secp256k1.zig+5-7
......@@ -51,7 +51,7 @@ pub const Secp256k1 = struct {
5151 };
5252
5353 /// Compute r1 and r2 so that k = r1 + r2*lambda (mod L).
54 pub fn splitScalar(s: [32]u8, endian: std.builtin.Endian) NonCanonicalError!SplitScalar {
54 pub fn splitScalar(s: [32]u8, endian: std.lang.Endian) NonCanonicalError!SplitScalar {
5555 const b1_neg_s = comptime s: {
5656 var buf: [32]u8 = undefined;
5757 mem.writeInt(u256, &buf, 303414439467246543595250775667605759171, .little);
......@@ -109,7 +109,7 @@ pub const Secp256k1 = struct {
109109 }
110110
111111 /// Create a point from serialized affine coordinates.
112 pub fn fromSerializedAffineCoordinates(xs: [32]u8, ys: [32]u8, endian: std.builtin.Endian) (NonCanonicalError || EncodingError)!Secp256k1 {
112 pub fn fromSerializedAffineCoordinates(xs: [32]u8, ys: [32]u8, endian: std.lang.Endian) (NonCanonicalError || EncodingError)!Secp256k1 {
113113 const x = try Fe.fromBytes(xs, endian);
114114 const y = try Fe.fromBytes(ys, endian);
115115 return fromAffineCoordinates(.{ .x = x, .y = y });
......@@ -423,7 +423,7 @@ pub const Secp256k1 = struct {
423423
424424 /// Multiply an elliptic curve point by a scalar.
425425 /// Return error.IdentityElement if the result is the identity element.
426 pub fn mul(p: Secp256k1, s_: [32]u8, endian: std.builtin.Endian) IdentityElementError!Secp256k1 {
426 pub fn mul(p: Secp256k1, s_: [32]u8, endian: std.lang.Endian) IdentityElementError!Secp256k1 {
427427 const s = if (endian == .little) s_ else Fe.orderSwap(s_);
428428 if (p.is_base) {
429429 return pcMul16(&basePointPc, s, false);
......@@ -435,7 +435,7 @@ pub const Secp256k1 = struct {
435435
436436 /// Multiply an elliptic curve point by a *PUBLIC* scalar *IN VARIABLE TIME*
437437 /// This can be used for signature verification.
438 pub fn mulPublic(p: Secp256k1, s_: [32]u8, endian: std.builtin.Endian) (IdentityElementError || NonCanonicalError)!Secp256k1 {
438 pub fn mulPublic(p: Secp256k1, s_: [32]u8, endian: std.lang.Endian) (IdentityElementError || NonCanonicalError)!Secp256k1 {
439439 const s = if (endian == .little) s_ else Fe.orderSwap(s_);
440440 const zero = comptime scalar.Scalar.zero.toBytes(.little);
441441 if (mem.eql(u8, &zero, &s)) {
......@@ -497,7 +497,7 @@ pub const Secp256k1 = struct {
497497
498498 /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME*
499499 /// This can be used for signature verification.
500 pub fn mulDoubleBasePublic(p1: Secp256k1, s1_: [32]u8, p2: Secp256k1, s2_: [32]u8, endian: std.builtin.Endian) IdentityElementError!Secp256k1 {
500 pub fn mulDoubleBasePublic(p1: Secp256k1, s1_: [32]u8, p2: Secp256k1, s2_: [32]u8, endian: std.lang.Endian) IdentityElementError!Secp256k1 {
501501 const s1 = if (endian == .little) s1_ else Fe.orderSwap(s1_);
502502 const s2 = if (endian == .little) s2_ else Fe.orderSwap(s2_);
503503 try p1.rejectIdentity();
......@@ -556,7 +556,5 @@ pub const AffineCoordinates = struct {
556556};
557557
558558test {
559 if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest;
560
561559 _ = @import("tests/secp256k1.zig");
562560}
lib/std/crypto/pcurves/secp256k1/secp256k1_64.zig+17-17
......@@ -79,7 +79,7 @@ fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
7979/// out1: [0x0 ~> 0xffffffffffffffff]
8080/// out2: [0x0 ~> 0xffffffffffffffff]
8181fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
82 @setRuntimeSafety(mode == .Debug);
82 @setRuntimeSafety(mode == .debug);
8383
8484 const x = @as(u128, arg1) * @as(u128, arg2);
8585 out1.* = @as(u64, @truncate(x));
......@@ -98,7 +98,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
9898/// Output Bounds:
9999/// out1: [0x0 ~> 0xffffffffffffffff]
100100fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
101 @setRuntimeSafety(mode == .Debug);
101 @setRuntimeSafety(mode == .debug);
102102
103103 const mask = 0 -% @as(u64, arg1);
104104 out1.* = (mask & arg3) | ((~mask) & arg2);
......@@ -114,7 +114,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
114114/// 0 ≤ eval out1 < m
115115///
116116pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
117 @setRuntimeSafety(mode == .Debug);
117 @setRuntimeSafety(mode == .debug);
118118
119119 const x1 = (arg1[1]);
120120 const x2 = (arg1[2]);
......@@ -454,7 +454,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
454454/// 0 ≤ eval out1 < m
455455///
456456pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
457 @setRuntimeSafety(mode == .Debug);
457 @setRuntimeSafety(mode == .debug);
458458
459459 const x1 = (arg1[1]);
460460 const x2 = (arg1[2]);
......@@ -795,7 +795,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl
795795/// 0 ≤ eval out1 < m
796796///
797797pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
798 @setRuntimeSafety(mode == .Debug);
798 @setRuntimeSafety(mode == .debug);
799799
800800 var x1: u64 = undefined;
801801 var x2: u1 = undefined;
......@@ -848,7 +848,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
848848/// 0 ≤ eval out1 < m
849849///
850850pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
851 @setRuntimeSafety(mode == .Debug);
851 @setRuntimeSafety(mode == .debug);
852852
853853 var x1: u64 = undefined;
854854 var x2: u1 = undefined;
......@@ -891,7 +891,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
891891/// 0 ≤ eval out1 < m
892892///
893893pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
894 @setRuntimeSafety(mode == .Debug);
894 @setRuntimeSafety(mode == .debug);
895895
896896 var x1: u64 = undefined;
897897 var x2: u1 = undefined;
......@@ -934,7 +934,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
934934/// 0 ≤ eval out1 < m
935935///
936936pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
937 @setRuntimeSafety(mode == .Debug);
937 @setRuntimeSafety(mode == .debug);
938938
939939 const x1 = (arg1[0]);
940940 var x2: u64 = undefined;
......@@ -1167,7 +1167,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo
11671167/// 0 ≤ eval out1 < m
11681168///
11691169pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void {
1170 @setRuntimeSafety(mode == .Debug);
1170 @setRuntimeSafety(mode == .debug);
11711171
11721172 const x1 = (arg1[1]);
11731173 const x2 = (arg1[2]);
......@@ -1430,7 +1430,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma
14301430/// Output Bounds:
14311431/// out1: [0x0 ~> 0xffffffffffffffff]
14321432pub fn nonzero(out1: *u64, arg1: [4]u64) void {
1433 @setRuntimeSafety(mode == .Debug);
1433 @setRuntimeSafety(mode == .debug);
14341434
14351435 const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3]))));
14361436 out1.* = x1;
......@@ -1448,7 +1448,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void {
14481448/// Output Bounds:
14491449/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
14501450pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void {
1451 @setRuntimeSafety(mode == .Debug);
1451 @setRuntimeSafety(mode == .debug);
14521452
14531453 var x1: u64 = undefined;
14541454 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 {
14761476/// Output Bounds:
14771477/// 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]]
14781478pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {
1479 @setRuntimeSafety(mode == .Debug);
1479 @setRuntimeSafety(mode == .debug);
14801480
14811481 const x1 = (arg1[3]);
14821482 const x2 = (arg1[2]);
......@@ -1585,7 +1585,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {
15851585/// Output Bounds:
15861586/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
15871587pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {
1588 @setRuntimeSafety(mode == .Debug);
1588 @setRuntimeSafety(mode == .debug);
15891589
15901590 const x1 = (@as(u64, (arg1[31])) << 56);
15911591 const x2 = (@as(u64, (arg1[30])) << 48);
......@@ -1660,7 +1660,7 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {
16601660/// 0 ≤ eval out1 < m
16611661///
16621662pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
1663 @setRuntimeSafety(mode == .Debug);
1663 @setRuntimeSafety(mode == .debug);
16641664
16651665 out1[0] = 0x1000003d1;
16661666 out1[1] = 0x0;
......@@ -1677,7 +1677,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
16771677/// Output Bounds:
16781678/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
16791679pub fn msat(out1: *[5]u64) void {
1680 @setRuntimeSafety(mode == .Debug);
1680 @setRuntimeSafety(mode == .debug);
16811681
16821682 out1[0] = 0xfffffffefffffc2f;
16831683 out1[1] = 0xffffffffffffffff;
......@@ -1715,7 +1715,7 @@ pub fn msat(out1: *[5]u64) void {
17151715/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
17161716/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
17171717pub 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 {
1718 @setRuntimeSafety(mode == .Debug);
1718 @setRuntimeSafety(mode == .debug);
17191719
17201720 var x1: u64 = undefined;
17211721 var x2: u1 = undefined;
......@@ -1949,7 +1949,7 @@ pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[
19491949/// Output Bounds:
19501950/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
19511951pub fn divstepPrecomp(out1: *[4]u64) void {
1952 @setRuntimeSafety(mode == .Debug);
1952 @setRuntimeSafety(mode == .debug);
19531953
19541954 out1[0] = 0xf201a41831525e0a;
19551955 out1[1] = 0x9953f9ddcd648d85;
lib/std/crypto/pcurves/secp256k1/secp256k1_scalar_64.zig+17-17
......@@ -79,7 +79,7 @@ fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
7979/// out1: [0x0 ~> 0xffffffffffffffff]
8080/// out2: [0x0 ~> 0xffffffffffffffff]
8181fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
82 @setRuntimeSafety(mode == .Debug);
82 @setRuntimeSafety(mode == .debug);
8383
8484 const x = @as(u128, arg1) * @as(u128, arg2);
8585 out1.* = @as(u64, @truncate(x));
......@@ -98,7 +98,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
9898/// Output Bounds:
9999/// out1: [0x0 ~> 0xffffffffffffffff]
100100fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
101 @setRuntimeSafety(mode == .Debug);
101 @setRuntimeSafety(mode == .debug);
102102
103103 const mask = 0 -% @as(u64, arg1);
104104 out1.* = (mask & arg3) | ((~mask) & arg2);
......@@ -114,7 +114,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
114114/// 0 ≤ eval out1 < m
115115///
116116pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
117 @setRuntimeSafety(mode == .Debug);
117 @setRuntimeSafety(mode == .debug);
118118
119119 const x1 = (arg1[1]);
120120 const x2 = (arg1[2]);
......@@ -454,7 +454,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
454454/// 0 ≤ eval out1 < m
455455///
456456pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
457 @setRuntimeSafety(mode == .Debug);
457 @setRuntimeSafety(mode == .debug);
458458
459459 const x1 = (arg1[1]);
460460 const x2 = (arg1[2]);
......@@ -795,7 +795,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl
795795/// 0 ≤ eval out1 < m
796796///
797797pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
798 @setRuntimeSafety(mode == .Debug);
798 @setRuntimeSafety(mode == .debug);
799799
800800 var x1: u64 = undefined;
801801 var x2: u1 = undefined;
......@@ -848,7 +848,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
848848/// 0 ≤ eval out1 < m
849849///
850850pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
851 @setRuntimeSafety(mode == .Debug);
851 @setRuntimeSafety(mode == .debug);
852852
853853 var x1: u64 = undefined;
854854 var x2: u1 = undefined;
......@@ -891,7 +891,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
891891/// 0 ≤ eval out1 < m
892892///
893893pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
894 @setRuntimeSafety(mode == .Debug);
894 @setRuntimeSafety(mode == .debug);
895895
896896 var x1: u64 = undefined;
897897 var x2: u1 = undefined;
......@@ -934,7 +934,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
934934/// 0 ≤ eval out1 < m
935935///
936936pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
937 @setRuntimeSafety(mode == .Debug);
937 @setRuntimeSafety(mode == .debug);
938938
939939 const x1 = (arg1[0]);
940940 var x2: u64 = undefined;
......@@ -1167,7 +1167,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo
11671167/// 0 ≤ eval out1 < m
11681168///
11691169pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void {
1170 @setRuntimeSafety(mode == .Debug);
1170 @setRuntimeSafety(mode == .debug);
11711171
11721172 const x1 = (arg1[1]);
11731173 const x2 = (arg1[2]);
......@@ -1490,7 +1490,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma
14901490/// Output Bounds:
14911491/// out1: [0x0 ~> 0xffffffffffffffff]
14921492pub fn nonzero(out1: *u64, arg1: [4]u64) void {
1493 @setRuntimeSafety(mode == .Debug);
1493 @setRuntimeSafety(mode == .debug);
14941494
14951495 const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3]))));
14961496 out1.* = x1;
......@@ -1508,7 +1508,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void {
15081508/// Output Bounds:
15091509/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
15101510pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void {
1511 @setRuntimeSafety(mode == .Debug);
1511 @setRuntimeSafety(mode == .debug);
15121512
15131513 var x1: u64 = undefined;
15141514 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 {
15361536/// Output Bounds:
15371537/// 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]]
15381538pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {
1539 @setRuntimeSafety(mode == .Debug);
1539 @setRuntimeSafety(mode == .debug);
15401540
15411541 const x1 = (arg1[3]);
15421542 const x2 = (arg1[2]);
......@@ -1645,7 +1645,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {
16451645/// Output Bounds:
16461646/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
16471647pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {
1648 @setRuntimeSafety(mode == .Debug);
1648 @setRuntimeSafety(mode == .debug);
16491649
16501650 const x1 = (@as(u64, (arg1[31])) << 56);
16511651 const x2 = (@as(u64, (arg1[30])) << 48);
......@@ -1720,7 +1720,7 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {
17201720/// 0 ≤ eval out1 < m
17211721///
17221722pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
1723 @setRuntimeSafety(mode == .Debug);
1723 @setRuntimeSafety(mode == .debug);
17241724
17251725 out1[0] = 0x402da1732fc9bebf;
17261726 out1[1] = 0x4551231950b75fc4;
......@@ -1737,7 +1737,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
17371737/// Output Bounds:
17381738/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
17391739pub fn msat(out1: *[5]u64) void {
1740 @setRuntimeSafety(mode == .Debug);
1740 @setRuntimeSafety(mode == .debug);
17411741
17421742 out1[0] = 0xbfd25e8cd0364141;
17431743 out1[1] = 0xbaaedce6af48a03b;
......@@ -1775,7 +1775,7 @@ pub fn msat(out1: *[5]u64) void {
17751775/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
17761776/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
17771777pub 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 {
1778 @setRuntimeSafety(mode == .Debug);
1778 @setRuntimeSafety(mode == .debug);
17791779
17801780 var x1: u64 = undefined;
17811781 var x2: u1 = undefined;
......@@ -2009,7 +2009,7 @@ pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[
20092009/// Output Bounds:
20102010/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
20112011pub fn divstepPrecomp(out1: *[4]u64) void {
2012 @setRuntimeSafety(mode == .Debug);
2012 @setRuntimeSafety(mode == .debug);
20132013
20142014 out1[0] = 0xd7431a4d2b9cb4e9;
20152015 out1[1] = 0xab67d35a32d9c503;
lib/std/crypto/tls/Client.zig+1-1
......@@ -1588,7 +1588,7 @@ const CertificatePublicKey = struct {
15881588 inline 128, 256, 384, 512 => |modulus_len| {
15891589 const key: PublicKey = try .fromBytes(exponent, modulus);
15901590 const sig = RsaSignature.fromBytes(modulus_len, encoded_sig);
1591 try RsaSignature.concatVerify(modulus_len, sig, msg, key, Hash);
1591 try RsaSignature.concatVerify(modulus_len, &sig, msg, key, Hash);
15921592 },
15931593 else => return error.TlsBadRsaSignatureBitCount,
15941594 }
lib/std/debug.zig+19-12
......@@ -151,6 +151,10 @@ pub fn FullPanic(comptime panicFn: fn ([]const u8, ?usize) noreturn) type {
151151 @branchHint(.cold);
152152 call("invalid error code", @returnAddress());
153153 }
154 pub fn unexpectedErrorCode(err: anyerror) noreturn {
155 @branchHint(.cold);
156 std.debug.panicExtra(@returnAddress(), "unexpected error code, found error.{s}", .{@errorName(err)});
157 }
154158 pub fn integerOutOfBounds() noreturn {
155159 @branchHint(.cold);
156160 call("integer does not fit in destination type", @returnAddress());
......@@ -207,6 +211,10 @@ pub fn FullPanic(comptime panicFn: fn ([]const u8, ?usize) noreturn) type {
207211 @branchHint(.cold);
208212 call("'noreturn' function returned", @returnAddress());
209213 }
214 pub fn loadUninstantiableType() noreturn {
215 @branchHint(.cold);
216 call("attempt to load uninstantiable type", @returnAddress());
217 }
210218 };
211219}
212220
......@@ -237,13 +245,12 @@ pub const Symbol = struct {
237245 };
238246};
239247
240/// Deprecated because it returns the optimization mode of the standard
241/// library, when the caller probably wants to use the optimization mode of
242/// their own module.
243pub const runtime_safety = switch (builtin.mode) {
244 .Debug, .ReleaseSafe => true,
245 .ReleaseFast, .ReleaseSmall => false,
246};
248/// Deprecated in favor of `std.lang.Optimize.runtimeSafety`, to be removed after 0.18.0
249///
250/// Returns whether the standard library has safety checks enabled. Callsites
251/// likely would rather know whether their own module's optimization mode
252/// (found via `@import("builtin").optimize`) has safety checks enabled.
253pub const runtime_safety = builtin.mode.runtimeSafety();
247254
248255/// Whether we can unwind the stack on this target, allowing capturing and/or printing the current
249256/// stack trace. It is still legal to call `captureCurrentStackTrace`, `writeCurrentStackTrace`, and
......@@ -257,7 +264,7 @@ pub const sys_can_stack_trace = switch (builtin.cpu.arch) {
257264 // because Emscripten's implementation is very slow.
258265 .wasm32,
259266 .wasm64,
260 => native_os == .emscripten and builtin.mode == .Debug,
267 => native_os == .emscripten and builtin.mode == .debug,
261268
262269 // `@returnAddress()` is unsupported in LLVM 21.
263270 .bpfel,
......@@ -419,16 +426,16 @@ pub const CpuContextPtr = if (cpu_context.Native == noreturn) noreturn else *con
419426
420427/// Invokes detectable illegal behavior when `ok` is `false`.
421428///
422/// In Debug and ReleaseSafe modes, calls to this function are always
429/// In debug and safe modes, calls to this function are always
423430/// generated, and the `unreachable` statement triggers a panic.
424431///
425/// In ReleaseFast and ReleaseSmall modes, calls to this function are optimized
432/// In fast and small modes, calls to this function are optimized
426433/// away, and in fact the optimizer is able to use the assertion in its
427434/// heuristics.
428435///
429436/// Inside a test block, it is best to use the `testing` module rather than
430437/// this function, because this function may not detect a test failure in
431/// ReleaseFast and ReleaseSmall mode. Outside of a test block, this assert
438/// fast and small mode. Outside of a test block, this assert
432439/// function is the correct function to use.
433440pub fn assert(ok: bool) void {
434441 @disableInstrumentation();
......@@ -1760,7 +1767,7 @@ test "manage resources correctly" {
17601767/// In release mode, it is size 0 and all methods are no-ops.
17611768/// This is a pre-made type with default settings.
17621769/// For more advanced usage, see `ConfigurableTrace`.
1763pub const Trace = ConfigurableTrace(2, 4, builtin.mode == .Debug);
1770pub const Trace = ConfigurableTrace(2, 4, builtin.mode == .debug);
17641771
17651772pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize, comptime is_enabled: bool) type {
17661773 return struct {
lib/std/debug/Dwarf.zig+16-5
......@@ -450,6 +450,7 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void {
450450 unit_header.format,
451451 endian,
452452 address_size,
453 version,
453454 )) orelse continue;
454455
455456 switch (die_obj.tag_id) {
......@@ -485,6 +486,7 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void {
485486 unit_header.format,
486487 endian,
487488 address_size,
489 version,
488490 )) orelse return bad();
489491 } else if (this_die_obj.getAttr(AT.specification)) |_| {
490492 const after_die_offset = fr.seek;
......@@ -500,6 +502,7 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void {
500502 unit_header.format,
501503 endian,
502504 address_size,
505 version,
503506 )) orelse return bad();
504507 } else {
505508 break :x null;
......@@ -611,6 +614,7 @@ fn scanAllCompileUnits(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!voi
611614 unit_header.format,
612615 endian,
613616 address_size,
617 version,
614618 )) orelse return bad();
615619
616620 if (compile_unit_die.tag_id != DW.TAG.compile_unit) return bad();
......@@ -931,6 +935,7 @@ fn parseDie(
931935 format: Format,
932936 endian: Endian,
933937 addr_size_bytes: u8,
938 version: u16,
934939) ScanError!?Die {
935940 const abbrev_code = try fr.takeLeb128(u64);
936941 if (abbrev_code == 0) return null;
......@@ -939,7 +944,7 @@ fn parseDie(
939944 const attrs = attrs_buf[0..table_entry.attrs.len];
940945 for (attrs, table_entry.attrs) |*result_attr, attr| result_attr.* = .{
941946 .id = attr.id,
942 .value = try parseFormValue(fr, attr.form_id, format, endian, addr_size_bytes, attr.payload),
947 .value = try parseFormValue(fr, attr.form_id, format, endian, addr_size_bytes, attr.payload, version),
943948 };
944949 return .{
945950 .tag_id = table_entry.tag_id,
......@@ -1042,7 +1047,7 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, endian: Endian, compile_unit:
10421047 for (try directories.addManyAsSlice(gpa, directories_count)) |*e| {
10431048 e.* = .{ .path = &.{} };
10441049 for (dir_ent_fmt_buf[0..directory_entry_format_count]) |ent_fmt| {
1045 const form_value = try parseFormValue(&fr, ent_fmt.form_code, unit_header.format, endian, addr_size_bytes, null);
1050 const form_value = try parseFormValue(&fr, ent_fmt.form_code, unit_header.format, endian, addr_size_bytes, null, version);
10461051 switch (ent_fmt.content_type_code) {
10471052 DW.LNCT.path => e.path = try form_value.getString(d.*),
10481053 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:
10741079 for (try file_entries.addManyAsSlice(gpa, file_names_count)) |*e| {
10751080 e.* = .{ .path = &.{} };
10761081 for (file_ent_fmt_buf[0..file_name_entry_format_count]) |ent_fmt| {
1077 const form_value = try parseFormValue(&fr, ent_fmt.form_code, unit_header.format, endian, addr_size_bytes, null);
1082 const form_value = try parseFormValue(&fr, ent_fmt.form_code, unit_header.format, endian, addr_size_bytes, null, version);
10781083 switch (ent_fmt.content_type_code) {
10791084 DW.LNCT.path => e.path = try form_value.getString(d.*),
10801085 DW.LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),
......@@ -1285,6 +1290,7 @@ fn parseFormValue(
12851290 endian: Endian,
12861291 addr_size_bytes: u8,
12871292 implicit_const: ?i64,
1293 version: u16,
12881294) ScanError!FormValue {
12891295 return switch (form_id) {
12901296 // DWARF5.pdf page 213: the size of this value is encoded in the
......@@ -1319,7 +1325,12 @@ fn parseFormValue(
13191325 FORM.ref8 => .{ .ref = try r.takeInt(u64, endian) },
13201326 FORM.ref_udata => .{ .ref = try r.takeLeb128(u64) },
13211327
1322 FORM.ref_addr => .{ .ref_addr = try readFormatSizedInt(r, format, endian) },
1328 FORM.ref_addr => .{
1329 .ref_addr = switch (version) {
1330 2 => try readAddress(r, endian, addr_size_bytes),
1331 else => try readFormatSizedInt(r, format, endian),
1332 },
1333 },
13231334 FORM.ref_sig8 => .{ .ref = try r.takeInt(u64, endian) },
13241335
13251336 FORM.string => .{ .string = try r.takeSentinel(0) },
......@@ -1330,7 +1341,7 @@ fn parseFormValue(
13301341 FORM.strx4 => .{ .strx = try r.takeInt(u32, endian) },
13311342 FORM.strx => .{ .strx = try r.takeLeb128(usize) },
13321343 FORM.line_strp => .{ .line_strp = try readFormatSizedInt(r, format, endian) },
1333 FORM.indirect => parseFormValue(r, try r.takeLeb128(u64), format, endian, addr_size_bytes, implicit_const),
1344 FORM.indirect => parseFormValue(r, try r.takeLeb128(u64), format, endian, addr_size_bytes, implicit_const, version),
13341345 FORM.implicit_const => .{ .sdata = implicit_const orelse return bad() },
13351346 FORM.loclistx => .{ .loclistx = try r.takeLeb128(u64) },
13361347 FORM.rnglistx => .{ .rnglistx = try r.takeLeb128(u64) },
lib/std/debug/MachOFile.zig+174-54
......@@ -2,6 +2,8 @@ mapped_memory: []align(std.heap.page_size_min) const u8,
22symbols: []const Symbol,
33strings: []const u8,
44text_vmaddr: u64,
5uuid: ?Uuid,
6adjacent_dsym: ?DsymFile,
57
68/// Key is index into `strings` of the file path.
79ofiles: std.array_hash_map.Auto(u32, Error!OFile),
......@@ -16,6 +18,7 @@ pub const Error = error{
1618};
1719
1820pub fn deinit(mf: *MachOFile, gpa: Allocator) void {
21 if (mf.adjacent_dsym) |*dsym| dsym.deinit(gpa);
1922 for (mf.ofiles.values()) |*maybe_of| {
2023 const of = &(maybe_of.* catch continue);
2124 posix.munmap(of.mapped_memory);
......@@ -36,48 +39,7 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch)
3639 const all_mapped_memory = try mapDebugInfoFile(io, path);
3740 errdefer posix.munmap(all_mapped_memory);
3841
39 // In most cases, the file we just mapped is a Mach-O binary. However, it could be a "universal
40 // binary": a simple file format which contains Mach-O binaries for multiple targets. For
41 // instance, `/usr/lib/dyld` is currently distributed as a universal binary containing images
42 // for both ARM64 macOS and x86_64 macOS.
43 if (all_mapped_memory.len < 4) return error.InvalidMachO;
44 const magic = std.mem.readInt(u32, all_mapped_memory.ptr[0..4], .little);
45
46 // The contents of a Mach-O file, which may or may not be the whole of `all_mapped_memory`.
47 const mapped_macho = switch (magic) {
48 macho.MH_MAGIC_64 => all_mapped_memory,
49
50 macho.FAT_CIGAM => mapped_macho: {
51 // This is the universal binary format (aka a "fat binary").
52 var fat_r: Io.Reader = .fixed(all_mapped_memory);
53 const hdr = fat_r.takeStruct(macho.fat_header, .big) catch |err| switch (err) {
54 error.ReadFailed => unreachable,
55 error.EndOfStream => return error.InvalidMachO,
56 };
57 const want_cpu_type = switch (arch) {
58 .x86_64 => macho.CPU_TYPE_X86_64,
59 .aarch64 => macho.CPU_TYPE_ARM64,
60 else => unreachable,
61 };
62 for (0..hdr.nfat_arch) |_| {
63 const fat_arch = fat_r.takeStruct(macho.fat_arch, .big) catch |err| switch (err) {
64 error.ReadFailed => unreachable,
65 error.EndOfStream => return error.InvalidMachO,
66 };
67 if (fat_arch.cputype != want_cpu_type) continue;
68 if (fat_arch.offset + fat_arch.size > all_mapped_memory.len) return error.InvalidMachO;
69 break :mapped_macho all_mapped_memory[fat_arch.offset..][0..fat_arch.size];
70 }
71 // `arch` was not present in the fat binary.
72 return error.MissingDebugInfo;
73 },
74
75 // Even on modern 64-bit targets, this format doesn't seem to be too extensively used. It
76 // will be fairly easy to add support here if necessary; it's very similar to above.
77 macho.FAT_CIGAM_64 => return error.UnsupportedDebugInfo,
78
79 else => return error.InvalidMachO,
80 };
42 const mapped_macho = try selectMachOSlice(all_mapped_memory, arch);
8143
8244 var r: Io.Reader = .fixed(mapped_macho);
8345 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)
8850 if (hdr.magic != macho.MH_MAGIC_64)
8951 return error.InvalidMachO;
9052
91 const symtab: macho.symtab_command, const text_vmaddr: u64 = lcs: {
53 const symtab: macho.symtab_command, const text_vmaddr: u64, const uuid: ?Uuid = lcs: {
9254 var it: macho.LoadCommandIterator = try .init(&hdr, mapped_macho[@sizeOf(macho.mach_header_64)..]);
9355 var symtab: ?macho.symtab_command = null;
9456 var text_vmaddr: ?u64 = null;
57 var uuid: ?Uuid = null;
9558 while (try it.next()) |cmd| switch (cmd.hdr.cmd) {
9659 .SYMTAB => symtab = cmd.cast(macho.symtab_command) orelse return error.InvalidMachO,
9760 .SEGMENT_64 => if (cmd.cast(macho.segment_command_64)) |seg_cmd| {
9861 if (!mem.eql(u8, seg_cmd.segName(), "__TEXT")) continue;
9962 text_vmaddr = seg_cmd.vmaddr;
10063 },
64 .UUID => if (cmd.cast(macho.uuid_command)) |uuid_cmd| {
65 uuid = uuid_cmd.uuid;
66 },
10167 else => {},
10268 };
10369 break :lcs .{
10470 symtab orelse return error.MissingDebugInfo,
10571 text_vmaddr orelse return error.MissingDebugInfo,
72 uuid,
10673 };
10774 };
10875
......@@ -253,15 +220,27 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch)
253220 // This sort is so that we can binary search later.
254221 mem.sort(Symbol, symbols_slice, {}, Symbol.addressLessThan);
255222
223 const adjacent_dsym = if (uuid) |expected_uuid|
224 try loadAdjacentDsym(gpa, io, path, arch, expected_uuid)
225 else
226 null;
227
256228 return .{
257229 .mapped_memory = all_mapped_memory,
258230 .symbols = symbols_slice,
259231 .strings = strings,
260232 .ofiles = .empty,
261233 .text_vmaddr = text_vmaddr,
234 .uuid = uuid,
235 .adjacent_dsym = adjacent_dsym,
262236 };
263237}
238
264239pub fn getDwarfForAddress(mf: *MachOFile, gpa: Allocator, io: Io, vaddr: u64) !struct { *Dwarf, u64 } {
240 if (mf.adjacent_dsym) |*dsym| {
241 return .{ &dsym.dwarf, vaddr };
242 }
243
265244 const symbol = Symbol.find(mf.symbols, vaddr) orelse return error.MissingDebugInfo;
266245
267246 if (symbol.ofile == Symbol.unknown_ofile) return error.MissingDebugInfo;
......@@ -324,6 +303,16 @@ const OFile = struct {
324303 };
325304};
326305
306const DsymFile = struct {
307 mapped_memory: []align(std.heap.page_size_min) const u8,
308 dwarf: Dwarf,
309
310 fn deinit(df: *DsymFile, gpa: Allocator) void {
311 df.dwarf.deinit(gpa);
312 posix.munmap(df.mapped_memory);
313 }
314};
315
327316const Symbol = struct {
328317 strx: u32,
329318 addr: u64,
......@@ -394,6 +383,74 @@ fn appendStabSymbol(
394383 }
395384}
396385
386fn loadAdjacentDsym(
387 gpa: Allocator,
388 io: Io,
389 binary_path: []const u8,
390 arch: std.Target.Cpu.Arch,
391 uuid: Uuid,
392) Error!?DsymFile {
393 const s = std.fs.path.sep_str;
394 const dsym_path = try std.fmt.allocPrint(
395 gpa,
396 "{s}.dSYM" ++ s ++ "Contents" ++ s ++ "Resources" ++ s ++ "DWARF" ++ s ++ "{s}",
397 .{ binary_path, std.fs.path.basename(binary_path) },
398 );
399 defer gpa.free(dsym_path);
400 return loadDsymFile(gpa, io, dsym_path, arch, uuid) catch |err| switch (err) {
401 error.MissingDebugInfo,
402 error.InvalidMachO,
403 error.InvalidDwarf,
404 error.UnsupportedDebugInfo,
405 error.ReadFailed,
406 => null,
407 error.OutOfMemory => |e| return e,
408 };
409}
410
411fn loadDsymFile(
412 gpa: Allocator,
413 io: Io,
414 path: []const u8,
415 arch: std.Target.Cpu.Arch,
416 expected_uuid: Uuid,
417) Error!DsymFile {
418 const all_mapped_memory = try mapDebugInfoFile(io, path);
419 errdefer posix.munmap(all_mapped_memory);
420 const mapped_macho = try selectMachOSlice(all_mapped_memory, arch);
421
422 var r: Io.Reader = .fixed(mapped_macho);
423 const hdr = r.takeStruct(macho.mach_header_64, .little) catch |err| switch (err) {
424 error.ReadFailed => unreachable,
425 error.EndOfStream => return error.InvalidMachO,
426 };
427 if (hdr.magic != macho.MH_MAGIC_64) return error.InvalidMachO;
428 if (hdr.filetype != macho.MH_DSYM) return error.MissingDebugInfo;
429
430 var uuid: ?Uuid = null;
431 var dwarf_sections: ?[]align(1) const macho.section_64 = null;
432
433 var it: macho.LoadCommandIterator = try .init(&hdr, mapped_macho[@sizeOf(macho.mach_header_64)..]);
434 while (try it.next()) |lc| switch (lc.hdr.cmd) {
435 .SEGMENT_64 => if (lc.cast(macho.segment_command_64)) |seg_cmd| {
436 if (!mem.eql(u8, "__DWARF", seg_cmd.segName())) continue;
437 dwarf_sections = lc.getSections();
438 },
439 .UUID => if (lc.cast(macho.uuid_command)) |uuid_cmd| {
440 uuid = uuid_cmd.uuid;
441 },
442 else => {},
443 };
444
445 const actual_uuid = uuid orelse return error.MissingDebugInfo;
446 if (!mem.eql(u8, &actual_uuid, &expected_uuid)) return error.MissingDebugInfo;
447
448 return .{
449 .mapped_memory = all_mapped_memory,
450 .dwarf = try loadDwarfFromSections(gpa, mapped_macho, dwarf_sections orelse return error.MissingDebugInfo),
451 };
452}
453
397454fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile {
398455 const all_mapped_memory, const mapped_ofile = map: {
399456 const open_paren = paren: {
......@@ -497,19 +554,38 @@ fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile {
497554 gop.key_ptr.* = @intCast(sym_index);
498555 }
499556
557 const dwarf = try loadDwarfFromSections(gpa, mapped_ofile, seg_cmd.getSections());
558
559 return .{
560 .mapped_memory = all_mapped_memory,
561 .dwarf = dwarf,
562 .strtab = strtab,
563 .symtab_raw = symtab_raw,
564 .symbols_by_name = symbols_by_name.move(),
565 };
566}
567
568fn loadDwarfFromSections(
569 gpa: Allocator,
570 mapped_macho: []const u8,
571 section_headers: []align(1) const macho.section_64,
572) !Dwarf {
500573 var sections: Dwarf.SectionArray = @splat(null);
501 for (seg_cmd.getSections()) |sect_raw| {
574 for (section_headers) |sect_raw| {
502575 var sect = sect_raw;
503576 if (builtin.cpu.arch.endian() != .little) std.mem.byteSwapAllFields(macho.section_64, &sect);
504577
505578 if (!std.mem.eql(u8, "__DWARF", sect.segName())) continue;
506579
507 const section_index: usize = inline for (@typeInfo(Dwarf.Section.Id).@"enum".field_names, 0..) |section_name, i| {
508 if (mem.eql(u8, "__" ++ section_name, sect.sectName())) break i;
580 const section_index: usize = inline for (@typeInfo(Dwarf.Section.Id).@"enum".field_names, 0..) |field_name, i| {
581 const section_name_long = "__" ++ field_name;
582 // Some dwarf section names don't fit in the `sectname` buffer, so they are truncated.
583 const section_name_trunc = section_name_long[0..@min(section_name_long.len, sect.sectname.len)];
584 if (mem.eql(u8, section_name_trunc, sect.sectName())) break i;
509585 } else continue;
510586
511 if (mapped_ofile.len < sect.offset + sect.size) return error.InvalidMachO;
512 const section_bytes = mapped_ofile[sect.offset..][0..sect.size];
587 if (mapped_macho.len < sect.offset + sect.size) return error.InvalidMachO;
588 const section_bytes = mapped_macho[sect.offset..][0..sect.size];
513589 sections[section_index] = .{
514590 .data = section_bytes,
515591 .owned = false,
......@@ -539,13 +615,56 @@ fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile {
539615 => |e| return e,
540616 };
541617
542 return .{
543 .mapped_memory = all_mapped_memory,
544 .dwarf = dwarf,
545 .strtab = strtab,
546 .symtab_raw = symtab_raw,
547 .symbols_by_name = symbols_by_name.move(),
618 return dwarf;
619}
620
621fn selectMachOSlice(
622 all_mapped_memory: []align(std.heap.page_size_min) const u8,
623 arch: std.Target.Cpu.Arch,
624) Error![]const u8 {
625 // In most cases, the file we just mapped is a Mach-O binary. However, it could be a "universal
626 // binary": a simple file format which contains Mach-O binaries for multiple targets. For
627 // instance, `/usr/lib/dyld` is currently distributed as a universal binary containing images
628 // for both ARM64 macOS and x86_64 macOS.
629 if (all_mapped_memory.len < 4) return error.InvalidMachO;
630 const magic = std.mem.readInt(u32, all_mapped_memory.ptr[0..4], .little);
631
632 // The contents of a Mach-O file, which may or may not be the whole of `all_mapped_memory`.
633 const mapped_macho = switch (magic) {
634 macho.MH_MAGIC_64 => all_mapped_memory,
635
636 macho.FAT_CIGAM => mapped_macho: {
637 // This is the universal binary format (aka a "fat binary").
638 var fat_r: Io.Reader = .fixed(all_mapped_memory);
639 const hdr = fat_r.takeStruct(macho.fat_header, .big) catch |err| switch (err) {
640 error.ReadFailed => unreachable,
641 error.EndOfStream => return error.InvalidMachO,
642 };
643 const want_cpu_type = switch (arch) {
644 .x86_64 => macho.CPU_TYPE_X86_64,
645 .aarch64 => macho.CPU_TYPE_ARM64,
646 else => unreachable,
647 };
648 for (0..hdr.nfat_arch) |_| {
649 const fat_arch = fat_r.takeStruct(macho.fat_arch, .big) catch |err| switch (err) {
650 error.ReadFailed => unreachable,
651 error.EndOfStream => return error.InvalidMachO,
652 };
653 if (fat_arch.cputype != want_cpu_type) continue;
654 if (fat_arch.offset + fat_arch.size > all_mapped_memory.len) return error.InvalidMachO;
655 break :mapped_macho all_mapped_memory[fat_arch.offset..][0..fat_arch.size];
656 }
657 // `arch` was not present in the fat binary.
658 return error.MissingDebugInfo;
659 },
660
661 // Even on modern 64-bit targets, this format doesn't seem to be too extensively used. It
662 // will be fairly easy to add support here if necessary; it's very similar to above.
663 macho.FAT_CIGAM_64 => return error.UnsupportedDebugInfo,
664
665 else => return error.InvalidMachO,
548666 };
667 return mapped_macho;
549668}
550669
551670/// Uses `mmap` to map the file at `path` into memory.
......@@ -583,4 +702,5 @@ const testing = std.testing;
583702
584703const builtin = @import("builtin");
585704
705const Uuid = @FieldType(macho.uuid_command, "uuid");
586706const MachOFile = @This();
lib/std/debug/SelfInfo/Elf.zig+4-1
......@@ -428,6 +428,9 @@ fn findModule(si: *SelfInfo, gpa: Allocator, io: Io, address: usize, lock: enum
428428 // Rebuild module list with the exclusive lock.
429429 {
430430 errdefer si.rwlock.unlock(io);
431 if (si.unwind_cache) |cache| {
432 @memset(cache, .empty);
433 }
431434 for (si.modules.items) |*mod| {
432435 unwind: {
433436 const u = &(mod.unwind orelse break :unwind catch break :unwind);
......@@ -515,7 +518,7 @@ const DlIterContext = struct {
515518 for (info.phdr[0..info.phnum]) |phdr| {
516519 if (phdr.type != .LOAD) continue;
517520 try context.si.ranges.append(gpa, .{
518 // Overflowing addition handles VSDOs having p_vaddr = 0xffffffffff700000
521 // Overflowing addition handles VSDOs having vaddr = 0xffffffffff700000
519522 .start = info.addr +% phdr.vaddr,
520523 .len = phdr.memsz,
521524 .module_index = module_index,
lib/std/debug/cpu_context.zig+2
......@@ -2020,6 +2020,8 @@ const signal_ucontext_t = switch (native_os) {
20202020 .mips64el,
20212021 .or1k,
20222022 .s390x,
2023 .sh,
2024 .sheb,
20232025 .x86,
20242026 .x86_64,
20252027 .xtensa,
lib/std/debug/no_panic.zig+10
......@@ -65,6 +65,11 @@ pub fn invalidErrorCode() noreturn {
6565 @trap();
6666}
6767
68pub fn unexpectedErrorCode(_: anyerror) noreturn {
69 @branchHint(.cold);
70 @trap();
71}
72
6873pub fn integerOutOfBounds() noreturn {
6974 @branchHint(.cold);
7075 @trap();
......@@ -134,3 +139,8 @@ pub fn noreturnReturned() noreturn {
134139 @branchHint(.cold);
135140 @trap();
136141}
142
143pub fn loadUninstantiableType() noreturn {
144 @branchHint(.cold);
145 @trap();
146}
lib/std/debug/simple_panic.zig+35
......@@ -20,109 +20,144 @@ pub fn call(msg: []const u8, ra: ?usize) noreturn {
2020}
2121
2222pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn {
23 @branchHint(.cold);
2324 _ = found;
2425 call("sentinel mismatch", null);
2526}
2627
2728pub fn unwrapError(err: anyerror) noreturn {
29 @branchHint(.cold);
2830 _ = &err;
2931 call("attempt to unwrap error", null);
3032}
3133
3234pub fn outOfBounds(index: usize, len: usize) noreturn {
35 @branchHint(.cold);
3336 _ = index;
3437 _ = len;
3538 call("index out of bounds", null);
3639}
3740
3841pub fn startGreaterThanEnd(start: usize, end: usize) noreturn {
42 @branchHint(.cold);
3943 _ = start;
4044 _ = end;
4145 call("start index is larger than end index", null);
4246}
4347
4448pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn {
49 @branchHint(.cold);
4550 _ = accessed;
4651 call("access of inactive union field", null);
4752}
4853
4954pub fn sliceCastLenRemainder(src_len: usize) noreturn {
55 @branchHint(.cold);
5056 _ = src_len;
5157 call("slice length does not divide exactly into destination elements", null);
5258}
5359
5460pub fn reachedUnreachable() noreturn {
61 @branchHint(.cold);
5562 call("reached unreachable code", null);
5663}
5764
5865pub fn unwrapNull() noreturn {
66 @branchHint(.cold);
5967 call("attempt to use null value", null);
6068}
6169
6270pub fn castToNull() noreturn {
71 @branchHint(.cold);
6372 call("cast causes pointer to be null", null);
6473}
6574
6675pub fn incorrectAlignment() noreturn {
76 @branchHint(.cold);
6777 call("incorrect alignment", null);
6878}
6979
7080pub fn invalidErrorCode() noreturn {
81 @branchHint(.cold);
7182 call("invalid error code", null);
7283}
7384
85pub fn unexpectedErrorCode(err: anyerror) noreturn {
86 @branchHint(.cold);
87 _ = err;
88 call("unexpected error code", null);
89}
90
7491pub fn integerOutOfBounds() noreturn {
92 @branchHint(.cold);
7593 call("integer does not fit in destination type", null);
7694}
7795
7896pub fn integerOverflow() noreturn {
97 @branchHint(.cold);
7998 call("integer overflow", null);
8099}
81100
82101pub fn shlOverflow() noreturn {
102 @branchHint(.cold);
83103 call("left shift overflowed bits", null);
84104}
85105
86106pub fn shrOverflow() noreturn {
107 @branchHint(.cold);
87108 call("right shift overflowed bits", null);
88109}
89110
90111pub fn divideByZero() noreturn {
112 @branchHint(.cold);
91113 call("division by zero", null);
92114}
93115
94116pub fn exactDivisionRemainder() noreturn {
117 @branchHint(.cold);
95118 call("exact division produced remainder", null);
96119}
97120
98121pub fn integerPartOutOfBounds() noreturn {
122 @branchHint(.cold);
99123 call("integer part of floating point value out of bounds", null);
100124}
101125
102126pub fn corruptSwitch() noreturn {
127 @branchHint(.cold);
103128 call("switch on corrupt value", null);
104129}
105130
106131pub fn shiftRhsTooBig() noreturn {
132 @branchHint(.cold);
107133 call("shift amount is greater than the type size", null);
108134}
109135
110136pub fn invalidEnumValue() noreturn {
137 @branchHint(.cold);
111138 call("invalid enum value", null);
112139}
113140
114141pub fn forLenMismatch() noreturn {
142 @branchHint(.cold);
115143 call("for loop over objects with non-equal lengths", null);
116144}
117145
118146pub fn copyLenMismatch() noreturn {
147 @branchHint(.cold);
119148 call("source and destination have non-equal lengths", null);
120149}
121150
122151pub fn memcpyAlias() noreturn {
152 @branchHint(.cold);
123153 call("@memcpy arguments alias", null);
124154}
125155
126156pub fn noreturnReturned() noreturn {
157 @branchHint(.cold);
127158 call("'noreturn' function returned", null);
128159}
160
161pub fn loadUninstantiableType() noreturn {
162 call("attempt to load uninstantiable type", null);
163}
lib/std/deque.zig+1-1
......@@ -696,7 +696,7 @@ fn fuzzAgainstArrayList(_: void, smith: *std.testing.Smith) anyerror!void {
696696 try q.ensureTotalCapacityPrecise(q_gpa, q.len + growth);
697697 },
698698 }
699 try testing.expectEqual(l.getLast(), q.back());
699 try testing.expectEqual(l.last(), q.back());
700700 try testing.expectEqual(
701701 if (l.items.len > 0) l.items[0] else null,
702702 q.front(),
lib/std/dynamic_library.zig+17-17
......@@ -103,7 +103,7 @@ pub fn get_DYNAMIC() ?[*]const elf.Dyn {
103103
104104pub fn linkmap_iterator() error{InvalidExe}!LinkMap.Iterator {
105105 const _DYNAMIC = get_DYNAMIC() orelse {
106 // No PT_DYNAMIC means this is a statically-linked non-PIE program.
106 // No PT.DYNAMIC means this is a statically-linked non-PIE program.
107107 return .{ .current = null };
108108 };
109109
......@@ -261,10 +261,10 @@ pub const ElfDynLib = struct {
261261 i += 1;
262262 ph_addr += eh.e_phentsize;
263263 }) {
264 const ph = @as(*elf.Phdr, @ptrFromInt(ph_addr));
265 switch (ph.p_type) {
266 elf.PT_LOAD => virt_addr_end = @max(virt_addr_end, ph.p_vaddr + ph.p_memsz),
267 elf.PT_DYNAMIC => maybe_dynv = @as([*]usize, @ptrFromInt(elf_addr + ph.p_offset)),
264 const ph = @as(*elf.ElfN.Phdr, @ptrFromInt(ph_addr));
265 switch (ph.type) {
266 .LOAD => virt_addr_end = @max(virt_addr_end, ph.vaddr + ph.memsz),
267 .DYNAMIC => maybe_dynv = @as([*]usize, @ptrFromInt(elf_addr + ph.offset)),
268268 else => {},
269269 }
270270 }
......@@ -292,23 +292,23 @@ pub const ElfDynLib = struct {
292292 i += 1;
293293 ph_addr += eh.e_phentsize;
294294 }) {
295 const ph = @as(*elf.Phdr, @ptrFromInt(ph_addr));
296 switch (ph.p_type) {
297 elf.PT_LOAD => {
295 const ph = @as(*elf.ElfN.Phdr, @ptrFromInt(ph_addr));
296 switch (ph.type) {
297 .LOAD => {
298298 // The VirtAddr may not be page-aligned; in such case there will be
299299 // extra nonsense mapped before/after the VirtAddr,MemSiz
300 const aligned_addr = (base + ph.p_vaddr) & ~(@as(usize, page_size) - 1);
301 const extra_bytes = (base + ph.p_vaddr) - aligned_addr;
302 const extended_memsz = mem.alignForward(usize, ph.p_memsz + extra_bytes, page_size);
300 const aligned_addr = (base + ph.vaddr) & ~(@as(usize, page_size) - 1);
301 const extra_bytes = (base + ph.vaddr) - aligned_addr;
302 const extended_memsz = mem.alignForward(usize, ph.memsz + extra_bytes, page_size);
303303 const ptr = @as([*]align(std.heap.page_size_min) u8, @ptrFromInt(aligned_addr));
304 const prot = elfToProt(ph.p_flags);
304 const prot = elfToProt(ph.flags);
305305 _ = try posix.mmap(
306306 ptr,
307307 extended_memsz,
308308 prot,
309309 .{ .TYPE = .PRIVATE, .FIXED = true },
310310 file.handle,
311 ph.p_offset - extra_bytes,
311 ph.offset - extra_bytes,
312312 );
313313 },
314314 else => {},
......@@ -517,11 +517,11 @@ pub const ElfDynLib = struct {
517517 return null;
518518 }
519519
520 fn elfToProt(elf_prot: u64) posix.PROT {
520 fn elfToProt(elf_prot: elf.PF) posix.PROT {
521521 return .{
522 .READ = (elf_prot & elf.PF_R) != 0,
523 .WRITE = (elf_prot & elf.PF_W) != 0,
524 .EXEC = (elf_prot & elf.PF_X) != 0,
522 .READ = elf_prot.R,
523 .WRITE = elf_prot.W,
524 .EXEC = elf_prot.X,
525525 };
526526 }
527527};
lib/std/elf.zig+19-88
......@@ -290,47 +290,6 @@ pub const VER_FLG_BASE = 1;
290290/// Weak version identifier
291291pub const VER_FLG_WEAK = 2;
292292
293/// Deprecated, use `@intFromEnum(std.elf.PT.NULL)`
294pub const PT_NULL = @backingInt(std.elf.PT.NULL);
295/// Deprecated, use `@intFromEnum(std.elf.PT.LOAD)`
296pub const PT_LOAD = @backingInt(std.elf.PT.LOAD);
297/// Deprecated, use `@intFromEnum(std.elf.PT.DYNAMIC)`
298pub const PT_DYNAMIC = @backingInt(std.elf.PT.DYNAMIC);
299/// Deprecated, use `@intFromEnum(std.elf.PT.INTERP)`
300pub const PT_INTERP = @backingInt(std.elf.PT.INTERP);
301/// Deprecated, use `@intFromEnum(std.elf.PT.NOTE)`
302pub const PT_NOTE = @backingInt(std.elf.PT.NOTE);
303/// Deprecated, use `@intFromEnum(std.elf.PT.SHLIB)`
304pub const PT_SHLIB = @backingInt(std.elf.PT.SHLIB);
305/// Deprecated, use `@intFromEnum(std.elf.PT.PHDR)`
306pub const PT_PHDR = @backingInt(std.elf.PT.PHDR);
307/// Deprecated, use `@intFromEnum(std.elf.PT.TLS)`
308pub const PT_TLS = @backingInt(std.elf.PT.TLS);
309/// Deprecated, use `std.elf.PT.NUM`.
310pub const PT_NUM = PT.NUM;
311/// Deprecated, use `@intFromEnum(std.elf.PT.LOOS)`
312pub const PT_LOOS = @backingInt(std.elf.PT.LOOS);
313/// Deprecated, use `@intFromEnum(std.elf.PT.GNU_EH_FRAME)`
314pub const PT_GNU_EH_FRAME = @backingInt(std.elf.PT.GNU_EH_FRAME);
315/// Deprecated, use `@intFromEnum(std.elf.PT.GNU_STACK)`
316pub const PT_GNU_STACK = @backingInt(std.elf.PT.GNU_STACK);
317/// Deprecated, use `@intFromEnum(std.elf.PT.GNU_RELRO)`
318pub const PT_GNU_RELRO = @backingInt(std.elf.PT.GNU_RELRO);
319/// Deprecated, use `@intFromEnum(std.elf.PT.LOSUNW)`
320pub const PT_LOSUNW = @backingInt(std.elf.PT.LOSUNW);
321/// Deprecated, use `@intFromEnum(std.elf.PT.SUNWBSS)`
322pub const PT_SUNWBSS = @backingInt(std.elf.PT.SUNWBSS);
323/// Deprecated, use `@intFromEnum(std.elf.PT.SUNWSTACK)`
324pub const PT_SUNWSTACK = @backingInt(std.elf.PT.SUNWSTACK);
325/// Deprecated, use `@intFromEnum(std.elf.PT.HISUNW)`
326pub const PT_HISUNW = @backingInt(std.elf.PT.HISUNW);
327/// Deprecated, use `@intFromEnum(std.elf.PT.HIOS)`
328pub const PT_HIOS = @backingInt(std.elf.PT.HIOS);
329/// Deprecated, use `@intFromEnum(std.elf.PT.LOPROC)`
330pub const PT_LOPROC = @backingInt(std.elf.PT.LOPROC);
331/// Deprecated, use `@intFromEnum(std.elf.PT.HIPROC)`
332pub const PT_HIPROC = @backingInt(std.elf.PT.HIPROC);
333
334293pub const PN_XNUM = 0xffff;
335294
336295/// Deprecated, use `@intFromEnum(std.elf.SHT.NULL)`
......@@ -848,11 +807,11 @@ pub const ProgramHeaderIterator = struct {
848807 file_reader: *Io.File.Reader,
849808 index: usize = 0,
850809
851 pub fn next(it: *ProgramHeaderIterator) !?Elf64_Phdr {
810 pub fn next(it: *ProgramHeaderIterator) !?Elf64.Phdr {
852811 if (it.index >= it.phnum) return null;
853812 defer it.index += 1;
854813
855 const size: u64 = if (it.is_64) @sizeOf(Elf64_Phdr) else @sizeOf(Elf32_Phdr);
814 const size: u64 = if (it.is_64) @sizeOf(Elf64.Phdr) else @sizeOf(Elf32.Phdr);
856815 const offset = it.phoff + size * it.index;
857816 try it.file_reader.seekTo(offset);
858817
......@@ -869,11 +828,11 @@ pub const ProgramHeaderBufferIterator = struct {
869828 buf: []const u8,
870829 index: usize = 0,
871830
872 pub fn next(it: *ProgramHeaderBufferIterator) !?Elf64_Phdr {
831 pub fn next(it: *ProgramHeaderBufferIterator) !?Elf64.Phdr {
873832 if (it.index >= it.phnum) return null;
874833 defer it.index += 1;
875834
876 const size: usize = if (it.is_64) @sizeOf(Elf64_Phdr) else @sizeOf(Elf32_Phdr);
835 const size: usize = if (it.is_64) @sizeOf(Elf64.Phdr) else @sizeOf(Elf32.Phdr);
877836 const offset = @as(usize, @intCast(it.phoff)) + size * it.index;
878837 var reader = Io.Reader.fixed(it.buf[offset..]);
879838
......@@ -881,22 +840,22 @@ pub const ProgramHeaderBufferIterator = struct {
881840 }
882841};
883842
884pub fn takeProgramHeader(reader: *Io.Reader, is_64: bool, endian: Endian) !Elf64_Phdr {
843pub fn takeProgramHeader(reader: *Io.Reader, is_64: bool, endian: Endian) !Elf64.Phdr {
885844 if (is_64) {
886 const phdr = try reader.takeStruct(Elf64_Phdr, endian);
845 const phdr = try reader.takeStruct(Elf64.Phdr, endian);
887846 return phdr;
888847 }
889848
890 const phdr = try reader.takeStruct(Elf32_Phdr, endian);
849 const phdr = try reader.takeStruct(Elf32.Phdr, endian);
891850 return .{
892 .p_type = phdr.p_type,
893 .p_offset = phdr.p_offset,
894 .p_vaddr = phdr.p_vaddr,
895 .p_paddr = phdr.p_paddr,
896 .p_filesz = phdr.p_filesz,
897 .p_memsz = phdr.p_memsz,
898 .p_flags = phdr.p_flags,
899 .p_align = phdr.p_align,
851 .type = phdr.type,
852 .offset = phdr.offset,
853 .vaddr = phdr.vaddr,
854 .paddr = phdr.paddr,
855 .filesz = phdr.filesz,
856 .memsz = phdr.memsz,
857 .flags = phdr.flags,
858 .@"align" = phdr.@"align",
900859 };
901860}
902861
......@@ -1276,28 +1235,6 @@ pub const Elf64_Ehdr = extern struct {
12761235 e_shnum: Half,
12771236 e_shstrndx: Half,
12781237};
1279/// Deprecated, use `std.elf.Elf32.Phdr`
1280pub const Elf32_Phdr = extern struct {
1281 p_type: Word,
1282 p_offset: Elf32_Off,
1283 p_vaddr: Elf32_Addr,
1284 p_paddr: Elf32_Addr,
1285 p_filesz: Word,
1286 p_memsz: Word,
1287 p_flags: Word,
1288 p_align: Word,
1289};
1290/// Deprecated, use `std.elf.Elf64.Phdr`
1291pub const Elf64_Phdr = extern struct {
1292 p_type: Word,
1293 p_flags: Word,
1294 p_offset: Elf64_Off,
1295 p_vaddr: Elf64_Addr,
1296 p_paddr: Elf64_Addr,
1297 p_filesz: Elf64_Xword,
1298 p_memsz: Elf64_Xword,
1299 p_align: Elf64_Xword,
1300};
13011238/// Deprecated, use `std.elf.Elf32.Shdr`
13021239pub const Elf32_Shdr = extern struct {
13031240 sh_name: Word,
......@@ -1568,12 +1505,6 @@ pub const Ehdr = switch (@sizeOf(usize)) {
15681505 8 => Elf64_Ehdr,
15691506 else => @compileError("expected pointer size of 32 or 64"),
15701507};
1571/// Deprecated, use `std.elf.ElfN.Phdr`
1572pub const Phdr = switch (@sizeOf(usize)) {
1573 4 => Elf32_Phdr,
1574 8 => Elf64_Phdr,
1575 else => @compileError("expected pointer size of 32 or 64"),
1576};
15771508pub const Dyn = switch (@sizeOf(usize)) {
15781509 4 => Elf32_Dyn,
15791510 8 => Elf64_Dyn,
......@@ -3272,12 +3203,12 @@ pub const ar_hdr = extern struct {
32723203 ar_fmag: [2]u8,
32733204
32743205 pub fn date(self: ar_hdr) std.fmt.ParseIntError!u64 {
3275 const value = mem.trimEnd(u8, &self.ar_date, &[_]u8{0x20});
3206 const value = mem.trimEnd(u8, &self.ar_date, " ");
32763207 return std.fmt.parseInt(u64, value, 10);
32773208 }
32783209
32793210 pub fn size(self: ar_hdr) std.fmt.ParseIntError!u32 {
3280 const value = mem.trimEnd(u8, &self.ar_size, &[_]u8{0x20});
3211 const value = mem.trimEnd(u8, &self.ar_size, " ");
32813212 return std.fmt.parseInt(u32, value, 10);
32823213 }
32833214
......@@ -3311,7 +3242,7 @@ pub const ar_hdr = extern struct {
33113242 pub fn nameOffset(self: ar_hdr) std.fmt.ParseIntError!?u32 {
33123243 const value = &self.ar_name;
33133244 if (value[0] != '/') return null;
3314 const trimmed = mem.trimEnd(u8, value, &[_]u8{0x20});
3245 const trimmed = mem.trimEnd(u8, value, " ");
33153246 return try std.fmt.parseInt(u32, trimmed[1..], 10);
33163247 }
33173248};
......@@ -3319,7 +3250,7 @@ pub const ar_hdr = extern struct {
33193250fn genSpecialMemberName(comptime name: []const u8) *const [16]u8 {
33203251 assert(name.len <= 16);
33213252 const padding = 16 - name.len;
3322 return name ++ @as([padding]u8, @splat(0x20));
3253 return name ++ @as([padding]u8, @splat(' '));
33233254}
33243255
33253256// Archive files start with the ARMAG identifying string. Then follows a
lib/std/enums.zig+3-2
......@@ -33,7 +33,8 @@ pub fn fromInt(comptime E: type, integer: anytype) ?E {
3333pub fn EnumFieldStruct(comptime E: type, comptime Data: type, comptime field_default: ?Data) type {
3434 @setEvalBranchQuota(@typeInfo(E).@"enum".field_names.len + eval_branch_quota_cushion);
3535 const default_ptr: ?*const anyopaque = if (field_default) |d| @ptrCast(&d) else null;
36 return @Struct(.auto, null, std.meta.fieldNames(E), &@splat(Data), &@splat(.{ .default_value_ptr = default_ptr }));
36 const field_names = @typeInfo(E).@"enum".field_names;
37 return @Struct(.auto, null, field_names, &@splat(Data), &@splat(.{ .default_value_ptr = default_ptr }));
3738}
3839
3940/// 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 {
454455 }
455456 }
456457 } else {
457 inline for (std.meta.fieldNames(E)) |field_name| {
458 inline for (@typeInfo(E).@"enum".field_names) |field_name| {
458459 const key = @field(E, field_name);
459460 if (@field(init_values, field_name)) |*v| {
460461 const i = comptime Indexer.indexOf(key);
lib/std/fmt.zig+2-4
......@@ -261,7 +261,7 @@ test printInt {
261261
262262/// Converts values in the range [0, 100) to a base 10 string.
263263pub fn digits2(value: u8) [2]u8 {
264 if (builtin.mode == .ReleaseSmall) {
264 if (builtin.mode == .small) {
265265 return .{ @intCast('0' + value / 10), @intCast('0' + value % 10) };
266266 } else {
267267 return "00010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899"[value * 2 ..][0..2].*;
......@@ -924,7 +924,7 @@ test "enum" {
924924
925925 // test very large enum to verify ct branch quota is large enough
926926 // TODO: https://github.com/ziglang/zig/issues/15609
927 if (!((builtin.cpu.arch == .wasm32) and builtin.mode == .Debug)) {
927 if (!((builtin.cpu.arch == .wasm32) and builtin.mode == .debug)) {
928928 try expectFmt("enum: .INVALID_FUNCTION\n", "enum: {}\n", .{std.os.windows.Win32Error.INVALID_FUNCTION});
929929 }
930930
......@@ -1082,8 +1082,6 @@ test "float.libc.sanity" {
10821082}
10831083
10841084test "union" {
1085 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1086
10871085 const TU = union(enum) {
10881086 float: f32,
10891087 int: u32,
lib/std/fmt/float.zig+1-1
......@@ -65,7 +65,7 @@ pub fn render(buf: []u8, value: anytype, options: Options) Error![]const u8 {
6565
6666 const DT = if (@bitSizeOf(T) <= 64) u64 else u128;
6767 const tables = switch (DT) {
68 u64 => if (@import("builtin").mode == .ReleaseSmall) &Backend64_TablesSmall else &Backend64_TablesFull,
68 u64 => if (builtin.mode == .small) &Backend64_TablesSmall else &Backend64_TablesFull,
6969 u128 => &Backend128_Tables,
7070 else => unreachable,
7171 };
lib/std/fs/path.zig+9-3
......@@ -1830,7 +1830,7 @@ fn testRelativeWindows(from: []const u8, to: []const u8, expected_output: []cons
18301830/// pointer address range of `path`, even if it is length zero.
18311831pub fn extension(path: []const u8) []const u8 {
18321832 const filename = basename(path);
1833 const index = mem.lastIndexOfScalar(u8, filename, '.') orelse return path[path.len..];
1833 const index = mem.findScalarLast(u8, filename, '.') orelse return path[path.len..];
18341834 if (index == 0) return path[path.len..];
18351835 return filename[index..];
18361836}
......@@ -1887,8 +1887,8 @@ test extension {
18871887/// - "hello/world/lib" ⇒ "lib"
18881888pub fn stem(path: []const u8) []const u8 {
18891889 const filename = basename(path);
1890 const index = mem.lastIndexOfScalar(u8, filename, '.') orelse return filename[0..];
1891 if (index == 0) return path;
1890 const index = mem.findScalarLast(u8, filename, '.') orelse return filename;
1891 if (index == 0) return filename;
18921892 return filename[0..index];
18931893}
18941894
......@@ -1904,8 +1904,14 @@ test stem {
19041904 try testStem("hello...", "hello..");
19051905 try testStem("hello.", "hello");
19061906 try testStem("/hello.", "hello");
1907 try testStem("hello/world/.gitignore", ".gitignore");
1908 try testStem("/.gitignore", ".gitignore");
19071909 try testStem(".gitignore", ".gitignore");
1910 try testStem(".gitignore/", ".gitignore");
1911 try testStem("hello/world/.image.png", ".image");
1912 try testStem("/.image.png", ".image");
19081913 try testStem(".image.png", ".image");
1914 try testStem(".image.png/", ".image");
19091915 try testStem("file.ext", "file");
19101916 try testStem("file.ext.", "file.ext");
19111917 try testStem("a.b.c", "a.b");
lib/std/fs/test.zig+41-3
......@@ -758,6 +758,43 @@ test "readFileAlloc" {
758758 );
759759}
760760
761test "file operations with follow_symlinks=false" {
762 const io = testing.io;
763
764 var tmp_dir = tmpDir(.{});
765 defer tmp_dir.cleanup();
766
767 const contents = "this is a test.\nthis is a test.\nthis is a test.\nthis is a test.\n";
768 try tmp_dir.dir.writeFile(io, .{
769 .sub_path = "test_file",
770 .data = contents,
771 });
772
773 // Without lock
774 {
775 var file = try tmp_dir.dir.openFile(io, "test_file", .{ .follow_symlinks = false });
776 defer file.close(io);
777
778 var file_reader = file.reader(io, &.{});
779 const actual_contents = try file_reader.interface.allocRemaining(testing.allocator, .unlimited);
780 defer testing.allocator.free(actual_contents);
781
782 try std.testing.expectEqualSlices(u8, contents, actual_contents);
783 }
784
785 // With lock
786 {
787 var file = try tmp_dir.dir.openFile(io, "test_file", .{ .follow_symlinks = false, .lock = .exclusive });
788 defer file.close(io);
789
790 var file_reader = file.reader(io, &.{});
791 const actual_contents = try file_reader.interface.allocRemaining(testing.allocator, .unlimited);
792 defer testing.allocator.free(actual_contents);
793
794 try std.testing.expectEqualSlices(u8, contents, actual_contents);
795 }
796}
797
761798test "Dir.statFile" {
762799 try testWithAllSupportedPathTypes(struct {
763800 fn impl(ctx: *TestContext) !void {
......@@ -902,6 +939,8 @@ test "createDirPathOpen parent dirs do not exist" {
902939}
903940
904941test "deleteDir" {
942 if (builtin.target.os.tag == .windows) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35686
943
905944 try testWithAllSupportedPathTypes(struct {
906945 fn impl(ctx: *TestContext) !void {
907946 const io = ctx.io;
......@@ -2168,7 +2207,7 @@ test "'.' and '..' in absolute functions" {
21682207}
21692208
21702209test "chmod" {
2171 if (native_os == .windows or native_os == .wasi) return;
2210 if (native_os == .windows or native_os == .wasi) return error.SkipZigTest;
21722211
21732212 const io = testing.io;
21742213
......@@ -2191,8 +2230,7 @@ test "chmod" {
21912230}
21922231
21932232test "change ownership" {
2194 if (native_os == .windows or native_os == .wasi)
2195 return error.SkipZigTest;
2233 if (native_os == .windows or native_os == .wasi) return error.SkipZigTest;
21962234
21972235 const io = testing.io;
21982236
lib/std/hash/auto_hash.zig+1-1
......@@ -225,7 +225,7 @@ fn testHashDeepRecursive(key: anytype) u64 {
225225
226226test "typeContainsSlice" {
227227 comptime {
228 try testing.expect(!typeContainsSlice(std.meta.Tag(std.builtin.Type)));
228 try testing.expect(!typeContainsSlice(std.meta.Tag(std.lang.Type)));
229229
230230 try testing.expect(typeContainsSlice([]const u8));
231231 try testing.expect(!typeContainsSlice(u8));
lib/std/hash/benchmark.zig+1-1
......@@ -355,7 +355,7 @@ fn usage() void {
355355}
356356
357357fn mode(comptime x: comptime_int) comptime_int {
358 return if (builtin.mode == .Debug) x / 64 else x;
358 return if (builtin.mode == .debug) x / 64 else x;
359359}
360360
361361pub fn main(init: std.process.Init) !void {
lib/std/hash/cityhash.zig+1-1
......@@ -16,7 +16,7 @@ fn fetch64(ptr: [*]const u8, offset: usize) u64 {
1616pub const CityHash32 = struct {
1717 const Self = @This();
1818
19 // Magic numbers for 32-bit hashing. Copied from Murmur3.
19 // Magic numbers for 32-bit hashing. Copied from Murmur3.
2020 const c1: u32 = 0xcc9e2d51;
2121 const c2: u32 = 0x1b873593;
2222
lib/std/hash/xxhash.zig+1-5
......@@ -1,5 +1,4 @@
11const std = @import("std");
2const builtin = @import("builtin");
32const mem = std.mem;
43const expectEqual = std.testing.expectEqual;
54
......@@ -761,7 +760,7 @@ pub const XxHash3 = struct {
761760 var accumulator_copy = self.accumulator;
762761 var last_block_copy: [block_bytes]u8 = undefined;
763762
764 // Digest the last block onthe Accumulator copy.
763 // Digest the last block on the Accumulator copy.
765764 return accumulator_copy.digest(self.total_len, last_block: {
766765 if (self.buffered >= block_bytes) {
767766 const block_count = ((self.buffered - 1) / block_bytes) * block_bytes;
......@@ -788,7 +787,6 @@ fn testExpect(comptime H: type, seed: anytype, input: []const u8, expected: u64)
788787}
789788
790789test "xxhash3" {
791 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
792790 const H = XxHash3;
793791 // Non-Seeded Tests
794792 try testExpect(H, 0, "", 0x2d06800538d394c2);
......@@ -820,7 +818,6 @@ test "xxhash3" {
820818}
821819
822820test "xxhash3 smhasher" {
823 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
824821 const Test = struct {
825822 fn do() !void {
826823 try expectEqual(verify.smhasher(XxHash3.hash), 0x9a636405);
......@@ -832,7 +829,6 @@ test "xxhash3 smhasher" {
832829}
833830
834831test "xxhash3 iterative api" {
835 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
836832 const Test = struct {
837833 fn do() !void {
838834 try verify.iterativeApi(XxHash3);
lib/std/hash_map.zig+1-1
......@@ -1518,7 +1518,7 @@ fn Custom(
15181518 self.available = 0;
15191519 }
15201520
1521 /// This function is used in the debugger pretty formatters in tools/ to fetch the
1521 /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the
15221522 /// header type to facilitate fancy debug printing for this type.
15231523 fn dbHelper(self: *Self, hdr: *Header, entry: *Entry) void {
15241524 _ = self;
lib/std/heap/PageAllocator.zig+1
......@@ -24,6 +24,7 @@ pub const vtable: Allocator.VTable = .{
2424/// that don't provide a hint (for security reasons, but it serves our needs
2525/// too).
2626const enable_hints = switch (builtin.target.os.tag) {
27 .linux => !builtin.target.cpu.arch.isSPARC(), // https://bugzilla.kernel.org/show_bug.cgi?id=221820
2728 .openbsd => false,
2829 else => true,
2930};
lib/std/heap/SafeAllocator.zig+2-2
......@@ -39,7 +39,7 @@ const SafeAllocator = @This();
3939const scoped_log = std.log.scoped(.SafeAllocator);
4040
4141pub const Options = struct {
42 const is_debug = @import("builtin").mode == .Debug;
42 const is_debug = @import("builtin").mode == .debug;
4343 const page_size_log2 = @max(math.log2_int(usize, std.heap.page_size_max), 8);
4444
4545 stack_trace_frames: usize = if (is_debug and std.debug.sys_can_stack_trace) 7 else 0,
......@@ -1519,7 +1519,7 @@ const FuzzSingleThreadedAllocator = struct {
15191519 @disableInstrumentation();
15201520
15211521 const allocs_slice = f.allocs.slice();
1522 const i = mem.indexOfScalar([*]u8, allocs_slice.items(.ptr), memory.ptr) orelse panic(
1522 const i = mem.findScalar([*]u8, allocs_slice.items(.ptr), memory.ptr) orelse panic(
15231523 "invalid SafeAllocator free of {f}",
15241524 .{FormatMemory{ .memory = memory, .alignment = alignment }},
15251525 );
lib/std/http.zig+8-5
......@@ -20,6 +20,8 @@ pub const Version = enum {
2020/// https://datatracker.ietf.org/doc/html/rfc7231#section-4 Initial definition
2121///
2222/// https://datatracker.ietf.org/doc/html/rfc5789#section-2 PATCH
23///
24/// https://datatracker.ietf.org/doc/html/rfc10008#name-query-method QUERY
2325pub const Method = enum {
2426 GET,
2527 HEAD,
......@@ -30,12 +32,13 @@ pub const Method = enum {
3032 OPTIONS,
3133 TRACE,
3234 PATCH,
35 QUERY,
3336
3437 /// Returns true if a request of this method is allowed to have a body
3538 /// Actual behavior from servers may vary and should still be checked
3639 pub fn requestHasBody(m: Method) bool {
3740 return switch (m) {
38 .POST, .PUT, .PATCH => true,
41 .POST, .PUT, .PATCH, .QUERY => true,
3942 .GET, .HEAD, .DELETE, .CONNECT, .OPTIONS, .TRACE => false,
4043 };
4144 }
......@@ -44,7 +47,7 @@ pub const Method = enum {
4447 /// Actual behavior from clients may vary and should still be checked
4548 pub fn responseHasBody(m: Method) bool {
4649 return switch (m) {
47 .GET, .POST, .PUT, .DELETE, .CONNECT, .OPTIONS, .PATCH => true,
50 .GET, .POST, .PUT, .DELETE, .CONNECT, .OPTIONS, .PATCH, .QUERY => true,
4851 .HEAD, .TRACE => false,
4952 };
5053 }
......@@ -56,7 +59,7 @@ pub const Method = enum {
5659 /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.1
5760 pub fn safe(m: Method) bool {
5861 return switch (m) {
59 .GET, .HEAD, .OPTIONS, .TRACE => true,
62 .GET, .HEAD, .OPTIONS, .TRACE, .QUERY => true,
6063 .POST, .PUT, .DELETE, .CONNECT, .PATCH => false,
6164 };
6265 }
......@@ -70,7 +73,7 @@ pub const Method = enum {
7073 /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.2
7174 pub fn idempotent(m: Method) bool {
7275 return switch (m) {
73 .GET, .HEAD, .PUT, .DELETE, .OPTIONS, .TRACE => true,
76 .GET, .HEAD, .PUT, .DELETE, .OPTIONS, .TRACE, .QUERY => true,
7477 .CONNECT, .POST, .PATCH => false,
7578 };
7679 }
......@@ -83,7 +86,7 @@ pub const Method = enum {
8386 /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.3
8487 pub fn cacheable(m: Method) bool {
8588 return switch (m) {
86 .GET, .HEAD => true,
89 .GET, .HEAD, .QUERY => true,
8790 .POST, .PUT, .DELETE, .CONNECT, .OPTIONS, .TRACE, .PATCH => false,
8891 };
8992 }
lib/std/http/Server.zig+1-1
......@@ -102,7 +102,7 @@ pub const Request = struct {
102102 const method = std.meta.stringToEnum(http.Method, first_line[0..method_end]) orelse
103103 return error.UnknownHttpMethod;
104104
105 const version_start = mem.lastIndexOfScalar(u8, first_line, ' ') orelse
105 const version_start = mem.findScalarLast(u8, first_line, ' ') orelse
106106 return error.HttpHeadersInvalid;
107107 if (version_start == method_end) return error.HttpHeadersInvalid;
108108
lib/std/http/test.zig+1-20
......@@ -1,5 +1,4 @@
11const builtin = @import("builtin");
2const native_endian = builtin.cpu.arch.endian();
32
43const std = @import("std");
54const http = std.http;
......@@ -34,7 +33,6 @@ test "content length reader state update" {
3433}
3534
3635test "trailers" {
37 if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257
3836 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
3937
4038 const io = std.testing.io;
......@@ -121,7 +119,6 @@ test "trailers" {
121119}
122120
123121test "HTTP server handles a chunked transfer coding request" {
124 if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257
125122 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
126123
127124 const io = std.testing.io;
......@@ -190,7 +187,6 @@ test "HTTP server handles a chunked transfer coding request" {
190187}
191188
192189test "echo content server" {
193 if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257
194190 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
195191
196192 const io = std.testing.io;
......@@ -281,12 +277,11 @@ test "echo content server" {
281277}
282278
283279test "Server.Request.respondStreaming non-chunked, unknown content-length" {
284 if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257
285280 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
286281
287282 const io = std.testing.io;
288283
289 if (builtin.os.tag == .windows) {
284 if (builtin.cpu.arch == .aarch64 and builtin.os.tag == .windows) {
290285 // https://github.com/ziglang/zig/issues/21457
291286 return error.SkipZigTest;
292287 }
......@@ -360,7 +355,6 @@ test "Server.Request.respondStreaming non-chunked, unknown content-length" {
360355}
361356
362357test "receiving arbitrary http headers from the client" {
363 if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257
364358 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
365359
366360 const io = std.testing.io;
......@@ -426,16 +420,10 @@ test "receiving arbitrary http headers from the client" {
426420}
427421
428422test "general client/server API coverage" {
429 if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257
430423 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
431424
432425 const io = std.testing.io;
433426
434 if (builtin.os.tag == .windows) {
435 // This test was never passing on Windows.
436 return error.SkipZigTest;
437 }
438
439427 const test_server = try createTestServer(io, struct {
440428 fn run(test_server: *TestServer) anyerror!void {
441429 const net_server = &test_server.net_server;
......@@ -922,7 +910,6 @@ test "general client/server API coverage" {
922910}
923911
924912test "Server streams both reading and writing" {
925 if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257
926913 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
927914
928915 const io = std.testing.io;
......@@ -1162,10 +1149,6 @@ const TestServer = struct {
11621149
11631150fn createTestServer(io: Io, S: type) !*TestServer {
11641151 if (builtin.single_threaded) return error.SkipZigTest;
1165 if (builtin.zig_backend == .stage2_llvm and native_endian == .big) {
1166 // https://github.com/ziglang/zig/issues/13782
1167 return error.SkipZigTest;
1168 }
11691152
11701153 const address = try net.IpAddress.parse("127.0.0.1", 0);
11711154
......@@ -1192,7 +1175,6 @@ fn createTestServer(io: Io, S: type) !*TestServer {
11921175}
11931176
11941177test "redirect to different connection" {
1195 if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257
11961178 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
11971179
11981180 const io = std.testing.io;
......@@ -1280,7 +1262,6 @@ test "redirect to different connection" {
12801262}
12811263
12821264test "boot failed connections from the pool" {
1283 if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257
12841265 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
12851266
12861267 const io = std.testing.io;
lib/std/json/Stringify.zig+3-3
......@@ -54,8 +54,8 @@ else
5454 void = if (build_mode_has_safety) .none else {},
5555
5656const build_mode_has_safety = switch (@import("builtin").mode) {
57 .Debug, .ReleaseSafe => true,
58 .ReleaseFast, .ReleaseSmall => false,
57 .debug, .safe => true,
58 .fast, .small => false,
5959};
6060
6161/// 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) {
6666/// If `.checked_to_fixed_depth` is used, there is additionally an assertion that the nesting depth never exceeds the given limit.
6767/// `.checked_to_fixed_depth` embeds the storage required in the `Stringify` struct.
6868/// `.assumed_correct` requires no space and performs none of these assertions.
69/// In `ReleaseFast` and `ReleaseSmall` mode, the given `safety_checks_hint` is ignored and is always treated as `.assumed_correct`.
69/// In fast and small optimization modes, the given `safety_checks_hint` is ignored and is always treated as `.assumed_correct`.
7070const safety_checks_hint: union(enum) {
7171 /// Rounded up to the nearest multiple of 8.
7272 checked_to_fixed_depth: usize,
lib/std/lang.zig+47-5
......@@ -107,13 +107,52 @@ pub const CodeModel = enum(u4) {
107107 tiny,
108108};
109109
110/// Deprecated, to be removed after 0.18.0
111pub const OptimizeMode = Optimize;
112
110113/// This data structure is used by the Zig language code generation and
111114/// therefore must be kept in sync with the compiler implementation.
112pub const OptimizeMode = enum {
113 Debug,
114 ReleaseSafe,
115 ReleaseFast,
116 ReleaseSmall,
115pub const Optimize = enum {
116 /// Safety checks enabled. Optimize for bug detection, accurate debug info,
117 /// and compilation speed (in that order).
118 debug,
119 /// Safety checks enabled. Optimize for runtime performance.
120 safe,
121 /// Safety checks disabled. Optimize for runtime performance.
122 fast,
123 /// Safety checks disabled. Optimize for machine code size, then runtime performance.
124 small,
125
126 /// Deprecated, to be removed after 0.18.0
127 pub const Debug: @This() = .debug;
128 /// Deprecated, to be removed after 0.18.0
129 pub const ReleaseSafe: @This() = .safe;
130 /// Deprecated, to be removed after 0.18.0
131 pub const ReleaseFast: @This() = .fast;
132 /// Deprecated, to be removed after 0.18.0
133 pub const ReleaseSmall: @This() = .small;
134 /// Deprecated, to be removed after 0.18.0
135 pub fn fromString(s: []const u8) ?@This() {
136 return std.StaticStringMap(@This()).initComptime(&.{
137 .{ "Debug", .debug },
138 .{ "ReleaseSafe", .safe },
139 .{ "ReleaseFast", .fast },
140 .{ "ReleaseSmall", .small },
141 .{ "debug", .debug },
142 .{ "safe", .safe },
143 .{ "fast", .fast },
144 .{ "small", .small },
145 }).get(s);
146 }
147
148 /// Returns whether illegal behavior safety checks are enabled based on the
149 /// provided optimization mode.
150 pub fn runtimeSafety(o: @This()) bool {
151 return switch (o) {
152 .debug, .safe => true,
153 .fast, .small => false,
154 };
155 }
117156};
118157
119158/// The calling convention of a function defines how arguments and return values are passed, as well
......@@ -171,10 +210,12 @@ pub const CallingConvention = union(enum(u8)) {
171210 x86_64_regcall_v4_win: CommonOptions,
172211 x86_64_vectorcall: CommonOptions,
173212 x86_64_interrupt: CommonOptions,
213 x86_64_preserve_none: CommonOptions,
174214
175215 // Calling conventions for the `x86` architecture.
176216 x86_sysv: X86RegparmOptions,
177217 x86_win: X86RegparmOptions,
218 x86_mingw: X86RegparmOptions,
178219 x86_stdcall: X86RegparmOptions,
179220 x86_fastcall: CommonOptions,
180221 x86_thiscall: CommonOptions,
......@@ -197,6 +238,7 @@ pub const CallingConvention = union(enum(u8)) {
197238 aarch64_aapcs_win: CommonOptions,
198239 aarch64_vfabi: CommonOptions,
199240 aarch64_vfabi_sve: CommonOptions,
241 aarch64_preserve_none: CommonOptions,
200242
201243 /// The standard `alpha` calling convention.
202244 alpha_osf: CommonOptions,
lib/std/log.zig+1-1
......@@ -53,7 +53,7 @@ pub const Level = enum {
5353/// The default log level is based on build mode.
5454pub const default_level: Level = switch (builtin.mode) {
5555 .Debug => .debug,
56 .ReleaseSafe, .ReleaseFast, .ReleaseSmall => .info,
56 .safe, .fast, .small => .info,
5757};
5858
5959pub const ScopeLevel = struct {
lib/std/macho.zig+19
......@@ -588,6 +588,25 @@ pub const rpath_command = extern struct {
588588 path: u32,
589589};
590590
591pub const encryption_info_command = extern struct {
592 cmd: LC = .ENCRYPTION_INFO,
593 cmdsize: u32 = @sizeOf(encryption_info_command),
594
595 cryptoff: u32,
596 cryptsize: u32,
597 cryptid: u32 = 0,
598};
599
600pub const encryption_info_command_64 = extern struct {
601 cmd: LC = .ENCRYPTION_INFO_64,
602 cmdsize: u32 = @sizeOf(encryption_info_command_64),
603
604 cryptoff: u32,
605 cryptsize: u32,
606 cryptid: u32 = 0,
607 _pad: u32 = 0,
608};
609
591610/// The segment load command indicates that a part of this file is to be
592611/// mapped into the task's address space. The size of this segment in memory,
593612/// vmsize, maybe equal to or larger than the amount to map from this file,
lib/std/math.zig+5-4
......@@ -75,7 +75,7 @@ pub const snan = float.snan;
7575///
7676/// NaN values are never considered equal to any value.
7777pub fn approxEqAbs(comptime T: type, x: T, y: T, tolerance: T) bool {
78 assert(@typeInfo(T) == .float or @typeInfo(T) == .comptime_float);
78 comptime assert(@typeInfo(T) == .float or @typeInfo(T) == .comptime_float);
7979 assert(tolerance >= 0);
8080
8181 // 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 {
103103///
104104/// NaN values are never considered equal to any value.
105105pub fn approxEqRel(comptime T: type, x: T, y: T, tolerance: T) bool {
106 assert(@typeInfo(T) == .float or @typeInfo(T) == .comptime_float);
106 comptime assert(@typeInfo(T) == .float or @typeInfo(T) == .comptime_float);
107107 assert(tolerance > 0);
108108
109109 // Fast path for equal values (and signed zeros and infinites).
......@@ -461,7 +461,7 @@ pub fn wrap(x: anytype, r: anytype) @TypeOf(x) {
461461 }
462462}
463463test wrap {
464 if (builtin.os.tag == .windows and builtin.cpu.arch == .x86) {
464 if (builtin.os.tag == .windows and builtin.cpu.arch == .x86 and builtin.abi == .msvc) {
465465 // https://codeberg.org/ziglang/zig/issues/35520
466466 return error.SkipZigTest;
467467 }
......@@ -1385,7 +1385,8 @@ pub fn lerp(a: anytype, b: anytype, t: anytype) @TypeOf(a, b, t) {
13851385}
13861386
13871387test lerp {
1388 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/17884
1388 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
1389 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isX86()) return error.SkipZigTest;
13891390 if (builtin.zig_backend == .stage2_x86_64 and !comptime builtin.cpu.has(.x86, .fma)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/17884
13901391
13911392 try testing.expectEqual(@as(f64, 75), lerp(50, 100, 0.5));
lib/std/math/acos.zig-4
......@@ -337,8 +337,6 @@ fn acosBinary128(x: f128) f128 {
337337}
338338
339339test "acosBinary16.special" {
340 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
341
342340 try testing.expectApproxEqAbs(0x1.92p0, acosBinary16(0x0p+0), math.floatEpsAt(f16, 0x1.92p0));
343341 try testing.expectApproxEqAbs(0x1.92p1, acosBinary16(-0x1p+0), math.floatEpsAt(f16, 0x1.92p1));
344342 try testing.expectEqual(0x0p+0, acosBinary16(0x1p+0));
......@@ -350,8 +348,6 @@ test "acosBinary16.special" {
350348}
351349
352350test "acosBinary16" {
353 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
354
355351 try testing.expectApproxEqAbs(0x1.834p0, acosBinary16(0x1.db4p-5), math.floatEpsAt(f16, 0x1.834p0));
356352 try testing.expectApproxEqAbs(0x1.d48p0, acosBinary16(-0x1.068p-2), math.floatEpsAt(f16, 0x1.d48p0));
357353 try testing.expectApproxEqAbs(0x1.b7cp0, acosBinary16(-0x1.2c4p-3), math.floatEpsAt(f16, 0x1.b7cp0));
lib/std/math/asin.zig-4
......@@ -326,8 +326,6 @@ fn asinBinary128(x: f128) f128 {
326326}
327327
328328test "asinBinary16.special" {
329 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
330
331329 try testing.expectApproxEqAbs(0x1.92p0, asinBinary16(0x1p+0), math.floatEpsAt(f16, 0x1.92p0));
332330 try testing.expectApproxEqAbs(-0x1.92p0, asinBinary16(-0x1p+0), math.floatEpsAt(f16, -0x1.92p0));
333331 try testing.expectEqual(0x0p+0, asinBinary16(0x0p+0));
......@@ -340,8 +338,6 @@ test "asinBinary16.special" {
340338}
341339
342340test "asinBinary16" {
343 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
344
345341 try testing.expectApproxEqAbs(-0x1.e4cp-6, asinBinary16(-0x1.e4cp-6), math.floatEpsAt(f16, -0x1.e4cp-6));
346342 try testing.expectApproxEqAbs(0x1.2a8p0, asinBinary16(0x1.d68p-1), math.floatEpsAt(f16, 0x1.2a8p0));
347343 try testing.expectApproxEqAbs(-0x1.eep-1, asinBinary16(-0x1.a4cp-1), math.floatEpsAt(f16, -0x1.eep-1));
lib/std/math/atan.zig-4
......@@ -481,8 +481,6 @@ fn atanBinary128(x: f128) f128 {
481481}
482482
483483test "atanBinary16.special" {
484 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
485
486484 try testing.expectEqual(0x0p+0, atanBinary16(0x0p+0));
487485 try testing.expectEqual(-0x0p+0, atanBinary16(-0x0p+0));
488486 try testing.expectApproxEqAbs(0x1.92p-1, atanBinary16(0x1p+0), math.floatEpsAt(f16, 0x1.92p-1));
......@@ -493,8 +491,6 @@ test "atanBinary16.special" {
493491}
494492
495493test "atanBinary16" {
496 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
497
498494 try testing.expectApproxEqAbs(-0x1.74cp-2, atanBinary16(-0x1.864p-2), math.floatEpsAt(f16, -0x1.74cp-2));
499495 try testing.expectApproxEqAbs(-0x1.374p0, atanBinary16(-0x1.59cp1), math.floatEpsAt(f16, -0x1.374p0));
500496 try testing.expectApproxEqAbs(-0x1.11cp0, atanBinary16(-0x1.d2cp0), math.floatEpsAt(f16, -0x1.11cp0));
lib/std/math/atan2.zig+4-4
......@@ -252,8 +252,8 @@ test "atan2_32.special" {
252252
253253 try expect(math.isNan(atan2_32(1.0, math.nan(f32))));
254254 try expect(math.isNan(atan2_32(math.nan(f32), 1.0)));
255 try expect(atan2_32(0.0, 5.0) == 0.0);
256 try expect(atan2_32(-0.0, 5.0) == -0.0);
255 try expect(math.isPositiveZero(atan2_32(0.0, 5.0)));
256 try expect(math.isNegativeZero(atan2_32(-0.0, 5.0)));
257257 try expect(math.approxEqAbs(f32, atan2_32(0.0, -5.0), math.pi, epsilon));
258258 //expect(math.approxEqAbs(f32, atan2_32(-0.0, -5.0), -math.pi, .{.rel=0,.abs=epsilon})); TODO support negative zero?
259259 try expect(math.approxEqAbs(f32, atan2_32(1.0, 0.0), math.pi / 2.0, epsilon));
......@@ -276,8 +276,8 @@ test "atan2_64.special" {
276276
277277 try expect(math.isNan(atan2_64(1.0, math.nan(f64))));
278278 try expect(math.isNan(atan2_64(math.nan(f64), 1.0)));
279 try expect(atan2_64(0.0, 5.0) == 0.0);
280 try expect(atan2_64(-0.0, 5.0) == -0.0);
279 try expect(math.isPositiveZero(atan2_64(0.0, 5.0)));
280 try expect(math.isNegativeZero(atan2_64(-0.0, 5.0)));
281281 try expect(math.approxEqAbs(f64, atan2_64(0.0, -5.0), math.pi, epsilon));
282282 //expect(math.approxEqAbs(f64, atan2_64(-0.0, -5.0), -math.pi, .{.rel=0,.abs=epsilon})); TODO support negative zero?
283283 try expect(math.approxEqAbs(f64, atan2_64(1.0, 0.0), math.pi / 2.0, epsilon));
lib/std/math/big/int_test.zig+1-38
......@@ -1,5 +1,4 @@
11const std = @import("../../std.zig");
2const builtin = @import("builtin");
32const mem = std.mem;
43const testing = std.testing;
54const Managed = std.math.big.int.Managed;
......@@ -276,8 +275,6 @@ fn setFloat(comptime Float: type) !void {
276275 try expectNormalized(1 << 10, res.toConst());
277276}
278277test setFloat {
279 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
280
281278 try setFloat(f16);
282279 try setFloat(f32);
283280 try setFloat(f64);
......@@ -484,7 +481,6 @@ fn toFloat(comptime Float: type) !void {
484481 );
485482}
486483test toFloat {
487 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
488484 try toFloat(f16);
489485 try toFloat(f32);
490486 try toFloat(f64);
......@@ -1391,8 +1387,6 @@ test "mul multi-single" {
13911387}
13921388
13931389test "mul multi-multi" {
1394 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1395
13961390 var op1: u256 = 0x998888efefefefefefefef;
13971391 var op2: u256 = 0x333000abababababababab;
13981392 _ = .{ &op1, &op2 };
......@@ -1514,8 +1508,6 @@ test "mulWrap single-single signed" {
15141508}
15151509
15161510test "mulWrap multi-multi unsigned" {
1517 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1518
15191511 var op1: u256 = 0x998888efefefefefefefef;
15201512 var op2: u256 = 0x333000abababababababab;
15211513 _ = .{ &op1, &op2 };
......@@ -1533,11 +1525,6 @@ test "mulWrap multi-multi unsigned" {
15331525}
15341526
15351527test "mulWrap multi-multi signed" {
1536 switch (builtin.zig_backend) {
1537 .stage2_c => return error.SkipZigTest,
1538 else => {},
1539 }
1540
15411528 var a = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb) - 1);
15421529 defer a.deinit();
15431530 var b = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb));
......@@ -1744,8 +1731,6 @@ test "div q=0 alias" {
17441731}
17451732
17461733test "div multi-multi q < r" {
1747 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1748
17491734 const op1 = 0x1ffffffff0078f432;
17501735 const op2 = 0x1ffffffff01000000;
17511736 var a = try Managed.initSet(testing.allocator, op1);
......@@ -2166,8 +2151,6 @@ test "div ceil multi-limb" {
21662151}
21672152
21682153test "div multi-multi with rem" {
2169 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2170
21712154 var a = try Managed.initSet(testing.allocator, 0x8888999911110000ffffeeeeddddccccbbbbaaaa9999);
21722155 defer a.deinit();
21732156 var b = try Managed.initSet(testing.allocator, 0x99990000111122223333);
......@@ -2184,8 +2167,6 @@ test "div multi-multi with rem" {
21842167}
21852168
21862169test "div multi-multi no rem" {
2187 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2188
21892170 var a = try Managed.initSet(testing.allocator, 0x8888999911110000ffffeeeedb4fec200ee3a4286361);
21902171 defer a.deinit();
21912172 var b = try Managed.initSet(testing.allocator, 0x99990000111122223333);
......@@ -2202,8 +2183,6 @@ test "div multi-multi no rem" {
22022183}
22032184
22042185test "div multi-multi (2 branch)" {
2205 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2206
22072186 var a = try Managed.initSet(testing.allocator, 0x866666665555555588888887777777761111111111111111);
22082187 defer a.deinit();
22092188 var b = try Managed.initSet(testing.allocator, 0x86666666555555554444444433333333);
......@@ -2220,8 +2199,6 @@ test "div multi-multi (2 branch)" {
22202199}
22212200
22222201test "div multi-multi (3.1/3.3 branch)" {
2223 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2224
22252202 var a = try Managed.initSet(testing.allocator, 0x11111111111111111111111111111111111111111111111111111111111111);
22262203 defer a.deinit();
22272204 var b = try Managed.initSet(testing.allocator, 0x1111111111111111111111111111111111111111171);
......@@ -2238,8 +2215,6 @@ test "div multi-multi (3.1/3.3 branch)" {
22382215}
22392216
22402217test "div multi-single zero-limb trailing" {
2241 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2242
22432218 var a = try Managed.initSet(testing.allocator, 0x60000000000000000000000000000000000000000000000000000000000000000);
22442219 defer a.deinit();
22452220 var b = try Managed.initSet(testing.allocator, 0x10000000000000000);
......@@ -2258,8 +2233,6 @@ test "div multi-single zero-limb trailing" {
22582233}
22592234
22602235test "div multi-multi zero-limb trailing (with rem)" {
2261 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2262
22632236 var a = try Managed.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000);
22642237 defer a.deinit();
22652238 var b = try Managed.initSet(testing.allocator, 0x8666666655555555444444443333333300000000000000000000000000000000);
......@@ -2279,8 +2252,6 @@ test "div multi-multi zero-limb trailing (with rem)" {
22792252}
22802253
22812254test "div multi-multi zero-limb trailing (with rem) and dividend zero-limb count > divisor zero-limb count" {
2282 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2283
22842255 var a = try Managed.initSet(testing.allocator, 0x8666666655555555888888877777777611111111111111110000000000000000);
22852256 defer a.deinit();
22862257 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
23002271}
23012272
23022273test "div multi-multi zero-limb trailing (with rem) and dividend zero-limb count < divisor zero-limb count" {
2303 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2304
23052274 var a = try Managed.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000);
23062275 defer a.deinit();
23072276 var b = try Managed.initSet(testing.allocator, 0x866666665555555544444444333333330000000000000000);
......@@ -2832,10 +2801,6 @@ test "bitNotWrap signed multi" {
28322801}
28332802
28342803test "bitNotWrap more than two limbs" {
2835 // This test requires int sizes greater than 128 bits.
2836 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
2837 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2838
28392804 var a = try Managed.initSet(testing.allocator, maxInt(Limb));
28402805 defer a.deinit();
28412806
......@@ -3179,8 +3144,6 @@ test "gcd non-one large" {
31793144}
31803145
31813146test "gcd large multi-limb result" {
3182 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
3183
31843147 var a = try Managed.initSet(testing.allocator, 0x12345678123456781234567812345678123456781234567812345678);
31853148 defer a.deinit();
31863149 var b = try Managed.initSet(testing.allocator, 0x12345671234567123456712345671234567123456712345671234567);
......@@ -3431,7 +3394,7 @@ test "big int conversion read/write twos complement" {
34313394 var buffer1 = try testing.allocator.alloc(u8, 64);
34323395 defer testing.allocator.free(buffer1);
34333396
3434 const endians = [_]std.builtin.Endian{ .little, .big };
3397 const endians = [_]std.lang.Endian{ .little, .big };
34353398 const abi_size = 64;
34363399
34373400 for (endians) |endian| {
lib/std/math/float.zig+3-3
......@@ -112,17 +112,17 @@ pub fn FloatRepr(comptime Float: type) type {
112112 /// This currently truncates denormal values, which needs to be fixed before this can be used to
113113 /// produce a rounded value.
114114 pub fn reconstruct(normalized: Normalized, sign: std.math.Sign) Float {
115 if (normalized.exponent > BiasedExponent.max_normal.unbias()) return @bitCast(Repr{
115 if (normalized.exponent > comptime BiasedExponent.max_normal.unbias()) return @bitCast(Repr{
116116 .mantissa = 0,
117117 .exponent = .infinite,
118118 .sign = sign,
119119 });
120120 const mantissa = @as(Mantissa, 1 << fractional_bits) | normalized.fraction;
121 if (normalized.exponent < BiasedExponent.min_normal.unbias()) return @bitCast(Repr{
121 if (normalized.exponent < comptime BiasedExponent.min_normal.unbias()) return @bitCast(Repr{
122122 .mantissa = @truncate(std.math.shr(
123123 Mantissa,
124124 mantissa,
125 BiasedExponent.min_normal.unbias() - normalized.exponent,
125 (comptime BiasedExponent.min_normal.unbias()) - normalized.exponent,
126126 )),
127127 .exponent = .denormal,
128128 .sign = sign,
lib/std/math/gamma.zig-2
......@@ -263,8 +263,6 @@ test gamma {
263263}
264264
265265test "gamma.special" {
266 if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
267
268266 inline for (&.{ f32, f64 }) |T| {
269267 try expect(std.math.isNan(gamma(T, -std.math.nan(T))));
270268 try expect(std.math.isNan(gamma(T, std.math.nan(T))));
lib/std/math/hypot.zig-9
......@@ -1,4 +1,3 @@
1const builtin = @import("builtin");
21const std = @import("../std.zig");
32const math = std.math;
43const expect = std.testing.expect;
......@@ -93,14 +92,10 @@ const hypot_test_cases = .{
9392};
9493
9594test hypot {
96 if (builtin.cpu.arch.isPowerPC() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869
9795 try expect(hypot(0.3, 0.4) == 0.5);
9896}
9997
10098test "hypot.correct" {
101 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
102 if (builtin.cpu.arch.isPowerPC() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869
103
10499 inline for (.{ f16, f32, f64, f128 }) |T| {
105100 inline for (hypot_test_cases) |v| {
106101 const a: T, const b: T, const c: T = v;
......@@ -110,9 +105,6 @@ test "hypot.correct" {
110105}
111106
112107test "hypot.precise" {
113 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
114 if (builtin.cpu.arch.isPowerPC() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869
115
116108 inline for (.{ f16, f32, f64 }) |T| { // f128 seems to be 5 ulp
117109 inline for (hypot_test_cases) |v| {
118110 const a: T, const b: T, const c: T = v;
......@@ -122,7 +114,6 @@ test "hypot.precise" {
122114}
123115
124116test "hypot.special" {
125 if (builtin.cpu.arch.isPowerPC() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869
126117 @setEvalBranchQuota(2000);
127118 inline for (.{ f16, f32, f64, f128 }) |T| {
128119 try expect(math.isNan(hypot(nan(T), 0.0)));
lib/std/math/isnan.zig+1-7
......@@ -27,13 +27,6 @@ test isNan {
2727}
2828
2929test isSignalNan {
30 if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff and builtin.abi != .gnu) return error.SkipZigTest;
31
32 if (builtin.os.tag == .windows) {
33 // https://codeberg.org/ziglang/zig/issues/35519
34 return error.SkipZigTest;
35 }
36
3730 inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| {
3831 // TODO: Signalling NaN values get converted to quiet NaN values in
3932 // some cases where they shouldn't such that this can fail.
......@@ -43,6 +36,7 @@ test isSignalNan {
4336 builtin.cpu.arch != .hexagon and
4437 !builtin.cpu.arch.isMIPS32() and
4538 !builtin.cpu.arch.isPowerPC() and
39 !(builtin.cpu.arch.isX86() and builtin.os.tag == .windows and builtin.abi == .msvc) and // https://codeberg.org/ziglang/zig/issues/35519
4640 builtin.zig_backend != .stage2_c)
4741 {
4842 try expect(isSignalNan(math.snan(T)));
lib/std/math/log10.zig-5
......@@ -1,5 +1,4 @@
11const std = @import("../std.zig");
2const builtin = @import("builtin");
32const testing = std.testing;
43
54/// Returns the base-10 logarithm of x.
......@@ -135,10 +134,6 @@ inline fn less_than_5(x: u32) u32 {
135134}
136135
137136test log10_int {
138 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
139 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
140 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
141
142137 inline for (
143138 .{ u8, u16, u32, u64, u128, u256, u512 },
144139 .{ 2, 4, 9, 19, 38, 77, 154 },
lib/std/math/modf.zig-4
......@@ -1,5 +1,4 @@
11const std = @import("../std.zig");
2const builtin = @import("builtin");
32const math = std.math;
43const expect = std.testing.expect;
54const expectEqual = std.testing.expectEqual;
......@@ -85,9 +84,6 @@ fn ModfTests(comptime T: type) type {
8584 try expectApproxEqAbs(expected_c, r.fpart, epsilon);
8685 }
8786 test "vector" {
88 if (builtin.os.tag.isDarwin() and builtin.cpu.arch == .aarch64) return error.SkipZigTest;
89 if (builtin.cpu.arch == .s390x) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194256
90
9187 const widths = [_]comptime_int{ 1, 2, 3, 4, 8, 16 };
9288
9389 inline for (widths) |len| {
lib/std/math/signbit.zig+1
......@@ -1,3 +1,4 @@
1const builtin = @import("builtin");
12const std = @import("../std.zig");
23const math = std.math;
34const expect = std.testing.expect;
lib/std/mem.zig+166-127
......@@ -9,6 +9,7 @@ const assert = debug.assert;
99const math = std.math;
1010const testing = std.testing;
1111const Endian = std.lang.Endian;
12const AbsorbSentinel = std.meta.AbsorbSentinel;
1213
1314/// The standard library currently thoroughly depends on byte size
1415/// being 8 bits. (see the use of u8 throughout allocation code as
......@@ -756,7 +757,8 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
756757 }
757758
758759 if (a.len != b.len) return false;
759 if (a.len == 0 or a.ptr == b.ptr) return true;
760 if (a.len == 0) return true;
761 if (@typeInfo(T) != .float and a.ptr == b.ptr) return true;
760762
761763 for (a, b) |a_elem, b_elem| {
762764 if (a_elem != b_elem) return false;
......@@ -781,6 +783,9 @@ test eql {
781783
782784 try testing.expect(eql(void, &.{ {}, {} }, &.{ {}, {} }));
783785 try testing.expect(!eql(void, &.{{}}, &.{ {}, {} }));
786
787 const x: [3]f64 = .{ 42.0, math.nan(f64), 3.1415 };
788 try testing.expect(!eql(f64, &x, &x));
784789}
785790
786791/// std.mem.eql heavily optimized for slices of bytes.
......@@ -850,20 +855,25 @@ pub const indexOfDiff = findDiff;
850855/// Compares two slices and returns the index of the first inequality.
851856/// Returns null if the slices are equal.
852857pub fn findDiff(comptime T: type, a: []const T, b: []const T) ?usize {
853 const shortest = @min(a.len, b.len);
854 if (a.ptr == b.ptr)
855 return if (a.len == b.len) null else shortest;
856 var index: usize = 0;
857 while (index < shortest) : (index += 1) if (a[index] != b[index]) return index;
858 return if (a.len == b.len) null else shortest;
858 const shorter = @min(a.len, b.len);
859 if (@typeInfo(T) != .float and a.ptr == b.ptr) {
860 return if (a.len == b.len) null else shorter;
861 }
862 for (a[0..shorter], b[0..shorter], 0..) |a_elem, b_elem, i| {
863 if (a_elem != b_elem) return i;
864 }
865 return if (a.len == b.len) null else shorter;
859866}
860867
861868test findDiff {
862 try testing.expectEqual(findDiff(u8, "one", "one"), null);
863 try testing.expectEqual(findDiff(u8, "one two", "one"), 3);
864 try testing.expectEqual(findDiff(u8, "one", "one two"), 3);
865 try testing.expectEqual(findDiff(u8, "one twx", "one two"), 6);
866 try testing.expectEqual(findDiff(u8, "xne", "one"), 0);
869 try testing.expectEqual(null, findDiff(u8, "one", "one"));
870 try testing.expectEqual(3, findDiff(u8, "one two", "one"));
871 try testing.expectEqual(3, findDiff(u8, "one", "one two"));
872 try testing.expectEqual(6, findDiff(u8, "one twx", "one two"));
873 try testing.expectEqual(0, findDiff(u8, "xne", "one"));
874
875 const x: [3]f64 = .{ 42.0, math.nan(f64), 3.1415 };
876 try testing.expectEqual(1, findDiff(f64, &x, &x));
867877}
868878
869879/// Takes a sentinel-terminated pointer and returns a slice preserving pointer attributes.
......@@ -1519,7 +1529,7 @@ pub fn findLast(comptime T: type, haystack: []const T, needle: []const T) ?usize
15191529 if (needle.len == 0) return haystack.len;
15201530
15211531 if (!std.meta.hasUniqueRepresentation(T) or haystack.len < 52 or needle.len <= 4)
1522 return lastIndexOfLinear(T, haystack, needle);
1532 return findLastLinear(T, haystack, needle);
15231533
15241534 const haystack_bytes = sliceAsBytes(haystack);
15251535 const needle_bytes = sliceAsBytes(needle);
......@@ -1574,26 +1584,26 @@ pub fn findPos(comptime T: type, haystack: []const T, start_index: usize, needle
15741584
15751585test find {
15761586 try testing.expect(find(u8, "one two three four five six seven eight nine ten eleven", "three four").? == 8);
1577 try testing.expect(lastIndexOf(u8, "one two three four five six seven eight nine ten eleven", "three four").? == 8);
1587 try testing.expect(findLast(u8, "one two three four five six seven eight nine ten eleven", "three four").? == 8);
15781588 try testing.expect(find(u8, "one two three four five six seven eight nine ten eleven", "two two") == null);
1579 try testing.expect(lastIndexOf(u8, "one two three four five six seven eight nine ten eleven", "two two") == null);
1589 try testing.expect(findLast(u8, "one two three four five six seven eight nine ten eleven", "two two") == null);
15801590
15811591 try testing.expect(find(u8, "one two three four five six seven eight nine ten", "").? == 0);
1582 try testing.expect(lastIndexOf(u8, "one two three four five six seven eight nine ten", "").? == 48);
1592 try testing.expect(findLast(u8, "one two three four five six seven eight nine ten", "").? == 48);
15831593
15841594 try testing.expect(find(u8, "one two three four", "four").? == 14);
1585 try testing.expect(lastIndexOf(u8, "one two three two four", "two").? == 14);
1595 try testing.expect(findLast(u8, "one two three two four", "two").? == 14);
15861596 try testing.expect(find(u8, "one two three four", "gour") == null);
1587 try testing.expect(lastIndexOf(u8, "one two three four", "gour") == null);
1597 try testing.expect(findLast(u8, "one two three four", "gour") == null);
15881598 try testing.expect(find(u8, "foo", "foo").? == 0);
1589 try testing.expect(lastIndexOf(u8, "foo", "foo").? == 0);
1599 try testing.expect(findLast(u8, "foo", "foo").? == 0);
15901600 try testing.expect(find(u8, "foo", "fool") == null);
1591 try testing.expect(lastIndexOf(u8, "foo", "lfoo") == null);
1592 try testing.expect(lastIndexOf(u8, "foo", "fool") == null);
1601 try testing.expect(findLast(u8, "foo", "lfoo") == null);
1602 try testing.expect(findLast(u8, "foo", "fool") == null);
15931603
15941604 try testing.expect(find(u8, "foo foo", "foo").? == 0);
1595 try testing.expect(lastIndexOf(u8, "foo foo", "foo").? == 4);
1596 try testing.expect(lastIndexOfAny(u8, "boo, cat", "abo").? == 6);
1605 try testing.expect(findLast(u8, "foo foo", "foo").? == 4);
1606 try testing.expect(findLastAny(u8, "boo, cat", "abo").? == 6);
15971607 try testing.expect(findScalarLast(u8, "boo", 'o').? == 2);
15981608}
15991609
......@@ -1615,13 +1625,13 @@ test "find multibyte" {
16151625 // make haystack and needle long enough to trigger Boyer-Moore-Horspool algorithm
16161626 const haystack = [_]u16{ 0xbbaa, 0xccbb, 0xddcc, 0xeedd, 0xffee, 0x00ff } ++ @as([100]u16, @splat(0));
16171627 const needle = [_]u16{ 0xbbaa, 0xccbb, 0xddcc, 0xeedd, 0xffee };
1618 try testing.expectEqual(lastIndexOf(u16, &haystack, &needle), 0);
1628 try testing.expectEqual(findLast(u16, &haystack, &needle), 0);
16191629
16201630 // check for misaligned false positives (little and big endian)
16211631 const needleLE = [_]u16{ 0xbbbb, 0xcccc, 0xdddd, 0xeeee, 0xffff };
1622 try testing.expectEqual(lastIndexOf(u16, &haystack, &needleLE), null);
1632 try testing.expectEqual(findLast(u16, &haystack, &needleLE), null);
16231633 const needleBE = [_]u16{ 0xaacc, 0xbbdd, 0xccee, 0xddff, 0xee00 };
1624 try testing.expectEqual(lastIndexOf(u16, &haystack, &needleBE), null);
1634 try testing.expectEqual(findLast(u16, &haystack, &needleBE), null);
16251635 }
16261636}
16271637
......@@ -2215,33 +2225,54 @@ test writeVarPackedInt {
22152225 try testing.expectEqual(T{ .a = 1, .b = value, .c = 4 }, st);
22162226}
22172227
2218/// Swap the byte order of all the members of the fields of a struct
2219/// (Changing their endianness)
2220pub fn byteSwapAllFields(comptime S: type, ptr: *S) void {
2221 byteSwapAllFieldsAligned(S, .of(S), ptr);
2228/// Deprecated: use `byteSwap` instead.
2229pub const byteSwapAllFields = byteSwap;
2230
2231/// Deprecated: use `byteSwapAligned` instead.
2232pub const byteSwapAllFieldsAligned = byteSwapAligned;
2233
2234/// Reverses the byte order.
2235/// Handles structs, unions, arrays, enums, floats, and integers recursively.
2236/// The order of extern struct fields and array elements remains unchanged and
2237/// will be byte swapped recursively.
2238/// Useful for converting between little-endian and big-endian representations.
2239pub fn byteSwap(comptime S: type, ptr: *S) void {
2240 byteSwapAligned(S, .of(S), ptr);
22222241}
22232242
2224/// Swap the byte order of all the members of the fields of a struct
2225/// (Changing their endianness)
2226pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *align(a.toByteUnits()) S) void {
2243/// Reverses the byte order.
2244/// Handles structs, unions, arrays, enums, floats, and integers recursively.
2245/// The order of extern struct fields and array elements remains unchanged and
2246/// will be byte swapped recursively.
2247/// Useful for converting between little-endian and big-endian representations.
2248pub fn byteSwapAligned(
2249 comptime S: type,
2250 comptime a: Alignment,
2251 ptr: *align(a.toByteUnits()) S,
2252) void {
22272253 switch (@typeInfo(S)) {
22282254 .@"struct" => |@"struct"| {
22292255 if (@"struct".backing_integer) |Int| {
22302256 ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*))));
2231 } else inline for (@"struct".field_types, @"struct".field_names, @"struct".field_attrs) |f_type, f_name, f_attr| {
2232 switch (@typeInfo(f_type)) {
2233 .@"struct" => byteSwapAllFieldsAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)),
2234 .@"union", .array => byteSwapAllFieldsAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)),
2235 .@"enum" => {
2236 @field(ptr, f_name) = @fromBackingInt(@intCast(@byteSwap(@backingInt(@field(ptr, f_name)))));
2237 },
2238 .bool => {},
2239 .float => |float| {
2240 @field(ptr, f_name) = @bitCast(@byteSwap(@as(@Int(.unsigned, float.bits), @bitCast(@field(ptr, f_name)))));
2241 },
2242 else => {
2243 @field(ptr, f_name) = @byteSwap(@field(ptr, f_name));
2244 },
2257 } else {
2258 if (@"struct".layout != .@"extern") {
2259 @compileError("byteSwapAligned expects a packed or extern struct");
2260 }
2261 inline for (@"struct".field_types, @"struct".field_names, @"struct".field_attrs) |f_type, f_name, f_attr| {
2262 switch (@typeInfo(f_type)) {
2263 .@"struct" => byteSwapAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)),
2264 .@"union", .array => byteSwapAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)),
2265 .@"enum" => {
2266 @field(ptr, f_name) = @fromBackingInt(@byteSwap(@backingInt(@field(ptr, f_name))));
2267 },
2268 .bool => {},
2269 .float => |float| {
2270 @field(ptr, f_name) = @bitCast(@byteSwap(@as(@Int(.unsigned, float.bits), @bitCast(@field(ptr, f_name)))));
2271 },
2272 else => {
2273 @field(ptr, f_name) = @byteSwap(@field(ptr, f_name));
2274 },
2275 }
22452276 }
22462277 }
22472278 },
......@@ -2249,7 +2280,7 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a
22492280 ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*))));
22502281 } else {
22512282 if (@"union".layout != .@"extern") {
2252 @compileError("byteSwapAllFields expects a packed or extern union");
2283 @compileError("byteSwapAligned expects a packed or extern union");
22532284 }
22542285
22552286 const first_size = @bitSizeOf(@"union".field_types[0]);
......@@ -2266,13 +2297,21 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a
22662297 .array => |array| {
22672298 byteSwapAllElements(array.child, ptr);
22682299 },
2300 .@"enum" => {
2301 ptr.* = @fromBackingInt(@byteSwap(@backingInt(ptr.*)));
2302 },
2303 .bool => {},
2304 .float => |float| {
2305 const int_repr: @Int(.unsigned, float.bits) = @bitCast(ptr.*);
2306 ptr.* = @bitCast(@byteSwap(int_repr));
2307 },
22692308 else => {
22702309 ptr.* = @byteSwap(ptr.*);
22712310 },
22722311 }
22732312}
22742313
2275test byteSwapAllFields {
2314test byteSwap {
22762315 const T = extern struct {
22772316 f0: u8,
22782317 f1: u16,
......@@ -2304,6 +2343,9 @@ test byteSwapAllFields {
23042343 } align(4),
23052344 f2: u32,
23062345 };
2346 const E = enum(u32) {
2347 _,
2348 };
23072349 var s = T{
23082350 .f0 = 0x12,
23092351 .f1 = 0x1234,
......@@ -2327,10 +2369,14 @@ test byteSwapAllFields {
23272369 .f1 = .{ .f0 = 0x123456789ABCDEF0 },
23282370 .f2 = 0x87654321,
23292371 };
2330 byteSwapAllFields(T, &s);
2331 byteSwapAllFields(K, &k);
2332 byteSwapAllFields(P, &p);
2333 byteSwapAllFields(A, &a);
2372 var e: E = @fromBackingInt(0x12345678);
2373 var f: f32 = @bitCast(@as(u32, 0x4640e400));
2374 byteSwap(T, &s);
2375 byteSwap(K, &k);
2376 byteSwap(P, &p);
2377 byteSwap(A, &a);
2378 byteSwap(E, &e);
2379 byteSwap(f32, &f);
23342380 try std.testing.expectEqual(T{
23352381 .f0 = 0x12,
23362382 .f1 = 0x3412,
......@@ -2354,28 +2400,15 @@ test byteSwapAllFields {
23542400 .f1 = .{ .f0 = 0xF0DEBC9A78563412 },
23552401 .f2 = 0x21436587,
23562402 }, a);
2403 try std.testing.expectEqual(@as(E, @fromBackingInt(0x78563412)), e);
2404 try std.testing.expectEqual(@as(f32, @bitCast(@as(u32, 0x00e44046))), f);
23572405}
23582406
23592407/// Reverses the byte order of all elements in a slice.
23602408/// Handles structs, unions, arrays, enums, floats, and integers recursively.
23612409/// Useful for converting between little-endian and big-endian representations.
23622410pub fn byteSwapAllElements(comptime Elem: type, slice: []Elem) void {
2363 for (slice) |*elem| {
2364 switch (@typeInfo(@TypeOf(elem.*))) {
2365 .@"struct", .@"union", .array => byteSwapAllFields(@TypeOf(elem.*), elem),
2366 .@"enum" => {
2367 elem.* = @fromBackingInt(@intCast(@byteSwap(@backingInt(elem.*))));
2368 },
2369 .bool => {},
2370 .float => |float| {
2371 const int_repr: @Int(.unsigned, float.bits) = @bitCast(elem.*);
2372 elem.* = @bitCast(@byteSwap(int_repr));
2373 },
2374 else => {
2375 elem.* = @byteSwap(elem.*);
2376 },
2377 }
2378 }
2411 for (slice) |*elem| byteSwap(Elem, elem);
23792412}
23802413
23812414/// Returns an iterator that iterates over the slices of `buffer` that are not
......@@ -3453,8 +3486,8 @@ pub fn SplitBackwardsIterator(comptime T: type, comptime delimiter_type: Delimit
34533486 pub fn next(self: *Self) ?[]const T {
34543487 const end = self.index orelse return null;
34553488 const start = if (switch (delimiter_type) {
3456 .sequence => lastIndexOf(T, self.buffer[0..end], self.delimiter),
3457 .any => lastIndexOfAny(T, self.buffer[0..end], self.delimiter),
3489 .sequence => findLast(T, self.buffer[0..end], self.delimiter),
3490 .any => findLastAny(T, self.buffer[0..end], self.delimiter),
34583491 .scalar => findScalarLast(T, self.buffer[0..end], self.delimiter),
34593492 }) |delim_start| blk: {
34603493 self.index = delim_start;
......@@ -4706,22 +4739,28 @@ test "sliceAsBytes preserves pointer attributes" {
47064739 try testing.expectEqual(in_attrs.@"align", out_attrs.@"align");
47074740}
47084741
4709fn AbsorbSentinelReturnType(comptime Slice: type) type {
4710 const info = @typeInfo(Slice).pointer;
4711 assert(info.size == .slice);
4712 return @Pointer(.slice, info.attrs, info.child, null);
4713}
4714
47154742/// If the provided slice is not sentinel terminated, do nothing and return that slice.
47164743/// If it is sentinel-terminated, return a non-sentinel-terminated slice with the
47174744/// length increased by one to include the absorbed sentinel element.
4718pub fn absorbSentinel(slice: anytype) AbsorbSentinelReturnType(@TypeOf(slice)) {
4745pub fn absorbSentinel(slice: anytype) AbsorbSentinel(@TypeOf(slice)) {
47194746 const info = @typeInfo(@TypeOf(slice)).pointer;
4720 comptime assert(info.size == .slice);
4721 if (info.sentinel_ptr == null) {
4722 return slice;
4723 } else {
4724 return slice.ptr[0 .. slice.len + 1];
4747 switch (info.size) {
4748 .slice => {
4749 if (info.sentinel_ptr == null) {
4750 return slice;
4751 } else {
4752 return slice.ptr[0 .. slice.len + 1];
4753 }
4754 },
4755 .one => {
4756 const child_info = @typeInfo(info.child).array;
4757 if (child_info.sentinel_ptr == null) {
4758 return slice;
4759 } else {
4760 return slice[0 .. child_info.len + 1];
4761 }
4762 },
4763 else => unreachable,
47254764 }
47264765}
47274766
......@@ -4730,21 +4769,28 @@ test absorbSentinel {
47304769 var buffer: [3:0]u8 = .{ 1, 2, 3 };
47314770 const foo: [:0]const u8 = &buffer;
47324771 const bar: []const u8 = &buffer;
4772 const baz: *const [3:0]u8 = &buffer;
47334773 try testing.expectEqual([]const u8, @TypeOf(absorbSentinel(foo)));
47344774 try testing.expectEqual([]const u8, @TypeOf(absorbSentinel(bar)));
4775 try testing.expectEqual(*const [4]u8, @TypeOf(absorbSentinel(baz)));
47354776 try testing.expectEqualSlices(u8, &.{ 1, 2, 3, 0 }, absorbSentinel(foo));
47364777 try testing.expectEqualSlices(u8, &.{ 1, 2, 3 }, absorbSentinel(bar));
4778 try testing.expectEqualSlices(u8, &.{ 1, 2, 3, 0 }, absorbSentinel(baz));
47374779 }
47384780 {
47394781 var buffer: [3:0]u8 = .{ 1, 2, 3 };
47404782 const foo: [:0]u8 = &buffer;
47414783 const bar: []u8 = &buffer;
4784 const baz: *[3:0]u8 = &buffer;
47424785 try testing.expectEqual([]u8, @TypeOf(absorbSentinel(foo)));
47434786 try testing.expectEqual([]u8, @TypeOf(absorbSentinel(bar)));
4787 try testing.expectEqual(*[4]u8, @TypeOf(absorbSentinel(baz)));
47444788 var expected_foo = [_]u8{ 1, 2, 3, 0 };
47454789 try testing.expectEqualSlices(u8, &expected_foo, absorbSentinel(foo));
47464790 var expected_bar = [_]u8{ 1, 2, 3 };
47474791 try testing.expectEqualSlices(u8, &expected_bar, absorbSentinel(bar));
4792 var expected_baz = [_]u8{ 1, 2, 3, 0 };
4793 try testing.expectEqualSlices(u8, &expected_baz, absorbSentinel(baz));
47484794 }
47494795}
47504796
......@@ -4780,62 +4826,58 @@ pub fn alignForwardLog2(addr: usize, log2_alignment: u8) usize {
47804826pub fn doNotOptimizeAway(val: anytype) void {
47814827 if (@inComptime()) return;
47824828
4783 const max_gp_register_bits = @bitSizeOf(c_long);
4784 const t = @typeInfo(@TypeOf(val));
4785 switch (t) {
4829 if (builtin.zig_backend == .stage2_c and builtin.abi == .msvc) {
4830 _ = @atomicRmw(*const anyopaque, @as(*volatile *const anyopaque, &struct {
4831 var escape: *const anyopaque = undefined;
4832 }.escape), .Xchg, &val, .acq_rel); // TODO: syncscope("singlethreaded")
4833 return;
4834 }
4835
4836 switch (@typeInfo(@TypeOf(val))) {
47864837 .void, .null, .comptime_int, .comptime_float => return,
47874838 .@"enum" => doNotOptimizeAway(@backingInt(val)),
47884839 .bool => doNotOptimizeAway(@intFromBool(val)),
4789 .int => {
4790 const bits = t.int.bits;
4791 if (bits <= max_gp_register_bits and builtin.zig_backend != .stage2_c) {
4840 .int => |int| {
4841 // SPIR-V targets do not have registers per se, they have values
4842 // tied to IDs that can be passed to valid instructions. Some
4843 // SPIR-V targets do not define c_long, so we just allow any sized
4844 // integer on these targets
4845 const val_fits_in_gp_register = builtin.target.cpu.arch.isSpirV() or fits: {
4846 const max_gp_register_bits = @bitSizeOf(c_long);
4847 break :fits int.bits <= max_gp_register_bits;
4848 };
4849 if (val_fits_in_gp_register) {
47924850 const val2 = @as(
4793 @Int(t.int.signedness, @max(8, std.math.ceilPowerOfTwoAssert(u16, bits))),
4851 @Int(int.signedness, @max(8, std.math.ceilPowerOfTwoAssert(u16, int.bits))),
47944852 val,
47954853 );
47964854 asm volatile (""
47974855 :
47984856 : [_] "r" (val2),
47994857 );
4800 } else doNotOptimizeAway(&val);
4801 },
4802 .float => {
4803 if ((t.float.bits == 32 or t.float.bits == 64) and builtin.zig_backend != .stage2_c) {
4804 asm volatile (""
4805 :
4806 : [_] "rm" (val),
4807 );
4808 } else doNotOptimizeAway(&val);
4809 },
4810 .pointer => {
4811 if (builtin.zig_backend == .stage2_c) {
4812 doNotOptimizeAwayC(val);
48134858 } else {
4814 asm volatile (""
4815 :
4816 : [_] "m" (val),
4817 : .{ .memory = true });
4859 doNotOptimizeAway(&val);
48184860 }
48194861 },
4820 .array => {
4821 if (t.array.len * @sizeOf(t.array.child) <= 64) {
4822 for (val) |v| doNotOptimizeAway(v);
4823 } else doNotOptimizeAway(&val);
4862 .float => |float| switch (float.bits) {
4863 else => comptime unreachable,
4864 16, 80, 128 => doNotOptimizeAway(&val),
4865 32, 64 => asm volatile (""
4866 :
4867 : [_] "rm" (val),
4868 ),
48244869 },
4870 .pointer => asm volatile (""
4871 :
4872 : [_] "m" (val),
4873 : .{ .memory = true }),
4874 .array => |array| if (array.len * @sizeOf(array.child) <= 64) {
4875 for (val) |v| doNotOptimizeAway(v);
4876 } else doNotOptimizeAway(&val),
48254877 else => doNotOptimizeAway(&val),
48264878 }
48274879}
48284880
4829/// .stage2_c doesn't support asm blocks yet, so use volatile stores instead
4830var deopt_target: if (builtin.zig_backend == .stage2_c) u8 else void = undefined;
4831fn doNotOptimizeAwayC(ptr: anytype) void {
4832 const dest = @as(*volatile u8, @ptrCast(&deopt_target));
4833 for (asBytes(ptr)) |b| {
4834 dest.* = b;
4835 }
4836 dest.* = 0;
4837}
4838
48394881test doNotOptimizeAway {
48404882 comptime doNotOptimizeAway("test");
48414883
......@@ -4994,12 +5036,9 @@ pub fn alignInSlice(slice: anytype, comptime new_alignment: usize) ?AlignedSlice
49945036}
49955037
49965038test "read/write(Var)PackedInt" {
4997 switch (builtin.cpu.arch) {
4998 // This test generates too much code to execute on WASI.
4999 // LLVM backend fails with "too many locals: locals exceed maximum"
5000 .wasm32, .wasm64 => return error.SkipZigTest,
5001 else => {},
5002 }
5039 // This test generates too much code to execute on WASI.
5040 // LLVM backend fails with "too many locals: locals exceed maximum"
5041 if (builtin.cpu.arch.isWasm()) return error.SkipZigTest;
50035042
50045043 const foreign_endian: Endian = if (native_endian == .big) .little else .big;
50055044 const expect = std.testing.expect;
lib/std/mem/Allocator.zig+56-16
......@@ -8,6 +8,8 @@ const assert = std.debug.assert;
88const math = std.math;
99const mem = std.mem;
1010const Alignment = std.mem.Alignment;
11const Slice = std.meta.Slice;
12const AbsorbSentinel = std.meta.AbsorbSentinel;
1113
1214pub const Error = error{OutOfMemory};
1315pub const Log2Align = math.Log2Int(usize);
......@@ -316,8 +318,10 @@ pub fn allocBytesAligned(
316318/// `new_len` may be zero, in which case the allocation is freed.
317319pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
318320 const slice_info = @typeInfo(@TypeOf(allocation)).pointer;
319 comptime assert(slice_info.size == .slice);
320 const T = slice_info.child;
321 const T = if (slice_info.size != .slice) comptime T: {
322 assert(slice_info.size == .one);
323 break :T @typeInfo(slice_info.child).array.child;
324 } else slice_info.child;
321325 if (new_len == 0) {
322326 self.free(allocation);
323327 return true;
......@@ -326,9 +330,6 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
326330 return false;
327331 }
328332 const old_memory: []u8 = @ptrCast(@constCast(mem.absorbSentinel(allocation)));
329 // I would like to use saturating multiplication here, but LLVM cannot lower it
330 // on WebAssembly: https://github.com/ziglang/zig/issues/9660
331 //const new_len_bytes = new_len *| @sizeOf(T);
332333 const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return false;
333334 return self.rawResize(
334335 old_memory,
......@@ -354,10 +355,12 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
354355/// `new_len` may be zero, in which case the allocation is freed.
355356///
356357/// If the allocation's elements' type is zero bytes sized, `allocation.len` is set to `new_len`.
357pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?@TypeOf(allocation) {
358pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?Slice(AbsorbSentinel(@TypeOf(allocation))) {
358359 const slice_info = @typeInfo(@TypeOf(allocation)).pointer;
359 comptime assert(slice_info.size == .slice);
360 const T = slice_info.child;
360 const T = if (slice_info.size != .slice) comptime T: {
361 assert(slice_info.size == .one);
362 break :T @typeInfo(slice_info.child).array.child;
363 } else slice_info.child;
361364
362365 if (new_len == 0) {
363366 self.free(allocation);
......@@ -372,9 +375,6 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?@TypeOf(allo
372375 return new_memory;
373376 }
374377 const old_memory: []u8 = @ptrCast(@constCast(mem.absorbSentinel(allocation)));
375 // I would like to use saturating multiplication here, but LLVM cannot lower it
376 // on WebAssembly: https://github.com/ziglang/zig/issues/9660
377 //const new_len_bytes = new_len *| @sizeOf(T);
378378 const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return null;
379379 const new_ptr = self.rawRemap(
380380 old_memory,
......@@ -399,7 +399,7 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?@TypeOf(allo
399399/// do the realloc more efficiently than the caller
400400/// * `resize` which returns `false` when the `Allocator` implementation cannot
401401/// change the size without relocating the allocation.
402pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) Error!@TypeOf(old_mem) {
402pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) Error!Slice(AbsorbSentinel(@TypeOf(old_mem))) {
403403 return self.reallocAdvanced(old_mem, new_n, @returnAddress());
404404}
405405
......@@ -408,10 +408,12 @@ pub fn reallocAdvanced(
408408 old_mem: anytype,
409409 new_n: usize,
410410 return_address: usize,
411) Error!@TypeOf(old_mem) {
411) Error!Slice(AbsorbSentinel(@TypeOf(old_mem))) {
412412 const slice_info = @typeInfo(@TypeOf(old_mem)).pointer;
413 comptime assert(slice_info.size == .slice);
414 const T = slice_info.child;
413 const T = if (slice_info.size != .slice) comptime T: {
414 assert(slice_info.size == .one);
415 break :T @typeInfo(slice_info.child).array.child;
416 } else slice_info.child;
415417 if (old_mem.len == 0) {
416418 return self.allocAdvancedWithRetAddr(T, .fromByteUnitsOptional(slice_info.attrs.@"align"), new_n, return_address);
417419 }
......@@ -446,7 +448,6 @@ pub fn reallocAdvanced(
446448pub fn free(self: Allocator, memory: anytype) void {
447449 const slice_info = @typeInfo(@TypeOf(memory)).pointer;
448450 if (slice_info.size != .slice) {
449 // slicing with comptime-known start and end results in *[len]T, which may be free'd
450451 comptime assert(slice_info.size == .one and @typeInfo(slice_info.child) == .array);
451452 }
452453 const bytes: []u8 = @ptrCast(@constCast(mem.absorbSentinel(memory)));
......@@ -587,4 +588,43 @@ fn unreachableFree(
587588test failing {
588589 const f: Allocator = .failing;
589590 try std.testing.expectError(error.OutOfMemory, f.alloc(u8, 123));
591 // Expect very large allocations to fail at the implementation level and not in the interface
592 try std.testing.expectError(error.OutOfMemory, f.alloc(u8, std.math.maxInt(usize)));
593 try std.testing.expectError(error.OutOfMemory, f.allocSentinel(u8, std.math.maxInt(usize) - 1, 0));
594}
595
596test "free single-pointer to array" {
597 const allocator = std.testing.allocator;
598 {
599 const allocation = try allocator.alloc(u32, 128);
600 allocation[127] = 0;
601 const ptr: *[127:0]u32 = allocation[0..127 :0];
602 allocator.free(ptr);
603 }
604 {
605 const allocation = try allocator.alloc(u32, 128);
606 allocation[127] = 0;
607 const ptr: *[127:0]u32 = allocation[0..127 :0];
608 if (allocator.resize(ptr, 16)) {
609 allocator.free(ptr[0..16]);
610 } else allocator.free(ptr);
611 }
612 {
613 const allocation = try allocator.alloc(u32, 128);
614 allocation[127] = 0;
615 const ptr: *[127:0]u32 = allocation[0..127 :0];
616 if (allocator.remap(ptr, 16)) |new| {
617 allocator.free(new);
618 } else allocator.free(ptr);
619 }
620 {
621 const allocation = try allocator.alloc(u32, 128);
622 allocation[127] = 0;
623 const ptr: *[127:0]u32 = allocation[0..127 :0];
624 if (allocator.realloc(ptr, 16)) |new| {
625 allocator.free(new);
626 } else |_| {
627 allocator.free(allocation);
628 }
629 }
590630}
lib/std/meta.zig+69-12
......@@ -1,10 +1,9 @@
11const builtin = @import("builtin");
2
23const std = @import("std.zig");
3const debug = std.debug;
4const assert = std.debug.assert;
45const mem = std.mem;
5const math = std.math;
66const testing = std.testing;
7const root = @import("root");
87
98pub const TrailerFlags = @import("meta/trailer_flags.zig").TrailerFlags;
109
......@@ -198,15 +197,17 @@ test containerLayout {
198197 try testing.expect(containerLayout(U3) == .@"extern");
199198}
200199
201/// Instead of this function, prefer to use e.g. `@typeInfo(foo).@"struct".decl_names`
202/// directly when you know what kind of type it is.
200/// Returns the list of declaration names of namespace types.
201///
202/// This function is only useful when the callsite does not know statically
203/// which kind of container it is.
203204pub fn declarations(comptime T: type) []const [:0]const u8 {
204205 return switch (@typeInfo(T)) {
205206 .@"struct" => |info| info.decl_names,
206207 .@"enum" => |info| info.decl_names,
207208 .@"union" => |info| info.decl_names,
208209 .@"opaque" => |info| info.decl_names,
209 else => @compileError("Expected struct, enum, union, or opaque type, found '" ++ @typeName(T) ++ "'"),
210 else => comptime unreachable, // type lacks namespace
210211 };
211212}
212213
......@@ -242,10 +243,13 @@ test declarations {
242243}
243244
244245/// To be removed after Zig 0.17.0 is tagged.
245pub const declarationInfo = @compileError("Deprecated; use '@hasDecl' instead");
246pub const declarationInfo = @compileError("deprecated in favor of @hasDecl");
246247/// To be removed after Zig 0.17.0 is tagged.
247pub const fields = @compileError("Deprecated; use 'fieldNames' and 'fieldTypes' instead");
248pub const fields = @compileError("deprecated in favor of @typeInfo");
248249
250/// Deprecated in favor of `@typeInfo`.
251///
252/// To be removed after 0.17.0 is tagged.
249253pub fn fieldInfo(comptime T: type, comptime field: FieldEnum(T)) switch (@typeInfo(T)) {
250254 .@"struct" => struct { name: [:0]const u8, type: type, attrs: Type.Struct.FieldAttributes },
251255 .@"union" => struct { name: [:0]const u8, type: type, attrs: Type.Union.FieldAttributes },
......@@ -299,13 +303,16 @@ test fieldInfo {
299303 try testing.expect(comptime uf.type == u8);
300304}
301305
306/// Deprecated in favor of `@typeInfo`.
307///
308/// To be removed after 0.17.0 is tagged.
302309pub fn fieldNames(comptime T: type) []const [:0]const u8 {
303310 return switch (@typeInfo(T)) {
304311 .@"struct" => |s| s.field_names,
305312 .@"union" => |u| u.field_names,
306313 .@"enum" => |e| e.field_names,
307314 .error_set => |es| es.error_names.?,
308 else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"),
315 else => comptime unreachable,
309316 };
310317}
311318
......@@ -337,11 +344,14 @@ test fieldNames {
337344 try testing.expectEqualSlices(u8, u1names[1], "b");
338345}
339346
347/// Deprecated in favor of `@typeInfo`.
348///
349/// To be removed after 0.17.0 is tagged.
340350pub fn fieldTypes(comptime T: type) []const type {
341351 return switch (@typeInfo(T)) {
342352 .@"struct" => |s| s.field_types,
343353 .@"union" => |u| u.field_types,
344 else => @compileError("Expected struct or union type, found '" ++ @typeName(T) ++ "'"),
354 else => comptime unreachable,
345355 };
346356}
347357
......@@ -821,8 +831,8 @@ pub fn isError(error_union: anytype) bool {
821831}
822832
823833test isError {
824 try std.testing.expect(isError(math.divTrunc(u8, 5, 0)));
825 try std.testing.expect(!isError(math.divTrunc(u8, 5, 5)));
834 try std.testing.expect(isError(std.math.divTrunc(u8, 5, 0)));
835 try std.testing.expect(!isError(std.math.divTrunc(u8, 5, 5)));
826836}
827837
828838/// Returns true if a type has a namespace and the namespace contains `name`;
......@@ -1070,3 +1080,50 @@ test hasUniqueRepresentation {
10701080
10711081 try testing.expect(hasUniqueRepresentation(StructWithComptimeFields));
10721082}
1083
1084/// Given a pointer type, type-erases the array length if present, returning an
1085/// equivalent pointer type that is always a slice.
1086pub fn Slice(comptime Pointer: type) type {
1087 const info = @typeInfo(Pointer).pointer;
1088 switch (info.size) {
1089 .slice => return Pointer,
1090 .one => {
1091 const child_info = @typeInfo(info.child);
1092 comptime assert(child_info == .array);
1093 const sentinel_ptr: ?*const child_info.array.child = @ptrCast(@alignCast(child_info.array.sentinel_ptr));
1094 return @Pointer(
1095 .slice,
1096 info.attrs,
1097 child_info.array.child,
1098 if (sentinel_ptr) |ptr| ptr.* else null,
1099 );
1100 },
1101 else => unreachable,
1102 }
1103}
1104
1105/// Given a pointer type, removes the sentinel if present, returning an
1106/// equivalent pointer type with no sentinel
1107pub fn AbsorbSentinel(comptime Pointer: type) type {
1108 const info = @typeInfo(Pointer).pointer;
1109 switch (info.size) {
1110 .slice => return @Pointer(.slice, info.attrs, info.child, null),
1111 .one => {
1112 const child_info = @typeInfo(info.child).array;
1113 if (child_info.sentinel_ptr == null) {
1114 return Pointer;
1115 } else {
1116 return @Pointer(.one, info.attrs, [child_info.len + 1]child_info.child, null);
1117 }
1118 },
1119 else => unreachable,
1120 }
1121}
1122
1123test Slice {
1124 try testing.expectEqual([]i32, Slice(*[10]i32));
1125}
1126
1127test AbsorbSentinel {
1128 try testing.expectEqual(*[5]u32, AbsorbSentinel(*[4:0]u32));
1129}
lib/std/meta/trailer_flags.zig+1-1
......@@ -39,7 +39,7 @@ pub fn TrailerFlags(comptime Fields: type) type {
3939 break :blk @Struct(.auto, null, &field_names, &field_types, &field_attrs);
4040 };
4141
42 pub const Self = @This();
42 const Self = @This();
4343
4444 pub fn has(self: Self, comptime field: FieldEnum) bool {
4545 const field_index = @backingInt(field);
lib/std/multi_array_list.zig+2-2
......@@ -163,7 +163,7 @@ pub fn MultiArrayList(comptime T: type) type {
163163 };
164164 }
165165
166 /// This function is used in the debugger pretty formatters in tools/ to fetch the
166 /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the
167167 /// child field order and entry type to facilitate fancy debug printing for this type.
168168 fn dbHelper(self: *Slice, child: *Elem, field: *Field, entry: *Entry) void {
169169 _ = self;
......@@ -681,7 +681,7 @@ pub fn MultiArrayList(comptime T: type) type {
681681 }
682682 break :entry @Struct(.@"extern", null, &entry_field_names, &entry_field_types, &entry_field_attrs);
683683 };
684 /// This function is used in the debugger pretty formatters in tools/ to fetch the
684 /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the
685685 /// child field order and entry type to facilitate fancy debug printing for this type.
686686 fn dbHelper(self: *Self, child: *Elem, field: *Field, entry: *Entry) void {
687687 _ = self;
lib/std/os/emscripten.zig+1-1
......@@ -730,7 +730,7 @@ pub const clock_t = i32;
730730pub const dl_phdr_info = extern struct {
731731 addr: usize,
732732 name: ?[*:0]const u8,
733 phdr: [*]std.elf.Phdr,
733 phdr: [*]std.elf.ElfN.Phdr,
734734 phnum: u16,
735735};
736736
lib/std/os/linux.zig+4-6
......@@ -2058,8 +2058,8 @@ pub const F = struct {
20582058 },
20592059 };
20602060
2061 pub const SETSIG = if (is_hppa or native_arch == .alpha) 13 else 11;
2062 pub const GETSIG = if (is_hppa or native_arch == .alpha) 14 else 12;
2061 pub const SETSIG = if (is_hppa) 13 else 10;
2062 pub const GETSIG = if (is_hppa) 14 else 11;
20632063
20642064 pub const SETOWN_EX = 15;
20652065 pub const GETOWN_EX = 16;
......@@ -8181,13 +8181,11 @@ pub const rusage = extern struct {
81818181
81828182pub const NCC = if (is_ppc) 10 else 8;
81838183pub const NCCS = if (is_mips)
8184 32
8185else if (is_ppc or native_arch == .alpha)
8186 19
8184 23
81878185else if (is_sparc)
81888186 17
81898187else
8190 32;
8188 19;
81918189
81928190pub const speed_t = if (is_ppc) enum(c_uint) {
81938191 B0 = 0x0000000,
lib/std/os/linux/IoUring.zig+1-1
......@@ -267,7 +267,7 @@ pub fn cq_ready(self: *IoUring) u32 {
267267}
268268
269269/// Copies as many CQEs as are ready, and that can fit into the destination `cqes` slice.
270/// If none are available, enters into the kernel to wait for at most `wait_nr` CQEs.
270/// If none are available, enters into the kernel to wait for at least `wait_nr` CQEs.
271271/// Returns the number of CQEs copied, advancing the CQ ring.
272272/// Provides all the wait/peek methods found in liburing, but with batching and a single method.
273273/// The rationale for copying CQEs rather than copying pointers is that pointers are 8 bytes
lib/std/os/linux/IoUring/test.zig+26-64
......@@ -475,9 +475,6 @@ test "close" {
475475}
476476
477477test "accept/connect/send/recv" {
478 const io = testing.io;
479 _ = io;
480
481478 var ring = IoUring.init(16, 0) catch |err| switch (err) {
482479 error.SystemOutdated => return error.SkipZigTest,
483480 error.PermissionDenied => return error.SkipZigTest,
......@@ -620,7 +617,7 @@ test "timeout (after a relative time)" {
620617
621618 const ms = 10;
622619 const margin = 5;
623 const ts: linux.kernel_timespec = .{ .sec = 0, .nsec = ms * 1000000 };
620 const ts: linux.kernel_timespec = .{ .sec = 0, .nsec = ms * std.time.ns_per_ms };
624621
625622 const started = std.Io.Clock.awake.now(io);
626623 const sqe = try ring.timeout(0x55555555, &ts, 0, 0);
......@@ -730,9 +727,6 @@ test "timeout_remove" {
730727}
731728
732729test "accept/connect/recv/link_timeout" {
733 const io = testing.io;
734 _ = io;
735
736730 var ring = IoUring.init(16, 0) catch |err| switch (err) {
737731 error.SystemOutdated => return error.SkipZigTest,
738732 error.PermissionDenied => return error.SkipZigTest,
......@@ -748,7 +742,7 @@ test "accept/connect/recv/link_timeout" {
748742 const sqe_recv = try ring.recv(0xffffffff, socket_test_harness.server, .{ .buffer = buffer_recv[0..] }, 0);
749743 sqe_recv.flags |= linux.IOSQE_IO_LINK;
750744
751 const ts = linux.kernel_timespec{ .sec = 0, .nsec = 1000000 };
745 const ts: linux.kernel_timespec = .{ .sec = 0, .nsec = std.time.ns_per_ms };
752746 _ = try ring.link_timeout(0x22222222, &ts, 0);
753747
754748 const nr_wait = try ring.submit();
......@@ -883,9 +877,6 @@ test "statx" {
883877}
884878
885879test "accept/connect/recv/cancel" {
886 const io = testing.io;
887 _ = io;
888
889880 var ring = IoUring.init(16, 0) catch |err| switch (err) {
890881 error.SystemOutdated => return error.SkipZigTest,
891882 error.PermissionDenied => return error.SkipZigTest,
......@@ -1568,9 +1559,6 @@ test "remove_buffers" {
15681559}
15691560
15701561test "provide_buffers: accept/connect/send/recv" {
1571 const io = testing.io;
1572 _ = io;
1573
15741562 var ring = IoUring.init(16, 0) catch |err| switch (err) {
15751563 error.SystemOutdated => return error.SkipZigTest,
15761564 error.PermissionDenied => return error.SkipZigTest,
......@@ -1777,11 +1765,6 @@ test "accept multishot" {
17771765}
17781766
17791767test "accept/connect/send_zc/recv" {
1780 try skipKernelLessThan(.{ .major = 6, .minor = 0, .patch = 0 });
1781
1782 const io = testing.io;
1783 _ = io;
1784
17851768 var ring = IoUring.init(16, 0) catch |err| switch (err) {
17861769 error.SystemOutdated => return error.SkipZigTest,
17871770 error.PermissionDenied => return error.SkipZigTest,
......@@ -1789,6 +1772,13 @@ test "accept/connect/send_zc/recv" {
17891772 };
17901773 defer ring.deinit();
17911774
1775 const probe = ring.get_probe() catch return error.SkipZigTest;
1776 const ops_not_supported = !probe.is_supported(.ACCEPT) or
1777 !probe.is_supported(.CONNECT) or
1778 !probe.is_supported(.SEND_ZC) or
1779 !probe.is_supported(.RECV);
1780 if (ops_not_supported) return error.SkipZigTest;
1781
17921782 const socket_test_harness = try createSocketTestHarness(&ring);
17931783 defer socket_test_harness.close();
17941784
......@@ -1836,16 +1826,16 @@ test "accept/connect/send_zc/recv" {
18361826}
18371827
18381828test "accept_direct" {
1839 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30854
1840
1841 try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 });
1842
18431829 var ring = IoUring.init(1, 0) catch |err| switch (err) {
18441830 error.SystemOutdated => return error.SkipZigTest,
18451831 error.PermissionDenied => return error.SkipZigTest,
18461832 else => return err,
18471833 };
18481834 defer ring.deinit();
1835
1836 const probe = ring.get_probe() catch return error.SkipZigTest;
1837 if (!probe.is_supported(.ACCEPT)) return error.SkipZigTest;
1838
18491839 var address: linux.sockaddr.in = .{
18501840 .port = 0,
18511841 .addr = @as(*align(1) const u32, @ptrCast(
......@@ -1923,13 +1913,6 @@ test "accept_direct" {
19231913}
19241914
19251915test "accept_multishot_direct" {
1926 try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 });
1927
1928 if (builtin.cpu.arch == .riscv64) {
1929 // https://github.com/ziglang/zig/issues/25734
1930 return error.SkipZigTest;
1931 }
1932
19331916 var ring = IoUring.init(1, 0) catch |err| switch (err) {
19341917 error.SystemOutdated => return error.SkipZigTest,
19351918 error.PermissionDenied => return error.SkipZigTest,
......@@ -1937,6 +1920,9 @@ test "accept_multishot_direct" {
19371920 };
19381921 defer ring.deinit();
19391922
1923 const probe = ring.get_probe() catch return error.SkipZigTest;
1924 if (!probe.is_supported(.ACCEPT)) return error.SkipZigTest;
1925
19401926 var address: linux.sockaddr.in = .{
19411927 .port = 0,
19421928 .addr = @as(*align(1) const u32, @ptrCast(
......@@ -1991,8 +1977,6 @@ test "accept_multishot_direct" {
19911977}
19921978
19931979test "socket" {
1994 try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 });
1995
19961980 var ring = IoUring.init(1, 0) catch |err| switch (err) {
19971981 error.SystemOutdated => return error.SkipZigTest,
19981982 error.PermissionDenied => return error.SkipZigTest,
......@@ -2000,6 +1984,9 @@ test "socket" {
20001984 };
20011985 defer ring.deinit();
20021986
1987 const probe = ring.get_probe() catch return error.SkipZigTest;
1988 if (!probe.is_supported(.SOCKET)) return error.SkipZigTest;
1989
20031990 // prepare, submit socket operation
20041991 _ = try ring.socket(0, linux.AF.INET, posix.SOCK.STREAM, 0, 0);
20051992 try testing.expectEqual(@as(u32, 1), try ring.submit());
......@@ -2014,8 +2001,6 @@ test "socket" {
20142001}
20152002
20162003test "socket_direct/socket_direct_alloc/close_direct" {
2017 try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 });
2018
20192004 var ring = IoUring.init(2, 0) catch |err| switch (err) {
20202005 error.SystemOutdated => return error.SkipZigTest,
20212006 error.PermissionDenied => return error.SkipZigTest,
......@@ -2023,6 +2008,9 @@ test "socket_direct/socket_direct_alloc/close_direct" {
20232008 };
20242009 defer ring.deinit();
20252010
2011 const probe = ring.get_probe() catch return error.SkipZigTest;
2012 if (!probe.is_supported(.SOCKET) or !probe.is_supported(.CLOSE)) return error.SkipZigTest;
2013
20262014 var registered_fds: [3]linux.fd_t = @splat(-1);
20272015 try ring.register_files(registered_fds[0..]);
20282016
......@@ -2097,8 +2085,6 @@ test "socket_direct/socket_direct_alloc/close_direct" {
20972085}
20982086
20992087test "openat_direct/close_direct" {
2100 try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 });
2101
21022088 var ring = IoUring.init(2, 0) catch |err| switch (err) {
21032089 error.SystemOutdated => return error.SkipZigTest,
21042090 error.PermissionDenied => return error.SkipZigTest,
......@@ -2106,6 +2092,9 @@ test "openat_direct/close_direct" {
21062092 };
21072093 defer ring.deinit();
21082094
2095 const probe = ring.get_probe() catch return error.SkipZigTest;
2096 if (!probe.is_supported(.OPENAT) or !probe.is_supported(.CLOSE)) return error.SkipZigTest;
2097
21092098 var registered_fds: [3]linux.fd_t = @splat(-1);
21102099 try ring.register_files(registered_fds[0..]);
21112100
......@@ -2148,9 +2137,6 @@ test "openat_direct/close_direct" {
21482137}
21492138
21502139test "ring mapped buffers recv" {
2151 const io = testing.io;
2152 _ = io;
2153
21542140 var ring = IoUring.init(16, 0) catch |err| switch (err) {
21552141 error.SystemOutdated => return error.SkipZigTest,
21562142 error.PermissionDenied => return error.SkipZigTest,
......@@ -2238,9 +2224,6 @@ test "ring mapped buffers recv" {
22382224}
22392225
22402226test "ring mapped buffers multishot recv" {
2241 const io = testing.io;
2242 _ = io;
2243
22442227 var ring = IoUring.init(16, 0) catch |err| switch (err) {
22452228 error.SystemOutdated => return error.SkipZigTest,
22462229 error.PermissionDenied => return error.SkipZigTest,
......@@ -2672,7 +2655,7 @@ pub fn createSocketTestHarness(ring: *IoUring) !SocketTestHarness {
26722655
26732656 // All good
26742657
2675 return SocketTestHarness{
2658 return .{
26762659 .listener = listener_socket,
26772660 .server = cqe_accept.res,
26782661 .client = client,
......@@ -2695,27 +2678,6 @@ fn createListenerSocket(address: *linux.sockaddr.in) !posix.socket_t {
26952678 return listener_socket;
26962679}
26972680
2698/// For use in tests. Returns SkipZigTest if kernel version is less than required.
2699inline fn skipKernelLessThan(required: std.SemanticVersion) !void {
2700 var uts: linux.utsname = undefined;
2701 const res = linux.uname(&uts);
2702 switch (linux.errno(res)) {
2703 .SUCCESS => {},
2704 else => |errno| return posix.unexpectedErrno(errno),
2705 }
2706
2707 const release = mem.sliceTo(&uts.release, 0);
2708 // Strips potential extra, as kernel version might not be semver compliant, example "6.8.9-300.fc40.x86_64"
2709 const extra_index = std.mem.indexOfAny(u8, release, "-+");
2710 const stripped = release[0..(extra_index orelse release.len)];
2711 // Make sure the input don't rely on the extra we just stripped
2712 try testing.expect(required.pre == null and required.build == null);
2713
2714 var current = try std.SemanticVersion.parse(stripped);
2715 current.pre = null; // don't check pre field
2716 if (required.order(current) == .gt) return error.SkipZigTest;
2717}
2718
27192681fn addrAny(addr: *linux.sockaddr.in) *linux.sockaddr {
27202682 return @ptrCast(addr);
27212683}
lib/std/os/linux/aarch64.zig+1-1
......@@ -154,7 +154,7 @@ pub const restore = restore_rt;
154154pub fn restore_rt() callconv(.naked) noreturn {
155155 switch (builtin.zig_backend) {
156156 .stage2_c => asm volatile (
157 \\ mov x8, %[number]
157 \\ mov w8, %[number]
158158 \\ svc #0
159159 :
160160 : [number] "i" (@backingInt(SYS.rt_sigreturn)),
lib/std/os/linux/s390x.zig+26-10
......@@ -174,19 +174,35 @@ pub fn clone() callconv(.naked) u64 {
174174}
175175
176176pub fn restore() callconv(.naked) noreturn {
177 asm volatile (
178 \\svc 0
179 :
180 : [number] "{r1}" (@backingInt(SYS.sigreturn)),
181 );
177 switch (builtin.zig_backend) {
178 .stage2_c => asm volatile (
179 \\lghi %%r1, %[number]
180 \\svc 0
181 :
182 : [number] "K" (@backingInt(SYS.sigreturn)),
183 ),
184 else => asm volatile (
185 \\svc 0
186 :
187 : [number] "{r1}" (@backingInt(SYS.sigreturn)),
188 ),
189 }
182190}
183191
184192pub fn restore_rt() callconv(.naked) noreturn {
185 asm volatile (
186 \\svc 0
187 :
188 : [number] "{r1}" (@backingInt(SYS.rt_sigreturn)),
189 );
193 switch (builtin.zig_backend) {
194 .stage2_c => asm volatile (
195 \\lghi %%r1, %[number]
196 \\svc 0
197 :
198 : [number] "K" (@backingInt(SYS.rt_sigreturn)),
199 ),
200 else => asm volatile (
201 \\svc 0
202 :
203 : [number] "{r1}" (@backingInt(SYS.rt_sigreturn)),
204 ),
205 }
190206}
191207
192208pub const time_t = i64;
lib/std/os/linux/sparc.zig+8-5
......@@ -260,13 +260,16 @@ pub fn clone() callconv(.naked) u32 {
260260
261261pub const restore = restore_rt;
262262
263// Need to use C ABI here instead of naked
264// to prevent an infinite loop when calling rt_sigreturn.
265pub fn restore_rt() callconv(.c) void {
266 return asm volatile ("t 0x10"
263pub fn restore_rt() callconv(.naked) noreturn {
264 asm volatile (
265 \\ nop
266 \\ nop
267 );
268 asm volatile (
269 \\ t 0x10
267270 :
268271 : [number] "{g1}" (@backingInt(SYS.rt_sigreturn)),
269 : .{ .memory = true, .xcc = true, .o0 = true, .o1 = true, .o2 = true, .o3 = true, .o4 = true, .o5 = true, .o7 = true });
272 );
270273}
271274
272275pub const VDSO = struct {
lib/std/os/linux/sparc64.zig+8-5
......@@ -259,13 +259,16 @@ pub fn clone() callconv(.naked) u64 {
259259
260260pub const restore = restore_rt;
261261
262// Need to use C ABI here instead of naked
263// to prevent an infinite loop when calling rt_sigreturn.
264pub fn restore_rt() callconv(.c) void {
265 return asm volatile ("t 0x6d"
262pub fn restore_rt() callconv(.naked) noreturn {
263 asm volatile (
264 \\ nop
265 \\ nop
266 );
267 asm volatile (
268 \\ t 0x6d
266269 :
267270 : [number] "{g1}" (@backingInt(SYS.rt_sigreturn)),
268 : .{ .memory = true, .xcc = true, .o0 = true, .o1 = true, .o2 = true, .o3 = true, .o4 = true, .o5 = true, .o7 = true });
271 );
269272}
270273
271274pub const VDSO = struct {
lib/std/os/linux/tls.zig+35-14
......@@ -22,7 +22,7 @@ const page_size_min = std.heap.page_size_min;
2222/// Represents an ELF TLS variant.
2323///
2424/// In all variants, the TP and the TLS blocks must be aligned to the `p_align` value in the
25/// `PT_TLS` ELF program header. Everything else has natural alignment.
25/// `PT.TLS` ELF program header. Everything else has natural alignment.
2626///
2727/// The location of the DTV does not actually matter. For simplicity, we put it in the TLS area, but
2828/// there is no actual ABI requirement that it reside there.
......@@ -480,17 +480,17 @@ pub fn getThreadPointer() usize {
480480 };
481481}
482482
483fn computeAreaDesc(phdrs: []elf.Phdr) void {
483fn computeAreaDesc(phdrs: []elf.ElfN.Phdr) void {
484484 @setRuntimeSafety(false);
485485 @disableInstrumentation();
486486
487 var tls_phdr: ?*elf.Phdr = null;
487 var tls_phdr: ?*elf.ElfN.Phdr = null;
488488 var img_base: usize = 0;
489489
490490 for (phdrs) |*phdr| {
491 switch (phdr.p_type) {
492 elf.PT_PHDR => img_base = @intFromPtr(phdrs.ptr) - phdr.p_vaddr,
493 elf.PT_TLS => tls_phdr = phdr,
491 switch (phdr.type) {
492 .PHDR => img_base = @intFromPtr(phdrs.ptr) - phdr.vaddr,
493 .TLS => tls_phdr = phdr,
494494 else => {},
495495 }
496496 }
......@@ -500,12 +500,12 @@ fn computeAreaDesc(phdrs: []elf.Phdr) void {
500500 var block_size: usize = undefined;
501501
502502 if (tls_phdr) |phdr| {
503 align_factor = phdr.p_align;
503 align_factor = phdr.@"align";
504504
505 // The effective size in memory is represented by `p_memsz`; the length of the data stored
506 // in the `PT_TLS` segment is `p_filesz` and may be less than the former.
507 block_init = @as([*]u8, @ptrFromInt(img_base + phdr.p_vaddr))[0..phdr.p_filesz];
508 block_size = phdr.p_memsz;
505 // The effective size in memory is represented by `memsz`; the length of the data stored
506 // in the `PT.TLS` segment is `filesz` and may be less than the former.
507 block_init = @as([*]u8, @ptrFromInt(img_base + phdr.vaddr))[0..phdr.filesz];
508 block_size = phdr.memsz;
509509 } else {
510510 align_factor = @alignOf(usize);
511511
......@@ -651,7 +651,7 @@ var main_thread_area_buffer: [0x1000]u8 align(page_size_min) = undefined;
651651
652652/// Computes the layout of the static TLS area, allocates the area, initializes all of its fields,
653653/// and assigns the architecture-specific value to the TP register.
654pub fn initStatic(phdrs: []elf.Phdr) void {
654pub fn initStatic(phdrs: []elf.ElfN.Phdr) void {
655655 @setRuntimeSafety(false);
656656 @disableInstrumentation();
657657
......@@ -726,12 +726,14 @@ comptime {
726726 // function for the GD and LD models. This function is unlikely to actually be used, since
727727 // the linker should be able to relax every TLS access to the LE model and therefore
728728 // eliminate all calls to this function, but that isn't guaranteed.
729 _ = struct {
729 const Fns = struct {
730730 const TlsIndex = switch (native_arch) {
731731 .x86_64 => extern struct { module: u64, offset: u64 }, // Even for x32...
732732 else => extern struct { module: usize, offset: usize }, // ...but not MIPS N32!
733733 };
734 export fn __tls_get_addr(ti: *const TlsIndex) *anyopaque {
734 fn __tls_get_addr(ti: *const TlsIndex) callconv(.c) *anyopaque {
735 comptime assert(native_arch != .s390x);
736
735737 assert(ti.module == 1); // The executable's module ID is always 1
736738 const tp = getThreadPointer();
737739 const block: [*]u8 = switch (current_variant) {
......@@ -743,6 +745,25 @@ comptime {
743745 };
744746 return block[@intCast(ti.offset)..];
745747 }
748 fn __tls_get_offset() callconv(.naked) noreturn {
749 comptime assert(native_arch == .s390x);
750
751 // We receive the module's GOT pointer in r12 and the GOT offset in r2.
752 asm volatile (
753 \\ la %%r1, 0(%%r12, %%r2)
754 \\ lg %%r2, 8(%%r1)
755 \\ lgrl %%r0, %[block_size]
756 \\ sgr %%r2, %%r0
757 \\ br %%r14
758 :
759 : [block_size] "s" (&area_desc.block.size),
760 );
761 }
746762 };
763
764 if (native_arch == .s390x)
765 @export(&Fns.__tls_get_offset, .{ .name = "__tls_get_offset" })
766 else
767 @export(&Fns.__tls_get_addr, .{ .name = "__tls_get_addr" });
747768 }
748769}
lib/std/os/linux/vdso.zig+5-5
......@@ -19,14 +19,14 @@ pub fn lookup(vername: []const u8, name: []const u8) usize {
1919 i += 1;
2020 ph_addr += eh.e_phentsize;
2121 }) {
22 const this_ph = @as(*elf.Phdr, @ptrFromInt(ph_addr));
23 switch (this_ph.p_type) {
22 const this_ph = @as(*elf.ElfN.Phdr, @ptrFromInt(ph_addr));
23 switch (this_ph.type) {
2424 // On WSL1 as well as older kernels, the VDSO ELF image is pre-linked in the upper half
25 // of the memory space (e.g. p_vaddr = 0xffffffffff700000 on WSL1).
25 // of the memory space (e.g. vaddr = 0xffffffffff700000 on WSL1).
2626 // Wrapping operations are used on this line as well as subsequent calculations relative to base
2727 // (lines 47, 78) to ensure no overflow check is tripped.
28 elf.PT_LOAD => base = vdso_addr +% this_ph.p_offset -% this_ph.p_vaddr,
29 elf.PT_DYNAMIC => maybe_dynv = @as([*]usize, @ptrFromInt(vdso_addr + this_ph.p_offset)),
28 .LOAD => base = vdso_addr +% this_ph.offset -% this_ph.vaddr,
29 .DYNAMIC => maybe_dynv = @as([*]usize, @ptrFromInt(vdso_addr + this_ph.offset)),
3030 else => {},
3131 }
3232 }
lib/std/pie.zig+3-3
......@@ -293,7 +293,7 @@ inline fn getDynamicSymbol() [*]const elf.Dyn {
293293 };
294294}
295295
296pub fn relocate(phdrs: []const elf.Phdr) void {
296pub fn relocate(phdrs: []const elf.ElfN.Phdr) void {
297297 @setRuntimeSafety(false);
298298 @disableInstrumentation();
299299
......@@ -303,8 +303,8 @@ pub fn relocate(phdrs: []const elf.Phdr) void {
303303 // the theoretical load addresses for the `_DYNAMIC` symbol.
304304 const base_addr = base: {
305305 for (phdrs) |*phdr| {
306 if (phdr.p_type != elf.PT_DYNAMIC) continue;
307 break :base @intFromPtr(dynv) - phdr.p_vaddr;
306 if (phdr.type != .DYNAMIC) continue;
307 break :base @intFromPtr(dynv) - phdr.vaddr;
308308 }
309309 // This is not supposed to happen for well-formed binaries.
310310 @trap();
lib/std/posix/test.zig+1-1
......@@ -75,7 +75,7 @@ fn iter_fn(info: *dl_phdr_info, size: usize, counter: *usize) IterFnError!void {
7575 // Count how many libraries are loaded
7676 counter.* += @as(usize, 1);
7777
78 // The image should contain at least a PT_LOAD segment
78 // The image should contain at least a PT.LOAD segment
7979 if (info.phnum < 1) return error.MissingPtLoadSegment;
8080
8181 // Quick & dirty validation of the phdr pointers, make sure we're not
lib/std/process.zig+5-5
......@@ -100,7 +100,7 @@ pub const UserInfo = struct {
100100};
101101
102102/// POSIX function which gets a uid from username.
103pub fn getUserInfo(name: []const u8) !UserInfo {
103pub fn getUserInfo(io: Io, name: []const u8) !UserInfo {
104104 return switch (native_os) {
105105 .linux,
106106 .driverkit,
......@@ -116,7 +116,7 @@ pub fn getUserInfo(name: []const u8) !UserInfo {
116116 .haiku,
117117 .illumos,
118118 .serenity,
119 => posixGetUserInfo(name),
119 => posixGetUserInfo(io, name),
120120 else => @compileError("Unsupported OS"),
121121 };
122122}
......@@ -127,7 +127,7 @@ pub fn posixGetUserInfo(io: Io, name: []const u8) !UserInfo {
127127 const file = try Io.Dir.openFileAbsolute(io, "/etc/passwd", .{});
128128 defer file.close(io);
129129 var buffer: [4096]u8 = undefined;
130 var file_reader = file.reader(&buffer);
130 var file_reader = file.reader(io, &buffer);
131131 return posixGetUserInfoPasswdStream(name, &file_reader.interface) catch |err| switch (err) {
132132 error.ReadFailed => return file_reader.err.?,
133133 error.EndOfStream => return error.UserNotFound,
......@@ -644,7 +644,7 @@ pub fn totalSystemMemory() TotalSystemMemoryError!u64 {
644644/// leaks can be accurate. In release builds, this calls `exit` with code zero,
645645/// and does not return.
646646pub fn cleanExit(io: Io) void {
647 if (builtin.mode == .Debug) return;
647 if (builtin.mode == .debug) return;
648648 _ = io.lockStderr(&.{}, .no_color) catch {};
649649 exit(0);
650650}
......@@ -809,7 +809,7 @@ pub fn abort() noreturn {
809809 // even when linking libc on Windows we use our own abort implementation.
810810 // See https://github.com/ziglang/zig/issues/2071 for more details.
811811 if (native_os == .windows) {
812 if (builtin.mode == .Debug and windows.peb().BeingDebugged.toBool()) {
812 if (builtin.mode == .debug and windows.peb().BeingDebugged.toBool()) {
813813 @breakpoint();
814814 }
815815 windows.ntdll.RtlExitUserProcess(3);
lib/std/process/Args.zig+1-1
......@@ -752,7 +752,7 @@ pub fn IteratorGeneral(comptime options: IteratorGeneralOptions) type {
752752 start: usize = 0,
753753 end: usize = 0,
754754
755 pub const Self = @This();
755 const Self = @This();
756756
757757 pub const InitError = error{OutOfMemory};
758758
lib/std/sort/block.zig+1-1
......@@ -103,7 +103,7 @@ pub fn block(
103103 context: anytype,
104104 comptime lessThanFn: fn (@TypeOf(context), lhs: T, rhs: T) bool,
105105) void {
106 const lessThan = if (builtin.mode == .Debug) struct {
106 const lessThan = if (builtin.mode == .debug) struct {
107107 fn lessThan(ctx: @TypeOf(context), lhs: T, rhs: T) bool {
108108 const lt = lessThanFn(ctx, lhs, rhs);
109109 const gt = lessThanFn(ctx, rhs, lhs);
lib/std/spirv.zig+1-1
......@@ -97,7 +97,7 @@ pub fn specConst(T: type, comptime default_value: T, comptime spec_id: u32) T {
9797 },
9898 .int, .float => return asm (
9999 \\%ret = OpSpecConstant %ty $default_value
100 \\ OpDecorate %ret SpecId $spec_id"
100 \\ OpDecorate %ret SpecId $spec_id
101101 : [ret] "" (-> T),
102102 : [ty] "t" (T),
103103 [default_value] "c" (default_value),
lib/std/start.zig+11-11
......@@ -589,7 +589,7 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn {
589589 else => continue,
590590 }
591591 }
592 break :init @as([*]elf.Phdr, @ptrFromInt(at_phdr))[0..at_phnum];
592 break :init @as([*]elf.ElfN.Phdr, @ptrFromInt(at_phdr))[0..at_phnum];
593593 };
594594
595595 // Apply the initial relocations as early as possible in the startup process. We cannot
......@@ -621,7 +621,7 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn {
621621 std.os.linux.tls.initStatic(phdrs);
622622 }
623623
624 // The way Linux executables represent stack size is via the PT_GNU_STACK
624 // The way Linux executables represent stack size is via the PT.GNU_STACK
625625 // program header. However the kernel does not recognize it; it always gives 8 MiB.
626626 // Here we look for the stack size in our program headers and use setrlimit
627627 // to ask for more stack space.
......@@ -645,19 +645,19 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn {
645645 std.process.exit(callMainWithArgs(argc, argv, envp));
646646}
647647
648fn expandStackSize(phdrs: []elf.Phdr) void {
648fn expandStackSize(phdrs: []elf.ElfN.Phdr) void {
649649 @disableInstrumentation();
650650 for (phdrs) |*phdr| {
651 switch (phdr.p_type) {
652 elf.PT_GNU_STACK => {
653 if (phdr.p_memsz == 0) break;
654 assert(phdr.p_memsz % std.heap.page_size_min == 0);
651 switch (phdr.type) {
652 .GNU_STACK => {
653 if (phdr.memsz == 0) break;
654 assert(phdr.memsz % std.heap.page_size_min == 0);
655655
656656 // Silently fail if we are unable to get limits.
657657 const limits = std.posix.getrlimit(.STACK) catch break;
658658
659659 // Clamp to limits.max .
660 const wanted_stack_size = @min(phdr.p_memsz, limits.max);
660 const wanted_stack_size = @min(phdr.memsz, limits.max);
661661
662662 if (wanted_stack_size > limits.cur) {
663663 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
702702 .linux => {
703703 const at_phdr = std.c.getauxval(elf.AT_PHDR);
704704 const at_phnum = std.c.getauxval(elf.AT_PHNUM);
705 const phdrs = (@as([*]elf.Phdr, @ptrFromInt(at_phdr)))[0..at_phnum];
705 const phdrs = (@as([*]elf.ElfN.Phdr, @ptrFromInt(at_phdr)))[0..at_phnum];
706706 expandStackSize(phdrs);
707707 },
708708 .windows => {
......@@ -742,8 +742,8 @@ fn mainWithoutEnv(c_argc: c_int, c_argv: [*][*:0]c_char) callconv(.c) c_int {
742742const bad_main_ret = "expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'";
743743
744744const use_safe_allocator = !is_wasm and switch (builtin.mode) {
745 .Debug, .ReleaseSafe => true,
746 .ReleaseFast, .ReleaseSmall => !builtin.link_libc and builtin.single_threaded, // Also not ideal.
745 .debug, .safe => true,
746 .fast, .small => !builtin.link_libc and builtin.single_threaded, // Also not ideal.
747747};
748748var safe_allocator: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{});
749749
lib/std/std.zig+2-2
......@@ -162,7 +162,7 @@ pub const Options = struct {
162162 /// This enables `std.http.Client` to log ssl secrets to the file specified by the SSLKEYLOGFILE
163163 /// env var. Creating such a log file allows other programs with access to that file to decrypt
164164 /// all `std.http.Client` traffic made by this program.
165 http_enable_ssl_key_log_file: bool = @import("builtin").mode == .Debug,
165 http_enable_ssl_key_log_file: bool = @import("builtin").mode == .debug,
166166
167167 side_channels_mitigations: crypto.SideChannelsMitigations = crypto.default_side_channels_mitigations,
168168
......@@ -192,7 +192,7 @@ pub const Options = struct {
192192 /// If this happens the fix is to add the error code to the corresponding
193193 /// switch expression, possibly introduce a new error in the error set, and
194194 /// send a patch to Zig.
195 unexpected_error_tracing: bool = @import("builtin").mode == .Debug and switch (@import("builtin").zig_backend) {
195 unexpected_error_tracing: bool = @import("builtin").mode == .debug and switch (@import("builtin").zig_backend) {
196196 .stage2_llvm, .stage2_x86_64 => true,
197197 else => false,
198198 },
lib/std/tar/Writer.zig+1-1
......@@ -312,7 +312,7 @@ pub const Header = extern struct {
312312
313313 // add as much to prefix as you can, must split at /
314314 const prefix_remaining = max_prefix - prefix_pos;
315 if (std.mem.lastIndexOf(u8, sub_path[0..@min(prefix_remaining, sub_path.len)], &.{'/'})) |sep_pos| {
315 if (std.mem.findLast(u8, sub_path[0..@min(prefix_remaining, sub_path.len)], &.{'/'})) |sep_pos| {
316316 @memcpy(w.prefix[prefix_pos..][0..sep_pos], sub_path[0..sep_pos]);
317317 if ((sub_path.len - sep_pos - 1) > max_name) return error.NameTooLong;
318318 @memcpy(w.name[0..][0 .. sub_path.len - sep_pos - 1], sub_path[sep_pos + 1 ..]);
lib/std/tar/test.zig+3-3
......@@ -474,14 +474,14 @@ test "should not overwrite existing file" {
474474 defer root.cleanup();
475475 try testing.expectError(
476476 error.PathAlreadyExists,
477 tar.pipeToFileSystem(io, root.dir, &r, .{ .mode_mode = .ignore, .strip_components = 1 }),
477 tar.extract(io, root.dir, &r, .{ .mode_mode = .ignore, .strip_components = 1 }),
478478 );
479479
480480 // Unpack with strip_components = 0 should pass
481481 r = .fixed(data);
482482 var root2 = std.testing.tmpDir(.{});
483483 defer root2.cleanup();
484 try tar.pipeToFileSystem(io, root2.dir, &r, .{ .mode_mode = .ignore, .strip_components = 0 });
484 try tar.extract(io, root2.dir, &r, .{ .mode_mode = .ignore, .strip_components = 0 });
485485}
486486
487487test "case sensitivity" {
......@@ -501,7 +501,7 @@ test "case sensitivity" {
501501 var root = std.testing.tmpDir(.{});
502502 defer root.cleanup();
503503
504 tar.pipeToFileSystem(io, root.dir, &r, .{ .mode_mode = .ignore, .strip_components = 1 }) catch |err| {
504 tar.extract(io, root.dir, &r, .{ .mode_mode = .ignore, .strip_components = 1 }) catch |err| {
505505 // on case insensitive fs we fail on overwrite existing file
506506 try testing.expectEqual(error.PathAlreadyExists, err);
507507 return;
lib/std/testing.zig+1-1
......@@ -999,7 +999,7 @@ test "expectEqualDeep composite type" {
999999}
10001000
10011001fn printIndicatorLine(source: []const u8, indicator_index: usize) void {
1002 const line_begin_index = if (std.mem.lastIndexOfScalar(u8, source[0..indicator_index], '\n')) |line_begin|
1002 const line_begin_index = if (std.mem.findScalarLast(u8, source[0..indicator_index], '\n')) |line_begin|
10031003 line_begin + 1
10041004 else
10051005 0;
lib/std/testing/Smith.zig+2-2
......@@ -52,7 +52,7 @@ pub inline fn baselineWeights(T: type) []const Weight {
5252 .bool, .int, .float => i: {
5353 // Reject types that don't have a fixed bitsize (esp. usize)
5454 // since they are not gauraunteed to fit in a u64 across targets.
55 if (std.mem.indexOfScalar(type, &.{
55 if (std.mem.findScalar(type, &.{
5656 isize, usize,
5757 c_char, c_longdouble,
5858 c_short, c_ushort,
......@@ -708,7 +708,7 @@ fn constructInput(comptime values: []const union(enum) {
708708}
709709
710710test value {
711 if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO
711 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
712712
713713 const S = struct {
714714 v: void = {},
lib/std/unicode.zig+35
......@@ -425,6 +425,15 @@ pub const Utf8Iterator = struct {
425425
426426 return it.bytes[original_i..end_ix];
427427 }
428
429 /// Look ahead at the next codepoint without advancing the iterator.
430 /// If no codepoints exist, then returns null.
431 pub fn peekCodepoint(it: *Utf8Iterator) ?u21 {
432 const original_i = it.i;
433 defer it.i = original_i;
434
435 return it.nextCodepoint();
436 }
428437};
429438
430439pub fn utf16IsHighSurrogate(c: u16) bool {
......@@ -768,6 +777,9 @@ fn testMiscInvalidUtf8() !void {
768777test "utf8 iterator peeking" {
769778 try comptime testUtf8Peeking();
770779 try testUtf8Peeking();
780
781 comptime try testUtf8PeekCodepoint();
782 try testUtf8PeekCodepoint();
771783}
772784
773785fn testUtf8Peeking() !void {
......@@ -790,6 +802,20 @@ fn testUtf8Peeking() !void {
790802 try testing.expect(mem.eql(u8, &[_]u8{}, it.peek(1)));
791803}
792804
805fn testUtf8PeekCodepoint() !void {
806 const s = Utf8View.initComptime("東京市");
807 var it = s.iterator();
808
809 try testing.expect(it.peekCodepoint().? == 0x6771);
810 try testing.expect(it.peekCodepoint().? == 0x6771);
811 _ = it.nextCodepoint();
812 try testing.expect(it.peekCodepoint().? == 0x4eac);
813 _ = it.nextCodepoint();
814 try testing.expect(it.peekCodepoint().? == 0x5e02);
815 _ = it.nextCodepoint();
816 try testing.expect(it.peekCodepoint() == null);
817}
818
793819fn testError(bytes: []const u8, expected_err: anyerror) !void {
794820 try testing.expectError(expected_err, testDecode(bytes));
795821}
......@@ -1758,6 +1784,15 @@ pub const Wtf8Iterator = struct {
17581784
17591785 return it.bytes[original_i..end_ix];
17601786 }
1787
1788 /// Look ahead at the next codepoint without advancing the iterator.
1789 /// If no codepoints exist, then returns null.
1790 pub fn peekCodepoint(it: *Wtf8Iterator) ?u21 {
1791 const original_i = it.i;
1792 defer it.i = original_i;
1793
1794 return it.nextCodepoint();
1795 }
17611796};
17621797
17631798pub fn wtf16LeToWtf8ArrayList(result: *std.array_list.Managed(u8), utf16le: []const u16) Allocator.Error!void {
lib/std/zig.zig+47-77
......@@ -386,23 +386,6 @@ pub const Subsystem = enum {
386386 efi_boot_service_driver,
387387 efi_rom,
388388 efi_runtime_driver,
389
390 /// Deprecated; use '.console' instead. To be removed after 0.16.0 is tagged.
391 pub const Console: Subsystem = .console;
392 /// Deprecated; use '.windows' instead. To be removed after 0.16.0 is tagged.
393 pub const Windows: Subsystem = .windows;
394 /// Deprecated; use '.posix' instead. To be removed after 0.16.0 is tagged.
395 pub const Posix: Subsystem = .posix;
396 /// Deprecated; use '.native' instead. To be removed after 0.16.0 is tagged.
397 pub const Native: Subsystem = .native;
398 /// Deprecated; use '.efi_application' instead. To be removed after 0.16.0 is tagged.
399 pub const EfiApplication: Subsystem = .efi_application;
400 /// Deprecated; use '.efi_boot_service_driver' instead. To be removed after 0.16.0 is tagged.
401 pub const EfiBootServiceDriver: Subsystem = .efi_boot_service_driver;
402 /// Deprecated; use '.efi_rom' instead. To be removed after 0.16.0 is tagged.
403 pub const EfiRom: Subsystem = .efi_rom;
404 /// Deprecated; use '.efi_runtime_driver' instead. To be removed after 0.16.0 is tagged.
405 pub const EfiRuntimeDriver: Subsystem = .efi_runtime_driver;
406389};
407390
408391pub const CompressDebugSections = enum(u2) { none, zlib, zstd };
......@@ -562,8 +545,7 @@ pub fn stringEscape(bytes: []const u8, w: *Writer) Writer.Error!void {
562545 '\t' => try w.writeAll("\\t"),
563546 '\\' => try w.writeAll("\\\\"),
564547 '"' => try w.writeAll("\\\""),
565 '\'' => try w.writeByte('\''),
566 ' ', '!', '#'...'&', '('...'[', ']'...'~' => try w.writeByte(byte),
548 ' ', '!', '#'...'[', ']'...'~' => try w.writeByte(byte),
567549 else => {
568550 try w.writeAll("\\x");
569551 try w.printInt(byte, 16, .lower, .{ .width = 2, .fill = '0' });
......@@ -780,11 +762,11 @@ pub const EnvVar = enum {
780762 ZIG_LIBC,
781763 ZIG_BUILD_ERROR_STYLE,
782764 ZIG_BUILD_MULTILINE_ERRORS,
765 ZIG_BUILD_SUMMARY,
783766 ZIG_VERBOSE_LINK,
784767 ZIG_VERBOSE_CC,
785768 ZIG_VERBOSE_CMD,
786769 ZIG_DEBUG_CMD,
787 ZIG_DEBUG_MAKER,
788770 ZIG_IS_DETECTING_LIBC_PATHS,
789771 ZIG_IS_AVOIDING_CALLING_ITSELF,
790772
......@@ -1577,7 +1559,7 @@ pub fn resolvePath(
15771559 // Heuristic for a fast path: if no component is absolute and ".." never appears, we just need to resolve `paths`.
15781560 for (paths) |p| {
15791561 if (Dir.path.isAbsolute(p)) break; // absolute path
1580 if (mem.indexOf(u8, p, "..") != null) break; // may contain up-dir
1562 if (mem.find(u8, p, "..") != null) break; // may contain up-dir
15811563 } else {
15821564 // no absolute path, no "..".
15831565 const res = try Dir.path.resolve(gpa, paths);
......@@ -1675,31 +1657,32 @@ pub fn buildExeSubprocess(
16751657 };
16761658 defer child.kill(io);
16771659
1678 var stderr_task = io.concurrent(readStreamAlloc, .{ gpa, io, child.stderr.?, .unlimited }) catch
1679 @panic("TODO use multireader instead");
1680 defer if (stderr_task.cancel(io)) |slice| gpa.free(slice) else |_| {};
1660 var multi_reader_buffer: Io.File.MultiReader.Buffer(2) = undefined;
1661 var multi_reader: Io.File.MultiReader = undefined;
1662 multi_reader.init(gpa, io, multi_reader_buffer.toStreams(), &.{ child.stdout.?, child.stderr.? });
1663 defer multi_reader.deinit();
1664 const stdout = multi_reader.reader(0);
1665 const stderr = multi_reader.reader(1);
16811666
1682 var stdout_buffer: [512]u8 = undefined;
1683 var stdout_reader: Io.File.Reader = .initStreaming(child.stdout.?, io, &stdout_buffer);
1684 const stdout = &stdout_reader.interface;
1667 var stdin_buffer: [8]u8 = undefined;
1668 var stdin_writer = child.stdin.?.writerStreaming(io, &stdin_buffer);
16851669
1686 {
1687 var w = child.stdin.?.writer(io, &.{});
1688 w.interface.writeStruct(Client.Message.Header{ .tag = .update, .bytes_len = 0 }, .little) catch |err| switch (err) {
1689 error.WriteFailed => {
1690 log.err("{t} writing to command: {f}", .{ w.err.?, cmd });
1691 return error.AlreadyReported;
1692 },
1693 };
1694 w.interface.writeStruct(Client.Message.Header{ .tag = .exit, .bytes_len = 0 }, .little) catch |err| switch (err) {
1695 error.WriteFailed => {
1696 log.err("{t} writing to command: {f}", .{ w.err.?, cmd });
1697 return error.AlreadyReported;
1698 },
1699 };
1700 }
1670 var client: Client = .{
1671 .in = stdout,
1672 .out = &stdin_writer.interface,
1673 };
17011674
1702 const Header = Server.Message.Header;
1675 (blk: {
1676 client.serveMessageHeader(.{ .tag = .update, .bytes_len = 0 }) catch |err| break :blk err;
1677 client.serveMessageHeader(.{ .tag = .exit, .bytes_len = 0 }) catch |err| break :blk err;
1678 client.out.flush() catch |err| break :blk err;
1679 }) catch |err| switch (err) {
1680 error.WriteFailed => {
1681 if (stdin_writer.err.? == error.Canceled) return error.Canceled;
1682 log.err("{t} writing to command: {f}", .{ stdin_writer.err.?, cmd });
1683 return error.AlreadyReported;
1684 },
1685 };
17031686
17041687 var result: ?Cache.Path = null;
17051688 defer if (result) |r| gpa.free(r.sub_path);
......@@ -1707,33 +1690,29 @@ pub fn buildExeSubprocess(
17071690 var result_error_bundle: ErrorBundle = .empty;
17081691 defer result_error_bundle.deinit(gpa);
17091692
1710 var body_buffer: std.ArrayList(u8) = .empty;
1711 defer body_buffer.deinit(gpa);
1712
17131693 var received_fs_inputs = false;
17141694 var cache_hit = false;
17151695
1696 var eos_err: error{EndOfStream}!void = {};
1697
17161698 while (true) {
1717 const header = stdout.takeStruct(Header, .little) catch |err| switch (err) {
1718 error.ReadFailed => {
1719 log.err("{t} reading from command: {f}", .{ stdout_reader.err.?, cmd });
1720 return error.AlreadyReported;
1721 },
1722 error.EndOfStream => break,
1723 };
1724 body_buffer.clearRetainingCapacity();
1725 stdout.appendExact(gpa, &body_buffer, header.bytes_len) catch |err| switch (err) {
1726 error.ReadFailed => {
1727 log.err("{t} reading from command: {f}", .{ stdout_reader.err.?, cmd });
1728 return error.AlreadyReported;
1699 const header = client.receiveMessageWithMultiReader(&multi_reader, .none) catch |err| switch (err) {
1700 error.Timeout => unreachable,
1701 error.EndOfStream => |e| {
1702 if (client.in.bufferedLen() == 0) break;
1703 // Better to report the crash with stderr below, but we set
1704 // this in case the child exits successfully while violating
1705 // this protocol.
1706 eos_err = e;
1707 break;
17291708 },
1730 error.OutOfMemory => |e| return e,
1731 error.EndOfStream => {
1732 log.err("unexpected end of stream from command: {f}", .{cmd});
1709 error.Canceled, error.OutOfMemory => |e| return e,
1710 else => |e| {
1711 log.err("{t} reading from command: {f}", .{ e, cmd });
17331712 return error.AlreadyReported;
17341713 },
17351714 };
1736 const body = body_buffer.items;
1715 const body = stdout.take(header.bytes_len) catch unreachable;
17371716
17381717 switch (header.tag) {
17391718 .zig_version => {
......@@ -1784,16 +1763,15 @@ pub fn buildExeSubprocess(
17841763 }
17851764 }
17861765
1787 const stderr_contents = stderr_task.await(io) catch |err| switch (err) {
1788 error.Canceled, error.OutOfMemory => |e| return e,
1789 else => |e| c: {
1790 log.warn("{t} reading stderr from command: {f}", .{ e, cmd });
1791 break :c "";
1792 },
1793 };
1766 const stderr_contents = stderr.buffered();
17941767 if (stderr_contents.len > 0)
17951768 log.warn("unexpected stderr from {s} command:\n{s}", .{ options.argv[0], stderr_contents });
17961769
1770 eos_err catch {
1771 log.err("unexpected end of stream from command: {f}", .{cmd});
1772 return error.AlreadyReported;
1773 };
1774
17971775 // Send EOF to stdin.
17981776 child.stdin.?.close(io);
17991777 child.stdin = null;
......@@ -1851,14 +1829,6 @@ pub fn buildExeSubprocess(
18511829 };
18521830}
18531831
1854fn readStreamAlloc(gpa: Allocator, io: Io, file: Io.File, limit: Io.Limit) ![]u8 {
1855 var file_reader: Io.File.Reader = .initStreaming(file, io, &.{});
1856 return file_reader.interface.allocRemaining(gpa, limit) catch |err| switch (err) {
1857 error.ReadFailed => return file_reader.err.?,
1858 else => |e| return e,
1859 };
1860}
1861
18621832test {
18631833 _ = Ast;
18641834 _ = AstRlAnnotate;
lib/std/zig/Ast/Render.zig+7-7
......@@ -941,20 +941,20 @@ fn renderExpressionFixup(r: *Render, node: Ast.Node.Index, space: Space) Error!v
941941}
942942
943943fn drainNoNewline(w: *Writer, data: []const []const u8, splat: usize) Writer.Error!usize {
944 if (std.mem.indexOfScalar(u8, w.buffered(), '\n') != null) {
944 if (std.mem.findScalar(u8, w.buffered(), '\n') != null) {
945945 return error.WriteFailed;
946946 }
947947
948948 var n: usize = 0;
949949 for (data[0 .. data.len - 1]) |v| {
950 if (std.mem.indexOfScalar(u8, v, '\n') != null) {
950 if (std.mem.findScalar(u8, v, '\n') != null) {
951951 return error.WriteFailed;
952952 }
953953 n += v.len;
954954 }
955955
956956 const pattern = data[data.len - 1];
957 if (splat != 0 and std.mem.indexOfScalar(u8, pattern, '\n') != null) {
957 if (splat != 0 and std.mem.findScalar(u8, pattern, '\n') != null) {
958958 return error.WriteFailed;
959959 }
960960 n += pattern.len * splat;
......@@ -990,7 +990,7 @@ fn rendersMultiline(r: *const Render, node: Ast.Node.Index) error{OutOfMemory}!b
990990 error.WriteFailed => return true,
991991 };
992992 if (sub_ais.disabled_offset != null) return true;
993 if (std.mem.indexOfScalar(u8, no_nl_w.buffered(), '\n') != null) {
993 if (std.mem.findScalar(u8, no_nl_w.buffered(), '\n') != null) {
994994 return true;
995995 }
996996
......@@ -2993,7 +2993,7 @@ fn hasMultilineString(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.Tok
29932993/// Returns true if there exists a doc comment between the start
29942994/// of token `start_token` and the start of token `end_token`.
29952995fn hasDocComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {
2996 return std.mem.indexOfScalar(
2996 return std.mem.findScalar(
29972997 Token.Tag,
29982998 tree.tokens.items(.tag)[start_token..end_token],
29992999 .doc_comment,
......@@ -3459,7 +3459,7 @@ const AutoIndentingStream = struct {
34593459 /// Sets current indentation level to be the same as that of the last pushSpace.
34603460 pub fn enableSpaceMode(ais: *AutoIndentingStream, space: Space) void {
34613461 if (ais.space_stack.items.len == 0) return;
3462 const curr = ais.space_stack.getLast().?;
3462 const curr = ais.space_stack.last().?;
34633463 if (curr.space != space) return;
34643464 ais.space_mode = curr.indent_count;
34653465 }
......@@ -3470,7 +3470,7 @@ const AutoIndentingStream = struct {
34703470
34713471 pub fn lastSpaceModeIndent(ais: *AutoIndentingStream) usize {
34723472 if (ais.space_stack.items.len == 0) return 0;
3473 return ais.space_stack.getLast().?.indent_count * ais.indent_delta;
3473 return ais.space_stack.last().?.indent_count * ais.indent_delta;
34743474 }
34753475
34763476 /// Push default indentation
lib/std/zig/AstGen.zig+3-2
......@@ -74,13 +74,13 @@ src_hasher: std.zig.SrcHasher,
7474const InnerError = error{ OutOfMemory, AnalysisFail };
7575
7676fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 {
77 const field_count = std.meta.fieldNames(@TypeOf(extra)).len;
77 const field_count = @typeInfo(@TypeOf(extra)).@"struct".field_names.len;
7878 try astgen.extra.ensureUnusedCapacity(astgen.gpa, field_count);
7979 return addExtraAssumeCapacity(astgen, extra);
8080}
8181
8282fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 {
83 const field_count = std.meta.fieldNames(@TypeOf(extra)).len;
83 const field_count = @typeInfo(@TypeOf(extra)).@"struct".field_names.len;
8484 const extra_index: u32 = @intCast(astgen.extra.items.len);
8585 astgen.extra.items.len += field_count;
8686 setExtra(astgen, extra_index, extra);
......@@ -7453,6 +7453,7 @@ fn switchExpr(
74537453 const ident_name = try astgen.identAsString(ident_token);
74547454 const ident_name_str = tree.tokenSlice(ident_token);
74557455 if (mem.eql(u8, "_", ident_name_str)) {
7456 if (non_err_is_ref != .no) return astgen.failTok(payload_token, "pointer modifier invalid on discard", .{});
74567457 break :scope &scratch_scope.base;
74577458 }
74587459 non_err_capture = if (non_err_is_ref != .no) .by_ref else .by_val;
lib/std/zig/Client.zig+126-2
......@@ -1,3 +1,18 @@
1const Client = @This();
2
3const std = @import("std");
4const Io = std.Io;
5const Allocator = std.mem.Allocator;
6const assert = std.debug.assert;
7const Configuration = std.Build.Configuration;
8const OutMessage = std.zig.Client.Message;
9const InMessage = std.zig.Server.Message;
10const Reader = Io.Reader;
11const Writer = Io.Writer;
12
13in: *Reader,
14out: *Writer,
15
116pub const Message = struct {
217 pub const Header = extern struct {
318 tag: Tag,
......@@ -46,11 +61,120 @@ pub const Message = struct {
4661 /// The message body has the same format as in Server.
4762 new_fuzz_input,
4863
64 /// Asks the server to run a list of steps.
65 /// Body is a `BuildSteps`.
66 /// This message only applies to the build system protocol.
67 bsp_build_steps = 0x80000000,
68
4969 _,
5070 };
5171
72 /// Trailing:
73 /// * step_indices: [step_count]std.Build.Configuration.Step.Index,
74 pub const BuildSteps = extern struct {
75 step_count: u32,
76 flags: Flags,
77
78 pub const Flags = packed struct(u32) {
79 /// Can only be enabled when the server declared support for file
80 /// watching.
81 watch: bool,
82 reserved: u31 = 0,
83 };
84 };
85
5286 comptime {
53 const std = @import("std");
54 std.debug.assert(@sizeOf(std.Build.abi.fuzz.LimitKind) == 1);
87 assert(@sizeOf(std.Build.abi.fuzz.LimitKind) == 1);
5588 }
5689};
90
91pub fn receiveMessage(c: *const Client) Reader.Error!InMessage.Header {
92 return c.in.takeStruct(InMessage.Header, .little);
93}
94
95/// Assumes that `c.in` is a reader in `multi_reader`.
96/// Guarantees that the response body will be buffered in `c.in` on success.
97pub fn receiveMessageWithMultiReader(
98 c: *Client,
99 multi_reader: *Io.File.MultiReader,
100 timeout: Io.Timeout,
101) (Io.File.MultiReader.Error || Io.Timeout.Error)!InMessage.Header {
102 while (c.in.bufferedLen() < @sizeOf(InMessage.Header)) {
103 multi_reader.fill(64, timeout) catch |err| switch (err) {
104 error.Canceled,
105 error.Timeout,
106 error.ConcurrencyUnavailable,
107 error.EndOfStream,
108 => |e| return e,
109 };
110 }
111 const header = c.in.takeStruct(InMessage.Header, .little) catch unreachable;
112 while (c.in.bufferedLen() < header.bytes_len) {
113 try multi_reader.fill(header.bytes_len - c.in.bufferedLen(), timeout);
114 }
115 try multi_reader.checkAnyError();
116 return header;
117}
118
119/// Don't forget to flush!
120pub fn serveMessageHeader(c: *const Client, header: OutMessage.Header) Writer.Error!void {
121 try c.out.writeStruct(header, .little);
122}
123
124pub fn serveBodylessMessage(c: *const Client, tag: OutMessage.Tag) Writer.Error!void {
125 try c.serveMessageHeader(.{ .tag = tag, .bytes_len = 0 });
126 try c.out.flush();
127}
128
129pub fn serveRunTest(c: *const Client, index: u32) !void {
130 try c.serveMessageHeader(.{
131 .tag = .run_test,
132 .bytes_len = @sizeOf(u32),
133 });
134 try c.out.writeInt(u32, index, .little);
135 try c.out.flush();
136}
137
138pub fn serveRunFuzzTestMessage(
139 c: *const Client,
140 test_names: []const []const u8,
141 kind: std.Build.abi.fuzz.LimitKind,
142 amount_or_instance: u64,
143) !void {
144 try c.serveMessageHeader(.{
145 .tag = .start_fuzzing,
146 .bytes_len = 1 + 8 + 4 + count: {
147 var bytes_len: u32 = @intCast(test_names.len * 4);
148 for (test_names) |name| {
149 bytes_len += @intCast(name.len);
150 }
151 break :count bytes_len;
152 },
153 });
154 try c.out.writeByte(@backingInt(kind));
155 try c.out.writeInt(u64, amount_or_instance, .little);
156 try c.out.writeInt(u32, @intCast(test_names.len), .little);
157 for (test_names) |test_name| {
158 try c.out.writeInt(u32, @intCast(test_name.len), .little);
159 try c.out.writeAll(test_name);
160 }
161 try c.out.flush();
162}
163
164pub fn serveBuildSteps(
165 c: *const Client,
166 steps: []const Configuration.Step.Index,
167 flags: OutMessage.BuildSteps.Flags,
168) !void {
169 try c.serveMessageHeader(.{
170 .tag = .bsp_build_steps,
171 .bytes_len = @intCast(@sizeOf(OutMessage.BuildSteps) + steps.len * @sizeOf(Configuration.Step.Index)),
172 });
173 const body: OutMessage.BuildSteps = .{
174 .step_count = @intCast(steps.len),
175 .flags = flags,
176 };
177 try c.out.writeStruct(body, .little);
178 try c.out.writeSliceEndian(Configuration.Step.Index, steps, .little);
179 try c.out.flush();
180}
lib/std/zig/LibCInstallation.zig+1-1
......@@ -43,7 +43,7 @@ pub const FindError = error{
4343pub fn parse(allocator: Allocator, io: Io, libc_file: []const u8, target: *const std.Target) !LibCInstallation {
4444 var self: LibCInstallation = .{};
4545
46 const field_names = comptime std.meta.fieldNames(LibCInstallation);
46 const field_names = @typeInfo(LibCInstallation).@"struct".field_names;
4747 const FoundKey = struct {
4848 found: bool,
4949 allocated: ?[]u8,
lib/std/zig/Server.zig+66-19
......@@ -1,12 +1,8 @@
11const Server = @This();
22
3const builtin = @import("builtin");
4
53const std = @import("std");
64const Allocator = std.mem.Allocator;
75const assert = std.debug.assert;
8const native_endian = builtin.target.cpu.arch.endian();
9const need_bswap = native_endian != .little;
106const Cache = std.Build.Cache;
117const OutMessage = std.zig.Server.Message;
128const InMessage = std.zig.Client.Message;
......@@ -16,6 +12,14 @@ const Writer = std.Io.Writer;
1612in: *Reader,
1713out: *Writer,
1814
15/// The ABI version of the build system protocol. Will be bumped whenever a
16/// backwards incompatible changes to the protocol is made.
17///
18/// Does not apply to the internal compiler protocol or test runner.
19///
20/// See `version` in `Message.Handshake`.
21pub const build_system_version: u32 = 1;
22
1923pub const Message = struct {
2024 pub const Header = extern struct {
2125 tag: Tag,
......@@ -70,9 +74,62 @@ pub const Message = struct {
7074 /// Body is a TimeReport.
7175 time_report,
7276
77 /// The first message sent by the server over the build system protocol.
78 /// Body is a `Handshake`.
79 /// This message only applies to the build system protocol.
80 bsp_handshake = 0x80000000,
81 /// Notifies that a new configuration file is available.
82 /// Body is a cwd relative path to the configuration file.
83 /// This message only applies to the build system protocol.
84 bsp_configuration,
85 /// Does not have a body.
86 /// This message only applies to the build system protocol.
87 bsp_build_started,
88 /// Does not have a body.
89 /// This message only applies to the build system protocol.
90 bsp_build_completed,
91 /// Body is a `Configuration.Step.Index`.
92 /// This message only applies to the build system protocol.
93 bsp_step_started,
94 /// Body is a `BuildStepCompleted`.
95 /// This message only applies to the build system protocol.
96 bsp_step_completed,
97
7398 _,
7499 };
75100
101 /// Trailing:
102 /// * base_paths: BasePaths,
103 pub const Handshake = extern struct {
104 /// See `build_system_version`.
105 version: u32,
106 flags: Flags,
107
108 pub const Flags = packed struct(u32) {
109 file_system_watch_supported: bool,
110 _: u31 = 0,
111 };
112 };
113
114 /// Trailing:
115 /// * error_bundle: ErrorBundle,
116 pub const BuildStepCompleted = extern struct {
117 step_index: std.Build.Configuration.Step.Index,
118 status: Status,
119 error_bundle: ErrorBundle,
120 // TODO result_error_msgs
121 // TODO result_stderr
122 // TODO result_peak_rss
123 // TODO result_duration_ns
124
125 pub const Status = enum(u32) {
126 success,
127 failure,
128 skipped,
129 skipped_oom,
130 };
131 };
132
76133 pub const PathPrefix = enum(u8) {
77134 cwd,
78135 zig_lib,
......@@ -140,21 +197,6 @@ pub const Message = struct {
140197 };
141198};
142199
143pub const Options = struct {
144 in: *Reader,
145 out: *Writer,
146 zig_version: []const u8,
147};
148
149pub fn init(options: Options) !Server {
150 var s: Server = .{
151 .in = options.in,
152 .out = options.out,
153 };
154 try s.serveStringMessage(.zig_version, options.zig_version);
155 return s;
156}
157
158200pub fn receiveMessage(s: *Server) !InMessage.Header {
159201 return s.in.takeStruct(InMessage.Header, .little);
160202}
......@@ -183,6 +225,11 @@ pub fn serveMessageHeader(s: *const Server, header: OutMessage.Header) !void {
183225 try s.out.writeStruct(header, .little);
184226}
185227
228pub fn serveBodylessMessage(s: *const Server, tag: OutMessage.Tag) Writer.Error!void {
229 try s.serveMessageHeader(.{ .tag = tag, .bytes_len = 0 });
230 try s.out.flush();
231}
232
186233pub fn serveU32Message(s: *const Server, tag: OutMessage.Tag, int: u32) !void {
187234 try serveMessageHeader(s, .{
188235 .tag = tag,
lib/std/zig/WindowsSdk.zig+4-4
......@@ -891,7 +891,7 @@ const MsvcLibDir = struct {
891891
892892 lib_dir_buf.appendSliceAssumeCapacity(installation_path);
893893
894 if (!Dir.path.isSep(lib_dir_buf.getLast().?)) {
894 if (!Dir.path.isSep(lib_dir_buf.last().?)) {
895895 try lib_dir_buf.append('\\');
896896 }
897897 const installation_path_with_trailing_sep_len = lib_dir_buf.items.len;
......@@ -1064,7 +1064,7 @@ const MsvcLibDir = struct {
10641064 errdefer msvc_dir.deinit();
10651065
10661066 // String might contain trailing slash, so trim it here
1067 if (msvc_dir.items.len > "C:\\".len and msvc_dir.getLast().? == '\\') _ = msvc_dir.pop();
1067 if (msvc_dir.items.len > "C:\\".len and msvc_dir.last().? == '\\') _ = msvc_dir.pop();
10681068
10691069 // Remove `\include` at the end of path
10701070 if (std.mem.endsWith(u8, msvc_dir.items, "\\include")) {
......@@ -1108,7 +1108,7 @@ const MsvcLibDir = struct {
11081108
11091109 try list.appendSlice(VS140COMNTOOLS); // C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools
11101110 // String might contain trailing slash, so trim it here
1111 if (list.items.len > "C:\\".len and list.getLast().? == '\\') _ = list.pop();
1111 if (list.items.len > "C:\\".len and list.last().? == '\\') _ = list.pop();
11121112 list.shrinkRetainingCapacity(list.items.len - "\\Common7\\Tools".len); // C:\Program Files (x86)\Microsoft Visual Studio 14.0
11131113 break :base_path list;
11141114 }
......@@ -1131,7 +1131,7 @@ const MsvcLibDir = struct {
11311131 errdefer path.deinit();
11321132
11331133 // String might contain trailing slash, so trim it here
1134 if (path.items.len > "C:\\".len and path.getLast().? == '\\') _ = path.pop();
1134 if (path.items.len > "C:\\".len and path.last().? == '\\') _ = path.pop();
11351135 break :base_path path;
11361136 }
11371137 return error.PathNotFound;
lib/std/zig/Zir.zig+2-2
......@@ -584,7 +584,7 @@ pub const Inst = struct {
584584 /// containing the instruction.
585585 /// Uses the `un_tok` union field.
586586 ref,
587 /// Implements the dereference operand (`.*`). Checks that operand is a pointer
587 /// Implements the dereference operator (`.*`). Checks that operand is a pointer
588588 /// that supports being directly dereferenced.
589589 /// Uses the `un_node` union field.
590590 deref,
......@@ -2522,7 +2522,7 @@ pub const Inst = struct {
25222522 // bigger than expected. Note that in Debug builds, Zig is allowed
25232523 // to insert a secret field for safety checks.
25242524 comptime {
2525 if (builtin.mode != .Debug and builtin.mode != .ReleaseSafe) {
2525 if (builtin.mode != .debug and builtin.mode != .safe) {
25262526 assert(@sizeOf(Data) == 8);
25272527 }
25282528 }
lib/std/zig/llvm/Builder.zig+1320-479
......@@ -17,7 +17,7 @@ gpa: Allocator,
1717strip: bool,
1818
1919source_filename: String,
20data_layout: String,
20data_layout: DataLayout,
2121target_triple: String,
2222module_asm: std.ArrayList(u8),
2323
......@@ -87,6 +87,455 @@ pub const Options = struct {
8787 triple: []const u8 = &.{},
8888};
8989
90pub const DataLayout = struct {
91 endian: ?std.lang.Endian,
92 int_specs: PrimitiveSpec.Map,
93 float_specs: PrimitiveSpec.Map,
94 vector_specs: PrimitiveSpec.Map,
95 pointer_specs: PointerSpec.Map,
96 string_repr: String,
97
98 const PrimitiveSpec = packed struct(u32) {
99 bit_width: BitWidth,
100 abi_align: Alignment,
101 pref_align: Alignment,
102
103 const BitWidth = u20;
104
105 const Map = std.array_hash_map.Custom(PrimitiveSpec, void, Context, false);
106
107 const Context = struct {
108 pub fn hash(_: Context, spec: PrimitiveSpec) u32 {
109 return std.hash.int(spec.bit_width);
110 }
111
112 pub fn eql(_: Context, lhs_spec: PrimitiveSpec, rhs_spec: PrimitiveSpec, _: usize) bool {
113 return lhs_spec.bit_width == rhs_spec.bit_width;
114 }
115 };
116 };
117
118 const PointerSpec = struct {
119 bit_width: BitWidth,
120 index_bit_width: BitWidth,
121 flags: packed struct(u32) {
122 abi_align: Alignment,
123 pref_align: Alignment,
124 has_unstable_repr: bool,
125 has_external_state: bool,
126 null_ptr_repr: NullPtrRepr,
127 unused: u17 = 0,
128 },
129 addr_space_name: String,
130
131 const BitWidth = u32;
132
133 const NullPtrRepr = enum(u1) { all_zeros, all_ones };
134
135 const Map = std.array_hash_map.Auto(AddrSpace, PointerSpec);
136 };
137
138 pub fn stringForTarget(target: *const std.Target) []const u8 {
139 // These data layouts should match Clang.
140 return switch (target.cpu.arch) {
141 .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",
142 .xcore => "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:32-f64:32-a:0:32-n32",
143 .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",
144 .lanai => "E-m:e-p:32:32-i64:64-a:0:32-n32-S64",
145 .aarch64 => if (target.ofmt == .macho)
146 if (target.os.tag == .windows or target.os.tag == .uefi)
147 "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
148 else if (target.abi == .ilp32)
149 "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
150 else
151 "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
152 else if (target.os.tag == .windows or target.os.tag == .uefi)
153 "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"
154 else
155 "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",
156 .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",
157 .arm => if (target.ofmt == .macho)
158 "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
159 else
160 "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
161 .armeb, .thumbeb => if (target.ofmt == .macho)
162 "E-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
163 else
164 "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
165 .thumb => if (target.ofmt == .macho)
166 "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
167 else if (target.os.tag == .windows or target.os.tag == .uefi)
168 "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
169 else
170 "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
171 .avr => "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8:16-a:8",
172 .bpfeb => "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
173 .bpfel => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
174 .msp430 => "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16",
175 .mips => "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64",
176 .mipsel => "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64",
177 .mips64 => switch (target.abi) {
178 .gnuabin32, .muslabin32, .abin32 => "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
179 else => "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
180 },
181 .mips64el => switch (target.abi) {
182 .gnuabin32, .muslabin32, .abin32 => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
183 else => "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
184 },
185 .m68k => "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16",
186 .powerpc => "E-m:e-p:32:32-Fn32-i64:64-n32",
187 .powerpcle => "e-m:e-p:32:32-Fn32-i64:64-n32",
188 .powerpc64 => switch (target.os.tag) {
189 .linux => "E-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512",
190 .ps3 => "E-m:e-p:32:32-Fi64-i64:64-i128:128-n32:64",
191 else => "E-m:e-Fn32-i64:64-i128:128-n32:64",
192 },
193 .powerpc64le => if (target.os.tag == .linux)
194 "e-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512"
195 else
196 "e-m:e-Fn32-i64:64-i128:128-n32:64",
197 .nvptx => "e-p:32:32-p6:32:32-p7:32:32-i64:64-i128:128-i256:256-v16:16-v32:32-n16:32:64",
198 .nvptx64 => "e-p6:32:32-i64:64-i128:128-i256:256-v16:16-v32:32-n16:32:64",
199 .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",
200 .riscv32 => if (target.cpu.has(.riscv, .e))
201 "e-m:e-p:32:32-i64:64-n32-S32"
202 else
203 "e-m:e-p:32:32-i64:64-n32-S128",
204 .riscv32be => if (target.cpu.has(.riscv, .e))
205 "E-m:e-p:32:32-i64:64-n32-S32"
206 else
207 "E-m:e-p:32:32-i64:64-n32-S128",
208 .riscv64 => if (target.cpu.has(.riscv, .e))
209 "e-m:e-p:64:64-i64:64-i128:128-n32:64-S64"
210 else
211 "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
212 .riscv64be => if (target.cpu.has(.riscv, .e))
213 "E-m:e-p:64:64-i64:64-i128:128-n32:64-S64"
214 else
215 "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
216 .sparc => "E-m:e-p:32:32-i64:64-i128:128-f128:64-n32-S64",
217 .sparc64 => "E-m:e-i64:64-i128:128-n32:64-S128",
218 .s390x => "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64",
219 .x86 => if (target.os.tag == .windows or target.os.tag == .uefi) switch (target.abi) {
220 .gnu => if (target.ofmt == .coff)
221 "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"
222 else
223 "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",
224 else => blk: {
225 const msvc = switch (target.abi) {
226 .none, .msvc => true,
227 else => false,
228 };
229
230 break :blk if (target.ofmt == .coff)
231 if (msvc)
232 "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"
233 else
234 "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"
235 else if (msvc)
236 "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"
237 else
238 "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";
239 },
240 } else if (target.ofmt == .macho)
241 "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"
242 else
243 "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",
244 .x86_64 => if (target.os.tag.isDarwin() or target.ofmt == .macho)
245 "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
246 else switch (target.abi) {
247 .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",
248 else => if ((target.os.tag == .windows or target.os.tag == .uefi) and target.ofmt == .coff)
249 "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
250 else
251 "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
252 },
253 .spirv32 => switch (target.os.tag) {
254 .vulkan, .opengl => "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1",
255 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",
256 },
257 .spirv64 => "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1",
258 .wasm32 => if (target.os.tag == .emscripten)
259 "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"
260 else
261 "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20",
262 .wasm64 => if (target.os.tag == .emscripten)
263 "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"
264 else
265 "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20",
266 .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",
267 .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",
268 .loongarch32 => "e-m:e-p:32:32-i64:64-n32-S128",
269 .loongarch64 => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
270 .xtensa => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32",
271
272 .alpha,
273 .arceb,
274 .ez80,
275 .hppa,
276 .hppa64,
277 .kalimba,
278 .kvx,
279 .m88k,
280 .microblaze,
281 .microblazeel,
282 .or1k,
283 .propeller,
284 .sh,
285 .sheb,
286 .x86_16,
287 .xtensaeb,
288 => unreachable,
289 };
290 }
291
292 const default_int_specs: []const PrimitiveSpec = &.{
293 .{ .bit_width = 8, .abi_align = .fromByteUnits(1), .pref_align = .fromByteUnits(1) }, // i8:8:8
294 .{ .bit_width = 16, .abi_align = .fromByteUnits(2), .pref_align = .fromByteUnits(2) }, // i16:16:16
295 .{ .bit_width = 32, .abi_align = .fromByteUnits(4), .pref_align = .fromByteUnits(4) }, // i32:32:32
296 .{ .bit_width = 64, .abi_align = .fromByteUnits(4), .pref_align = .fromByteUnits(8) }, // i64:32:64
297 };
298 const default_float_specs: []const PrimitiveSpec = &.{
299 .{ .bit_width = 16, .abi_align = .fromByteUnits(2), .pref_align = .fromByteUnits(2) }, // f16:16:16
300 .{ .bit_width = 32, .abi_align = .fromByteUnits(4), .pref_align = .fromByteUnits(4) }, // f32:32:32
301 .{ .bit_width = 64, .abi_align = .fromByteUnits(8), .pref_align = .fromByteUnits(8) }, // f64:64:64
302 .{ .bit_width = 128, .abi_align = .fromByteUnits(16), .pref_align = .fromByteUnits(16) }, // f128:128:128
303 };
304 const default_vector_specs: []const PrimitiveSpec = &.{
305 .{ .bit_width = 64, .abi_align = .fromByteUnits(8), .pref_align = .fromByteUnits(8) }, // v64:64:64
306 .{ .bit_width = 128, .abi_align = .fromByteUnits(16), .pref_align = .fromByteUnits(16) }, // v128:128:128
307 };
308
309 pub fn parseString(string_repr: String, builder: *Builder) Allocator.Error!DataLayout {
310 const gpa = builder.gpa;
311
312 var int_specs: PrimitiveSpec.Map = .empty;
313 defer int_specs.deinit(gpa);
314 var float_specs: PrimitiveSpec.Map = .empty;
315 defer float_specs.deinit(gpa);
316 var vector_specs: PrimitiveSpec.Map = .empty;
317 defer vector_specs.deinit(gpa);
318 var pointer_specs: PointerSpec.Map = .empty;
319 defer pointer_specs.deinit(gpa);
320 var non_integral_addr_spaces: std.ArrayList(AddrSpace) = .empty;
321 defer non_integral_addr_spaces.deinit(gpa);
322
323 try int_specs.ensureTotalCapacity(gpa, default_int_specs.len);
324 for (default_int_specs) |int_spec| int_specs.putAssumeCapacityNoClobber(int_spec, {});
325 try float_specs.ensureTotalCapacity(gpa, default_float_specs.len);
326 for (default_float_specs) |float_spec| float_specs.putAssumeCapacityNoClobber(float_spec, {});
327 try vector_specs.ensureTotalCapacity(gpa, default_vector_specs.len);
328 for (default_vector_specs) |vector_spec| vector_specs.putAssumeCapacityNoClobber(vector_spec, {});
329 try pointer_specs.putNoClobber(gpa, .default, comptime .{
330 .bit_width = 64,
331 .index_bit_width = 64,
332 .flags = .{
333 .abi_align = .fromByteUnits(8),
334 .pref_align = .fromByteUnits(8),
335 .has_unstable_repr = false,
336 .has_external_state = false,
337 .null_ptr_repr = .all_zeros,
338 },
339 .addr_space_name = .none,
340 });
341
342 var endian: ?std.lang.Endian = null;
343 var spec_it = std.mem.splitScalar(u8, string_repr.slice(builder).?, '-');
344 while (spec_it.next()) |spec| switch (spec[0]) {
345 else => {},
346 'E' => {
347 assert(spec.len == 1);
348 assert(endian == null);
349 endian = .big;
350 },
351 'e' => {
352 assert(spec.len == 1);
353 assert(endian == null);
354 endian = .little;
355 },
356 'p' => {
357 var field_it = std.mem.splitScalar(u8, spec[1..], ':');
358
359 const first = field_it.first();
360 var has_unstable_repr = false;
361 var has_external_state = false;
362 var null_ptr_repr: ?PointerSpec.NullPtrRepr = null;
363 var addr_space_name: String = .none;
364 const addr_space = for (first, 0..) |flag, as_start| switch (flag) {
365 'u' => has_unstable_repr = true,
366 'e' => has_external_state = true,
367 'z' => {
368 assert(null_ptr_repr == null);
369 null_ptr_repr = .all_zeros;
370 },
371 'o' => {
372 assert(null_ptr_repr == null);
373 null_ptr_repr = .all_ones;
374 },
375 else => {
376 if (first[first.len - ")".len] != ')') break first[as_start..];
377 const name_start = std.mem.findScalarPos(u8, first, as_start, '(').?;
378 addr_space_name = try builder.string(first[name_start + "(".len .. first.len - ")".len]);
379 break first[as_start..name_start];
380 },
381 } else first[first.len..];
382 const bit_width = std.fmt.parseInt(PointerSpec.BitWidth, field_it.next().?, 10) catch unreachable;
383 const abi_align: Alignment = .fromByteUnits(std.fmt.parseInt(u64, field_it.next().?, 10) catch unreachable);
384 const pref_align: Alignment = if (field_it.next()) |pref_align|
385 .fromByteUnits(std.fmt.parseInt(u64, pref_align, 10) catch unreachable)
386 else
387 abi_align;
388 const index_bit_width = if (field_it.next()) |index_bit_width|
389 std.fmt.parseInt(PointerSpec.BitWidth, index_bit_width, 10) catch unreachable
390 else
391 bit_width;
392 assert(field_it.peek() == null);
393
394 try pointer_specs.put(gpa, switch (addr_space.len) {
395 0 => .default,
396 else => @fromBackingInt(std.fmt.parseInt(u24, addr_space, 10) catch unreachable),
397 }, .{
398 .bit_width = bit_width,
399 .index_bit_width = index_bit_width,
400 .flags = .{
401 .abi_align = abi_align,
402 .pref_align = pref_align,
403 .has_unstable_repr = has_unstable_repr,
404 .has_external_state = has_external_state,
405 .null_ptr_repr = null_ptr_repr orelse .all_zeros,
406 },
407 .addr_space_name = addr_space_name,
408 });
409 },
410 'i', 'f', 'v' => |kind| {
411 if (std.mem.eql(u8, spec, "ve")) {
412 vector_specs.clearRetainingCapacity();
413 continue;
414 }
415 var field_it = std.mem.splitScalar(u8, spec[1..], ':');
416 const bit_width = std.fmt.parseInt(PrimitiveSpec.BitWidth, field_it.first(), 10) catch unreachable;
417 const abi_align: Alignment = .fromByteUnits(std.fmt.parseInt(u64, field_it.next().?, 10) catch unreachable);
418 const pref_align: Alignment = if (field_it.next()) |pref_align|
419 .fromByteUnits(std.fmt.parseInt(u64, pref_align, 10) catch unreachable)
420 else
421 abi_align;
422 assert(field_it.peek() == null);
423 const specs = switch (kind) {
424 else => unreachable,
425 'i' => &int_specs,
426 'f' => &float_specs,
427 'v' => &vector_specs,
428 };
429 try specs.put(gpa, .{ .bit_width = bit_width, .abi_align = abi_align, .pref_align = pref_align }, {});
430 },
431 'n' => {
432 var field_it = std.mem.splitScalar(u8, spec[1..], ':');
433 if (std.mem.eql(u8, field_it.first(), "i")) {
434 while (field_it.next()) |non_integral_addr_space| try non_integral_addr_spaces.append(
435 gpa,
436 @fromBackingInt(std.fmt.parseInt(u24, non_integral_addr_space, 10) catch unreachable),
437 );
438 } else {
439 field_it.reset();
440 while (field_it.next()) |native_bit_width| {
441 _ = std.fmt.parseInt(PrimitiveSpec.BitWidth, native_bit_width, 10) catch unreachable;
442 }
443 }
444 },
445 };
446
447 for (non_integral_addr_spaces.items) |non_integral_addr_space| {
448 const pointer_spec_gop = try pointer_specs.getOrPut(gpa, non_integral_addr_space);
449 if (!pointer_spec_gop.found_existing) pointer_spec_gop.value_ptr.* = pointer_specs.get(.default).?;
450 pointer_spec_gop.value_ptr.flags.has_unstable_repr = true;
451 pointer_spec_gop.value_ptr.flags.has_external_state = false;
452 }
453
454 {
455 const SortContext = struct {
456 specs: []const PrimitiveSpec,
457 pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool {
458 return ctx.specs[lhs_index].bit_width < ctx.specs[rhs_index].bit_width;
459 }
460 };
461 int_specs.sortUnstable(SortContext{ .specs = int_specs.keys() });
462 float_specs.sortUnstable(SortContext{ .specs = float_specs.keys() });
463 vector_specs.sortUnstable(SortContext{ .specs = vector_specs.keys() });
464 }
465 {
466 const SortContext = struct {
467 addr_spaces: []const AddrSpace,
468 pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool {
469 return @backingInt(ctx.addr_spaces[lhs_index]) < @backingInt(ctx.addr_spaces[rhs_index]);
470 }
471 };
472 pointer_specs.sortUnstable(SortContext{ .addr_spaces = pointer_specs.keys() });
473 assert(pointer_specs.keys()[0] == .default);
474 }
475
476 return .{
477 .endian = endian,
478 .int_specs = int_specs.move(),
479 .float_specs = float_specs.move(),
480 .vector_specs = vector_specs.move(),
481 .pointer_specs = pointer_specs.move(),
482 .string_repr = string_repr,
483 };
484 }
485
486 pub fn deinit(data_layout: *DataLayout, gpa: Allocator) void {
487 data_layout.int_specs.deinit(gpa);
488 data_layout.float_specs.deinit(gpa);
489 data_layout.vector_specs.deinit(gpa);
490 data_layout.pointer_specs.deinit(gpa);
491 }
492
493 pub fn getIntegerSpec(data_layout: *const DataLayout, bit_width: PrimitiveSpec.BitWidth) PrimitiveSpec {
494 const specs = data_layout.int_specs.keys();
495 return specs[
496 @min(std.sort.lowerBound(PrimitiveSpec, specs, bit_width, struct {
497 fn order(ctx: PrimitiveSpec.BitWidth, spec: PrimitiveSpec) std.math.Order {
498 return std.math.order(ctx, spec.bit_width);
499 }
500 }.order), specs.len - 1)
501 ];
502 }
503
504 pub fn getFloatSpec(data_layout: *const DataLayout, bit_width: PrimitiveSpec.BitWidth) PrimitiveSpec {
505 if (data_layout.float_specs.getEntry(.{
506 .bit_width = bit_width,
507 .abi_align = .default,
508 .pref_align = .default,
509 })) |entry| return entry.key_ptr.*;
510 const default_align: Alignment = .fromByteUnits(
511 std.math.ceilPowerOfTwoAssert(PrimitiveSpec.BitWidth, bit_width / 8),
512 );
513 return .{ .bit_width = bit_width, .abi_align = default_align, .pref_align = default_align };
514 }
515
516 pub fn getVectorSpec(
517 data_layout: *const DataLayout,
518 bit_width: PrimitiveSpec.BitWidth,
519 store_size: Type.Size,
520 ) PrimitiveSpec {
521 if (data_layout.float_specs.getEntry(.{
522 .bit_width = bit_width,
523 .abi_align = .default,
524 .pref_align = .default,
525 })) |entry| return entry.key_ptr.*;
526 const default_align: Alignment = .fromByteUnits(
527 std.math.ceilPowerOfTwoAssert(PrimitiveSpec.BitWidth, switch (store_size) {
528 .fixed, .scalable => |known_min| known_min,
529 }),
530 );
531 return .{ .bit_width = bit_width, .abi_align = default_align, .pref_align = default_align };
532 }
533
534 pub fn getPointerSpec(data_layout: *const DataLayout, addr_space: AddrSpace) PointerSpec {
535 return data_layout.pointer_specs.get(addr_space) orelse data_layout.pointer_specs.values()[0];
536 }
537};
538
90539pub const String = enum(u32) {
91540 none = maxInt(u31),
92541 empty,
......@@ -142,8 +591,8 @@ pub const String = enum(u32) {
142591 }
143592
144593 fn fromIndex(index: ?usize) String {
145 return @fromBackingInt(@intCast(@as(u32, @intCast((index orelse return .none) +
146 @backingInt(String.empty)))));
594 return @fromBackingInt(@as(u32, @intCast((index orelse return .none) +
595 @backingInt(String.empty))));
147596 }
148597
149598 fn toIndex(self: String) ?usize {
......@@ -489,7 +938,10 @@ pub const Type = enum(u32) {
489938 .double, .i64, .x86_mmx => 64,
490939 .x86_fp80, .i80 => 80,
491940 .fp128, .ppc_fp128, .i128 => 128,
492 .ptr, .@"ptr addrspace(4)" => @panic("TODO: query data layout"),
941 .ptr => @intCast(builder.data_layout.getPointerSpec(.default).bit_width),
942 .@"ptr addrspace(4)" => @intCast(
943 builder.data_layout.getPointerSpec(@fromBackingInt(@intCast(4))).bit_width,
944 ),
493945 _ => {
494946 const item = builder.type_items.items[@backingInt(self)];
495947 return switch (item.tag) {
......@@ -498,7 +950,9 @@ pub const Type = enum(u32) {
498950 .vararg_function,
499951 => unreachable,
500952 .integer => @intCast(item.data),
501 .pointer => @panic("TODO: query data layout"),
953 .pointer => @intCast(
954 builder.data_layout.getPointerSpec(@fromBackingInt(@intCast(item.data))).bit_width,
955 ),
502956 .target => unreachable,
503957 .vector,
504958 .scalable_vector,
......@@ -931,12 +1385,74 @@ pub const Type = enum(u32) {
9311385 },
9321386 };
9331387 }
1388
1389 const Size = union(enum) { fixed: u64, scalable: u64 };
1390 pub fn bits(ty: Type, builder: *const Builder) Size {
1391 const item = builder.type_items.items[@backingInt(ty)];
1392 return switch (item.tag) {
1393 else => unreachable,
1394 .simple => switch (@as(Simple, @fromBackingInt(@intCast(item.data)))) {
1395 else => unreachable,
1396 .label => .{ .fixed = builder.data_layout.getPointerSpec(.default).bit_width },
1397 .half, .bfloat => .{ .fixed = 16 },
1398 .float => .{ .fixed = 32 },
1399 .double => .{ .fixed = 64 },
1400 .ppc_fp128, .fp128 => .{ .fixed = 128 },
1401 .x86_amx => .{ .fixed = 8192 },
1402 .x86_fp80 => .{ .fixed = 80 },
1403 },
1404 .integer => .{ .fixed = item.data },
1405 .pointer => .{
1406 .fixed = builder.data_layout.getPointerSpec(@fromBackingInt(@intCast(item.data))).bit_width,
1407 },
1408 };
1409 }
1410
1411 pub fn alignment(ty: Type, kind: enum { abi, pref }, builder: *const Builder) Alignment {
1412 const item = builder.type_items.items[@backingInt(ty)];
1413 switch (item.tag) {
1414 else => unreachable,
1415 .simple => switch (@as(Simple, @fromBackingInt(@intCast(item.data)))) {
1416 else => unreachable,
1417 .label => {
1418 const spec = builder.data_layout.getPointerSpec(.default);
1419 return switch (kind) {
1420 .abi => spec.flags.abi_align,
1421 .pref => spec.flags.pref_align,
1422 };
1423 },
1424 .half, .bfloat, .float, .double, .ppc_fp128, .fp128, .x86_fp80 => {
1425 const spec = builder.data_layout.getFloatSpec(@intCast(ty.bits(builder).fixed));
1426 return switch (kind) {
1427 .abi => spec.abi_align,
1428 .pref => spec.pref_align,
1429 };
1430 },
1431 .x86_amx => return comptime .fromByteUnits(64),
1432 },
1433 .integer => {
1434 const spec = builder.data_layout.getIntegerSpec(@intCast(item.data));
1435 return switch (kind) {
1436 .abi => spec.abi_align,
1437 .pref => spec.pref_align,
1438 };
1439 },
1440 .pointer => {
1441 const spec = builder.data_layout.getPointerSpec(@fromBackingInt(@intCast(item.data)));
1442 return switch (kind) {
1443 .abi => spec.flags.abi_align,
1444 .pref => spec.flags.pref_align,
1445 };
1446 },
1447 }
1448 }
9341449};
9351450
9361451pub const Attribute = union(Kind) {
9371452 // Parameter Attributes
9381453 zeroext,
9391454 signext,
1455 noext,
9401456 inreg,
9411457 byval: Type,
9421458 byref: Type,
......@@ -947,6 +1463,7 @@ pub const Attribute = union(Kind) {
9471463 @"align": Alignment.Lazy,
9481464 @"noalias",
9491465 nocapture,
1466 captures: Captures,
9501467 nofree,
9511468 nest,
9521469 returned,
......@@ -965,6 +1482,11 @@ pub const Attribute = union(Kind) {
9651482 readnone,
9661483 readonly,
9671484 writeonly,
1485 writable,
1486 initializes: []const [2]u64,
1487 dead_on_unwind,
1488 dead_on_return: ?u32,
1489 range: [2]Constant,
9681490
9691491 // Function Attributes
9701492 //alignstack: Alignment.Lazy,
......@@ -974,7 +1496,7 @@ pub const Attribute = union(Kind) {
9741496 builtin,
9751497 cold,
9761498 convergent,
977 disable_sanitizer_information,
1499 disable_sanitizer_instrumentation,
9781500 fn_ret_thunk_extern,
9791501 hot,
9801502 inlinehint,
......@@ -984,6 +1506,7 @@ pub const Attribute = union(Kind) {
9841506 naked,
9851507 nobuiltin,
9861508 nocallback,
1509 nodivergencesource,
9871510 noduplicate,
9881511 //nofree,
9891512 noimplicitfloat,
......@@ -1001,6 +1524,7 @@ pub const Attribute = union(Kind) {
10011524 nosanitize_bounds,
10021525 nosanitize_coverage,
10031526 null_pointer_is_valid,
1527 optdebug,
10041528 optforfuzzing,
10051529 optnone,
10061530 optsize,
......@@ -1012,23 +1536,23 @@ pub const Attribute = union(Kind) {
10121536 sanitize_thread,
10131537 sanitize_hwaddress,
10141538 sanitize_memtag,
1539 sanitize_realtime,
1540 sanitize_realtime_blocking,
1541 sanitize_alloc_token,
10151542 speculative_load_hardening,
10161543 speculatable,
10171544 ssp,
10181545 sspstrong,
10191546 sspreq,
10201547 strictfp,
1548 denormal_fpenv,
10211549 uwtable: UwTable,
10221550 nocf_check,
10231551 shadowcallstack,
10241552 mustprogress,
10251553 vscale_range: VScaleRange,
1026
1027 // Global Attributes
1028 no_sanitize_address,
1029 no_sanitize_hwaddress,
1030 //sanitize_memtag,
1031 sanitize_address_dyninit,
1554 nooutline,
1555 nocreateundeforpoison,
10321556
10331557 string: struct { kind: String, value: String },
10341558 none: noreturn,
......@@ -1045,100 +1569,11 @@ pub const Attribute = union(Kind) {
10451569 const storage = self.toStorage(builder);
10461570 if (storage.kind.toString()) |kind| return .{ .string = .{
10471571 .kind = kind,
1048 .value = @fromBackingInt(@intCast(storage.value)),
1572 .value = @fromBackingInt(storage.value),
10491573 } } else return switch (storage.kind) {
1050 inline .zeroext,
1051 .signext,
1052 .inreg,
1053 .byval,
1054 .byref,
1055 .preallocated,
1056 .inalloca,
1057 .sret,
1058 .elementtype,
1059 .@"align",
1060 .@"noalias",
1061 .nocapture,
1062 .nofree,
1063 .nest,
1064 .returned,
1065 .nonnull,
1066 .dereferenceable,
1067 .dereferenceable_or_null,
1068 .swiftself,
1069 .swiftasync,
1070 .swifterror,
1071 .immarg,
1072 .noundef,
1073 .nofpclass,
1074 .alignstack,
1075 .allocalign,
1076 .allocptr,
1077 .readnone,
1078 .readonly,
1079 .writeonly,
1080 //.alignstack,
1081 .allockind,
1082 .allocsize,
1083 .alwaysinline,
1084 .builtin,
1085 .cold,
1086 .convergent,
1087 .disable_sanitizer_information,
1088 .fn_ret_thunk_extern,
1089 .hot,
1090 .inlinehint,
1091 .jumptable,
1092 .memory,
1093 .minsize,
1094 .naked,
1095 .nobuiltin,
1096 .nocallback,
1097 .noduplicate,
1098 //.nofree,
1099 .noimplicitfloat,
1100 .@"noinline",
1101 .nomerge,
1102 .nonlazybind,
1103 .noprofile,
1104 .skipprofile,
1105 .noredzone,
1106 .noreturn,
1107 .norecurse,
1108 .willreturn,
1109 .nosync,
1110 .nounwind,
1111 .nosanitize_bounds,
1112 .nosanitize_coverage,
1113 .null_pointer_is_valid,
1114 .optforfuzzing,
1115 .optnone,
1116 .optsize,
1117 //.preallocated,
1118 .returns_twice,
1119 .safestack,
1120 .sanitize_address,
1121 .sanitize_memory,
1122 .sanitize_thread,
1123 .sanitize_hwaddress,
1124 .sanitize_memtag,
1125 .speculative_load_hardening,
1126 .speculatable,
1127 .ssp,
1128 .sspstrong,
1129 .sspreq,
1130 .strictfp,
1131 .uwtable,
1132 .nocf_check,
1133 .shadowcallstack,
1134 .mustprogress,
1135 .vscale_range,
1136 .no_sanitize_address,
1137 .no_sanitize_hwaddress,
1138 .sanitize_address_dyninit,
1139 => |kind| {
1574 inline else => |kind| {
11401575 const field_name, const field_type = comptime blk: {
1141 @setEvalBranchQuota(10_000);
1576 @setEvalBranchQuota(12_000);
11421577 const info = @typeInfo(Attribute).@"union";
11431578 for (info.field_names, info.field_types) |field_name, field_type| {
11441579 if (std.mem.eql(u8, field_name, @tagName(kind))) break :blk .{ field_name, field_type };
......@@ -1149,14 +1584,17 @@ pub const Attribute = union(Kind) {
11491584 return @unionInit(Attribute, field_name, switch (field_type) {
11501585 void => {},
11511586 u32 => storage.value,
1152 Alignment.Lazy, String, Type, UwTable => @fromBackingInt(@intCast(storage.value)),
1153 AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(storage.value),
1587 Alignment.Lazy, String, Type, UwTable => @fromBackingInt(storage.value),
1588 AllocKind, AllocSize, Captures, FpClass, Memory, VScaleRange => @bitCast(storage.value),
11541589 else => @compileError("bad payload type: " ++ field_name ++ ": " ++
11551590 @typeName(field_type)),
11561591 });
11571592 },
1158 .string, .none => unreachable,
1159 _ => unreachable,
1593 .initializes,
1594 .dead_on_return,
1595 .range,
1596 => @panic("TODO"),
1597 .string, .none, _ => unreachable,
11601598 };
11611599 }
11621600
......@@ -1174,6 +1612,7 @@ pub const Attribute = union(Kind) {
11741612 switch (attribute) {
11751613 .zeroext,
11761614 .signext,
1615 .noext,
11771616 .inreg,
11781617 .@"noalias",
11791618 .nocapture,
......@@ -1191,11 +1630,13 @@ pub const Attribute = union(Kind) {
11911630 .readnone,
11921631 .readonly,
11931632 .writeonly,
1633 .writable,
1634 .dead_on_unwind,
11941635 .alwaysinline,
11951636 .builtin,
11961637 .cold,
11971638 .convergent,
1198 .disable_sanitizer_information,
1639 .disable_sanitizer_instrumentation,
11991640 .fn_ret_thunk_extern,
12001641 .hot,
12011642 .inlinehint,
......@@ -1204,6 +1645,7 @@ pub const Attribute = union(Kind) {
12041645 .naked,
12051646 .nobuiltin,
12061647 .nocallback,
1648 .nodivergencesource,
12071649 .noduplicate,
12081650 .noimplicitfloat,
12091651 .@"noinline",
......@@ -1220,6 +1662,7 @@ pub const Attribute = union(Kind) {
12201662 .nosanitize_bounds,
12211663 .nosanitize_coverage,
12221664 .null_pointer_is_valid,
1665 .optdebug,
12231666 .optforfuzzing,
12241667 .optnone,
12251668 .optsize,
......@@ -1230,18 +1673,21 @@ pub const Attribute = union(Kind) {
12301673 .sanitize_thread,
12311674 .sanitize_hwaddress,
12321675 .sanitize_memtag,
1676 .sanitize_realtime,
1677 .sanitize_realtime_blocking,
1678 .sanitize_alloc_token,
12331679 .speculative_load_hardening,
12341680 .speculatable,
12351681 .ssp,
12361682 .sspstrong,
12371683 .sspreq,
12381684 .strictfp,
1685 .denormal_fpenv,
12391686 .nocf_check,
12401687 .shadowcallstack,
12411688 .mustprogress,
1242 .no_sanitize_address,
1243 .no_sanitize_hwaddress,
1244 .sanitize_address_dyninit,
1689 .nooutline,
1690 .nocreateundeforpoison,
12451691 => try w.print(" {s}", .{@tagName(attribute)}),
12461692 .byval,
12471693 .byref,
......@@ -1254,6 +1700,45 @@ pub const Attribute = union(Kind) {
12541700 .dereferenceable,
12551701 .dereferenceable_or_null,
12561702 => |size| try w.print(" {s}({d})", .{ @tagName(attribute), size }),
1703 .captures => |captures| {
1704 try w.print(" {s}(", .{@tagName(attribute)});
1705 var need_comma = false;
1706 if (captures == Captures.none) {
1707 if (need_comma) try w.writeAll(", ");
1708 try w.writeAll("none");
1709 need_comma = true;
1710 }
1711 inline for (@typeInfo(Captures).@"struct".field_names) |field_name| {
1712 if (comptime std.mem.eql(u8, field_name, "_")) continue;
1713 const components = @field(captures, field_name);
1714 if (components != Captures.Components.none) {
1715 if (!comptime std.mem.eql(u8, field_name, "other")) {
1716 if (need_comma) try w.writeAll(", ");
1717 try w.writeAll(field_name ++ ": ");
1718 need_comma = false;
1719 }
1720 if (components.address) {
1721 if (need_comma) try w.writeAll(", ");
1722 try w.writeAll("address");
1723 need_comma = true;
1724 } else if (components.address_is_null) {
1725 if (need_comma) try w.writeAll(", ");
1726 try w.writeAll("address_is_null");
1727 need_comma = true;
1728 }
1729 if (components.provenance) {
1730 if (need_comma) try w.writeAll(", ");
1731 try w.writeAll("provenance");
1732 need_comma = true;
1733 } else if (components.read_provenance) {
1734 if (need_comma) try w.writeAll(", ");
1735 try w.writeAll("read_provenance");
1736 need_comma = true;
1737 }
1738 }
1739 }
1740 try w.writeByte(')');
1741 },
12571742 .nofpclass => |fpclass| {
12581743 const Int = @typeInfo(FpClass).@"struct".backing_integer.?;
12591744 try w.print(" {s}(", .{@tagName(attribute)});
......@@ -1281,6 +1766,9 @@ pub const Attribute = union(Kind) {
12811766 try w.print("({d})", .{alignment_bytes});
12821767 }
12831768 },
1769 .initializes => @panic("TODO"),
1770 .dead_on_return => @panic("TODO"),
1771 .range => @panic("TODO"),
12841772 .allockind => |allockind| {
12851773 try w.print(" {t}(\"", .{attribute});
12861774 var any = false;
......@@ -1344,100 +1832,109 @@ pub const Attribute = union(Kind) {
13441832
13451833 pub const Kind = enum(u32) {
13461834 // Parameter Attributes
1347 zeroext = 34,
1348 signext = 24,
1349 inreg = 5,
1350 byval = 3,
1351 byref = 69,
1352 preallocated = 65,
1353 inalloca = 38,
1354 sret = 29, // TODO: ?
1355 elementtype = 77,
1356 @"align" = 1,
1357 @"noalias" = 9,
1358 nocapture = 11,
1359 nofree = 62,
1360 nest = 8,
1361 returned = 22,
1362 nonnull = 39,
1363 dereferenceable = 41,
1364 dereferenceable_or_null = 42,
1365 swiftself = 46,
1366 swiftasync = 75,
1367 swifterror = 47,
1368 immarg = 60,
1369 noundef = 68,
1370 nofpclass = 87,
1371 alignstack = 25,
1372 allocalign = 80,
1373 allocptr = 81,
1374 readnone = 20,
1375 readonly = 21,
1376 writeonly = 52,
1835 zeroext = @backingInt(ATTR_KIND.Z_EXT),
1836 signext = @backingInt(ATTR_KIND.S_EXT),
1837 noext = @backingInt(ATTR_KIND.NO_EXT),
1838 inreg = @backingInt(ATTR_KIND.IN_REG),
1839 byval = @backingInt(ATTR_KIND.BY_VAL),
1840 byref = @backingInt(ATTR_KIND.BYREF),
1841 preallocated = @backingInt(ATTR_KIND.PREALLOCATED),
1842 inalloca = @backingInt(ATTR_KIND.IN_ALLOCA),
1843 sret = @backingInt(ATTR_KIND.STRUCT_RET),
1844 elementtype = @backingInt(ATTR_KIND.ELEMENTTYPE),
1845 @"align" = @backingInt(ATTR_KIND.ALIGNMENT),
1846 @"noalias" = @backingInt(ATTR_KIND.NO_ALIAS),
1847 nocapture = @backingInt(ATTR_KIND.NO_CAPTURE),
1848 captures = @backingInt(ATTR_KIND.CAPTURES),
1849 nofree = @backingInt(ATTR_KIND.NOFREE),
1850 nest = @backingInt(ATTR_KIND.NEST),
1851 returned = @backingInt(ATTR_KIND.RETURNED),
1852 nonnull = @backingInt(ATTR_KIND.NON_NULL),
1853 dereferenceable = @backingInt(ATTR_KIND.DEREFERENCEABLE),
1854 dereferenceable_or_null = @backingInt(ATTR_KIND.DEREFERENCEABLE_OR_NULL),
1855 swiftself = @backingInt(ATTR_KIND.SWIFT_SELF),
1856 swiftasync = @backingInt(ATTR_KIND.SWIFT_ASYNC),
1857 swifterror = @backingInt(ATTR_KIND.SWIFT_ERROR),
1858 immarg = @backingInt(ATTR_KIND.IMMARG),
1859 noundef = @backingInt(ATTR_KIND.NOUNDEF),
1860 nofpclass = @backingInt(ATTR_KIND.NOFPCLASS),
1861 alignstack = @backingInt(ATTR_KIND.STACK_ALIGNMENT),
1862 allocalign = @backingInt(ATTR_KIND.ALLOC_ALIGN),
1863 allocptr = @backingInt(ATTR_KIND.ALLOCATED_POINTER),
1864 readnone = @backingInt(ATTR_KIND.READ_NONE),
1865 readonly = @backingInt(ATTR_KIND.READ_ONLY),
1866 writeonly = @backingInt(ATTR_KIND.WRITEONLY),
1867 writable = @backingInt(ATTR_KIND.WRITABLE),
1868 initializes = @backingInt(ATTR_KIND.INITIALIZES),
1869 dead_on_unwind = @backingInt(ATTR_KIND.DEAD_ON_UNWIND),
1870 dead_on_return = @backingInt(ATTR_KIND.DEAD_ON_RETURN),
1871 range = @backingInt(ATTR_KIND.RANGE),
13771872
13781873 // Function Attributes
1379 //alignstack,
1380 allockind = 82,
1381 allocsize = 51,
1382 alwaysinline = 2,
1383 builtin = 35,
1384 cold = 36,
1385 convergent = 43,
1386 disable_sanitizer_information = 78,
1387 fn_ret_thunk_extern = 84,
1388 hot = 72,
1389 inlinehint = 4,
1390 jumptable = 40,
1391 memory = 86,
1392 minsize = 6,
1393 naked = 7,
1394 nobuiltin = 10,
1395 nocallback = 71,
1396 noduplicate = 12,
1397 //nofree,
1398 noimplicitfloat = 13,
1399 @"noinline" = 14,
1400 nomerge = 66,
1401 nonlazybind = 15,
1402 noprofile = 73,
1403 skipprofile = 85,
1404 noredzone = 16,
1405 noreturn = 17,
1406 norecurse = 48,
1407 willreturn = 61,
1408 nosync = 63,
1409 nounwind = 18,
1410 nosanitize_bounds = 79,
1411 nosanitize_coverage = 76,
1412 null_pointer_is_valid = 67,
1413 optforfuzzing = 57,
1414 optnone = 37,
1415 optsize = 19,
1416 //preallocated,
1417 returns_twice = 23,
1418 safestack = 44,
1419 sanitize_address = 30,
1420 sanitize_memory = 32,
1421 sanitize_thread = 31,
1422 sanitize_hwaddress = 55,
1423 sanitize_memtag = 64,
1424 speculative_load_hardening = 59,
1425 speculatable = 53,
1426 ssp = 26,
1427 sspstrong = 28,
1428 sspreq = 27,
1429 strictfp = 54,
1430 uwtable = 33,
1431 nocf_check = 56,
1432 shadowcallstack = 58,
1433 mustprogress = 70,
1434 vscale_range = 74,
1435
1436 // Global Attributes
1437 no_sanitize_address = 100,
1438 no_sanitize_hwaddress = 101,
1439 //sanitize_memtag,
1440 sanitize_address_dyninit = 102,
1874 //alignstack = @intFromEnum(ATTR_KIND.STACK_ALIGNMENT),
1875 allockind = @backingInt(ATTR_KIND.ALLOC_KIND),
1876 allocsize = @backingInt(ATTR_KIND.ALLOC_SIZE),
1877 alwaysinline = @backingInt(ATTR_KIND.ALWAYS_INLINE),
1878 builtin = @backingInt(ATTR_KIND.BUILTIN),
1879 cold = @backingInt(ATTR_KIND.COLD),
1880 convergent = @backingInt(ATTR_KIND.CONVERGENT),
1881 disable_sanitizer_instrumentation = @backingInt(ATTR_KIND.DISABLE_SANITIZER_INSTRUMENTATION),
1882 fn_ret_thunk_extern = @backingInt(ATTR_KIND.FNRETTHUNK_EXTERN),
1883 hot = @backingInt(ATTR_KIND.HOT),
1884 inlinehint = @backingInt(ATTR_KIND.INLINE_HINT),
1885 jumptable = @backingInt(ATTR_KIND.JUMP_TABLE),
1886 memory = @backingInt(ATTR_KIND.MEMORY),
1887 minsize = @backingInt(ATTR_KIND.MIN_SIZE),
1888 naked = @backingInt(ATTR_KIND.NAKED),
1889 nobuiltin = @backingInt(ATTR_KIND.NO_BUILTIN),
1890 nocallback = @backingInt(ATTR_KIND.NO_CALLBACK),
1891 nodivergencesource = @backingInt(ATTR_KIND.NO_DIVERGENCE_SOURCE),
1892 noduplicate = @backingInt(ATTR_KIND.NO_DUPLICATE),
1893 //nofree = @intFromEnum(ATTR_KIND.NOFREE),
1894 noimplicitfloat = @backingInt(ATTR_KIND.NO_IMPLICIT_FLOAT),
1895 @"noinline" = @backingInt(ATTR_KIND.NO_INLINE),
1896 nomerge = @backingInt(ATTR_KIND.NO_MERGE),
1897 nonlazybind = @backingInt(ATTR_KIND.NON_LAZY_BIND),
1898 noprofile = @backingInt(ATTR_KIND.NO_PROFILE),
1899 skipprofile = @backingInt(ATTR_KIND.SKIP_PROFILE),
1900 noredzone = @backingInt(ATTR_KIND.NO_RED_ZONE),
1901 noreturn = @backingInt(ATTR_KIND.NO_RETURN),
1902 norecurse = @backingInt(ATTR_KIND.NO_RECURSE),
1903 willreturn = @backingInt(ATTR_KIND.WILLRETURN),
1904 nosync = @backingInt(ATTR_KIND.NOSYNC),
1905 nounwind = @backingInt(ATTR_KIND.NO_UNWIND),
1906 nosanitize_bounds = @backingInt(ATTR_KIND.NO_SANITIZE_BOUNDS),
1907 nosanitize_coverage = @backingInt(ATTR_KIND.NO_SANITIZE_COVERAGE),
1908 null_pointer_is_valid = @backingInt(ATTR_KIND.NULL_POINTER_IS_VALID),
1909 optdebug = @backingInt(ATTR_KIND.OPTIMIZE_FOR_DEBUGGING),
1910 optforfuzzing = @backingInt(ATTR_KIND.OPT_FOR_FUZZING),
1911 optnone = @backingInt(ATTR_KIND.OPTIMIZE_NONE),
1912 optsize = @backingInt(ATTR_KIND.OPTIMIZE_FOR_SIZE),
1913 //preallocated = @intFromEnum(ATTR_KIND.PREALLOCATED),
1914 returns_twice = @backingInt(ATTR_KIND.RETURNS_TWICE),
1915 safestack = @backingInt(ATTR_KIND.SAFESTACK),
1916 sanitize_address = @backingInt(ATTR_KIND.SANITIZE_ADDRESS),
1917 sanitize_memory = @backingInt(ATTR_KIND.SANITIZE_MEMORY),
1918 sanitize_thread = @backingInt(ATTR_KIND.SANITIZE_THREAD),
1919 sanitize_hwaddress = @backingInt(ATTR_KIND.SANITIZE_HWADDRESS),
1920 sanitize_memtag = @backingInt(ATTR_KIND.SANITIZE_MEMTAG),
1921 sanitize_realtime = @backingInt(ATTR_KIND.SANITIZE_REALTIME),
1922 sanitize_realtime_blocking = @backingInt(ATTR_KIND.SANITIZE_REALTIME_BLOCKING),
1923 sanitize_alloc_token = @backingInt(ATTR_KIND.SANITIZE_ALLOC_TOKEN),
1924 speculative_load_hardening = @backingInt(ATTR_KIND.SPECULATIVE_LOAD_HARDENING),
1925 speculatable = @backingInt(ATTR_KIND.SPECULATABLE),
1926 ssp = @backingInt(ATTR_KIND.STACK_PROTECT),
1927 sspstrong = @backingInt(ATTR_KIND.STACK_PROTECT_STRONG),
1928 sspreq = @backingInt(ATTR_KIND.STACK_PROTECT_REQ),
1929 strictfp = @backingInt(ATTR_KIND.STRICT_FP),
1930 denormal_fpenv = @backingInt(ATTR_KIND.DENORMAL_FPENV),
1931 uwtable = @backingInt(ATTR_KIND.UW_TABLE),
1932 nocf_check = @backingInt(ATTR_KIND.NOCF_CHECK),
1933 shadowcallstack = @backingInt(ATTR_KIND.SHADOWCALLSTACK),
1934 mustprogress = @backingInt(ATTR_KIND.MUSTPROGRESS),
1935 vscale_range = @backingInt(ATTR_KIND.VSCALE_RANGE),
1936 nooutline = @backingInt(ATTR_KIND.NOOUTLINE),
1937 nocreateundeforpoison = @backingInt(ATTR_KIND.NO_CREATE_UNDEF_OR_POISON),
14411938
14421939 string = maxInt(u31),
14431940 none = maxInt(u32),
......@@ -1447,16 +1944,128 @@ pub const Attribute = union(Kind) {
14471944
14481945 pub fn fromString(str: String) Kind {
14491946 assert(!str.isAnon());
1450 const kind: Kind = @fromBackingInt(@intCast(@backingInt(str)));
1947 const kind: Kind = @fromBackingInt(@backingInt(str));
14511948 assert(kind != .none);
14521949 return kind;
14531950 }
14541951
14551952 fn toString(self: Kind) ?String {
14561953 assert(self != .none);
1457 const str: String = @fromBackingInt(@intCast(@backingInt(self)));
1954 const str: String = @fromBackingInt(@backingInt(self));
14581955 return if (str.isAnon()) null else str;
14591956 }
1957
1958 /// enum AttributeKindCodes
1959 const ATTR_KIND = enum(u32) {
1960 ALIGNMENT = 1,
1961 ALWAYS_INLINE = 2,
1962 BY_VAL = 3,
1963 INLINE_HINT = 4,
1964 IN_REG = 5,
1965 MIN_SIZE = 6,
1966 NAKED = 7,
1967 NEST = 8,
1968 NO_ALIAS = 9,
1969 NO_BUILTIN = 10,
1970 NO_CAPTURE = 11,
1971 NO_DUPLICATE = 12,
1972 NO_IMPLICIT_FLOAT = 13,
1973 NO_INLINE = 14,
1974 NON_LAZY_BIND = 15,
1975 NO_RED_ZONE = 16,
1976 NO_RETURN = 17,
1977 NO_UNWIND = 18,
1978 OPTIMIZE_FOR_SIZE = 19,
1979 READ_NONE = 20,
1980 READ_ONLY = 21,
1981 RETURNED = 22,
1982 RETURNS_TWICE = 23,
1983 S_EXT = 24,
1984 STACK_ALIGNMENT = 25,
1985 STACK_PROTECT = 26,
1986 STACK_PROTECT_REQ = 27,
1987 STACK_PROTECT_STRONG = 28,
1988 STRUCT_RET = 29,
1989 SANITIZE_ADDRESS = 30,
1990 SANITIZE_THREAD = 31,
1991 SANITIZE_MEMORY = 32,
1992 UW_TABLE = 33,
1993 Z_EXT = 34,
1994 BUILTIN = 35,
1995 COLD = 36,
1996 OPTIMIZE_NONE = 37,
1997 IN_ALLOCA = 38,
1998 NON_NULL = 39,
1999 JUMP_TABLE = 40,
2000 DEREFERENCEABLE = 41,
2001 DEREFERENCEABLE_OR_NULL = 42,
2002 CONVERGENT = 43,
2003 SAFESTACK = 44,
2004 ARGMEMONLY = 45,
2005 SWIFT_SELF = 46,
2006 SWIFT_ERROR = 47,
2007 NO_RECURSE = 48,
2008 INACCESSIBLEMEM_ONLY = 49,
2009 INACCESSIBLEMEM_OR_ARGMEMONLY = 50,
2010 ALLOC_SIZE = 51,
2011 WRITEONLY = 52,
2012 SPECULATABLE = 53,
2013 STRICT_FP = 54,
2014 SANITIZE_HWADDRESS = 55,
2015 NOCF_CHECK = 56,
2016 OPT_FOR_FUZZING = 57,
2017 SHADOWCALLSTACK = 58,
2018 SPECULATIVE_LOAD_HARDENING = 59,
2019 IMMARG = 60,
2020 WILLRETURN = 61,
2021 NOFREE = 62,
2022 NOSYNC = 63,
2023 SANITIZE_MEMTAG = 64,
2024 PREALLOCATED = 65,
2025 NO_MERGE = 66,
2026 NULL_POINTER_IS_VALID = 67,
2027 NOUNDEF = 68,
2028 BYREF = 69,
2029 MUSTPROGRESS = 70,
2030 NO_CALLBACK = 71,
2031 HOT = 72,
2032 NO_PROFILE = 73,
2033 VSCALE_RANGE = 74,
2034 SWIFT_ASYNC = 75,
2035 NO_SANITIZE_COVERAGE = 76,
2036 ELEMENTTYPE = 77,
2037 DISABLE_SANITIZER_INSTRUMENTATION = 78,
2038 NO_SANITIZE_BOUNDS = 79,
2039 ALLOC_ALIGN = 80,
2040 ALLOCATED_POINTER = 81,
2041 ALLOC_KIND = 82,
2042 PRESPLIT_COROUTINE = 83,
2043 FNRETTHUNK_EXTERN = 84,
2044 SKIP_PROFILE = 85,
2045 MEMORY = 86,
2046 NOFPCLASS = 87,
2047 OPTIMIZE_FOR_DEBUGGING = 88,
2048 WRITABLE = 89,
2049 CORO_ONLY_DESTROY_WHEN_COMPLETE = 90,
2050 DEAD_ON_UNWIND = 91,
2051 RANGE = 92,
2052 SANITIZE_NUMERICAL_STABILITY = 93,
2053 INITIALIZES = 94,
2054 HYBRID_PATCHABLE = 95,
2055 SANITIZE_REALTIME = 96,
2056 SANITIZE_REALTIME_BLOCKING = 97,
2057 CORO_ELIDE_SAFE = 98,
2058 NO_EXT = 99,
2059 NO_DIVERGENCE_SOURCE = 100,
2060 SANITIZE_TYPE = 101,
2061 CAPTURES = 102,
2062 DEAD_ON_RETURN = 103,
2063 SANITIZE_ALLOC_TOKEN = 104,
2064 NO_CREATE_UNDEF_OR_POISON = 105,
2065 DENORMAL_FPENV = 106,
2066 NOOUTLINE = 107,
2067 FLATTEN = 108,
2068 };
14602069 };
14612070
14622071 pub const FpClass = packed struct(u32) {
......@@ -1506,6 +2115,29 @@ pub const Attribute = union(Kind) {
15062115 pub const pnorm = FpClass{ .positive_normal = true };
15072116 };
15082117
2118 pub const Captures = packed struct(u32) {
2119 other: Components = .none,
2120 ret: Components = .none,
2121 _: u24 = 0,
2122
2123 pub const none: Captures = .{};
2124
2125 pub const Components = packed struct(u4) {
2126 address_is_null: bool = false,
2127 address: bool = false,
2128 read_provenance: bool = false,
2129 provenance: bool = false,
2130
2131 pub const none: Components = .{};
2132 pub const all: Components = .{
2133 .address_is_null = true,
2134 .address = true,
2135 .read_provenance = true,
2136 .provenance = true,
2137 };
2138 };
2139 };
2140
15092141 pub const AllocKind = packed struct(u32) {
15102142 alloc: bool,
15112143 realloc: bool,
......@@ -1582,9 +2214,13 @@ pub const Attribute = union(Kind) {
15822214 void => 0,
15832215 u32 => value,
15842216 Alignment.Lazy, String, Type, UwTable => @backingInt(value),
1585 AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(value),
1586 else => @compileError("bad payload type: " ++ @tagName(tag) ++ @typeName(@TypeOf(value))),
2217 AllocKind, AllocSize, Captures, FpClass, Memory, VScaleRange => @bitCast(value),
2218 else => @compileError("bad payload type: " ++ @tagName(tag) ++ ": " ++ @typeName(@TypeOf(value))),
15872219 } },
2220 .initializes,
2221 .dead_on_return,
2222 .range,
2223 => @panic("TODO"),
15882224 .string => |string_attr| .{
15892225 .kind = Kind.fromString(string_attr.kind),
15902226 .value = @backingInt(string_attr.value),
......@@ -1907,87 +2543,87 @@ pub const AddrSpace = enum(u24) {
19072543
19082544 // See llvm/lib/Target/X86/X86.h
19092545 pub const x86 = struct {
1910 pub const gs: AddrSpace = @fromBackingInt(@intCast(256));
1911 pub const fs: AddrSpace = @fromBackingInt(@intCast(257));
1912 pub const ss: AddrSpace = @fromBackingInt(@intCast(258));
2546 pub const gs: AddrSpace = @fromBackingInt(256);
2547 pub const fs: AddrSpace = @fromBackingInt(257);
2548 pub const ss: AddrSpace = @fromBackingInt(258);
19132549
1914 pub const ptr32_sptr: AddrSpace = @fromBackingInt(@intCast(270));
1915 pub const ptr32_uptr: AddrSpace = @fromBackingInt(@intCast(271));
1916 pub const ptr64: AddrSpace = @fromBackingInt(@intCast(272));
2550 pub const ptr32_sptr: AddrSpace = @fromBackingInt(270);
2551 pub const ptr32_uptr: AddrSpace = @fromBackingInt(271);
2552 pub const ptr64: AddrSpace = @fromBackingInt(272);
19172553 };
19182554 pub const x86_64 = x86;
19192555
19202556 // See llvm/lib/Target/AVR/AVR.h
19212557 pub const avr = struct {
1922 pub const data: AddrSpace = @fromBackingInt(@intCast(0));
1923 pub const program: AddrSpace = @fromBackingInt(@intCast(1));
1924 pub const program1: AddrSpace = @fromBackingInt(@intCast(2));
1925 pub const program2: AddrSpace = @fromBackingInt(@intCast(3));
1926 pub const program3: AddrSpace = @fromBackingInt(@intCast(4));
1927 pub const program4: AddrSpace = @fromBackingInt(@intCast(5));
1928 pub const program5: AddrSpace = @fromBackingInt(@intCast(6));
2558 pub const data: AddrSpace = @fromBackingInt(0);
2559 pub const program: AddrSpace = @fromBackingInt(1);
2560 pub const program1: AddrSpace = @fromBackingInt(2);
2561 pub const program2: AddrSpace = @fromBackingInt(3);
2562 pub const program3: AddrSpace = @fromBackingInt(4);
2563 pub const program4: AddrSpace = @fromBackingInt(5);
2564 pub const program5: AddrSpace = @fromBackingInt(6);
19292565 };
19302566
19312567 // See llvm/lib/Target/NVPTX/NVPTX.h
19322568 pub const nvptx = struct {
1933 pub const generic: AddrSpace = @fromBackingInt(@intCast(0));
1934 pub const global: AddrSpace = @fromBackingInt(@intCast(1));
1935 pub const constant: AddrSpace = @fromBackingInt(@intCast(2));
1936 pub const shared: AddrSpace = @fromBackingInt(@intCast(3));
1937 pub const param: AddrSpace = @fromBackingInt(@intCast(4));
1938 pub const local: AddrSpace = @fromBackingInt(@intCast(5));
2569 pub const generic: AddrSpace = @fromBackingInt(0);
2570 pub const global: AddrSpace = @fromBackingInt(1);
2571 pub const constant: AddrSpace = @fromBackingInt(2);
2572 pub const shared: AddrSpace = @fromBackingInt(3);
2573 pub const param: AddrSpace = @fromBackingInt(4);
2574 pub const local: AddrSpace = @fromBackingInt(5);
19392575 };
19402576
19412577 // See llvm/lib/Target/AMDGPU/AMDGPU.h
19422578 pub const amdgpu = struct {
1943 pub const flat: AddrSpace = @fromBackingInt(@intCast(0));
1944 pub const global: AddrSpace = @fromBackingInt(@intCast(1));
1945 pub const region: AddrSpace = @fromBackingInt(@intCast(2));
1946 pub const local: AddrSpace = @fromBackingInt(@intCast(3));
1947 pub const constant: AddrSpace = @fromBackingInt(@intCast(4));
1948 pub const private: AddrSpace = @fromBackingInt(@intCast(5));
1949 pub const constant_32bit: AddrSpace = @fromBackingInt(@intCast(6));
1950 pub const buffer_fat_pointer: AddrSpace = @fromBackingInt(@intCast(7));
1951 pub const buffer_resource: AddrSpace = @fromBackingInt(@intCast(8));
1952 pub const buffer_strided_pointer: AddrSpace = @fromBackingInt(@intCast(9));
1953 pub const param_d: AddrSpace = @fromBackingInt(@intCast(6));
1954 pub const param_i: AddrSpace = @fromBackingInt(@intCast(7));
1955 pub const constant_buffer_0: AddrSpace = @fromBackingInt(@intCast(8));
1956 pub const constant_buffer_1: AddrSpace = @fromBackingInt(@intCast(9));
1957 pub const constant_buffer_2: AddrSpace = @fromBackingInt(@intCast(10));
1958 pub const constant_buffer_3: AddrSpace = @fromBackingInt(@intCast(11));
1959 pub const constant_buffer_4: AddrSpace = @fromBackingInt(@intCast(12));
1960 pub const constant_buffer_5: AddrSpace = @fromBackingInt(@intCast(13));
1961 pub const constant_buffer_6: AddrSpace = @fromBackingInt(@intCast(14));
1962 pub const constant_buffer_7: AddrSpace = @fromBackingInt(@intCast(15));
1963 pub const constant_buffer_8: AddrSpace = @fromBackingInt(@intCast(16));
1964 pub const constant_buffer_9: AddrSpace = @fromBackingInt(@intCast(17));
1965 pub const constant_buffer_10: AddrSpace = @fromBackingInt(@intCast(18));
1966 pub const constant_buffer_11: AddrSpace = @fromBackingInt(@intCast(19));
1967 pub const constant_buffer_12: AddrSpace = @fromBackingInt(@intCast(20));
1968 pub const constant_buffer_13: AddrSpace = @fromBackingInt(@intCast(21));
1969 pub const constant_buffer_14: AddrSpace = @fromBackingInt(@intCast(22));
1970 pub const constant_buffer_15: AddrSpace = @fromBackingInt(@intCast(23));
1971 pub const streamout_register: AddrSpace = @fromBackingInt(@intCast(128));
2579 pub const flat: AddrSpace = @fromBackingInt(0);
2580 pub const global: AddrSpace = @fromBackingInt(1);
2581 pub const region: AddrSpace = @fromBackingInt(2);
2582 pub const local: AddrSpace = @fromBackingInt(3);
2583 pub const constant: AddrSpace = @fromBackingInt(4);
2584 pub const private: AddrSpace = @fromBackingInt(5);
2585 pub const constant_32bit: AddrSpace = @fromBackingInt(6);
2586 pub const buffer_fat_pointer: AddrSpace = @fromBackingInt(7);
2587 pub const buffer_resource: AddrSpace = @fromBackingInt(8);
2588 pub const buffer_strided_pointer: AddrSpace = @fromBackingInt(9);
2589 pub const param_d: AddrSpace = @fromBackingInt(6);
2590 pub const param_i: AddrSpace = @fromBackingInt(7);
2591 pub const constant_buffer_0: AddrSpace = @fromBackingInt(8);
2592 pub const constant_buffer_1: AddrSpace = @fromBackingInt(9);
2593 pub const constant_buffer_2: AddrSpace = @fromBackingInt(10);
2594 pub const constant_buffer_3: AddrSpace = @fromBackingInt(11);
2595 pub const constant_buffer_4: AddrSpace = @fromBackingInt(12);
2596 pub const constant_buffer_5: AddrSpace = @fromBackingInt(13);
2597 pub const constant_buffer_6: AddrSpace = @fromBackingInt(14);
2598 pub const constant_buffer_7: AddrSpace = @fromBackingInt(15);
2599 pub const constant_buffer_8: AddrSpace = @fromBackingInt(16);
2600 pub const constant_buffer_9: AddrSpace = @fromBackingInt(17);
2601 pub const constant_buffer_10: AddrSpace = @fromBackingInt(18);
2602 pub const constant_buffer_11: AddrSpace = @fromBackingInt(19);
2603 pub const constant_buffer_12: AddrSpace = @fromBackingInt(20);
2604 pub const constant_buffer_13: AddrSpace = @fromBackingInt(21);
2605 pub const constant_buffer_14: AddrSpace = @fromBackingInt(22);
2606 pub const constant_buffer_15: AddrSpace = @fromBackingInt(23);
2607 pub const streamout_register: AddrSpace = @fromBackingInt(128);
19722608 };
19732609
19742610 pub const spirv = struct {
1975 pub const function: AddrSpace = @fromBackingInt(@intCast(0));
1976 pub const cross_workgroup: AddrSpace = @fromBackingInt(@intCast(1));
1977 pub const uniform_constant: AddrSpace = @fromBackingInt(@intCast(2));
1978 pub const workgroup: AddrSpace = @fromBackingInt(@intCast(3));
1979 pub const generic: AddrSpace = @fromBackingInt(@intCast(4));
1980 pub const device_only_intel: AddrSpace = @fromBackingInt(@intCast(5));
1981 pub const host_only_intel: AddrSpace = @fromBackingInt(@intCast(6));
1982 pub const input: AddrSpace = @fromBackingInt(@intCast(7));
2611 pub const function: AddrSpace = @fromBackingInt(0);
2612 pub const cross_workgroup: AddrSpace = @fromBackingInt(1);
2613 pub const uniform_constant: AddrSpace = @fromBackingInt(2);
2614 pub const workgroup: AddrSpace = @fromBackingInt(3);
2615 pub const generic: AddrSpace = @fromBackingInt(4);
2616 pub const device_only_intel: AddrSpace = @fromBackingInt(5);
2617 pub const host_only_intel: AddrSpace = @fromBackingInt(6);
2618 pub const input: AddrSpace = @fromBackingInt(7);
19832619 };
19842620
19852621 // See llvm/include/llvm/CodeGen/WasmAddressSpaces.h
19862622 pub const wasm = struct {
1987 pub const default: AddrSpace = @fromBackingInt(@intCast(0));
1988 pub const variable: AddrSpace = @fromBackingInt(@intCast(1));
1989 pub const externref: AddrSpace = @fromBackingInt(@intCast(10));
1990 pub const funcref: AddrSpace = @fromBackingInt(@intCast(20));
2623 pub const default: AddrSpace = @fromBackingInt(0);
2624 pub const variable: AddrSpace = @fromBackingInt(1);
2625 pub const externref: AddrSpace = @fromBackingInt(10);
2626 pub const funcref: AddrSpace = @fromBackingInt(20);
19912627 };
19922628
19932629 pub fn format(addr_space: AddrSpace, w: *Writer) Writer.Error!void {
......@@ -2030,7 +2666,7 @@ pub const Alignment = enum(u6) {
20302666 _,
20312667
20322668 pub fn wrap(a: Alignment) Lazy {
2033 return @fromBackingInt(@intCast(@backingInt(a)));
2669 return @fromBackingInt(@backingInt(a));
20342670 }
20352671 pub fn resolve(l: Lazy, b: *const Builder) Alignment {
20362672 return switch (@backingInt(l)) {
......@@ -2061,11 +2697,18 @@ pub const Alignment = enum(u6) {
20612697 };
20622698 }
20632699
2064 /// Asserts that neither `a` nor `b` is `.default`.
2065 pub fn max(a: Alignment, b: Alignment) Alignment {
2066 assert(a != .default);
2067 assert(b != .default);
2068 return @fromBackingInt(@intCast(@max(@backingInt(a), @backingInt(b))));
2700 /// Asserts that neither `lhs` nor `rhs` is `.default`.
2701 pub fn max(lhs: Alignment, rhs: Alignment) Alignment {
2702 assert(lhs != .default);
2703 assert(rhs != .default);
2704 return @fromBackingInt(@max(@backingInt(lhs), @backingInt(rhs)));
2705 }
2706
2707 /// Asserts that neither `lhs` nor `rhs` is `.default`.
2708 pub fn order(lhs: Alignment, rhs: Alignment) std.math.Order {
2709 assert(lhs != .default);
2710 assert(rhs != .default);
2711 return std.math.order(@backingInt(lhs), @backingInt(rhs));
20692712 }
20702713
20712714 pub fn toLlvm(self: Alignment) u6 {
......@@ -2106,6 +2749,7 @@ pub const CallConv = enum(u10) {
21062749 tailcc,
21072750 cfguard_checkcc,
21082751 swifttailcc,
2752 preserve_nonecc,
21092753
21102754 x86_stdcallcc = 64,
21112755 x86_fastcallcc,
......@@ -2174,6 +2818,7 @@ pub const CallConv = enum(u10) {
21742818 .tailcc,
21752819 .cfguard_checkcc,
21762820 .swifttailcc,
2821 .preserve_nonecc,
21772822 .x86_stdcallcc,
21782823 .x86_fastcallcc,
21792824 .arm_apcscc,
......@@ -2261,8 +2906,7 @@ pub const StrtabString = enum(u32) {
22612906 }
22622907
22632908 fn fromIndex(index: ?usize) StrtabString {
2264 return @fromBackingInt(@intCast(@as(u32, @intCast((index orelse return .none) +
2265 @backingInt(StrtabString.empty)))));
2909 return @fromBackingInt(@intCast((index orelse return .none) + @backingInt(StrtabString.empty)));
22662910 }
22672911
22682912 fn toIndex(self: StrtabString) ?usize {
......@@ -2318,7 +2962,7 @@ pub fn trailingStrtabString(self: *Builder) Allocator.Error!StrtabString {
23182962}
23192963
23202964pub fn trailingStrtabStringAssumeCapacity(self: *Builder) StrtabString {
2321 const start = self.strtab_string_indices.getLast().?;
2965 const start = self.strtab_string_indices.last().?;
23222966 const bytes: []const u8 = self.strtab_string_bytes.items[start..];
23232967 const gop = self.strtab_string_map.getOrPutAssumeCapacityAdapted(bytes, StrtabString.Adapter{ .builder = self });
23242968 if (gop.found_existing) {
......@@ -2398,7 +3042,7 @@ pub const Global = struct {
23983042 }
23993043
24003044 pub fn toConst(global: Index) Constant {
2401 return @fromBackingInt(@intCast(@backingInt(Constant.first_global) + @backingInt(global)));
3045 return @fromBackingInt(@backingInt(Constant.first_global) + @backingInt(global));
24023046 }
24033047
24043048 pub fn toValue(global: Index) Value {
......@@ -2526,7 +3170,7 @@ pub const Global = struct {
25263170 _ = builder.addGlobalAssumeCapacity(new_name, builder.globals.values()[index]);
25273171 builder.globals.swapRemoveAt(index);
25283172 if (!old_name.isAnon()) return;
2529 builder.next_unnamed_global = @fromBackingInt(@intCast(@backingInt(builder.next_unnamed_global) - 1));
3173 builder.next_unnamed_global = @fromBackingInt(@backingInt(builder.next_unnamed_global) - 1);
25303174 if (builder.next_unnamed_global == old_name) return;
25313175 builder.getGlobal(builder.next_unnamed_global).?.renameAssumeCapacity(old_name, builder);
25323176 }
......@@ -2539,7 +3183,7 @@ pub const Global = struct {
25393183
25403184 fn replaceAssumeCapacity(self: Index, other: Index, builder: *Builder) void {
25413185 if (self.eql(other, builder)) return;
2542 builder.next_replaced_global = @fromBackingInt(@intCast(@backingInt(builder.next_replaced_global) - 1));
3186 builder.next_replaced_global = @fromBackingInt(@backingInt(builder.next_replaced_global) - 1);
25433187 self.renameAssumeCapacity(builder.next_replaced_global, builder);
25443188 self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) };
25453189 }
......@@ -2699,6 +3343,8 @@ pub const Intrinsic = enum {
26993343 smin,
27003344 umax,
27013345 umin,
3346 scmp,
3347 ucmp,
27023348 memcpy,
27033349 @"memcpy.inline",
27043350 memmove,
......@@ -2708,10 +3354,21 @@ pub const Intrinsic = enum {
27083354 powi,
27093355 sin,
27103356 cos,
3357 tan,
3358 asin,
3359 acos,
3360 atan,
3361 atan2,
3362 sinh,
3363 cosh,
3364 tanh,
3365 sincos,
3366 sincospi,
3367 modf,
27113368 pow,
27123369 exp,
2713 exp10,
27143370 exp2,
3371 exp10,
27153372 ldexp,
27163373 frexp,
27173374 log,
......@@ -2723,6 +3380,8 @@ pub const Intrinsic = enum {
27233380 maxnum,
27243381 minimum,
27253382 maximum,
3383 minimumnum,
3384 maximumnum,
27263385 copysign,
27273386 floor,
27283387 ceil,
......@@ -2744,6 +3403,7 @@ pub const Intrinsic = enum {
27443403 cttz,
27453404 fshl,
27463405 fshr,
3406 clmul,
27473407
27483408 // Arithmetic with Overflow
27493409 @"sadd.with.overflow",
......@@ -2904,21 +3564,21 @@ pub const Intrinsic = enum {
29043564 .{ .kind = .{ .type = .ptr } },
29053565 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
29063566 },
2907 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3567 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
29083568 },
29093569 .addressofreturnaddress = .{
29103570 .ret_len = 1,
29113571 .params = &.{
29123572 .{ .kind = .overloaded },
29133573 },
2914 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3574 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
29153575 },
29163576 .sponentry = .{
29173577 .ret_len = 1,
29183578 .params = &.{
29193579 .{ .kind = .overloaded },
29203580 },
2921 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3581 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
29223582 },
29233583 .frameaddress = .{
29243584 .ret_len = 1,
......@@ -2926,7 +3586,7 @@ pub const Intrinsic = enum {
29263586 .{ .kind = .overloaded },
29273587 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
29283588 },
2929 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3589 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
29303590 },
29313591 .prefetch = .{
29323592 .ret_len = 0,
......@@ -2936,14 +3596,14 @@ pub const Intrinsic = enum {
29363596 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
29373597 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
29383598 },
2939 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.readwrite) } },
3599 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.readwrite) } },
29403600 },
29413601 .@"thread.pointer" = .{
29423602 .ret_len = 1,
29433603 .params = &.{
29443604 .{ .kind = .{ .type = .ptr } },
29453605 },
2946 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3606 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
29473607 },
29483608
29493609 .abs = .{
......@@ -2953,7 +3613,7 @@ pub const Intrinsic = enum {
29533613 .{ .kind = .{ .matches = 0 } },
29543614 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
29553615 },
2956 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3616 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
29573617 },
29583618 .smax = .{
29593619 .ret_len = 1,
......@@ -2962,7 +3622,7 @@ pub const Intrinsic = enum {
29623622 .{ .kind = .{ .matches = 0 } },
29633623 .{ .kind = .{ .matches = 0 } },
29643624 },
2965 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3625 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
29663626 },
29673627 .smin = .{
29683628 .ret_len = 1,
......@@ -2971,7 +3631,7 @@ pub const Intrinsic = enum {
29713631 .{ .kind = .{ .matches = 0 } },
29723632 .{ .kind = .{ .matches = 0 } },
29733633 },
2974 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3634 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
29753635 },
29763636 .umax = .{
29773637 .ret_len = 1,
......@@ -2980,7 +3640,7 @@ pub const Intrinsic = enum {
29803640 .{ .kind = .{ .matches = 0 } },
29813641 .{ .kind = .{ .matches = 0 } },
29823642 },
2983 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3643 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
29843644 },
29853645 .umin = .{
29863646 .ret_len = 1,
......@@ -2989,7 +3649,25 @@ pub const Intrinsic = enum {
29893649 .{ .kind = .{ .matches = 0 } },
29903650 .{ .kind = .{ .matches = 0 } },
29913651 },
2992 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3652 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3653 },
3654 .scmp = .{
3655 .ret_len = 1,
3656 .params = &.{
3657 .{ .kind = .overloaded },
3658 .{ .kind = .overloaded },
3659 .{ .kind = .{ .matches = 1 } },
3660 },
3661 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3662 },
3663 .ucmp = .{
3664 .ret_len = 1,
3665 .params = &.{
3666 .{ .kind = .overloaded },
3667 .{ .kind = .overloaded },
3668 .{ .kind = .{ .matches = 1 } },
3669 },
3670 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
29933671 },
29943672 .memcpy = .{
29953673 .ret_len = 0,
......@@ -3047,7 +3725,7 @@ pub const Intrinsic = enum {
30473725 .{ .kind = .overloaded },
30483726 .{ .kind = .{ .matches = 0 } },
30493727 },
3050 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3728 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
30513729 },
30523730 .powi = .{
30533731 .ret_len = 1,
......@@ -3056,7 +3734,7 @@ pub const Intrinsic = enum {
30563734 .{ .kind = .{ .matches = 0 } },
30573735 .{ .kind = .overloaded },
30583736 },
3059 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3737 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
30603738 },
30613739 .sin = .{
30623740 .ret_len = 1,
......@@ -3064,7 +3742,7 @@ pub const Intrinsic = enum {
30643742 .{ .kind = .overloaded },
30653743 .{ .kind = .{ .matches = 0 } },
30663744 },
3067 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3745 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
30683746 },
30693747 .cos = .{
30703748 .ret_len = 1,
......@@ -3072,7 +3750,99 @@ pub const Intrinsic = enum {
30723750 .{ .kind = .overloaded },
30733751 .{ .kind = .{ .matches = 0 } },
30743752 },
3075 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3753 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3754 },
3755 .tan = .{
3756 .ret_len = 1,
3757 .params = &.{
3758 .{ .kind = .overloaded },
3759 .{ .kind = .{ .matches = 0 } },
3760 },
3761 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3762 },
3763 .asin = .{
3764 .ret_len = 1,
3765 .params = &.{
3766 .{ .kind = .overloaded },
3767 .{ .kind = .{ .matches = 0 } },
3768 },
3769 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3770 },
3771 .acos = .{
3772 .ret_len = 1,
3773 .params = &.{
3774 .{ .kind = .overloaded },
3775 .{ .kind = .{ .matches = 0 } },
3776 },
3777 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3778 },
3779 .atan = .{
3780 .ret_len = 1,
3781 .params = &.{
3782 .{ .kind = .overloaded },
3783 .{ .kind = .{ .matches = 0 } },
3784 },
3785 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3786 },
3787 .atan2 = .{
3788 .ret_len = 1,
3789 .params = &.{
3790 .{ .kind = .overloaded },
3791 .{ .kind = .{ .matches = 0 } },
3792 .{ .kind = .{ .matches = 0 } },
3793 },
3794 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3795 },
3796 .sinh = .{
3797 .ret_len = 1,
3798 .params = &.{
3799 .{ .kind = .overloaded },
3800 .{ .kind = .{ .matches = 0 } },
3801 },
3802 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3803 },
3804 .cosh = .{
3805 .ret_len = 1,
3806 .params = &.{
3807 .{ .kind = .overloaded },
3808 .{ .kind = .{ .matches = 0 } },
3809 },
3810 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3811 },
3812 .tanh = .{
3813 .ret_len = 1,
3814 .params = &.{
3815 .{ .kind = .overloaded },
3816 .{ .kind = .{ .matches = 0 } },
3817 },
3818 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3819 },
3820 .sincos = .{
3821 .ret_len = 2,
3822 .params = &.{
3823 .{ .kind = .overloaded },
3824 .{ .kind = .{ .matches = 0 } },
3825 .{ .kind = .{ .matches = 0 } },
3826 },
3827 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3828 },
3829 .sincospi = .{
3830 .ret_len = 2,
3831 .params = &.{
3832 .{ .kind = .overloaded },
3833 .{ .kind = .{ .matches = 0 } },
3834 .{ .kind = .{ .matches = 0 } },
3835 },
3836 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3837 },
3838 .modf = .{
3839 .ret_len = 2,
3840 .params = &.{
3841 .{ .kind = .overloaded },
3842 .{ .kind = .{ .matches = 0 } },
3843 .{ .kind = .{ .matches = 0 } },
3844 },
3845 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
30763846 },
30773847 .pow = .{
30783848 .ret_len = 1,
......@@ -3081,7 +3851,7 @@ pub const Intrinsic = enum {
30813851 .{ .kind = .{ .matches = 0 } },
30823852 .{ .kind = .{ .matches = 0 } },
30833853 },
3084 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3854 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
30853855 },
30863856 .exp = .{
30873857 .ret_len = 1,
......@@ -3089,7 +3859,7 @@ pub const Intrinsic = enum {
30893859 .{ .kind = .overloaded },
30903860 .{ .kind = .{ .matches = 0 } },
30913861 },
3092 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3862 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
30933863 },
30943864 .exp2 = .{
30953865 .ret_len = 1,
......@@ -3097,7 +3867,7 @@ pub const Intrinsic = enum {
30973867 .{ .kind = .overloaded },
30983868 .{ .kind = .{ .matches = 0 } },
30993869 },
3100 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3870 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31013871 },
31023872 .exp10 = .{
31033873 .ret_len = 1,
......@@ -3105,7 +3875,7 @@ pub const Intrinsic = enum {
31053875 .{ .kind = .overloaded },
31063876 .{ .kind = .{ .matches = 0 } },
31073877 },
3108 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3878 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31093879 },
31103880 .ldexp = .{
31113881 .ret_len = 1,
......@@ -3114,7 +3884,7 @@ pub const Intrinsic = enum {
31143884 .{ .kind = .{ .matches = 0 } },
31153885 .{ .kind = .overloaded },
31163886 },
3117 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3887 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31183888 },
31193889 .frexp = .{
31203890 .ret_len = 2,
......@@ -3123,7 +3893,7 @@ pub const Intrinsic = enum {
31233893 .{ .kind = .overloaded },
31243894 .{ .kind = .{ .matches = 0 } },
31253895 },
3126 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3896 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31273897 },
31283898 .log = .{
31293899 .ret_len = 1,
......@@ -3131,7 +3901,7 @@ pub const Intrinsic = enum {
31313901 .{ .kind = .overloaded },
31323902 .{ .kind = .{ .matches = 0 } },
31333903 },
3134 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3904 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31353905 },
31363906 .log10 = .{
31373907 .ret_len = 1,
......@@ -3139,7 +3909,7 @@ pub const Intrinsic = enum {
31393909 .{ .kind = .overloaded },
31403910 .{ .kind = .{ .matches = 0 } },
31413911 },
3142 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3912 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31433913 },
31443914 .log2 = .{
31453915 .ret_len = 1,
......@@ -3147,7 +3917,7 @@ pub const Intrinsic = enum {
31473917 .{ .kind = .overloaded },
31483918 .{ .kind = .{ .matches = 0 } },
31493919 },
3150 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3920 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31513921 },
31523922 .fma = .{
31533923 .ret_len = 1,
......@@ -3157,7 +3927,7 @@ pub const Intrinsic = enum {
31573927 .{ .kind = .{ .matches = 0 } },
31583928 .{ .kind = .{ .matches = 0 } },
31593929 },
3160 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3930 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31613931 },
31623932 .fabs = .{
31633933 .ret_len = 1,
......@@ -3165,7 +3935,7 @@ pub const Intrinsic = enum {
31653935 .{ .kind = .overloaded },
31663936 .{ .kind = .{ .matches = 0 } },
31673937 },
3168 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3938 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31693939 },
31703940 .minnum = .{
31713941 .ret_len = 1,
......@@ -3174,7 +3944,7 @@ pub const Intrinsic = enum {
31743944 .{ .kind = .{ .matches = 0 } },
31753945 .{ .kind = .{ .matches = 0 } },
31763946 },
3177 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3947 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31783948 },
31793949 .maxnum = .{
31803950 .ret_len = 1,
......@@ -3183,7 +3953,7 @@ pub const Intrinsic = enum {
31833953 .{ .kind = .{ .matches = 0 } },
31843954 .{ .kind = .{ .matches = 0 } },
31853955 },
3186 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3956 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31873957 },
31883958 .minimum = .{
31893959 .ret_len = 1,
......@@ -3192,7 +3962,7 @@ pub const Intrinsic = enum {
31923962 .{ .kind = .{ .matches = 0 } },
31933963 .{ .kind = .{ .matches = 0 } },
31943964 },
3195 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3965 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31963966 },
31973967 .maximum = .{
31983968 .ret_len = 1,
......@@ -3201,7 +3971,25 @@ pub const Intrinsic = enum {
32013971 .{ .kind = .{ .matches = 0 } },
32023972 .{ .kind = .{ .matches = 0 } },
32033973 },
3204 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3974 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3975 },
3976 .minimumnum = .{
3977 .ret_len = 1,
3978 .params = &.{
3979 .{ .kind = .overloaded },
3980 .{ .kind = .{ .matches = 0 } },
3981 .{ .kind = .{ .matches = 0 } },
3982 },
3983 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3984 },
3985 .maximumnum = .{
3986 .ret_len = 1,
3987 .params = &.{
3988 .{ .kind = .overloaded },
3989 .{ .kind = .{ .matches = 0 } },
3990 .{ .kind = .{ .matches = 0 } },
3991 },
3992 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32053993 },
32063994 .copysign = .{
32073995 .ret_len = 1,
......@@ -3210,7 +3998,7 @@ pub const Intrinsic = enum {
32103998 .{ .kind = .{ .matches = 0 } },
32113999 .{ .kind = .{ .matches = 0 } },
32124000 },
3213 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4001 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32144002 },
32154003 .floor = .{
32164004 .ret_len = 1,
......@@ -3218,7 +4006,7 @@ pub const Intrinsic = enum {
32184006 .{ .kind = .overloaded },
32194007 .{ .kind = .{ .matches = 0 } },
32204008 },
3221 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4009 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32224010 },
32234011 .ceil = .{
32244012 .ret_len = 1,
......@@ -3226,7 +4014,7 @@ pub const Intrinsic = enum {
32264014 .{ .kind = .overloaded },
32274015 .{ .kind = .{ .matches = 0 } },
32284016 },
3229 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4017 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32304018 },
32314019 .trunc = .{
32324020 .ret_len = 1,
......@@ -3234,7 +4022,7 @@ pub const Intrinsic = enum {
32344022 .{ .kind = .overloaded },
32354023 .{ .kind = .{ .matches = 0 } },
32364024 },
3237 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4025 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32384026 },
32394027 .rint = .{
32404028 .ret_len = 1,
......@@ -3242,7 +4030,7 @@ pub const Intrinsic = enum {
32424030 .{ .kind = .overloaded },
32434031 .{ .kind = .{ .matches = 0 } },
32444032 },
3245 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4033 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32464034 },
32474035 .nearbyint = .{
32484036 .ret_len = 1,
......@@ -3250,7 +4038,7 @@ pub const Intrinsic = enum {
32504038 .{ .kind = .overloaded },
32514039 .{ .kind = .{ .matches = 0 } },
32524040 },
3253 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4041 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32544042 },
32554043 .round = .{
32564044 .ret_len = 1,
......@@ -3258,7 +4046,7 @@ pub const Intrinsic = enum {
32584046 .{ .kind = .overloaded },
32594047 .{ .kind = .{ .matches = 0 } },
32604048 },
3261 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4049 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32624050 },
32634051 .roundeven = .{
32644052 .ret_len = 1,
......@@ -3266,7 +4054,7 @@ pub const Intrinsic = enum {
32664054 .{ .kind = .overloaded },
32674055 .{ .kind = .{ .matches = 0 } },
32684056 },
3269 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4057 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32704058 },
32714059 .lround = .{
32724060 .ret_len = 1,
......@@ -3274,7 +4062,7 @@ pub const Intrinsic = enum {
32744062 .{ .kind = .overloaded },
32754063 .{ .kind = .overloaded },
32764064 },
3277 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4065 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32784066 },
32794067 .llround = .{
32804068 .ret_len = 1,
......@@ -3282,7 +4070,7 @@ pub const Intrinsic = enum {
32824070 .{ .kind = .overloaded },
32834071 .{ .kind = .overloaded },
32844072 },
3285 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4073 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32864074 },
32874075 .lrint = .{
32884076 .ret_len = 1,
......@@ -3290,7 +4078,7 @@ pub const Intrinsic = enum {
32904078 .{ .kind = .overloaded },
32914079 .{ .kind = .overloaded },
32924080 },
3293 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4081 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32944082 },
32954083 .llrint = .{
32964084 .ret_len = 1,
......@@ -3298,7 +4086,7 @@ pub const Intrinsic = enum {
32984086 .{ .kind = .overloaded },
32994087 .{ .kind = .overloaded },
33004088 },
3301 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4089 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33024090 },
33034091
33044092 .bitreverse = .{
......@@ -3307,7 +4095,7 @@ pub const Intrinsic = enum {
33074095 .{ .kind = .overloaded },
33084096 .{ .kind = .{ .matches = 0 } },
33094097 },
3310 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4098 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33114099 },
33124100 .bswap = .{
33134101 .ret_len = 1,
......@@ -3315,7 +4103,7 @@ pub const Intrinsic = enum {
33154103 .{ .kind = .overloaded },
33164104 .{ .kind = .{ .matches = 0 } },
33174105 },
3318 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4106 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33194107 },
33204108 .ctpop = .{
33214109 .ret_len = 1,
......@@ -3323,7 +4111,7 @@ pub const Intrinsic = enum {
33234111 .{ .kind = .overloaded },
33244112 .{ .kind = .{ .matches = 0 } },
33254113 },
3326 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4114 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33274115 },
33284116 .ctlz = .{
33294117 .ret_len = 1,
......@@ -3332,7 +4120,7 @@ pub const Intrinsic = enum {
33324120 .{ .kind = .{ .matches = 0 } },
33334121 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
33344122 },
3335 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4123 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33364124 },
33374125 .cttz = .{
33384126 .ret_len = 1,
......@@ -3341,7 +4129,7 @@ pub const Intrinsic = enum {
33414129 .{ .kind = .{ .matches = 0 } },
33424130 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
33434131 },
3344 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4132 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33454133 },
33464134 .fshl = .{
33474135 .ret_len = 1,
......@@ -3351,7 +4139,7 @@ pub const Intrinsic = enum {
33514139 .{ .kind = .{ .matches = 0 } },
33524140 .{ .kind = .{ .matches = 0 } },
33534141 },
3354 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4142 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33554143 },
33564144 .fshr = .{
33574145 .ret_len = 1,
......@@ -3361,7 +4149,16 @@ pub const Intrinsic = enum {
33614149 .{ .kind = .{ .matches = 0 } },
33624150 .{ .kind = .{ .matches = 0 } },
33634151 },
3364 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4152 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
4153 },
4154 .clmul = .{
4155 .ret_len = 1,
4156 .params = &.{
4157 .{ .kind = .overloaded },
4158 .{ .kind = .{ .matches = 0 } },
4159 .{ .kind = .{ .matches = 0 } },
4160 },
4161 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33654162 },
33664163
33674164 .@"sadd.with.overflow" = .{
......@@ -3372,7 +4169,7 @@ pub const Intrinsic = enum {
33724169 .{ .kind = .{ .matches = 0 } },
33734170 .{ .kind = .{ .matches = 0 } },
33744171 },
3375 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4172 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33764173 },
33774174 .@"uadd.with.overflow" = .{
33784175 .ret_len = 2,
......@@ -3382,7 +4179,7 @@ pub const Intrinsic = enum {
33824179 .{ .kind = .{ .matches = 0 } },
33834180 .{ .kind = .{ .matches = 0 } },
33844181 },
3385 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4182 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33864183 },
33874184 .@"ssub.with.overflow" = .{
33884185 .ret_len = 2,
......@@ -3392,7 +4189,7 @@ pub const Intrinsic = enum {
33924189 .{ .kind = .{ .matches = 0 } },
33934190 .{ .kind = .{ .matches = 0 } },
33944191 },
3395 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4192 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33964193 },
33974194 .@"usub.with.overflow" = .{
33984195 .ret_len = 2,
......@@ -3402,7 +4199,7 @@ pub const Intrinsic = enum {
34024199 .{ .kind = .{ .matches = 0 } },
34034200 .{ .kind = .{ .matches = 0 } },
34044201 },
3405 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4202 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
34064203 },
34074204 .@"smul.with.overflow" = .{
34084205 .ret_len = 2,
......@@ -3412,7 +4209,7 @@ pub const Intrinsic = enum {
34124209 .{ .kind = .{ .matches = 0 } },
34134210 .{ .kind = .{ .matches = 0 } },
34144211 },
3415 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4212 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
34164213 },
34174214 .@"umul.with.overflow" = .{
34184215 .ret_len = 2,
......@@ -3422,7 +4219,7 @@ pub const Intrinsic = enum {
34224219 .{ .kind = .{ .matches = 0 } },
34234220 .{ .kind = .{ .matches = 0 } },
34244221 },
3425 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4222 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
34264223 },
34274224
34284225 .@"sadd.sat" = .{
......@@ -3432,7 +4229,7 @@ pub const Intrinsic = enum {
34324229 .{ .kind = .{ .matches = 0 } },
34334230 .{ .kind = .{ .matches = 0 } },
34344231 },
3435 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4232 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
34364233 },
34374234 .@"uadd.sat" = .{
34384235 .ret_len = 1,
......@@ -3441,7 +4238,7 @@ pub const Intrinsic = enum {
34414238 .{ .kind = .{ .matches = 0 } },
34424239 .{ .kind = .{ .matches = 0 } },
34434240 },
3444 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4241 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
34454242 },
34464243 .@"ssub.sat" = .{
34474244 .ret_len = 1,
......@@ -3450,7 +4247,7 @@ pub const Intrinsic = enum {
34504247 .{ .kind = .{ .matches = 0 } },
34514248 .{ .kind = .{ .matches = 0 } },
34524249 },
3453 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4250 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
34544251 },
34554252 .@"usub.sat" = .{
34564253 .ret_len = 1,
......@@ -3459,7 +4256,7 @@ pub const Intrinsic = enum {
34594256 .{ .kind = .{ .matches = 0 } },
34604257 .{ .kind = .{ .matches = 0 } },
34614258 },
3462 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4259 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
34634260 },
34644261 .@"sshl.sat" = .{
34654262 .ret_len = 1,
......@@ -3468,7 +4265,7 @@ pub const Intrinsic = enum {
34684265 .{ .kind = .{ .matches = 0 } },
34694266 .{ .kind = .{ .matches = 0 } },
34704267 },
3471 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4268 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
34724269 },
34734270 .@"ushl.sat" = .{
34744271 .ret_len = 1,
......@@ -3477,7 +4274,7 @@ pub const Intrinsic = enum {
34774274 .{ .kind = .{ .matches = 0 } },
34784275 .{ .kind = .{ .matches = 0 } },
34794276 },
3480 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4277 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
34814278 },
34824279
34834280 .@"smul.fix" = .{
......@@ -3488,7 +4285,7 @@ pub const Intrinsic = enum {
34884285 .{ .kind = .{ .matches = 0 } },
34894286 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
34904287 },
3491 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4288 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
34924289 },
34934290 .@"umul.fix" = .{
34944291 .ret_len = 1,
......@@ -3498,7 +4295,7 @@ pub const Intrinsic = enum {
34984295 .{ .kind = .{ .matches = 0 } },
34994296 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
35004297 },
3501 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4298 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
35024299 },
35034300 .@"smul.fix.sat" = .{
35044301 .ret_len = 1,
......@@ -3508,7 +4305,7 @@ pub const Intrinsic = enum {
35084305 .{ .kind = .{ .matches = 0 } },
35094306 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
35104307 },
3511 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4308 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
35124309 },
35134310 .@"umul.fix.sat" = .{
35144311 .ret_len = 1,
......@@ -3518,7 +4315,7 @@ pub const Intrinsic = enum {
35184315 .{ .kind = .{ .matches = 0 } },
35194316 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
35204317 },
3521 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4318 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
35224319 },
35234320 .@"sdiv.fix" = .{
35244321 .ret_len = 1,
......@@ -3528,7 +4325,7 @@ pub const Intrinsic = enum {
35284325 .{ .kind = .{ .matches = 0 } },
35294326 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
35304327 },
3531 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4328 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
35324329 },
35334330 .@"udiv.fix" = .{
35344331 .ret_len = 1,
......@@ -3538,7 +4335,7 @@ pub const Intrinsic = enum {
35384335 .{ .kind = .{ .matches = 0 } },
35394336 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
35404337 },
3541 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4338 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
35424339 },
35434340 .@"sdiv.fix.sat" = .{
35444341 .ret_len = 1,
......@@ -3548,7 +4345,7 @@ pub const Intrinsic = enum {
35484345 .{ .kind = .{ .matches = 0 } },
35494346 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
35504347 },
3551 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4348 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
35524349 },
35534350 .@"udiv.fix.sat" = .{
35544351 .ret_len = 1,
......@@ -3558,7 +4355,7 @@ pub const Intrinsic = enum {
35584355 .{ .kind = .{ .matches = 0 } },
35594356 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
35604357 },
3561 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4358 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
35624359 },
35634360
35644361 .canonicalize = .{
......@@ -3567,7 +4364,7 @@ pub const Intrinsic = enum {
35674364 .{ .kind = .overloaded },
35684365 .{ .kind = .{ .matches = 0 } },
35694366 },
3570 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4367 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
35714368 },
35724369 .fmuladd = .{
35734370 .ret_len = 1,
......@@ -3577,7 +4374,7 @@ pub const Intrinsic = enum {
35774374 .{ .kind = .{ .matches = 0 } },
35784375 .{ .kind = .{ .matches = 0 } },
35794376 },
3580 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4377 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
35814378 },
35824379
35834380 .@"vector.reduce.add" = .{
......@@ -3586,7 +4383,7 @@ pub const Intrinsic = enum {
35864383 .{ .kind = .{ .matches_scalar = 1 } },
35874384 .{ .kind = .overloaded },
35884385 },
3589 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4386 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
35904387 },
35914388 .@"vector.reduce.fadd" = .{
35924389 .ret_len = 1,
......@@ -3595,7 +4392,7 @@ pub const Intrinsic = enum {
35954392 .{ .kind = .{ .matches_scalar = 2 } },
35964393 .{ .kind = .overloaded },
35974394 },
3598 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4395 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
35994396 },
36004397 .@"vector.reduce.mul" = .{
36014398 .ret_len = 1,
......@@ -3603,7 +4400,7 @@ pub const Intrinsic = enum {
36034400 .{ .kind = .{ .matches_scalar = 1 } },
36044401 .{ .kind = .overloaded },
36054402 },
3606 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4403 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36074404 },
36084405 .@"vector.reduce.fmul" = .{
36094406 .ret_len = 1,
......@@ -3612,7 +4409,7 @@ pub const Intrinsic = enum {
36124409 .{ .kind = .{ .matches_scalar = 2 } },
36134410 .{ .kind = .overloaded },
36144411 },
3615 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4412 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36164413 },
36174414 .@"vector.reduce.and" = .{
36184415 .ret_len = 1,
......@@ -3620,7 +4417,7 @@ pub const Intrinsic = enum {
36204417 .{ .kind = .{ .matches_scalar = 1 } },
36214418 .{ .kind = .overloaded },
36224419 },
3623 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4420 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36244421 },
36254422 .@"vector.reduce.or" = .{
36264423 .ret_len = 1,
......@@ -3628,7 +4425,7 @@ pub const Intrinsic = enum {
36284425 .{ .kind = .{ .matches_scalar = 1 } },
36294426 .{ .kind = .overloaded },
36304427 },
3631 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4428 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36324429 },
36334430 .@"vector.reduce.xor" = .{
36344431 .ret_len = 1,
......@@ -3636,7 +4433,7 @@ pub const Intrinsic = enum {
36364433 .{ .kind = .{ .matches_scalar = 1 } },
36374434 .{ .kind = .overloaded },
36384435 },
3639 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4436 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36404437 },
36414438 .@"vector.reduce.smax" = .{
36424439 .ret_len = 1,
......@@ -3644,7 +4441,7 @@ pub const Intrinsic = enum {
36444441 .{ .kind = .{ .matches_scalar = 1 } },
36454442 .{ .kind = .overloaded },
36464443 },
3647 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4444 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36484445 },
36494446 .@"vector.reduce.smin" = .{
36504447 .ret_len = 1,
......@@ -3652,7 +4449,7 @@ pub const Intrinsic = enum {
36524449 .{ .kind = .{ .matches_scalar = 1 } },
36534450 .{ .kind = .overloaded },
36544451 },
3655 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4452 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36564453 },
36574454 .@"vector.reduce.umax" = .{
36584455 .ret_len = 1,
......@@ -3660,7 +4457,7 @@ pub const Intrinsic = enum {
36604457 .{ .kind = .{ .matches_scalar = 1 } },
36614458 .{ .kind = .overloaded },
36624459 },
3663 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4460 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36644461 },
36654462 .@"vector.reduce.umin" = .{
36664463 .ret_len = 1,
......@@ -3668,7 +4465,7 @@ pub const Intrinsic = enum {
36684465 .{ .kind = .{ .matches_scalar = 1 } },
36694466 .{ .kind = .overloaded },
36704467 },
3671 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4468 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36724469 },
36734470 .@"vector.reduce.fmax" = .{
36744471 .ret_len = 1,
......@@ -3676,7 +4473,7 @@ pub const Intrinsic = enum {
36764473 .{ .kind = .{ .matches_scalar = 1 } },
36774474 .{ .kind = .overloaded },
36784475 },
3679 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4476 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36804477 },
36814478 .@"vector.reduce.fmin" = .{
36824479 .ret_len = 1,
......@@ -3684,7 +4481,7 @@ pub const Intrinsic = enum {
36844481 .{ .kind = .{ .matches_scalar = 1 } },
36854482 .{ .kind = .overloaded },
36864483 },
3687 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4484 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36884485 },
36894486 .@"vector.reduce.fmaximum" = .{
36904487 .ret_len = 1,
......@@ -3692,7 +4489,7 @@ pub const Intrinsic = enum {
36924489 .{ .kind = .{ .matches_scalar = 1 } },
36934490 .{ .kind = .overloaded },
36944491 },
3695 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4492 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36964493 },
36974494 .@"vector.reduce.fminimum" = .{
36984495 .ret_len = 1,
......@@ -3700,7 +4497,7 @@ pub const Intrinsic = enum {
37004497 .{ .kind = .{ .matches_scalar = 1 } },
37014498 .{ .kind = .overloaded },
37024499 },
3703 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4500 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
37044501 },
37054502 .@"vector.insert" = .{
37064503 .ret_len = 1,
......@@ -3710,7 +4507,7 @@ pub const Intrinsic = enum {
37104507 .{ .kind = .overloaded },
37114508 .{ .kind = .{ .type = .i64 } },
37124509 },
3713 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4510 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
37144511 },
37154512 .@"vector.extract" = .{
37164513 .ret_len = 1,
......@@ -3719,7 +4516,7 @@ pub const Intrinsic = enum {
37194516 .{ .kind = .overloaded },
37204517 .{ .kind = .{ .type = .i64 } },
37214518 },
3722 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4519 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
37234520 },
37244521
37254522 .@"is.fpclass" = .{
......@@ -3729,7 +4526,7 @@ pub const Intrinsic = enum {
37294526 .{ .kind = .overloaded },
37304527 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
37314528 },
3732 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4529 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
37334530 },
37344531
37354532 .@"var.annotation" = .{
......@@ -3814,7 +4611,7 @@ pub const Intrinsic = enum {
38144611 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
38154612 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
38164613 },
3817 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4614 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
38184615 },
38194616 .expect = .{
38204617 .ret_len = 1,
......@@ -3823,7 +4620,7 @@ pub const Intrinsic = enum {
38234620 .{ .kind = .{ .matches = 0 } },
38244621 .{ .kind = .{ .matches = 0 } },
38254622 },
3826 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4623 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
38274624 },
38284625 .@"expect.with.probability" = .{
38294626 .ret_len = 1,
......@@ -3833,7 +4630,7 @@ pub const Intrinsic = enum {
38334630 .{ .kind = .{ .matches = 0 } },
38344631 .{ .kind = .{ .type = .double }, .attrs = &.{.immarg} },
38354632 },
3836 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4633 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
38374634 },
38384635 .assume = .{
38394636 .ret_len = 0,
......@@ -3848,7 +4645,7 @@ pub const Intrinsic = enum {
38484645 .{ .kind = .overloaded },
38494646 .{ .kind = .{ .matches = 0 }, .attrs = &.{.returned} },
38504647 },
3851 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4648 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
38524649 },
38534650 .@"type.test" = .{
38544651 .ret_len = 1,
......@@ -3857,7 +4654,7 @@ pub const Intrinsic = enum {
38574654 .{ .kind = .{ .type = .ptr } },
38584655 .{ .kind = .{ .type = .metadata } },
38594656 },
3860 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4657 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
38614658 },
38624659 .@"type.checked.load" = .{
38634660 .ret_len = 2,
......@@ -3868,7 +4665,7 @@ pub const Intrinsic = enum {
38684665 .{ .kind = .{ .type = .i32 } },
38694666 .{ .kind = .{ .type = .metadata } },
38704667 },
3871 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4668 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
38724669 },
38734670 .@"type.checked.load.relative" = .{
38744671 .ret_len = 2,
......@@ -3879,7 +4676,7 @@ pub const Intrinsic = enum {
38794676 .{ .kind = .{ .type = .i32 } },
38804677 .{ .kind = .{ .type = .metadata } },
38814678 },
3882 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4679 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
38834680 },
38844681 .@"arithmetic.fence" = .{
38854682 .ret_len = 1,
......@@ -3887,12 +4684,12 @@ pub const Intrinsic = enum {
38874684 .{ .kind = .overloaded },
38884685 .{ .kind = .{ .matches = 0 } },
38894686 },
3890 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4687 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
38914688 },
38924689 .donothing = .{
38934690 .ret_len = 0,
38944691 .params = &.{},
3895 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4692 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
38964693 },
38974694 .@"load.relative" = .{
38984695 .ret_len = 1,
......@@ -3914,7 +4711,7 @@ pub const Intrinsic = enum {
39144711 .{ .kind = .{ .type = .i1 } },
39154712 .{ .kind = .overloaded },
39164713 },
3917 .attrs = &.{ .convergent, .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4714 .attrs = &.{ .convergent, .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
39184715 },
39194716 .ptrmask = .{
39204717 .ret_len = 1,
......@@ -3923,7 +4720,7 @@ pub const Intrinsic = enum {
39234720 .{ .kind = .{ .matches = 0 } },
39244721 .{ .kind = .overloaded },
39254722 },
3926 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4723 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
39274724 },
39284725 .@"threadlocal.address" = .{
39294726 .ret_len = 1,
......@@ -3931,14 +4728,14 @@ pub const Intrinsic = enum {
39314728 .{ .kind = .overloaded, .attrs = &.{.nonnull} },
39324729 .{ .kind = .{ .matches = 0 }, .attrs = &.{.nonnull} },
39334730 },
3934 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4731 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
39354732 },
39364733 .vscale = .{
39374734 .ret_len = 1,
39384735 .params = &.{
39394736 .{ .kind = .overloaded },
39404737 },
3941 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4738 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
39424739 },
39434740
39444741 .@"dbg.declare" = .{
......@@ -3948,7 +4745,7 @@ pub const Intrinsic = enum {
39484745 .{ .kind = .{ .type = .metadata } },
39494746 .{ .kind = .{ .type = .metadata } },
39504747 },
3951 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4748 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
39524749 },
39534750 .@"dbg.value" = .{
39544751 .ret_len = 0,
......@@ -3957,7 +4754,7 @@ pub const Intrinsic = enum {
39574754 .{ .kind = .{ .type = .metadata } },
39584755 .{ .kind = .{ .type = .metadata } },
39594756 },
3960 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4757 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
39614758 },
39624759
39634760 .@"amdgcn.workitem.id.x" = .{
......@@ -3965,42 +4762,42 @@ pub const Intrinsic = enum {
39654762 .params = &.{
39664763 .{ .kind = .{ .type = .i32 } },
39674764 },
3968 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4765 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
39694766 },
39704767 .@"amdgcn.workitem.id.y" = .{
39714768 .ret_len = 1,
39724769 .params = &.{
39734770 .{ .kind = .{ .type = .i32 } },
39744771 },
3975 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4772 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
39764773 },
39774774 .@"amdgcn.workitem.id.z" = .{
39784775 .ret_len = 1,
39794776 .params = &.{
39804777 .{ .kind = .{ .type = .i32 } },
39814778 },
3982 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4779 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
39834780 },
39844781 .@"amdgcn.workgroup.id.x" = .{
39854782 .ret_len = 1,
39864783 .params = &.{
39874784 .{ .kind = .{ .type = .i32 } },
39884785 },
3989 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4786 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
39904787 },
39914788 .@"amdgcn.workgroup.id.y" = .{
39924789 .ret_len = 1,
39934790 .params = &.{
39944791 .{ .kind = .{ .type = .i32 } },
39954792 },
3996 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4793 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
39974794 },
39984795 .@"amdgcn.workgroup.id.z" = .{
39994796 .ret_len = 1,
40004797 .params = &.{
40014798 .{ .kind = .{ .type = .i32 } },
40024799 },
4003 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4800 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
40044801 },
40054802 .@"amdgcn.dispatch.ptr" = .{
40064803 .ret_len = 1,
......@@ -4010,7 +4807,7 @@ pub const Intrinsic = enum {
40104807 .attrs = &.{.{ .@"align" = .wrap(.fromByteUnits(4)) }},
40114808 },
40124809 },
4013 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4810 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
40144811 },
40154812
40164813 .@"nvvm.read.ptx.sreg.tid.x" = .{
......@@ -4085,7 +4882,7 @@ pub const Intrinsic = enum {
40854882 .{ .kind = .overloaded },
40864883 .{ .kind = .{ .type = .i32 } },
40874884 },
4088 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4885 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
40894886 },
40904887 .@"wasm.memory.grow" = .{
40914888 .ret_len = 1,
......@@ -4166,6 +4963,10 @@ pub const Function = struct {
41664963 self.ptr(builder).attributes = new_function_attributes;
41674964 }
41684965
4966 pub fn getAttributes(self: Index, builder: *Builder) FunctionAttributes {
4967 return self.ptr(builder).attributes;
4968 }
4969
41694970 pub fn setSection(self: Index, section: String, builder: *Builder) void {
41704971 self.ptr(builder).section = section;
41714972 }
......@@ -4487,7 +5288,7 @@ pub const Function = struct {
44875288 }
44885289
44895290 pub fn toValue(self: Instruction.Index) Value {
4490 return @fromBackingInt(@intCast(@backingInt(self)));
5291 return @fromBackingInt(@backingInt(self));
44915292 }
44925293
44935294 pub fn isTerminatorWip(self: Instruction.Index, wip: *const WipFunction) bool {
......@@ -4679,7 +5480,7 @@ pub const Function = struct {
46795480 .changeScalarAssumeCapacity(.i1, wip.builder),
46805481 .fneg,
46815482 .@"fneg fast",
4682 => @as(Value, @fromBackingInt(@intCast(instruction.data))).typeOfWip(wip),
5483 => @as(Value, @fromBackingInt(instruction.data)).typeOfWip(wip),
46835484 .getelementptr,
46845485 .@"getelementptr inbounds",
46855486 => {
......@@ -4871,7 +5672,7 @@ pub const Function = struct {
48715672 .changeScalarAssumeCapacity(.i1, builder),
48725673 .fneg,
48735674 .@"fneg fast",
4874 => @as(Value, @fromBackingInt(@intCast(instruction.data))).typeOf(function_index, builder),
5675 => @as(Value, @fromBackingInt(instruction.data)).typeOf(function_index, builder),
48755676 .getelementptr,
48765677 .@"getelementptr inbounds",
48775678 => {
......@@ -4963,7 +5764,7 @@ pub const Function = struct {
49635764
49645765 pub fn fromMetadata(metadata: Metadata) Weights {
49655766 assert(metadata.kind == .node);
4966 return @fromBackingInt(@intCast(metadata.index));
5767 return @fromBackingInt(metadata.index);
49675768 }
49685769
49695770 pub fn toMetadata(weights: Weights) Metadata {
......@@ -5156,7 +5957,7 @@ pub const Function = struct {
51565957 assert(argument.tag == .arg);
51575958 assert(argument.data == index);
51585959
5159 const argument_index: Instruction.Index = @fromBackingInt(@intCast(index));
5960 const argument_index: Instruction.Index = @fromBackingInt(index);
51605961 return argument_index.toValue();
51615962 }
51625963
......@@ -5202,7 +6003,7 @@ pub const Function = struct {
52026003 Type,
52036004 Value,
52046005 Instruction.BrCond.Weights,
5205 => @fromBackingInt(@intCast(value)),
6006 => @fromBackingInt(value),
52066007 MemoryAccessInfo,
52076008 Instruction.Alloca.Info,
52086009 Instruction.Call.Info,
......@@ -5327,7 +6128,7 @@ pub const WipFunction = struct {
53276128 assert(argument.tag == .arg);
53286129 assert(argument.data == index);
53296130
5330 const argument_index: Instruction.Index = @fromBackingInt(@intCast(index));
6131 const argument_index: Instruction.Index = @fromBackingInt(index);
53316132 return argument_index.toValue();
53326133 }
53336134
......@@ -5722,7 +6523,7 @@ pub const WipFunction = struct {
57226523 alignment: Alignment,
57236524 name: []const u8,
57246525 ) Allocator.Error!Value {
5725 return self.loadAtomic(access_kind, ty, ptr, .system, .none, alignment, name);
6526 return self.loadAtomic(access_kind, ty, ptr, undefined, .none, alignment, name);
57266527 }
57276528
57286529 pub fn loadAtomic(
......@@ -5766,7 +6567,7 @@ pub const WipFunction = struct {
57666567 ptr: Value,
57676568 alignment: Alignment,
57686569 ) Allocator.Error!Instruction.Index {
5769 return self.storeAtomic(kind, val, ptr, .system, .none, alignment);
6570 return self.storeAtomic(kind, val, ptr, undefined, .none, alignment);
57706571 }
57716572
57726573 pub fn storeAtomic(
......@@ -6414,24 +7215,24 @@ pub const WipFunction = struct {
64147215 errdefer function.instructions.shrinkRetainingCapacity(0);
64157216
64167217 {
6417 var final_instruction_index: Instruction.Index = @fromBackingInt(@intCast(0));
7218 var final_instruction_index: Instruction.Index = @fromBackingInt(0);
64187219 for (0..params_len) |param_index| {
64197220 instructions.items[param_index] = final_instruction_index;
6420 final_instruction_index = @fromBackingInt(@intCast(@backingInt(final_instruction_index) + 1));
7221 final_instruction_index = @fromBackingInt(@backingInt(final_instruction_index) + 1);
64217222 }
64227223 for (blocks, self.blocks.items) |*final_block, current_block| {
64237224 assert(current_block.incoming == current_block.branches);
64247225 final_block.instruction = final_instruction_index;
6425 final_instruction_index = @fromBackingInt(@intCast(@backingInt(final_instruction_index) + 1));
7226 final_instruction_index = @fromBackingInt(@backingInt(final_instruction_index) + 1);
64267227 for (current_block.instructions.items) |instruction| {
64277228 instructions.items[@backingInt(instruction)] = final_instruction_index;
6428 final_instruction_index = @fromBackingInt(@intCast(@backingInt(final_instruction_index) + 1));
7229 final_instruction_index = @fromBackingInt(@backingInt(final_instruction_index) + 1);
64297230 }
64307231 }
64317232 }
64327233
64337234 var wip_name: struct {
6434 next_name: String = @fromBackingInt(@intCast(0)),
7235 next_name: String = @fromBackingInt(0),
64357236 next_unique_name: std.AutoHashMap(String, String),
64367237 builder: *Builder,
64377238
......@@ -6440,19 +7241,19 @@ pub const WipFunction = struct {
64407241 .none => return .none,
64417242 .empty => {
64427243 assert(wip_name.next_name != .none);
6443 defer wip_name.next_name = @fromBackingInt(@intCast(@backingInt(wip_name.next_name) + 1));
7244 defer wip_name.next_name = @fromBackingInt(@backingInt(wip_name.next_name) + 1);
64447245 return wip_name.next_name;
64457246 },
64467247 _ => {
64477248 assert(!name.isAnon());
64487249 const gop = try wip_name.next_unique_name.getOrPut(name);
64497250 if (!gop.found_existing) {
6450 gop.value_ptr.* = @fromBackingInt(@intCast(0));
7251 gop.value_ptr.* = @fromBackingInt(0);
64517252 return name;
64527253 }
64537254
64547255 while (true) {
6455 gop.value_ptr.* = @fromBackingInt(@intCast(@backingInt(gop.value_ptr.*) + 1));
7256 gop.value_ptr.* = @fromBackingInt(@backingInt(gop.value_ptr.*) + 1);
64567257 const unique_name = try wip_name.builder.fmt("{f}{s}{f}", .{
64577258 name.fmtRaw(wip_name.builder),
64587259 sep,
......@@ -6460,7 +7261,7 @@ pub const WipFunction = struct {
64607261 });
64617262 const unique_gop = try wip_name.next_unique_name.getOrPut(unique_name);
64627263 if (!unique_gop.found_existing) {
6463 unique_gop.value_ptr.* = @fromBackingInt(@intCast(0));
7264 unique_gop.value_ptr.* = @fromBackingInt(0);
64647265 return unique_name;
64657266 }
64667267 }
......@@ -6702,7 +7503,7 @@ pub const WipFunction = struct {
67027503 .fneg,
67037504 .@"fneg fast",
67047505 .ret,
6705 => instruction.data = @backingInt(instructions.map(@fromBackingInt(@intCast(instruction.data)))),
7506 => instruction.data = @backingInt(instructions.map(@fromBackingInt(instruction.data))),
67067507 .getelementptr,
67077508 .@"getelementptr inbounds",
67087509 => {
......@@ -7079,7 +7880,7 @@ pub const WipFunction = struct {
70797880 Type,
70807881 Value,
70817882 Instruction.BrCond.Weights,
7082 => @fromBackingInt(@intCast(value)),
7883 => @fromBackingInt(value),
70837884 MemoryAccessInfo,
70847885 Instruction.Alloca.Info,
70857886 Instruction.Call.Info,
......@@ -7268,7 +8069,7 @@ pub const Constant = enum(u32) {
72688069 no_init = (1 << 30) - 1,
72698070 _,
72708071
7271 const first_global: Constant = @fromBackingInt(@intCast(1 << 29));
8072 const first_global: Constant = @fromBackingInt(1 << 29);
72728073
72738074 pub const Tag = enum(u7) {
72748075 positive_integer,
......@@ -7405,7 +8206,18 @@ pub const Constant = enum(u32) {
74058206 val: Constant,
74068207 type: Type,
74078208
7408 pub const Signedness = enum { unsigned, signed, unneeded };
8209 pub const Signedness = enum {
8210 unsigned,
8211 signed,
8212 unneeded,
8213
8214 pub fn fromStdLang(signedness: std.lang.Signedness) Signedness {
8215 return switch (signedness) {
8216 .unsigned => .unsigned,
8217 .signed => .signed,
8218 };
8219 }
8220 };
74098221 };
74108222
74118223 pub const GetElementPtr = struct {
......@@ -7444,11 +8256,11 @@ pub const Constant = enum(u32) {
74448256 return if (@backingInt(self) < @backingInt(first_global))
74458257 .{ .constant = @intCast(@backingInt(self)) }
74468258 else
7447 .{ .global = @fromBackingInt(@intCast(@backingInt(self) - @backingInt(first_global))) };
8259 .{ .global = @fromBackingInt(@backingInt(self) - @backingInt(first_global)) };
74488260 }
74498261
74508262 pub fn toValue(self: Constant) Value {
7451 return @fromBackingInt(@intCast(Value.first_constant + @backingInt(self)));
8263 return @fromBackingInt(Value.first_constant + @backingInt(self));
74528264 }
74538265
74548266 pub fn typeOf(self: Constant, builder: *Builder) Type {
......@@ -7474,7 +8286,7 @@ pub const Constant = enum(u32) {
74748286 .zeroinitializer,
74758287 .undef,
74768288 .poison,
7477 => @fromBackingInt(@intCast(item.data)),
8289 => @fromBackingInt(item.data),
74788290 .structure,
74798291 .packed_structure,
74808292 .array,
......@@ -7482,7 +8294,7 @@ pub const Constant = enum(u32) {
74828294 => builder.constantExtraData(Aggregate, item.data).type,
74838295 .splat => builder.constantExtraData(Splat, item.data).type,
74848296 .string => builder.arrayTypeAssumeCapacity(
7485 @as(String, @fromBackingInt(@intCast(item.data))).slice(builder).?.len,
8297 @as(String, @fromBackingInt(item.data)).slice(builder).?.len,
74868298 .i8,
74878299 ),
74888300 .blockaddress => builder.ptrTypeAssumeCapacity(
......@@ -7491,7 +8303,7 @@ pub const Constant = enum(u32) {
74918303 ),
74928304 .dso_local_equivalent,
74938305 .no_cfi,
7494 => builder.ptrTypeAssumeCapacity(@as(Function.Index, @fromBackingInt(@intCast(item.data)))
8306 => builder.ptrTypeAssumeCapacity(@as(Function.Index, @fromBackingInt(item.data))
74958307 .ptrConst(builder).global.ptrConst(builder).addr_space),
74968308 .trunc,
74978309 .ptrtoint,
......@@ -7802,7 +8614,7 @@ pub const Constant = enum(u32) {
78028614 try w.writeByte('>');
78038615 },
78048616 .string => try w.print("c{f}", .{
7805 @as(String, @fromBackingInt(@intCast(item.data))).fmtQ(data.builder),
8617 @as(String, @fromBackingInt(item.data)).fmtQ(data.builder),
78068618 }),
78078619 .blockaddress => |tag| {
78088620 const extra = data.builder.constantExtraData(BlockAddress, item.data);
......@@ -7816,7 +8628,7 @@ pub const Constant = enum(u32) {
78168628 .dso_local_equivalent,
78178629 .no_cfi,
78188630 => |tag| {
7819 const function: Function.Index = @fromBackingInt(@intCast(item.data));
8631 const function: Function.Index = @fromBackingInt(item.data);
78208632 try w.print("{s} {f}", .{
78218633 @tagName(tag),
78228634 function.ptrConst(data.builder).global.fmt(data.builder),
......@@ -7920,9 +8732,9 @@ pub const Value = enum(u32) {
79208732 metadata: Metadata,
79218733 } {
79228734 return if (@backingInt(self) < first_constant)
7923 .{ .instruction = @fromBackingInt(@intCast(@backingInt(self))) }
8735 .{ .instruction = @fromBackingInt(@backingInt(self)) }
79248736 else if (@backingInt(self) < first_metadata)
7925 .{ .constant = @fromBackingInt(@intCast(@backingInt(self) - first_constant)) }
8737 .{ .constant = @fromBackingInt(@backingInt(self) - first_constant) }
79268738 else
79278739 .{ .metadata = @bitCast(@backingInt(self) - first_metadata) };
79288740 }
......@@ -8016,7 +8828,7 @@ pub const Metadata = packed struct(u32) {
80168828 return .{ .index = metadata.index, .kind = metadata.kind, .is_none = false };
80178829 }
80188830 pub fn toValue(metadata: Metadata) Value {
8019 return @fromBackingInt(@intCast(Value.first_metadata + @as(u32, @bitCast(metadata))));
8831 return @fromBackingInt(Value.first_metadata + @as(u32, @bitCast(metadata)));
80208832 }
80218833
80228834 pub const String = enum(u32) {
......@@ -8032,7 +8844,7 @@ pub const Metadata = packed struct(u32) {
80328844 pub fn unwrap(metadata: Metadata.String.Optional) ?Metadata.String {
80338845 return switch (metadata) {
80348846 .none => null,
8035 else => @fromBackingInt(@intCast(@backingInt(metadata))),
8847 else => @fromBackingInt(@backingInt(metadata)),
80368848 };
80378849 }
80388850 pub fn toMetadata(metadata: Metadata.String.Optional) Metadata.Optional {
......@@ -8040,7 +8852,7 @@ pub const Metadata = packed struct(u32) {
80408852 }
80418853 };
80428854 pub fn toOptional(metadata: Metadata.String) Metadata.String.Optional {
8043 return @fromBackingInt(@intCast(@backingInt(metadata)));
8855 return @fromBackingInt(@backingInt(metadata));
80448856 }
80458857 pub fn toMetadata(metadata: Metadata.String) Metadata {
80468858 return .{ .index = @intCast(@backingInt(metadata)), .kind = .string };
......@@ -8077,7 +8889,7 @@ pub const Metadata = packed struct(u32) {
80778889 };
80788890 pub fn toString(metadata: Metadata) Metadata.String {
80798891 assert(metadata.kind == .string);
8080 return @fromBackingInt(@intCast(metadata.index));
8892 return @fromBackingInt(metadata.index);
80818893 }
80828894
80838895 pub const Tag = enum(u6) {
......@@ -8542,7 +9354,7 @@ pub const Metadata = packed struct(u32) {
85429354 try w.writeByte(')');
85439355 },
85449356 .constant => try Constant.format(.{
8545 .constant = @fromBackingInt(@intCast(node_item.data)),
9357 .constant = @fromBackingInt(node_item.data),
85469358 .builder = builder,
85479359 .flags = data.specialized orelse .{},
85489360 }, w),
......@@ -8705,7 +9517,7 @@ pub const Metadata = packed struct(u32) {
87059517 nodes: anytype,
87069518 w: *Writer,
87079519 ) !void {
8708 const names = comptime std.meta.fieldNames(@TypeOf(nodes));
9520 const names = @typeInfo(@TypeOf(nodes)).@"struct".field_names;
87099521
87109522 comptime var fmt_str: []const u8 = "{[distinct]s}{[node]s}(";
87119523 inline for (names) |name| fmt_str = fmt_str ++ "{[" ++ name ++ "]f}";
......@@ -8735,7 +9547,14 @@ pub fn init(options: Options) Allocator.Error!Builder {
87359547 .strip = options.strip,
87369548
87379549 .source_filename = .none,
8738 .data_layout = .none,
9550 .data_layout = .{
9551 .endian = null,
9552 .int_specs = .empty,
9553 .float_specs = .empty,
9554 .vector_specs = .empty,
9555 .pointer_specs = .empty,
9556 .string_repr = .none,
9557 },
87399558 .target_triple = .none,
87409559 .module_asm = .empty,
87419560
......@@ -8744,7 +9563,7 @@ pub fn init(options: Options) Allocator.Error!Builder {
87449563 .string_bytes = .empty,
87459564
87469565 .types = .empty,
8747 .next_unnamed_type = @fromBackingInt(@intCast(0)),
9566 .next_unnamed_type = @fromBackingInt(0),
87489567 .next_unique_type_id = .empty,
87499568 .type_map = .empty,
87509569 .type_items = .empty,
......@@ -8758,7 +9577,7 @@ pub fn init(options: Options) Allocator.Error!Builder {
87589577 .function_attributes_set = .empty,
87599578
87609579 .globals = .empty,
8761 .next_unnamed_global = @fromBackingInt(@intCast(0)),
9580 .next_unnamed_global = @fromBackingInt(0),
87629581 .next_replaced_global = .none,
87639582 .next_unique_global_id = .empty,
87649583 .aliases = .empty,
......@@ -8791,14 +9610,14 @@ pub fn init(options: Options) Allocator.Error!Builder {
87919610 try self.string_indices.append(self.gpa, 0);
87929611 assert(try self.string("") == .empty);
87939612
9613 self.data_layout = try .parseString(try self.string(DataLayout.stringForTarget(options.target)), &self);
9614
87949615 try self.strtab_string_indices.append(self.gpa, 0);
87959616 assert(try self.strtabString("") == .empty);
87969617
87979618 if (options.name.len > 0) self.source_filename = try self.string(options.name);
87989619
8799 if (options.triple.len > 0) {
8800 self.target_triple = try self.string(options.triple);
8801 }
9620 if (options.triple.len > 0) self.target_triple = try self.string(options.triple);
88029621
88039622 {
88049623 const static_len = @typeInfo(Type).@"enum".field_names.len - 1;
......@@ -8815,7 +9634,7 @@ pub fn init(options: Options) Allocator.Error!Builder {
88159634 assert(self.intTypeAssumeCapacity(bits) ==
88169635 @field(Type, std.fmt.comptimePrint("i{d}", .{bits})));
88179636 inline for (.{ 0, 4 }) |addr_space_index| {
8818 const addr_space: AddrSpace = @fromBackingInt(@intCast(addr_space_index));
9637 const addr_space: AddrSpace = @fromBackingInt(addr_space_index);
88199638 assert(self.ptrTypeAssumeCapacity(addr_space) ==
88209639 @field(Type, std.fmt.comptimePrint("ptr{f}", .{addr_space.fmt(" ")})));
88219640 }
......@@ -8891,6 +9710,8 @@ pub fn clearAndFree(self: *Builder) void {
88919710pub fn deinit(self: *Builder) void {
88929711 const gpa = self.gpa;
88939712
9713 self.data_layout.deinit(gpa);
9714
88949715 self.module_asm.deinit(gpa);
88959716
88969717 self.string_map.deinit(gpa);
......@@ -8944,7 +9765,7 @@ pub fn deinit(self: *Builder) void {
89449765
89459766pub fn finishModuleAsm(self: *Builder, aw: *Writer.Allocating) Allocator.Error!void {
89469767 self.module_asm = aw.toArrayList();
8947 if (self.module_asm.getLast()) |last| if (last != '\n')
9768 if (self.module_asm.last()) |last| if (last != '\n')
89489769 try self.module_asm.append(self.gpa, '\n');
89499770}
89509771
......@@ -8990,7 +9811,7 @@ pub fn trailingString(self: *Builder) Allocator.Error!String {
89909811}
89919812
89929813pub fn trailingStringAssumeCapacity(self: *Builder) String {
8993 const start = self.string_indices.getLast().?;
9814 const start = self.string_indices.last().?;
89949815 const bytes: []const u8 = self.string_bytes.items[start..];
89959816 const gop = self.string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self });
89969817 if (gop.found_existing) {
......@@ -9092,17 +9913,17 @@ pub fn attrs(self: *Builder, attributes: []Attribute.Index) Allocator.Error!Attr
90929913 return @backingInt(lhs_kind) < @backingInt(rhs_kind);
90939914 }
90949915 }.lessThan);
9095 return @fromBackingInt(@intCast(try self.attrGeneric(@ptrCast(attributes))));
9916 return @fromBackingInt(try self.attrGeneric(@ptrCast(attributes)));
90969917}
90979918
90989919pub fn fnAttrs(self: *Builder, fn_attributes: []const Attributes) Allocator.Error!FunctionAttributes {
90999920 try self.function_attributes_set.ensureUnusedCapacity(self.gpa, 1);
9100 const function_attributes: FunctionAttributes = @fromBackingInt(@intCast(try self.attrGeneric(@ptrCast(
9101 fn_attributes[0..if (std.mem.lastIndexOfNone(Attributes, fn_attributes, &.{.none})) |last|
9921 const function_attributes: FunctionAttributes = @fromBackingInt(try self.attrGeneric(@ptrCast(
9922 fn_attributes[0..if (std.mem.findLastNone(Attributes, fn_attributes, &.{.none})) |last|
91029923 last + 1
91039924 else
91049925 0],
9105 ))));
9926 )));
91069927
91079928 _ = self.function_attributes_set.getOrPutAssumeCapacity(function_attributes);
91089929 return function_attributes;
......@@ -9121,7 +9942,7 @@ pub fn addGlobalAssumeCapacity(self: *Builder, name: StrtabString, global: Globa
91219942 if (name == .empty) {
91229943 id = self.next_unnamed_global;
91239944 assert(id != self.next_replaced_global);
9124 self.next_unnamed_global = @fromBackingInt(@intCast(@backingInt(id) + 1));
9945 self.next_unnamed_global = @fromBackingInt(@backingInt(id) + 1);
91259946 }
91269947 while (true) {
91279948 const global_gop = self.globals.getOrPutAssumeCapacity(id);
......@@ -9710,17 +10531,17 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
971010531 var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined };
971110532 defer metadata_formatter.map.deinit(self.gpa);
971210533
9713 if (self.source_filename != .none or self.data_layout != .none or self.target_triple != .none) {
10534 if (self.source_filename != .none or self.data_layout.string_repr != .none or self.target_triple != .none) {
971410535 if (need_newline) try w.writeByte('\n') else need_newline = true;
971510536 if (self.source_filename != .none) try w.print(
971610537 \\; ModuleID = '{s}'
971710538 \\source_filename = {f}
971810539 \\
971910540 , .{ self.source_filename.slice(self).?, self.source_filename.fmtQ(self) });
9720 if (self.data_layout != .none) try w.print(
10541 if (self.data_layout.string_repr != .none) try w.print(
972110542 \\target datalayout = {f}
972210543 \\
9723 , .{self.data_layout.fmtQ(self)});
10544 , .{self.data_layout.string_repr.fmtQ(self)});
972410545 if (self.target_triple != .none) try w.print(
972510546 \\target triple = {f}
972610547 \\
......@@ -10058,7 +10879,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
1005810879 continue;
1005910880 },
1006010881 .br => |tag| {
10061 const target: Function.Block.Index = @fromBackingInt(@intCast(instruction.data));
10882 const target: Function.Block.Index = @fromBackingInt(instruction.data);
1006210883 try w.print(" {s} {f}", .{
1006310884 @tagName(tag), target.toInst(&function).fmt(function_index, self, .{ .percent = true }),
1006410885 });
......@@ -10187,7 +11008,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
1018711008 .fneg,
1018811009 .@"fneg fast",
1018911010 => |tag| {
10190 const val: Value = @fromBackingInt(@intCast(instruction.data));
11011 const val: Value = @fromBackingInt(instruction.data);
1019111012 try w.print(" %{f} = {s} {f}", .{
1019211013 instruction_index.name(&function).fmt(self),
1019311014 @tagName(tag),
......@@ -10288,7 +11109,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
1028811109 }
1028911110 },
1029011111 .ret => |tag| {
10291 const val: Value = @fromBackingInt(@intCast(instruction.data));
11112 const val: Value = @fromBackingInt(instruction.data);
1029211113 try w.print(" {s} {f}", .{
1029311114 @tagName(tag),
1029411115 val.fmt(function_index, self, .{ .percent = true }),
......@@ -11020,7 +11841,7 @@ fn opaqueTypeAssumeCapacity(self: *Builder, name: String) Type {
1102011841 if (name == .empty) {
1102111842 id = self.next_unnamed_type;
1102211843 assert(id != .none);
11023 self.next_unnamed_type = @fromBackingInt(@intCast(@backingInt(id) + 1));
11844 self.next_unnamed_type = @fromBackingInt(@backingInt(id) + 1);
1102411845 } else assert(!name.isAnon());
1102511846 while (true) {
1102611847 const type_gop = self.types.getOrPutAssumeCapacity(id);
......@@ -11135,7 +11956,7 @@ fn typeExtraDataTrail(
1113511956 ) |field_name, field_type, value|
1113611957 @field(result, field_name) = switch (field_type) {
1113711958 u32 => value,
11138 String, Type => @fromBackingInt(@intCast(value)),
11959 String, Type => @fromBackingInt(value),
1113911960 else => @compileError("bad field type: " ++ @typeName(field_type)),
1114011961 };
1114111962 return .{
......@@ -11746,7 +12567,7 @@ fn castConstAssumeCapacity(self: *Builder, tag: Constant.Tag, val: Constant, ty:
1174612567 return std.meta.eql(lhs_key.cast, rhs_extra);
1174712568 }
1174812569 };
11749 const data = Key{ .tag = tag, .cast = .{ .val = val, .type = ty } };
12570 const data: Key = .{ .tag = tag, .cast = .{ .val = val, .type = ty } };
1175012571 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
1175112572 if (!gop.found_existing) {
1175212573 gop.key_ptr.* = {};
......@@ -11828,10 +12649,10 @@ fn gepConstAssumeCapacity(
1182812649 std.mem.eql(Constant, lhs_key.indices, rhs_indices);
1182912650 }
1183012651 };
11831 const data = Key{
12652 const data: Key = .{
1183212653 .type = ty,
1183312654 .base = base,
11834 .inrange = if (inrange) |index| @fromBackingInt(@intCast(index)) else .none,
12655 .inrange = if (inrange) |index| @fromBackingInt(index) else .none,
1183512656 .indices = indices,
1183612657 };
1183712658 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
......@@ -11885,7 +12706,7 @@ fn binConstAssumeCapacity(
1188512706 return std.meta.eql(lhs_key.extra, rhs_extra);
1188612707 }
1188712708 };
11888 const data = Key{ .tag = tag, .extra = .{ .lhs = lhs, .rhs = rhs } };
12709 const data: Key = .{ .tag = tag, .extra = .{ .lhs = lhs, .rhs = rhs } };
1188912710 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
1189012711 if (!gop.found_existing) {
1189112712 gop.key_ptr.* = {};
......@@ -11924,8 +12745,8 @@ fn asmConstAssumeCapacity(
1192412745 }
1192512746 };
1192612747
11927 const data = Key{
11928 .tag = @fromBackingInt(@intCast(@backingInt(Constant.Tag.@"asm") + @as(u4, @bitCast(info)))),
12748 const data: Key = .{
12749 .tag = @fromBackingInt(@backingInt(Constant.Tag.@"asm") + @as(u4, @bitCast(info))),
1192912750 .extra = .{ .type = ty, .assembly = assembly, .constraints = constraints },
1193012751 };
1193112752 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
......@@ -12073,7 +12894,7 @@ fn constantExtraDataTrail(
1207312894 ) |field_name, field_type, value|
1207412895 @field(result, field_name) = switch (field_type) {
1207512896 u32 => value,
12076 String, Type, Constant, Function.Index, Function.Block.Index => @fromBackingInt(@intCast(value)),
12897 String, Type, Constant, Function.Index, Function.Block.Index => @fromBackingInt(value),
1207712898 Constant.GetElementPtr.Info => @bitCast(value),
1207812899 else => @compileError("bad field type: " ++ @typeName(field_type)),
1207912900 };
......@@ -12151,7 +12972,7 @@ fn metadataExtraDataTrail(
1215112972 ) |field_name, field_type, value|
1215212973 @field(result, field_name) = switch (field_type) {
1215312974 u32 => value,
12154 Metadata.String, Metadata.String.Optional, Variable.Index, Value => @fromBackingInt(@intCast(value)),
12975 Metadata.String, Metadata.String.Optional, Variable.Index, Value => @fromBackingInt(value),
1215512976 Metadata, Metadata.Optional, Metadata.DIFlags => @bitCast(value),
1215612977 else => @compileError("bad field type: " ++ @typeName(field_type)),
1215712978 };
......@@ -12221,7 +13042,7 @@ pub fn trailingMetadataString(self: *Builder) Allocator.Error!Metadata.String {
1222113042}
1222213043
1222313044pub fn trailingMetadataStringAssumeCapacity(self: *Builder) Metadata.String {
12224 const start = self.metadata_string_indices.getLast().?;
13045 const start = self.metadata_string_indices.last().?;
1222513046 const bytes: []const u8 = self.metadata_string_bytes.items[start..];
1222613047 assert(bytes.len > 0);
1222713048 const gop = self.metadata_string_map.getOrPutAssumeCapacityAdapted(bytes, Metadata.String.Adapter{ .builder = self });
......@@ -12663,7 +13484,7 @@ fn metadataSimpleAssumeCapacity(self: *Builder, tag: Metadata.Tag, value: anytyp
1266313484 builder: *const Builder,
1266413485 pub fn hash(_: @This(), key: Key) u32 {
1266513486 var hasher = std.hash.Wyhash.init(std.hash.int(@backingInt(key.tag)));
12666 inline for (comptime std.meta.fieldNames(@TypeOf(value))) |field_name| {
13487 inline for (@typeInfo(@TypeOf(value)).@"struct".field_names) |field_name| {
1266713488 hasher.update(std.mem.asBytes(&@field(key.value, field_name)));
1266813489 }
1266913490 return @truncate(hasher.final());
......@@ -12759,8 +13580,8 @@ fn debugSubprogramAssumeCapacity(
1275913580 compile_unit: ?Metadata,
1276013581) Metadata {
1276113582 assert(!self.strip);
12762 const tag: Metadata.Tag = @fromBackingInt(@intCast(@backingInt(Metadata.Tag.subprogram) +
12763 @as(u3, @truncate(@as(u32, @bitCast(options.sp_flags)) >> 2))));
13583 const tag: Metadata.Tag = @fromBackingInt(@backingInt(Metadata.Tag.subprogram) +
13584 @as(u3, @truncate(@as(u32, @bitCast(options.sp_flags)) >> 2)));
1276413585 return self.metadataDistinctAssumeCapacity(tag, Metadata.Subprogram{
1276513586 .file = .wrap(file),
1276613587 .name = .wrap(name),
......@@ -13345,7 +14166,7 @@ fn metadataConstantAssumeCapacity(self: *Builder, constant: Constant) Metadata {
1334514166
1334614167 pub fn eql(ctx: @This(), lhs_key: Constant, _: void, rhs_index: usize) bool {
1334714168 if (Metadata.Tag.constant != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false;
13348 const rhs_data: Constant = @fromBackingInt(@intCast(ctx.builder.metadata_items.items(.data)[rhs_index]));
14169 const rhs_data: Constant = @fromBackingInt(ctx.builder.metadata_items.items(.data)[rhs_index]);
1334914170 return rhs_data == lhs_key;
1335014171 }
1335114172 };
......@@ -13418,7 +14239,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1341814239 });
1341914240 }
1342014241
13421 if (self.data_layout.slice(self)) |data_layout| {
14242 if (self.data_layout.string_repr.slice(self)) |data_layout| {
1342214243 try module_block.writeAbbrev(ModuleBlock.String{
1342314244 .code = 3,
1342414245 .string = data_layout,
......@@ -13577,6 +14398,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1357714398 switch (attr_index.toAttribute(self)) {
1357814399 .zeroext,
1357914400 .signext,
14401 .noext,
1358014402 .inreg,
1358114403 .@"noalias",
1358214404 .nocapture,
......@@ -13594,11 +14416,13 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1359414416 .readnone,
1359514417 .readonly,
1359614418 .writeonly,
14419 .writable,
14420 .dead_on_unwind,
1359714421 .alwaysinline,
1359814422 .builtin,
1359914423 .cold,
1360014424 .convergent,
13601 .disable_sanitizer_information,
14425 .disable_sanitizer_instrumentation,
1360214426 .fn_ret_thunk_extern,
1360314427 .hot,
1360414428 .inlinehint,
......@@ -13607,6 +14431,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1360714431 .naked,
1360814432 .nobuiltin,
1360914433 .nocallback,
14434 .nodivergencesource,
1361014435 .noduplicate,
1361114436 .noimplicitfloat,
1361214437 .@"noinline",
......@@ -13623,6 +14448,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1362314448 .nosanitize_bounds,
1362414449 .nosanitize_coverage,
1362514450 .null_pointer_is_valid,
14451 .optdebug,
1362614452 .optforfuzzing,
1362714453 .optnone,
1362814454 .optsize,
......@@ -13633,18 +14459,21 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1363314459 .sanitize_thread,
1363414460 .sanitize_hwaddress,
1363514461 .sanitize_memtag,
14462 .sanitize_realtime,
14463 .sanitize_realtime_blocking,
14464 .sanitize_alloc_token,
1363614465 .speculative_load_hardening,
1363714466 .speculatable,
1363814467 .ssp,
1363914468 .sspstrong,
1364014469 .sspreq,
1364114470 .strictfp,
14471 .denormal_fpenv,
1364214472 .nocf_check,
1364314473 .shadowcallstack,
1364414474 .mustprogress,
13645 .no_sanitize_address,
13646 .no_sanitize_hwaddress,
13647 .sanitize_address_dyninit,
14475 .nooutline,
14476 .nocreateundeforpoison,
1364814477 => {
1364914478 try record.ensureUnusedCapacity(self.gpa, 2);
1365014479 record.appendAssumeCapacity(0);
......@@ -13670,6 +14499,12 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1367014499 record.appendAssumeCapacity(@backingInt(kind));
1367114500 record.appendAssumeCapacity(alignment.resolve(self).toByteUnits() orelse 0);
1367214501 },
14502 .captures => |captures| {
14503 try record.ensureUnusedCapacity(self.gpa, 3);
14504 record.appendAssumeCapacity(1);
14505 record.appendAssumeCapacity(@backingInt(kind));
14506 record.appendAssumeCapacity(@as(u32, @bitCast(captures)));
14507 },
1367314508 .dereferenceable,
1367414509 .dereferenceable_or_null,
1367514510 => |size| {
......@@ -13684,6 +14519,9 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1368414519 record.appendAssumeCapacity(@backingInt(kind));
1368514520 record.appendAssumeCapacity(@as(u32, @bitCast(fpclass)));
1368614521 },
14522 .initializes => @panic("TODO"),
14523 .dead_on_return => @panic("TODO"),
14524 .range => @panic("TODO"),
1368714525 .allockind => |allockind| {
1368814526 try record.ensureUnusedCapacity(self.gpa, 3);
1368914527 record.appendAssumeCapacity(1);
......@@ -13955,8 +14793,11 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1395514793 }
1395614794
1395714795 const strtab = alias.global.strtab(self);
13958
1395914796 const global = alias.global.ptrConst(self);
14797
14798 // LLVM requires the types to match
14799 assert(global.addr_space == alias.aliasee.typeOf(self).pointerAddrSpace(self));
14800
1396014801 try module_block.writeAbbrev(ModuleBlock.Alias{
1396114802 .strtab_offset = strtab.offset,
1396214803 .strtab_size = strtab.size,
......@@ -14096,7 +14937,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1409614937 }
1409714938 },
1409814939 .string => {
14099 const str: String = @fromBackingInt(@intCast(data));
14940 const str: String = @fromBackingInt(data);
1410014941 if (str == .none) {
1410114942 try constants_block.writeAbbrev(ConstantsBlock.Null{});
1410214943 } else {
......@@ -14223,7 +15064,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1422315064 .dso_local_equivalent,
1422415065 .no_cfi,
1422515066 => |tag| {
14226 const function: Function.Index = @fromBackingInt(@intCast(data));
15067 const function: Function.Index = @fromBackingInt(data);
1422715068 try constants_block.writeAbbrev(ConstantsBlock.DsoLocalEquivalentOrNoCfi{
1422815069 .code = switch (tag) {
1422915070 .dso_local_equivalent => .DSO_LOCAL_EQUIVALENT,
......@@ -14606,7 +15447,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1460615447 }, metadata_adapter);
1460715448 },
1460815449 .constant => {
14609 const constant: Constant = @fromBackingInt(@intCast(data));
15450 const constant: Constant = @fromBackingInt(data);
1461015451 try metadata_block.writeAbbrevAdapted(MetadataBlock.Constant{
1461115452 .ty = constant.typeOf(self),
1461215453 .constant = constant,
......@@ -14775,7 +15616,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1477515616 var adapter: FunctionAdapter = .{
1477615617 .metadata_adapter = metadata_adapter,
1477715618 .func = &func,
14778 .instruction_index = @fromBackingInt(@intCast(0)),
15619 .instruction_index = @fromBackingInt(0),
1477915620 };
1478015621
1478115622 // Emit function level metadata block
......@@ -14786,7 +15627,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1478615627 for (func.debug_values) |value| {
1478715628 try metadata_block.writeAbbrev(MetadataBlock.Value{
1478815629 .ty = value.typeOf(@fromBackingInt(@intCast(func_index)), self),
14789 .value = @fromBackingInt(@intCast(adapter.getValueIndex(value.toValue()))),
15630 .value = @fromBackingInt(adapter.getValueIndex(value.toValue())),
1479015631 });
1479115632 }
1479215633
......@@ -15068,10 +15909,10 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1506815909 });
1506915910 },
1507015911 .fneg => try function_block.writeAbbrev(FunctionBlock.FNeg{
15071 .val = adapter.getOffsetValueIndex(@fromBackingInt(@intCast(data))),
15912 .val = adapter.getOffsetValueIndex(@fromBackingInt(data)),
1507215913 }),
1507315914 .@"fneg fast" => try function_block.writeAbbrev(FunctionBlock.FNegFast{
15074 .val = adapter.getOffsetValueIndex(@fromBackingInt(@intCast(data))),
15915 .val = adapter.getOffsetValueIndex(@fromBackingInt(data)),
1507515916 .fast_math = FastMath.fast,
1507615917 }),
1507715918 .extractvalue => {
......@@ -15271,7 +16112,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1527116112 try function_block.writeUnabbrev(16, record.items);
1527216113 },
1527316114 .ret => try function_block.writeAbbrev(FunctionBlock.Ret{
15274 .val = adapter.getOffsetValueIndex(@fromBackingInt(@intCast(data))),
16115 .val = adapter.getOffsetValueIndex(@fromBackingInt(data)),
1527516116 }),
1527616117 .@"ret void" => try function_block.writeAbbrev(FunctionBlock.RetVoid{}),
1527716118 .atomicrmw => {
lib/std/zig/llvm/bitcode_writer.zig+1-1
......@@ -246,7 +246,7 @@ pub fn BitcodeWriter(comptime types: []const type) type {
246246
247247 try self.bitcode.writeBits(comptime abbrevId(Abbrev), abbrev_len);
248248
249 const field_names = comptime std.meta.fieldNames(Abbrev);
249 const field_names = @typeInfo(Abbrev).@"struct".field_names;
250250
251251 // This abbreviation might only contain literals
252252 if (field_names.len == 0) return;
lib/std/zig/system.zig+9-9
......@@ -597,23 +597,23 @@ fn abiAndDynamicLinkerFromFile(
597597 .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch),
598598 .dynamic_linker = query.dynamic_linker orelse .none,
599599 };
600 var rpath_offset: ?u64 = null; // Found inside PT_DYNAMIC
600 var rpath_offset: ?u64 = null; // Found inside PT.DYNAMIC
601601 const look_for_ld = query.dynamic_linker == null;
602602
603603 var got_dyn_section: bool = false;
604604 {
605605 var it = header.iterateProgramHeaders(file_reader);
606 while (try it.next()) |phdr| switch (phdr.p_type) {
607 elf.PT_INTERP => {
606 while (try it.next()) |phdr| switch (phdr.type) {
607 .INTERP => {
608608 got_dyn_section = true;
609609
610610 if (look_for_ld) {
611 const p_filesz = phdr.p_filesz;
611 const p_filesz = phdr.filesz;
612612 if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong;
613613 const filesz: usize = @intCast(p_filesz);
614 try file_reader.seekTo(phdr.p_offset);
614 try file_reader.seekTo(phdr.offset);
615615 try file_reader.interface.readSliceAll(result.dynamic_linker.buffer[0..filesz]);
616 // PT_INTERP includes a null byte in filesz.
616 // PT.INTERP includes a null byte in filesz.
617617 const len = filesz - 1;
618618 // dynamic_linker.max_byte is "max", not "len".
619619 // We know it will fit in u8 because we check against dynamic_linker.buffer.len above.
......@@ -631,11 +631,11 @@ fn abiAndDynamicLinkerFromFile(
631631 }
632632 },
633633 // We only need this for detecting glibc version.
634 elf.PT_DYNAMIC => {
634 .DYNAMIC => {
635635 got_dyn_section = true;
636636
637637 if (builtin.target.os.tag == .linux and result.isGnuLibC() and query.glibc_version == null) {
638 var dyn_it = header.iterateDynamicSection(file_reader, phdr.p_offset, phdr.p_filesz);
638 var dyn_it = header.iterateDynamicSection(file_reader, phdr.offset, phdr.filesz);
639639 while (try dyn_it.next()) |dyn| {
640640 if (dyn.d_tag == elf.DT_RUNPATH) {
641641 rpath_offset = dyn.d_val;
......@@ -973,7 +973,7 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ
973973 // relying on `builtin.target`.
974974 const all_abis = comptime blk: {
975975 assert(@backingInt(Target.Abi.none) == 0);
976 const field_names = std.meta.fieldNames(Target.Abi)[1..];
976 const field_names = @typeInfo(Target.Abi).@"enum".field_names[1..];
977977 var array: [field_names.len]Target.Abi = undefined;
978978 for (field_names, 0..) |field_name, i| {
979979 array[i] = @field(Target.Abi, field_name);
lib/std/zig/target.zig+25-25
......@@ -46,6 +46,8 @@ pub const available_libcs = [_]ArchOsAbi{
4646 .{ .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" },
4747 .{ .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" },
4848 .{ .arch = .hexagon, .os = .linux, .abi = .musl, .os_ver = .{ .major = 3, .minor = 2, .patch = 102 } },
49 .{ .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" },
50 .{ .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" },
4951 .{ .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" },
5052 .{ .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" },
5153 .{ .arch = .loongarch64, .os = .linux, .abi = .musl, .os_ver = .{ .major = 5, .minor = 19, .patch = 0 } },
......@@ -499,34 +501,32 @@ pub fn intByteSize(target: *const std.Target, bits: u16) u16 {
499501}
500502
501503pub fn intAlignment(target: *const std.Target, bits: u16) u16 {
502 return switch (target.cpu.arch) {
503 .x86 => switch (bits) {
504 0...8 => 1,
505 9...16 => 2,
506 17...32 => 4,
507 33...64 => switch (target.os.tag) {
508 .uefi, .windows => 8,
509 else => 4,
510 },
511 else => 16,
512 },
513 .x86_64 => switch (bits) {
514 0...8 => 1,
515 9...16 => 2,
516 17...32 => 4,
517 33...64 => 8,
518 else => 16,
519 },
520 else => switch (bits) {
521 0 => 1,
522 else => @min(
523 std.math.ceilPowerOfTwoPromote(u16, @intCast((@as(u17, bits) + 7) / 8)),
524 target.cMaxIntAlignment(),
525 ),
526 },
504 return switch (bits) {
505 0 => 1,
506 else => @min(
507 std.math.ceilPowerOfTwoPromote(u16, @intCast((@as(u17, bits) + 7) / 8)),
508 target.cMaxIntAlignment(),
509 ),
527510 };
528511}
529512
513pub fn compilerRtFloatAbi(target: *const std.Target, bits: u16) std.Target.Abi.Float {
514 if (target.cpu.has(.x86, .soft_float)) return .soft;
515 // Marks targets where clang does not even provide a usable C type.
516 const no_c_type_available = .soft;
517 switch (bits) {
518 else => unreachable,
519 16 => if (target.cpu.arch.isMIPS() or target.cpu.arch.isPowerPC()) return no_c_type_available,
520 32, 64 => {},
521 80 => if (target.cTypeBitSize(.longdouble) != 80) return no_c_type_available,
522 128 => {
523 if (target.cpu.arch.isX86()) return .hard; // if (target.abi == .msvc) __m128i else __float128
524 if (target.cTypeBitSize(.longdouble) != 128) return no_c_type_available;
525 },
526 }
527 return .hard;
528}
529
530530const std = @import("std");
531531const assert = std.debug.assert;
532532const Allocator = std.mem.Allocator;
lib/std/zip.zig+1-1
......@@ -109,7 +109,7 @@ pub const EndRecord = extern struct {
109109
110110 /// TODO audit this logic
111111 pub fn findBuffer(buffer: []const u8) FindBufferError!EndRecord {
112 const pos = std.mem.lastIndexOf(u8, buffer, &end_record_sig) orelse return error.ZipNoEndRecord;
112 const pos = std.mem.findLast(u8, buffer, &end_record_sig) orelse return error.ZipNoEndRecord;
113113 if (pos + @sizeOf(EndRecord) > buffer.len) return error.EndOfStream;
114114 const record_ptr: *EndRecord = @ptrCast(buffer[pos..][0..@sizeOf(EndRecord)]);
115115 var record = record_ptr.*;
lib/std/zon.zig+41
......@@ -37,10 +37,51 @@
3737//! ZON does not have syntax for pointers, but the parsers will allocate as needed to match the
3838//! given Zig types. Similarly, the serializer will traverse pointers.
3939
40const std = @import("std");
41
4042pub const parse = @import("zon/parse.zig");
4143pub const stringify = @import("zon/stringify.zig");
4244pub const Serializer = @import("zon/Serializer.zig");
4345
46/// Returns a formatter that formats the given value using stringify.
47pub fn fmt(value: anytype, options: stringify.SerializeOptions) Formatter(@TypeOf(value)) {
48 return Formatter(@TypeOf(value)){ .value = value, .options = options };
49}
50
51test fmt {
52 const expectFmt = std.testing.expectFmt;
53 try expectFmt("123", "{f}", .{fmt(@as(u32, 123), .{})});
54 try expectFmt(
55 \\.{
56 \\ .num = 927,
57 \\ .msg = "hello",
58 \\ .sub = .{ .mybool = true },
59 \\}
60 , "{f}", .{fmt(struct {
61 num: u32,
62 msg: []const u8,
63 sub: struct {
64 mybool: bool,
65 },
66 }{
67 .num = 927,
68 .msg = "hello",
69 .sub = .{ .mybool = true },
70 }, .{})});
71}
72
73/// Formats the given value using stringify.
74pub fn Formatter(comptime T: type) type {
75 return struct {
76 value: T,
77 options: stringify.SerializeOptions,
78
79 pub fn format(self: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void {
80 try stringify.serialize(self.value, self.options, writer);
81 }
82 };
83}
84
4485test {
4586 _ = parse;
4687 _ = stringify;
lib/std/zon/parse.zig+1-6
......@@ -9,7 +9,6 @@
99//! For lower level control over parsing, see `std.zig.Zoir`.
1010
1111const std = @import("std");
12const builtin = @import("builtin");
1312const Allocator = std.mem.Allocator;
1413const Ast = std.zig.Ast;
1514const Zoir = std.zig.Zoir;
......@@ -1868,8 +1867,6 @@ test "std.zon tuples" {
18681867
18691868// Test sizes 0 to 3 since small sizes get parsed differently
18701869test "std.zon arrays and slices" {
1871 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/20881
1872
18731870 const gpa = std.testing.allocator;
18741871
18751872 // Literals
......@@ -2802,8 +2799,6 @@ test "std.zon negative char" {
28022799}
28032800
28042801test "std.zon parse float" {
2805 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
2806
28072802 const gpa = std.testing.allocator;
28082803
28092804 // Test decimals
......@@ -3135,7 +3130,7 @@ test "std.zon free on error" {
31353130}
31363131
31373132test "std.zon vector" {
3138 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/15330
3133 const builtin = @import("builtin");
31393134 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .s390x) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/25957
31403135
31413136 const gpa = std.testing.allocator;
lib/std/zon/stringify.zig-3
......@@ -1151,9 +1151,6 @@ test "std.zon depth limits" {
11511151}
11521152
11531153test "std.zon stringify primitives" {
1154 // Issue: https://github.com/ziglang/zig/issues/20880
1155 if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest;
1156
11571154 try expectSerializeEqual(
11581155 \\.{
11591156 \\ .a = 1.5,
lib/zig.h+3079-991
......@@ -166,6 +166,12 @@
166166#endif
167167#define zig_expand_has_builtin(b) zig_has_builtin(b)
168168
169#if defined(__has_feature)
170#define zig_has_feature(feature) __has_feature(feature)
171#else
172#define zig_has_feature(feature) 0
173#endif
174
169175#if defined(__has_attribute)
170176#define zig_has_attribute(attribute) __has_attribute(attribute)
171177#else
......@@ -175,9 +181,9 @@
175181#if __STDC_VERSION__ >= 201112L
176182#define zig_static_assert(cond, msg) _Static_assert(cond, msg)
177183#elif zig_has_attribute(unused)
178#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] __attribute__((unused))
184#define zig_static_assert(cond, msg) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[(cond) ? 1 : -1] __attribute__((unused))
179185#else
180#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)]
186#define zig_static_assert(cond, msg) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[(cond) ? 1 : -1]
181187#endif
182188
183189#if __STDC_VERSION__ >= 202311L
......@@ -193,10 +199,8 @@
193199#endif
194200
195201#if defined(zig_msvc)
196#define zig_const_arr
197202#define zig_callconv(c) __##c
198203#else
199#define zig_const_arr static const
200204#define zig_callconv(c) __attribute__((c))
201205#endif
202206
......@@ -267,12 +271,20 @@
267271
268272#if __STDC_VERSION__ >= 202311L
269273#define zig_align(alignment) alignas(alignment)
270#elif __STDC_VERSION__ >= 201112L
274#elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignas)
271275#define zig_align(alignment) _Alignas(alignment)
272276#else
273277#define zig_align(alignment) zig_under_align(alignment)
274278#endif
275279
280#if __STDC_VERSION__ >= 202311L
281#define zig_alignOf(Type) alignof(Type)
282#elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignof)
283#define zig_alignOf(Type) _Alignof(Type)
284#else
285#define zig_alignOf(Type) (sizeof(struct { char c; Type t; }) - sizeof(Type))
286#endif
287
276288#if zig_has_attribute(aligned) || defined(zig_tinyc)
277289#define zig_align_fn(alignment) __attribute__((aligned(alignment)))
278290#elif defined(zig_msvc)
......@@ -350,11 +362,9 @@
350362#define zig_export(symbol, name) __attribute__((alias(symbol)))
351363#else
352364#define zig_export(symbol, name) ; \
353 __asm(zig_mangle_c(name) " = " zig_mangle_c(symbol))
365 __asm("\t.globl\t" zig_mangle_c(name) "\n" zig_mangle_c(name) " = " zig_mangle_c(symbol))
354366#endif
355367
356#define zig_mangled_tentative zig_mangled
357#define zig_mangled_final zig_mangled
358368#if defined(zig_msvc)
359369#define zig_mangled(mangled, unmangled) ; \
360370 zig_export(#mangled, unmangled)
......@@ -364,7 +374,7 @@
364374#else /* zig_msvc */
365375#define zig_mangled(mangled, unmangled) __asm(zig_mangle_c(unmangled))
366376#define zig_mangled_export(mangled, unmangled, symbol) \
367 zig_mangled_final(mangled, unmangled) \
377 zig_mangled(mangled, unmangled) \
368378 zig_export(symbol, unmangled)
369379#endif /* zig_msvc */
370380
......@@ -550,6 +560,9 @@
550560#define zig_noreturn
551561#endif
552562
563#define zig_has_always 1
564#define zig_has_never 0
565
553566#define zig_compiler_rt_abbrev_uint32_t si
554567#define zig_compiler_rt_abbrev_int32_t si
555568#define zig_compiler_rt_abbrev_uint64_t di
......@@ -560,7 +573,11 @@
560573#define zig_compiler_rt_abbrev_zig_f32 sf
561574#define zig_compiler_rt_abbrev_zig_f64 df
562575#define zig_compiler_rt_abbrev_zig_f80 xf
576#ifdef zig_powerpc
577#define zig_compiler_rt_abbrev_zig_f128 kf
578#else
563579#define zig_compiler_rt_abbrev_zig_f128 tf
580#endif
564581
565582zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t);
566583zig_extern void *memset (void *, int, size_t);
......@@ -645,16 +662,6 @@ typedef signed long long int16_t;
645662#define INT16_MAX ( INT16_C(0x7FFF))
646663#define UINT16_MAX ( INT16_C(0xFFFF))
647664
648#if defined(zig_ez80)
649typedef unsigned int uint24_t;
650typedef signed int int24_t;
651#define INT24_C(c) c
652#define UINT24_C(c) c##U
653#endif
654#define INT24_MIN (~INT24_C(0x7FFF))
655#define INT24_MAX ( INT24_C(0x7FFF))
656#define UINT24_MAX ( INT24_C(0xFFFF))
657
658665#if SCHAR_MIN == ~0x7FFFFFFF && SCHAR_MAX == 0x7FFFFFFF && UCHAR_MAX == 0xFFFFFFFF
659666typedef unsigned char uint32_t;
660667typedef signed char int32_t;
......@@ -685,17 +692,6 @@ typedef signed long long int32_t;
685692#define INT32_MAX ( INT32_C(0x7FFFFFFF))
686693#define UINT32_MAX ( INT32_C(0xFFFFFFFF))
687694
688#if defined(zig_ez80)
689typedef unsigned __int48 uint48_t;
690typedef signed __int48 int48_t;
691#define INT48_C(c) c
692/* no suffix */
693#define UINT48_C(c) ((uint48_t)(c))
694#endif
695#define INT48_MIN (~INT48_C(0x7FFFFFFFFFFF))
696#define INT48_MAX ( INT48_C(0x7FFFFFFFFFFF))
697#define UINT48_MAX ( INT48_C(0xFFFFFFFFFFFF))
698
699695#if SCHAR_MIN == ~0x7FFFFFFFFFFFFFFF && SCHAR_MAX == 0x7FFFFFFFFFFFFFFF && UCHAR_MAX == 0xFFFFFFFFFFFFFFFF
700696typedef unsigned char uint64_t;
701697typedef signed char int64_t;
......@@ -726,6 +722,27 @@ typedef signed long long int64_t;
726722#define INT64_MAX ( INT64_C(0x7FFFFFFFFFFFFFFF))
727723#define UINT64_MAX ( INT64_C(0xFFFFFFFFFFFFFFFF))
728724
725#if defined(zig_ez80)
726
727typedef unsigned int uint24_t;
728typedef signed int int24_t;
729#define INT24_C(c) c
730#define UINT24_C(c) c##U
731#define INT24_MIN (~INT24_C(0x7FFF))
732#define INT24_MAX ( INT24_C(0x7FFF))
733#define UINT24_MAX ( INT24_C(0xFFFF))
734
735typedef unsigned __int48 uint48_t;
736typedef signed __int48 int48_t;
737#define INT48_C(c) c
738/* no suffix */
739#define UINT48_C(c) ((uint48_t)(c))
740#define INT48_MIN (~INT48_C(0x7FFFFFFFFFFF))
741#define INT48_MAX ( INT48_C(0x7FFFFFFFFFFF))
742#define UINT48_MAX ( INT48_C(0xFFFFFFFFFFFF))
743
744#endif
745
729746typedef size_t uintptr_t;
730747typedef ptrdiff_t intptr_t;
731748
......@@ -739,23 +756,145 @@ typedef ptrdiff_t intptr_t;
739756#define zig_maxInt_i16 INT16_MAX
740757#define zig_minInt_u16 UINT16_C(0)
741758#define zig_maxInt_u16 UINT16_MAX
742#define zig_minInt_i24 INT24_MIN
743#define zig_maxInt_i24 INT24_MAX
744#define zig_minInt_u24 UINT24_C(0)
745#define zig_maxInt_u24 UINT24_MAX
746759#define zig_minInt_i32 INT32_MIN
747760#define zig_maxInt_i32 INT32_MAX
748761#define zig_minInt_u32 UINT32_C(0)
749762#define zig_maxInt_u32 UINT32_MAX
750#define zig_minInt_i48 INT48_MIN
751#define zig_maxInt_i48 INT48_MAX
752#define zig_minInt_u48 UINT48_C(0)
753#define zig_maxInt_u48 UINT48_MAX
754763#define zig_minInt_i64 INT64_MIN
755764#define zig_maxInt_i64 INT64_MAX
756765#define zig_minInt_u64 UINT64_C(0)
757766#define zig_maxInt_u64 UINT64_MAX
758767
768// zig_promoted_T implements C integral promotions except with signedness preserved, which
769// allows wrapping operations to avoid the ub that would be caused by the normal promotion.
770
771#if INT8_MAX <= INT_MAX
772typedef unsigned int zig_promoted_i8;
773#elif INT8_MAX <= LONG_MAX
774typedef unsigned long zig_promoted_i8;
775#elif INT8_MAX <= LLONG_MAX
776typedef unsigned long long zig_promoted_i8;
777#else
778typedef int8_t zig_promoted_i8;
779#endif
780#if UINT8_MAX <= UINT_MAX
781typedef unsigned int zig_promoted_u8;
782#elif UINT8_MAX <= ULONG_MAX
783typedef unsigned long zig_promoted_u8;
784#elif UINT8_MAX <= ULLONG_MAX
785typedef unsigned long long zig_promoted_u8;
786#else
787typedef uint8_t zig_promoted_u8;
788#endif
789
790#if INT16_MAX <= INT_MAX
791typedef unsigned int zig_promoted_i16;
792#elif INT16_MAX <= LONG_MAX
793typedef unsigned long zig_promoted_i16;
794#elif INT16_MAX <= LLONG_MAX
795typedef unsigned long long zig_promoted_i16;
796#else
797typedef int16_t zig_promoted_i16;
798#endif
799#if UINT16_MAX <= UINT_MAX
800typedef unsigned int zig_promoted_u16;
801#elif UINT16_MAX <= ULONG_MAX
802typedef unsigned long zig_promoted_u16;
803#elif UINT16_MAX <= ULLONG_MAX
804typedef unsigned long long zig_promoted_u16;
805#else
806typedef uint16_t zig_promoted_u16;
807#endif
808
809#if INT32_MAX <= INT_MAX
810typedef unsigned int zig_promoted_i32;
811#elif INT32_MAX <= LONG_MAX
812typedef unsigned long zig_promoted_i32;
813#elif INT32_MAX <= LLONG_MAX
814typedef unsigned long long zig_promoted_i32;
815#else
816typedef int32_t zig_promoted_i32;
817#endif
818#if UINT32_MAX <= UINT_MAX
819typedef unsigned int zig_promoted_u32;
820#elif UINT32_MAX <= ULONG_MAX
821typedef unsigned long zig_promoted_u32;
822#elif UINT32_MAX <= ULLONG_MAX
823typedef unsigned long long zig_promoted_u32;
824#else
825typedef uint32_t zig_promoted_u32;
826#endif
827
828#if INT64_MAX <= INT_MAX
829typedef unsigned int zig_promoted_i64;
830#elif INT64_MAX <= LONG_MAX
831typedef unsigned long zig_promoted_i64;
832#elif INT64_MAX <= LLONG_MAX
833typedef unsigned long long zig_promoted_i64;
834#else
835typedef int64_t zig_promoted_i64;
836#endif
837#if UINT64_MAX <= UINT_MAX
838typedef unsigned int zig_promoted_u64;
839#elif UINT64_MAX <= ULONG_MAX
840typedef unsigned long zig_promoted_u64;
841#elif UINT64_MAX <= ULLONG_MAX
842typedef unsigned long long zig_promoted_u64;
843#else
844typedef uint64_t zig_promoted_u64;
845#endif
846
847#ifdef zig_ez80
848
849#define zig_minInt_i24 INT24_MIN
850#define zig_maxInt_i24 INT24_MAX
851#define zig_minInt_u24 UINT24_C(0)
852#define zig_maxInt_u24 UINT24_MAX
853#define zig_minInt_i48 INT48_MIN
854#define zig_maxInt_i48 INT48_MAX
855#define zig_minInt_u48 UINT48_C(0)
856#define zig_maxInt_u48 UINT48_MAX
857
858#if INT24_MAX <= INT_MAX
859typedef unsigned int zig_promoted_i24;
860#elif INT24_MAX <= LONG_MAX
861typedef unsigned long zig_promoted_i24;
862#elif INT24_MAX <= LLONG_MAX
863typedef unsigned long long zig_promoted_i24;
864#else
865typedef int24_t zig_promoted_i24;
866#endif
867#if UINT24_MAX <= UINT_MAX
868typedef unsigned int zig_promoted_u24;
869#elif UINT24_MAX <= ULONG_MAX
870typedef unsigned long zig_promoted_u24;
871#elif UINT24_MAX <= ULLONG_MAX
872typedef unsigned long long zig_promoted_u24;
873#else
874typedef uint24_t zig_promoted_u24;
875#endif
876
877#if INT48_MAX <= INT_MAX
878typedef unsigned int zig_promoted_i48;
879#elif INT48_MAX <= LONG_MAX
880typedef unsigned long zig_promoted_i48;
881#elif INT48_MAX <= LLONG_MAX
882typedef unsigned long long zig_promoted_i48;
883#else
884typedef int48_t zig_promoted_i48;
885#endif
886#if UINT48_MAX <= UINT_MAX
887typedef unsigned int zig_promoted_u48;
888#elif UINT48_MAX <= ULONG_MAX
889typedef unsigned long zig_promoted_u48;
890#elif UINT48_MAX <= ULLONG_MAX
891typedef unsigned long long zig_promoted_u48;
892#else
893typedef uint48_t zig_promoted_u48;
894#endif
895
896#endif
897
759898#define zig_intLimit(s, w, limit, bits) zig_shr_##s##w(zig_##limit##Int_##s##w, w - (bits))
760899#define zig_minInt_i(w, bits) zig_intLimit(i, w, min, bits)
761900#define zig_maxInt_i(w, bits) zig_intLimit(i, w, max, bits)
......@@ -770,7 +909,33 @@ typedef ptrdiff_t intptr_t;
770909 zig_operator(Type, Type, operation, operator)
771910#define zig_shift_operator(Type, operation, operator) \
772911 zig_operator(Type, uint8_t, operation, operator)
773#define zig_int_helpers(w, PromotedUnsigned) \
912
913#define zig_int_casts_common(bw, sw) \
914 static inline uint##bw##_t zig_u##bw##_intCast_u##sw(uint##sw##_t arg) { \
915 return arg; \
916 } \
917\
918 static inline uint##bw##_t zig_u##bw##_intCast_i##sw(int##sw##_t arg) { \
919 return (uint##bw##_t)arg; \
920 } \
921\
922 static inline int##bw##_t zig_i##bw##_intCast_u##sw(uint##sw##_t arg) { \
923 return arg; \
924 } \
925\
926 static inline int##bw##_t zig_i##bw##_intCast_i##sw(int##sw##_t arg) { \
927 return arg; \
928 } \
929\
930 static inline uint##sw##_t zig_u##sw##_truncate_u##bw(uint##bw##_t arg, uint8_t bits) { \
931 return (uint##sw##_t)arg & zig_maxInt_u(sw, bits); \
932 } \
933\
934 static inline int##sw##_t zig_i##sw##_truncate_i##bw(int##bw##_t arg, uint8_t bits) { \
935 return ((uint##sw##_t)arg & UINT##sw##_C(1) << (bits - UINT8_C(1))) != UINT##sw##_C(0) \
936 ? (int##sw##_t)arg | zig_minInt_i(sw, bits) : (int##sw##_t)arg & zig_maxInt_i(sw, bits); \
937 }
938#define zig_int_operators(w) \
774939 zig_basic_operator(uint##w##_t, and_u##w, &) \
775940 zig_basic_operator( int##w##_t, and_i##w, &) \
776941 zig_basic_operator(uint##w##_t, or_u##w, |) \
......@@ -786,44 +951,48 @@ typedef ptrdiff_t intptr_t;
786951 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \
787952 } \
788953\
789 static inline uint##w##_t zig_not_u##w(uint##w##_t val, uint8_t bits) { \
790 return val ^ zig_maxInt_u(w, bits); \
954 static inline uint##w##_t zig_not_u##w(uint##w##_t arg, uint8_t bits) { \
955 return arg ^ zig_maxInt_u(w, bits); \
791956 } \
792957\
793 static inline int##w##_t zig_not_i##w(int##w##_t val, uint8_t bits) { \
958 static inline int##w##_t zig_not_i##w(int##w##_t arg, uint8_t bits) { \
794959 (void)bits; \
795 return ~val; \
960 return ~arg; \
796961 } \
797962\
798 static inline uint##w##_t zig_wrap_u##w(uint##w##_t val, uint8_t bits) { \
799 return val & zig_maxInt_u(w, bits); \
963 zig_basic_operator(uint##w##_t, divFloor_u##w, /) \
964\
965 static inline int##w##_t zig_divFloor_i##w(int##w##_t lhs, int##w##_t rhs) { \
966 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)); \
800967 } \
801968\
802 static inline int##w##_t zig_wrap_i##w(int##w##_t val, uint8_t bits) { \
803 return (val & UINT##w##_C(1) << (bits - UINT8_C(1))) != 0 \
804 ? val | zig_minInt_i(w, bits) : val & zig_maxInt_i(w, bits); \
969 static inline uint##w##_t zig_divCeil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \
970 return lhs / rhs + (lhs % rhs != UINT##w##_C(0) ? UINT##w##_C(1) : UINT##w##_C(0)); \
805971 } \
806972\
807 static inline uint##w##_t zig_abs_i##w(int##w##_t val) { \
808 return (val < 0) ? -(uint##w##_t)val : (uint##w##_t)val; \
973 static inline int##w##_t zig_divCeil_i##w(int##w##_t lhs, int##w##_t rhs) { \
974 return lhs / rhs + (lhs % rhs != INT##w##_C(0) \
975 ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) + INT##w##_C(1) : INT##w##_C(0)); \
809976 } \
810977\
811 zig_basic_operator(uint##w##_t, div_floor_u##w, /) \
978 zig_basic_operator(uint##w##_t, mod_u##w, %) \
979 zig_int_casts_common(w, w) \
812980\
813 static inline int##w##_t zig_div_floor_i##w(int##w##_t lhs, int##w##_t rhs) { \
814 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)); \
981 static inline uint##w##_t zig_u##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \
982 return zig_u##w##_truncate_u##w(arg, bits); \
815983 } \
816984\
817 static inline uint##w##_t zig_div_ceil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \
818 return lhs / rhs + (lhs % rhs != UINT##w##_C(0) ? UINT##w##_C(1) : UINT##w##_C(0)); \
985 static inline uint##w##_t zig_u##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \
986 return zig_u##w##_bitCast_u##w((uint##w##_t)arg, bits); \
819987 } \
820988\
821 static inline int##w##_t zig_div_ceil_i##w(int##w##_t lhs, int##w##_t rhs) { \
822 return lhs / rhs + (lhs % rhs != INT##w##_C(0) \
823 ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) + INT##w##_C(1) : INT##w##_C(0)); \
989 static inline int##w##_t zig_i##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \
990 return zig_i##w##_truncate_i##w(arg, bits); \
824991 } \
825992\
826 zig_basic_operator(uint##w##_t, mod_u##w, %) \
993 static inline int##w##_t zig_i##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \
994 return zig_i##w##_bitCast_i##w((int##w##_t)arg, bits); \
995 } \
827996\
828997 static inline int##w##_t zig_mod_i##w(int##w##_t lhs, int##w##_t rhs) { \
829998 int##w##_t rem = lhs % rhs; \
......@@ -831,100 +1000,102 @@ typedef ptrdiff_t intptr_t;
8311000 } \
8321001\
8331002 static inline uint##w##_t zig_shlw_u##w(uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \
834 return zig_wrap_u##w(zig_shl_u##w(lhs, rhs), bits); \
1003 return zig_u##w##_truncate_u##w(zig_shl_u##w(lhs, rhs), bits); \
8351004 } \
8361005\
8371006 static inline int##w##_t zig_shlw_i##w(int##w##_t lhs, uint8_t rhs, uint8_t bits) { \
838 return zig_wrap_i##w((int##w##_t)zig_shl_u##w((uint##w##_t)lhs, rhs), bits); \
1007 return zig_i##w##_bitCast_u##w(zig_shl_u##w(zig_u##w##_bitCast_i##w(lhs, bits), rhs), bits); \
8391008 } \
8401009\
8411010 static inline uint##w##_t zig_addw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
842 return zig_wrap_u##w(lhs + rhs, bits); \
1011 return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs + rhs, bits); \
8431012 } \
8441013\
8451014 static inline int##w##_t zig_addw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
846 return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs + (uint##w##_t)rhs), bits); \
1015 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); \
8471016 } \
8481017\
8491018 static inline uint##w##_t zig_subw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
850 return zig_wrap_u##w(lhs - rhs, bits); \
1019 return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs - rhs, bits); \
8511020 } \
8521021\
8531022 static inline int##w##_t zig_subw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
854 return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs - (uint##w##_t)rhs), bits); \
1023 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); \
8551024 } \
8561025\
8571026 static inline uint##w##_t zig_mulw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
858 return zig_wrap_u##w((PromotedUnsigned)lhs * rhs, bits); \
1027 return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs * rhs, bits); \
8591028 } \
8601029\
8611030 static inline int##w##_t zig_mulw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
862 return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs * (uint##w##_t)rhs), bits); \
1031 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); \
1032 } \
1033\
1034 static inline uint##w##_t zig_abs_i##w(int##w##_t arg) { \
1035 int##w##_t tmp = zig_shr_i##w(arg, UINT8_C(w) - UINT8_C(1)); \
1036 return zig_u##w##_bitCast_i##w(zig_subw_i##w(zig_xor_i##w(arg, tmp), tmp, UINT8_C(w)), UINT8_C(w)); \
1037 } \
1038\
1039 static inline uint##w##_t zig_min_u##w(uint##w##_t lhs, uint##w##_t rhs) { \
1040 return lhs < rhs ? lhs : rhs; \
1041 } \
1042\
1043 static inline int##w##_t zig_min_i##w(int##w##_t lhs, int##w##_t rhs) { \
1044 return lhs < rhs ? lhs : rhs; \
1045 } \
1046\
1047 static inline uint##w##_t zig_max_u##w(uint##w##_t lhs, uint##w##_t rhs) { \
1048 return lhs >= rhs ? lhs : rhs; \
1049 } \
1050\
1051 static inline int##w##_t zig_max_i##w(int##w##_t lhs, int##w##_t rhs) { \
1052 return lhs >= rhs ? lhs : rhs; \
8631053 }
864#if UINT8_MAX <= UINT_MAX
865zig_int_helpers(8, unsigned int)
866#elif UINT8_MAX <= ULONG_MAX
867zig_int_helpers(8, unsigned long)
868#elif UINT8_MAX <= ULLONG_MAX
869zig_int_helpers(8, unsigned long long)
870#else
871zig_int_helpers(8, uint8_t)
872#endif
873#if UINT16_MAX <= UINT_MAX
874zig_int_helpers(16, unsigned int)
875#elif UINT16_MAX <= ULONG_MAX
876zig_int_helpers(16, unsigned long)
877#elif UINT16_MAX <= ULLONG_MAX
878zig_int_helpers(16, unsigned long long)
879#else
880zig_int_helpers(16, uint16_t)
881#endif
882#if defined(zig_ez80)
883#if UINT24_MAX <= UINT_MAX
884zig_int_helpers(24, unsigned int)
885#elif UINT24_MAX <= ULONG_MAX
886zig_int_helpers(24, unsigned long)
887#elif UINT24_MAX <= ULLONG_MAX
888zig_int_helpers(24, unsigned long long)
889#else
890zig_int_helpers(24, uint24_t)
891#endif
892#endif
893#if UINT32_MAX <= UINT_MAX
894zig_int_helpers(32, unsigned int)
895#elif UINT32_MAX <= ULONG_MAX
896zig_int_helpers(32, unsigned long)
897#elif UINT32_MAX <= ULLONG_MAX
898zig_int_helpers(32, unsigned long long)
899#else
900zig_int_helpers(32, uint32_t)
901#endif
902#if defined(zig_ez80)
903#if UINT24_MAX <= UINT_MAX
904zig_int_helpers(48, unsigned int)
905#elif UINT24_MAX <= ULONG_MAX
906zig_int_helpers(48, unsigned long)
907#elif UINT24_MAX <= ULLONG_MAX
908zig_int_helpers(48, unsigned long long)
909#else
910zig_int_helpers(48, uint48_t)
911#endif
912#endif
913#if UINT64_MAX <= UINT_MAX
914zig_int_helpers(64, unsigned int)
915#elif UINT64_MAX <= ULONG_MAX
916zig_int_helpers(64, unsigned long)
917#elif UINT64_MAX <= ULLONG_MAX
918zig_int_helpers(64, unsigned long long)
919#else
920zig_int_helpers(64, uint64_t)
1054zig_int_operators(8)
1055zig_int_operators(16)
1056zig_int_operators(32)
1057zig_int_operators(64)
1058#ifdef zig_ez80
1059zig_int_operators(24)
1060zig_int_operators(48)
1061#endif
1062
1063#define zig_int_casts(bw, sw) \
1064 static inline uint##sw##_t zig_u##sw##_intCast_u##bw(uint##bw##_t arg) { \
1065 return (uint##sw##_t)arg; \
1066 } \
1067\
1068 static inline uint##sw##_t zig_u##sw##_intCast_i##bw(int##bw##_t arg) { \
1069 return (uint##sw##_t)arg; \
1070 } \
1071\
1072 static inline int##sw##_t zig_i##sw##_intCast_u##bw(uint##bw##_t arg) { \
1073 return (int##sw##_t)arg; \
1074 } \
1075\
1076 static inline int##sw##_t zig_i##sw##_intCast_i##bw(int##bw##_t arg) { \
1077 return (int##sw##_t)arg; \
1078 } \
1079\
1080 zig_int_casts_common(bw, sw)
1081zig_int_casts(16, 8)
1082zig_int_casts(32, 8)
1083zig_int_casts(64, 8)
1084zig_int_casts(32, 16)
1085zig_int_casts(64, 16)
1086zig_int_casts(64, 32)
1087#ifdef zig_ez80
1088zig_int_casts(32, 24)
1089zig_int_casts(48, 24)
1090zig_int_casts(64, 24)
1091zig_int_casts(64, 48)
9211092#endif
9221093
9231094static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
9241095#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9251096 uint32_t full_res;
9261097 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
927 *res = zig_wrap_u32(full_res, bits);
1098 *res = zig_u32_truncate_u32(full_res, bits);
9281099 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
9291100#else
9301101 *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
9361107#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9371108 int32_t full_res;
9381109 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1110 *res = zig_i32_truncate_i32(full_res, bits);
1111 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
9391112#else
940 int32_t full_res = (int32_t)((uint32_t)lhs + (uint32_t)rhs);
941 bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0;
1113 *res = zig_addw_i32(lhs, rhs, bits);
1114 return ((*res ^ lhs) & (*res ^ rhs)) < INT32_C(0);
9421115#endif
943 *res = zig_wrap_i32(full_res, bits);
944 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
9451116}
9461117
9471118static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
9481119#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9491120 uint64_t full_res;
9501121 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
951 *res = zig_wrap_u64(full_res, bits);
1122 *res = zig_u64_truncate_u64(full_res, bits);
9521123 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
9531124#else
9541125 *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
9601131#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9611132 int64_t full_res;
9621133 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1134 *res = zig_i64_truncate_i64(full_res, bits);
1135 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
9631136#else
964 int64_t full_res = (int64_t)((uint64_t)lhs + (uint64_t)rhs);
965 bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0;
1137 *res = zig_addw_i64(lhs, rhs, bits);
1138 return ((*res ^ lhs) & (*res ^ rhs)) < INT64_C(0);
9661139#endif
967 *res = zig_wrap_i64(full_res, bits);
968 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
9691140}
9701141
9711142static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
9721143#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9731144 uint8_t full_res;
9741145 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
975 *res = zig_wrap_u8(full_res, bits);
1146 *res = zig_u8_truncate_u8(full_res, bits);
9761147 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
9771148#else
9781149 uint32_t full_res;
9791150 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
980 *res = (uint8_t)full_res;
1151 *res = zig_u8_intCast_u32(full_res);
9811152 return overflow;
9821153#endif
9831154}
......@@ -986,12 +1157,12 @@ static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
9861157#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9871158 int8_t full_res;
9881159 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
989 *res = zig_wrap_i8(full_res, bits);
1160 *res = zig_i8_truncate_i8(full_res, bits);
9901161 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
9911162#else
9921163 int32_t full_res;
9931164 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
994 *res = (int8_t)full_res;
1165 *res = zig_i8_intCast_i32(full_res);
9951166 return overflow;
9961167#endif
9971168}
......@@ -1000,12 +1171,12 @@ static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
10001171#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10011172 uint16_t full_res;
10021173 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1003 *res = zig_wrap_u16(full_res, bits);
1174 *res = zig_u16_truncate_u16(full_res, bits);
10041175 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
10051176#else
10061177 uint32_t full_res;
10071178 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
1008 *res = (uint16_t)full_res;
1179 *res = zig_u16_intCast_u32(full_res);
10091180 return overflow;
10101181#endif
10111182}
......@@ -1014,27 +1185,28 @@ static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
10141185#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10151186 int16_t full_res;
10161187 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1017 *res = zig_wrap_i16(full_res, bits);
1188 *res = zig_i16_truncate_i16(full_res, bits);
10181189 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
10191190#else
10201191 int32_t full_res;
10211192 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
1022 *res = (int16_t)full_res;
1193 *res = zig_i16_intCast_i32(full_res);
10231194 return overflow;
10241195#endif
10251196}
10261197
10271198#if defined(zig_ez80)
1199
10281200static inline bool zig_addo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {
10291201#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10301202 uint24_t full_res;
10311203 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1032 *res = zig_wrap_u24(full_res, bits);
1204 *res = zig_u24_truncate_u24(full_res, bits);
10331205 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);
10341206#else
10351207 uint32_t full_res;
10361208 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
1037 *res = (uint24_t)full_res;
1209 *res = zig_u24_intCast_u32(full_res);
10381210 return overflow;
10391211#endif
10401212}
......@@ -1043,28 +1215,26 @@ static inline bool zig_addo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t
10431215#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10441216 int24_t full_res;
10451217 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1046 *res = zig_wrap_i24(full_res, bits);
1218 *res = zig_i24_truncate_i24(full_res, bits);
10471219 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);
10481220#else
10491221 int32_t full_res;
10501222 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
1051 *res = (int24_t)full_res;
1223 *res = zig_i24_intCast_i32(full_res);
10521224 return overflow;
10531225#endif
10541226}
1055#endif
10561227
1057#if defined(zig_ez80)
10581228static inline bool zig_addo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {
10591229#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10601230 uint48_t full_res;
10611231 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1062 *res = zig_wrap_u48(full_res, bits);
1232 *res = zig_u48_truncate_u48(full_res, bits);
10631233 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);
10641234#else
10651235 uint64_t full_res;
10661236 bool overflow = zig_addo_u64(&full_res, lhs, rhs, bits);
1067 *res = (uint48_t)full_res;
1237 *res = zig_u48_intCast_u64(full_res);
10681238 return overflow;
10691239#endif
10701240}
......@@ -1073,22 +1243,23 @@ static inline bool zig_addo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
10731243#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10741244 int48_t full_res;
10751245 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1076 *res = zig_wrap_i48(full_res, bits);
1246 *res = zig_i48_truncate_i48(full_res, bits);
10771247 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);
10781248#else
10791249 int64_t full_res;
10801250 bool overflow = zig_addo_i64(&full_res, lhs, rhs, bits);
1081 *res = (int48_t)full_res;
1251 *res = zig_i48_intCast_i64(full_res);
10821252 return overflow;
10831253#endif
10841254}
1255
10851256#endif
10861257
10871258static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
10881259#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
10891260 uint32_t full_res;
10901261 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1091 *res = zig_wrap_u32(full_res, bits);
1262 *res = zig_u32_truncate_u32(full_res, bits);
10921263 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
10931264#else
10941265 *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
11001271#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11011272 int32_t full_res;
11021273 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1274 *res = zig_i32_truncate_i32(full_res, bits);
1275 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
11031276#else
1104 int32_t full_res = (int32_t)((uint32_t)lhs - (uint32_t)rhs);
1105 bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0;
1277 *res = zig_subw_i32(lhs, rhs, bits);
1278 return ((lhs ^ rhs) & (*res ^ lhs)) < INT32_C(0);
11061279#endif
1107 *res = zig_wrap_i32(full_res, bits);
1108 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
11091280}
11101281
1111
11121282static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
11131283#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11141284 uint64_t full_res;
11151285 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1116 *res = zig_wrap_u64(full_res, bits);
1286 *res = zig_u64_truncate_u64(full_res, bits);
11171287 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
11181288#else
11191289 *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
11251295#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11261296 int64_t full_res;
11271297 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1298 *res = zig_i64_truncate_i64(full_res, bits);
1299 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
11281300#else
1129 int64_t full_res = (int64_t)((uint64_t)lhs - (uint64_t)rhs);
1130 bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0;
1301 *res = zig_subw_i64(lhs, rhs, bits);
1302 return ((lhs ^ rhs) & (*res ^ lhs)) < INT64_C(0);
11311303#endif
1132 *res = zig_wrap_i64(full_res, bits);
1133 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
11341304}
11351305
11361306static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
11371307#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11381308 uint8_t full_res;
11391309 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1140 *res = zig_wrap_u8(full_res, bits);
1310 *res = zig_u8_truncate_u8(full_res, bits);
11411311 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
11421312#else
11431313 uint32_t full_res;
11441314 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
1145 *res = (uint8_t)full_res;
1315 *res = zig_u8_intCast_u32(full_res);
11461316 return overflow;
11471317#endif
11481318}
......@@ -1151,12 +1321,12 @@ static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
11511321#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11521322 int8_t full_res;
11531323 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1154 *res = zig_wrap_i8(full_res, bits);
1324 *res = zig_i8_truncate_i8(full_res, bits);
11551325 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
11561326#else
11571327 int32_t full_res;
11581328 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
1159 *res = (int8_t)full_res;
1329 *res = zig_i8_intCast_i32(full_res);
11601330 return overflow;
11611331#endif
11621332}
......@@ -1165,12 +1335,12 @@ static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
11651335#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11661336 uint16_t full_res;
11671337 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1168 *res = zig_wrap_u16(full_res, bits);
1338 *res = zig_u16_truncate_u16(full_res, bits);
11691339 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
11701340#else
11711341 uint32_t full_res;
11721342 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
1173 *res = (uint16_t)full_res;
1343 *res = zig_u16_intCast_u32(full_res);
11741344 return overflow;
11751345#endif
11761346}
......@@ -1179,27 +1349,28 @@ static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
11791349#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11801350 int16_t full_res;
11811351 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1182 *res = zig_wrap_i16(full_res, bits);
1352 *res = zig_i16_truncate_i16(full_res, bits);
11831353 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
11841354#else
11851355 int32_t full_res;
11861356 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
1187 *res = (int16_t)full_res;
1357 *res = zig_i16_intCast_i32(full_res);
11881358 return overflow;
11891359#endif
11901360}
11911361
11921362#if defined(zig_ez80)
1363
11931364static inline bool zig_subo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {
11941365#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11951366 uint24_t full_res;
11961367 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1197 *res = zig_wrap_u24(full_res, bits);
1368 *res = zig_u24_truncate_u24(full_res, bits);
11981369 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);
11991370#else
12001371 uint32_t full_res;
12011372 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
1202 *res = (uint24_t)full_res;
1373 *res = zig_u24_intCast_u32(full_res);
12031374 return overflow;
12041375#endif
12051376}
......@@ -1208,28 +1379,26 @@ static inline bool zig_subo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t
12081379#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
12091380 int24_t full_res;
12101381 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1211 *res = zig_wrap_i24(full_res, bits);
1382 *res = zig_i24_truncate_i24(full_res, bits);
12121383 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);
12131384#else
12141385 int32_t full_res;
12151386 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
1216 *res = (int24_t)full_res;
1387 *res = zig_i24_intCast_i32(full_res);
12171388 return overflow;
12181389#endif
12191390}
1220#endif
12211391
1222#if defined(zig_ez80)
12231392static inline bool zig_subo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {
12241393#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
12251394 uint48_t full_res;
12261395 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1227 *res = zig_wrap_u48(full_res, bits);
1396 *res = zig_u48_truncate_u48(full_res, bits);
12281397 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);
12291398#else
12301399 uint64_t full_res;
12311400 bool overflow = zig_subo_u64(&full_res, lhs, rhs, bits);
1232 *res = (uint48_t)full_res;
1401 *res = zig_u48_intCast_u64(full_res);
12331402 return overflow;
12341403#endif
12351404}
......@@ -1238,22 +1407,23 @@ static inline bool zig_subo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
12381407#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
12391408 int48_t full_res;
12401409 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1241 *res = zig_wrap_i48(full_res, bits);
1410 *res = zig_i48_truncate_i48(full_res, bits);
12421411 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);
12431412#else
12441413 int64_t full_res;
12451414 bool overflow = zig_subo_i64(&full_res, lhs, rhs, bits);
1246 *res = (int48_t)full_res;
1415 *res = zig_i48_intCast_i64(full_res);
12471416 return overflow;
12481417#endif
12491418}
1419
12501420#endif
12511421
12521422static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
12531423#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
12541424 uint32_t full_res;
12551425 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1256 *res = zig_wrap_u32(full_res, bits);
1426 *res = zig_u32_truncate_u32(full_res, bits);
12571427 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
12581428#else
12591429 *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
12611431#endif
12621432}
12631433
1264zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow);
12651434static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) {
1435 zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow);
12661436#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
12671437 int32_t full_res;
12681438 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
12711441 int32_t full_res = __mulosi4(lhs, rhs, &overflow_int);
12721442 bool overflow = overflow_int != 0;
12731443#endif
1274 *res = zig_wrap_i32(full_res, bits);
1444 *res = zig_i32_truncate_i32(full_res, bits);
12751445 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
12761446}
12771447
......@@ -1279,7 +1449,7 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8
12791449#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
12801450 uint64_t full_res;
12811451 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1282 *res = zig_wrap_u64(full_res, bits);
1452 *res = zig_u64_truncate_u64(full_res, bits);
12831453 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
12841454#else
12851455 *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
12871457#endif
12881458}
12891459
1290zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow);
12911460static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) {
1461 zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow);
12921462#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
12931463 int64_t full_res;
12941464 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
12971467 int64_t full_res = __mulodi4(lhs, rhs, &overflow_int);
12981468 bool overflow = overflow_int != 0;
12991469#endif
1300 *res = zig_wrap_i64(full_res, bits);
1470 *res = zig_i64_truncate_i64(full_res, bits);
13011471 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
13021472}
13031473
......@@ -1305,12 +1475,12 @@ static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b
13051475#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13061476 uint8_t full_res;
13071477 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1308 *res = zig_wrap_u8(full_res, bits);
1478 *res = zig_u8_truncate_u8(full_res, bits);
13091479 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
13101480#else
13111481 uint32_t full_res;
13121482 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
1313 *res = (uint8_t)full_res;
1483 *res = zig_u8_intCast_u32(full_res);
13141484 return overflow;
13151485#endif
13161486}
......@@ -1319,12 +1489,12 @@ static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
13191489#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13201490 int8_t full_res;
13211491 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1322 *res = zig_wrap_i8(full_res, bits);
1492 *res = zig_i8_truncate_i8(full_res, bits);
13231493 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
13241494#else
13251495 int32_t full_res;
13261496 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
1327 *res = (int8_t)full_res;
1497 *res = zig_i8_intCast_i32(full_res);
13281498 return overflow;
13291499#endif
13301500}
......@@ -1333,12 +1503,12 @@ static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
13331503#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13341504 uint16_t full_res;
13351505 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1336 *res = zig_wrap_u16(full_res, bits);
1506 *res = zig_u16_truncate_u16(full_res, bits);
13371507 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
13381508#else
13391509 uint32_t full_res;
13401510 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
1341 *res = (uint16_t)full_res;
1511 *res = zig_u16_intCast_u32(full_res);
13421512 return overflow;
13431513#endif
13441514}
......@@ -1347,27 +1517,28 @@ static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
13471517#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13481518 int16_t full_res;
13491519 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1350 *res = zig_wrap_i16(full_res, bits);
1520 *res = zig_i16_truncate_i16(full_res, bits);
13511521 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
13521522#else
13531523 int32_t full_res;
13541524 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
1355 *res = (int16_t)full_res;
1525 *res = zig_i16_intCast_i32(full_res);
13561526 return overflow;
13571527#endif
13581528}
13591529
13601530#if defined(zig_ez80)
1531
13611532static inline bool zig_mulo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {
13621533#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13631534 uint24_t full_res;
13641535 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1365 *res = zig_wrap_u24(full_res, bits);
1536 *res = zig_u24_truncate_u24(full_res, bits);
13661537 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);
13671538#else
13681539 uint32_t full_res;
13691540 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
1370 *res = (uint24_t)full_res;
1541 *res = zig_u24_intCast_u32(full_res);
13711542 return overflow;
13721543#endif
13731544}
......@@ -1376,28 +1547,26 @@ static inline bool zig_mulo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t
13761547#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13771548 int24_t full_res;
13781549 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1379 *res = zig_wrap_i24(full_res, bits);
1550 *res = zig_i24_truncate_i24(full_res, bits);
13801551 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);
13811552#else
13821553 int32_t full_res;
13831554 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
1384 *res = (int24_t)full_res;
1555 *res = zig_i24_intCast_i32(full_res);
13851556 return overflow;
13861557#endif
13871558}
1388#endif
13891559
1390#if defined(zig_ez80)
13911560static inline bool zig_mulo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {
13921561#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13931562 uint48_t full_res;
13941563 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1395 *res = zig_wrap_u48(full_res, bits);
1564 *res = zig_u48_truncate_u48(full_res, bits);
13961565 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);
13971566#else
13981567 uint64_t full_res;
13991568 bool overflow = zig_mulo_u64(&full_res, lhs, rhs, bits);
1400 *res = (uint48_t)full_res;
1569 *res = zig_u48_intCast_u64(full_res);
14011570 return overflow;
14021571#endif
14031572}
......@@ -1406,18 +1575,32 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
14061575#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
14071576 int48_t full_res;
14081577 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1409 *res = zig_wrap_i48(full_res, bits);
1578 *res = zig_i48_truncate_i48(full_res, bits);
14101579 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);
14111580#else
14121581 int64_t full_res;
14131582 bool overflow = zig_mulo_i64(&full_res, lhs, rhs, bits);
1414 *res = (int48_t)full_res;
1583 *res = zig_i48_intCast_i64(full_res);
14151584 return overflow;
14161585#endif
14171586}
1587
14181588#endif
14191589
1420#define zig_int_builtins(w) \
1590#define zig_shls_builtins(lw, rw) \
1591 static inline uint##lw##_t zig_shls_u##lw##_u##rw(uint##lw##_t lhs, uint##rw##_t rhs, uint8_t bits) { \
1592 uint##lw##_t res; \
1593 if (rhs < bits && !zig_shlo_u##lw(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \
1594 return lhs == INT##lw##_C(0) ? zig_minInt_u(lw, bits) : zig_maxInt_u(lw, bits); \
1595 } \
1596\
1597 static inline int##lw##_t zig_shls_i##lw##_u##rw(int##lw##_t lhs, uint##rw##_t rhs, uint8_t bits) { \
1598 int##lw##_t res; \
1599 if (rhs < bits && !zig_shlo_i##lw(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \
1600 return lhs == INT##lw##_C(0) ? INT##lw##_C(0) : \
1601 lhs < INT##lw##_C(0) ? zig_minInt_i(lw, bits) : zig_maxInt_i(lw, bits); \
1602 }
1603#define zig_int_sat_builtins(w) \
14211604 static inline bool zig_shlo_u##w(uint##w##_t *res, uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \
14221605 *res = zig_shlw_u##w(lhs, rhs, bits); \
14231606 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
14291612 return (lhs & mask) != INT##w##_C(0) && (lhs & mask) != mask; \
14301613 } \
14311614\
1432 static inline uint##w##_t zig_shls_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
1433 uint##w##_t res; \
1434 if (rhs < bits && !zig_shlo_u##w(&res, lhs, rhs, bits)) return res; \
1435 return lhs == INT##w##_C(0) ? INT##w##_C(0) : zig_maxInt_u(w, bits); \
1436 } \
1437\
1438 static inline int##w##_t zig_shls_i##w(int##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
1439 int##w##_t res; \
1440 if (rhs < bits && !zig_shlo_i##w(&res, lhs, rhs, bits)) return res; \
1441 return lhs == INT##w##_C(0) ? INT##w##_C(0) : \
1442 lhs < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \
1443 } \
1615 zig_shls_builtins(w, 8) \
1616 zig_shls_builtins(w, 16) \
1617 zig_shls_builtins(w, 32) \
1618 zig_shls_builtins(w, 64) \
14441619\
14451620 static inline uint##w##_t zig_adds_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
14461621 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
14741649 if (!zig_mulo_i##w(&res, lhs, rhs, bits)) return res; \
14751650 return (lhs ^ rhs) < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \
14761651 }
1477zig_int_builtins(8)
1478zig_int_builtins(16)
1479#if defined(zig_ez80)
1480zig_int_builtins(24)
1481#endif
1482zig_int_builtins(32)
1652zig_int_sat_builtins(8)
1653zig_int_sat_builtins(16)
1654zig_int_sat_builtins(32)
1655zig_int_sat_builtins(64)
14831656#if defined(zig_ez80)
1484zig_int_builtins(48)
1657zig_int_sat_builtins(24)
1658zig_int_sat_builtins(48)
14851659#endif
1486zig_int_builtins(64)
14871660
1488#define zig_builtin8(name, val) __builtin_##name(val)
1661#define zig_builtin8(name, arg) __builtin_##name(arg)
14891662typedef unsigned int zig_Builtin8;
14901663
1491#define zig_builtin16(name, val) __builtin_##name(val)
1664#define zig_builtin16(name, arg) __builtin_##name(arg)
14921665typedef unsigned int zig_Builtin16;
14931666
1494#if defined(zig_ez80)
1495#define zig_builtin24(name, val) __builtin_##name(val)
1496typedef unsigned int zig_Builtin24;
1497#endif
1498
14991667#if INT_MIN <= INT32_MIN
1500#define zig_builtin32(name, val) __builtin_##name(val)
1668#define zig_builtin32(name, arg) __builtin_##name(arg)
15011669typedef unsigned int zig_Builtin32;
15021670#elif LONG_MIN <= INT32_MIN
1503#define zig_builtin32(name, val) __builtin_##name##l(val)
1671#define zig_builtin32(name, arg) __builtin_##name##l(arg)
15041672typedef unsigned long zig_Builtin32;
15051673#endif
15061674
1507#if defined(zig_ez80)
1508#define zig_builtin48(name, val) __builtin_##name(val)
1509typedef unsigned long long zig_Builtin48;
1510#endif
1511
15121675#if INT_MIN <= INT64_MIN
1513#define zig_builtin64(name, val) __builtin_##name(val)
1676#define zig_builtin64(name, arg) __builtin_##name(arg)
15141677typedef unsigned int zig_Builtin64;
15151678#elif LONG_MIN <= INT64_MIN
1516#define zig_builtin64(name, val) __builtin_##name##l(val)
1679#define zig_builtin64(name, arg) __builtin_##name##l(arg)
15171680typedef unsigned long zig_Builtin64;
15181681#elif LLONG_MIN <= INT64_MIN
1519#define zig_builtin64(name, val) __builtin_##name##ll(val)
1682#define zig_builtin64(name, arg) __builtin_##name##ll(arg)
15201683typedef unsigned long long zig_Builtin64;
15211684#endif
15221685
1523static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) {
1524 return zig_wrap_u8(val >> (8 - bits), bits);
1686#if defined(zig_ez80)
1687#define zig_builtin24(name, arg) __builtin_##name(arg)
1688typedef unsigned int zig_Builtin24;
1689#define zig_builtin48(name, arg) __builtin_##name(arg)
1690typedef unsigned long long zig_Builtin48;
1691#endif
1692
1693static inline uint8_t zig_byteSwap_u8(uint8_t arg, uint8_t bits) {
1694 return zig_u8_truncate_u8(arg >> (8 - bits), bits);
15251695}
15261696
1527static inline int8_t zig_byte_swap_i8(int8_t val, uint8_t bits) {
1528 return zig_wrap_i8((int8_t)zig_byte_swap_u8((uint8_t)val, bits), bits);
1697static inline int8_t zig_byteSwap_i8(int8_t arg, uint8_t bits) {
1698 return zig_i8_truncate_i8((int8_t)zig_byteSwap_u8((uint8_t)arg, bits), bits);
15291699}
15301700
1531static inline uint16_t zig_byte_swap_u16(uint16_t val, uint8_t bits) {
1701static inline uint16_t zig_byteSwap_u16(uint16_t arg, uint8_t bits) {
15321702 uint16_t full_res;
15331703#if zig_has_builtin(bswap16) || defined(zig_gcc)
1534 full_res = __builtin_bswap16(val);
1704 full_res = __builtin_bswap16(arg);
15351705#else
1536 full_res = (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 8 |
1537 (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 8), 8) >> 0;
1706 full_res = (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 8 |
1707 (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 8), 8) >> 0;
15381708#endif
1539 return zig_wrap_u16(full_res >> (16 - bits), bits);
1709 return zig_u16_truncate_u16(full_res >> (16 - bits), bits);
15401710}
15411711
1542static inline int16_t zig_byte_swap_i16(int16_t val, uint8_t bits) {
1543 return zig_wrap_i16((int16_t)zig_byte_swap_u16((uint16_t)val, bits), bits);
1712static inline int16_t zig_byteSwap_i16(int16_t arg, uint8_t bits) {
1713 return zig_i16_truncate_i16((int16_t)zig_byteSwap_u16((uint16_t)arg, bits), bits);
15441714}
15451715
15461716#if defined(zig_ez80)
1547static inline uint16_t zig_byte_swap_u24(uint24_t val, uint8_t bits) {
1717static inline uint16_t zig_byteSwap_u24(uint24_t arg, uint8_t bits) {
15481718 uint24_t full_res;
15491719#if zig_has_builtin(bswap24) || defined(zig_gcc)
1550 full_res = __builtin_bswap24(val);
1720 full_res = __builtin_bswap24(arg);
15511721#else
1552 full_res = (uint24_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 16 |
1553 (uint24_t)zig_byte_swap_u16((uint16_t)(val >> 8), 16) >> 0;
1722 full_res = (uint24_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 16 |
1723 (uint24_t)zig_byteSwap_u16((uint16_t)(arg >> 8), 16) >> 0;
15541724#endif
1555 return zig_wrap_u24(full_res >> (24 - bits), bits);
1725 return zig_u24_truncate_u24(full_res >> (24 - bits), bits);
15561726}
15571727
1558static inline int16_t zig_byte_swap_i24(int24_t val, uint8_t bits) {
1559 return zig_wrap_i24((int24_t)zig_byte_swap_u24((uint24_t)val, bits), bits);
1728static inline int16_t zig_byteSwap_i24(int24_t arg, uint8_t bits) {
1729 return zig_i24_truncate_i24((int24_t)zig_byteSwap_u24((uint24_t)arg, bits), bits);
15601730}
15611731#endif
15621732
1563static inline uint32_t zig_byte_swap_u32(uint32_t val, uint8_t bits) {
1733static inline uint32_t zig_byteSwap_u32(uint32_t arg, uint8_t bits) {
15641734 uint32_t full_res;
15651735#if zig_has_builtin(bswap32) || defined(zig_gcc)
1566 full_res = __builtin_bswap32(val);
1736 full_res = __builtin_bswap32(arg);
15671737#else
1568 full_res = (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 0), 16) << 16 |
1569 (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 16), 16) >> 0;
1738 full_res = (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 0), 16) << 16 |
1739 (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 16), 16) >> 0;
15701740#endif
1571 return zig_wrap_u32(full_res >> (32 - bits), bits);
1741 return zig_u32_truncate_u32(full_res >> (32 - bits), bits);
15721742}
15731743
1574static inline int32_t zig_byte_swap_i32(int32_t val, uint8_t bits) {
1575 return zig_wrap_i32((int32_t)zig_byte_swap_u32((uint32_t)val, bits), bits);
1744static inline int32_t zig_byteSwap_i32(int32_t arg, uint8_t bits) {
1745 return zig_i32_truncate_i32((int32_t)zig_byteSwap_u32((uint32_t)arg, bits), bits);
15761746}
15771747
15781748#if defined(zig_ez80)
1579static inline uint32_t zig_byte_swap_u48(uint48_t val, uint8_t bits) {
1749static inline uint32_t zig_byteSwap_u48(uint48_t arg, uint8_t bits) {
15801750 uint48_t full_res;
15811751#if zig_has_builtin(bswap48) || defined(zig_gcc)
1582 full_res = __builtin_bswap48(val);
1752 full_res = __builtin_bswap48(arg);
15831753#else
1584 full_res = (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 0), 24) << 24 |
1585 (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 24), 24) >> 0;
1754 full_res = (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 0), 24) << 24 |
1755 (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 24), 24) >> 0;
15861756#endif
1587 return zig_wrap_u48(full_res >> (48 - bits), bits);
1757 return zig_u48_truncate_u48(full_res >> (48 - bits), bits);
15881758}
15891759
1590static inline int32_t zig_byte_swap_i48(int48_t val, uint8_t bits) {
1591 return zig_wrap_i48((int48_t)zig_byte_swap_u48((uint48_t)val, bits), bits);
1760static inline int32_t zig_byteSwap_i48(int48_t arg, uint8_t bits) {
1761 return zig_i48_truncate_i48((int48_t)zig_byteSwap_u48((uint48_t)arg, bits), bits);
15921762}
15931763#endif
15941764
1595static inline uint64_t zig_byte_swap_u64(uint64_t val, uint8_t bits) {
1765static inline uint64_t zig_byteSwap_u64(uint64_t arg, uint8_t bits) {
15961766 uint64_t full_res;
15971767#if zig_has_builtin(bswap64) || defined(zig_gcc)
1598 full_res = __builtin_bswap64(val);
1768 full_res = __builtin_bswap64(arg);
15991769#else
1600 full_res = (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 0), 32) << 32 |
1601 (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 32), 32) >> 0;
1770 full_res = (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 0), 32) << 32 |
1771 (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 32), 32) >> 0;
16021772#endif
1603 return zig_wrap_u64(full_res >> (64 - bits), bits);
1773 return zig_u64_truncate_u64(full_res >> (64 - bits), bits);
16041774}
16051775
1606static inline int64_t zig_byte_swap_i64(int64_t val, uint8_t bits) {
1607 return zig_wrap_i64((int64_t)zig_byte_swap_u64((uint64_t)val, bits), bits);
1776static inline int64_t zig_byteSwap_i64(int64_t arg, uint8_t bits) {
1777 return zig_i64_truncate_i64((int64_t)zig_byteSwap_u64((uint64_t)arg, bits), bits);
16081778}
16091779
1610static inline uint8_t zig_bit_reverse_u8(uint8_t val, uint8_t bits) {
1780static inline uint8_t zig_bitReverse_u8(uint8_t arg, uint8_t bits) {
16111781 uint8_t full_res;
16121782#if zig_has_builtin(bitreverse8)
1613 full_res = __builtin_bitreverse8(val);
1783 full_res = __builtin_bitreverse8(arg);
16141784#else
16151785 static uint8_t const lut[0x10] = {
16161786 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
16171787 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
16181788 };
1619 full_res = lut[val >> 0 & 0xF] << 4 | lut[val >> 4 & 0xF] << 0;
1789 full_res = lut[arg >> 0 & 0xF] << 4 | lut[arg >> 4 & 0xF] << 0;
16201790#endif
1621 return zig_wrap_u8(full_res >> (8 - bits), bits);
1791 return zig_u8_truncate_u8(full_res >> (8 - bits), bits);
16221792}
16231793
1624static inline int8_t zig_bit_reverse_i8(int8_t val, uint8_t bits) {
1625 return zig_wrap_i8((int8_t)zig_bit_reverse_u8((uint8_t)val, bits), bits);
1794static inline int8_t zig_bitReverse_i8(int8_t arg, uint8_t bits) {
1795 return zig_i8_truncate_i8((int8_t)zig_bitReverse_u8((uint8_t)arg, bits), bits);
16261796}
16271797
1628static inline uint16_t zig_bit_reverse_u16(uint16_t val, uint8_t bits) {
1798static inline uint16_t zig_bitReverse_u16(uint16_t arg, uint8_t bits) {
16291799 uint16_t full_res;
16301800#if zig_has_builtin(bitreverse16)
1631 full_res = __builtin_bitreverse16(val);
1801 full_res = __builtin_bitreverse16(arg);
16321802#else
1633 full_res = (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 8 |
1634 (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 8), 8) >> 0;
1803 full_res = (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 8 |
1804 (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 8), 8) >> 0;
16351805#endif
1636 return zig_wrap_u16(full_res >> (16 - bits), bits);
1806 return zig_u16_truncate_u16(full_res >> (16 - bits), bits);
16371807}
16381808
1639static inline int16_t zig_bit_reverse_i16(int16_t val, uint8_t bits) {
1640 return zig_wrap_i16((int16_t)zig_bit_reverse_u16((uint16_t)val, bits), bits);
1809static inline int16_t zig_bitReverse_i16(int16_t arg, uint8_t bits) {
1810 return zig_i16_truncate_i16((int16_t)zig_bitReverse_u16((uint16_t)arg, bits), bits);
16411811}
16421812
16431813#if defined(zig_ez80)
1644static inline uint24_t zig_bit_reverse_u24(uint24_t val, uint8_t bits) {
1814static inline uint24_t zig_bitReverse_u24(uint24_t arg, uint8_t bits) {
16451815 uint24_t full_res;
16461816#if zig_has_builtin(bitreverse24)
1647 full_res = __builtin_bitreverse24(val);
1817 full_res = __builtin_bitreverse24(arg);
16481818#else
1649 full_res = (uint24_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 16 |
1650 (uint24_t)zig_bit_reverse_u16((uint16_t)(val >> 8), 16) >> 0;
1819 full_res = (uint24_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 16 |
1820 (uint24_t)zig_bitReverse_u16((uint16_t)(arg >> 8), 16) >> 0;
16511821#endif
1652 return zig_wrap_u24(full_res >> (24 - bits), bits);
1822 return zig_u24_truncate_u24(full_res >> (24 - bits), bits);
16531823}
16541824
1655static inline int24_t zig_bit_reverse_i24(int24_t val, uint8_t bits) {
1656 return zig_wrap_i24((int24_t)zig_bit_reverse_u24((uint24_t)val, bits), bits);
1825static inline int24_t zig_bitReverse_i24(int24_t arg, uint8_t bits) {
1826 return zig_i24_truncate_i24((int24_t)zig_bitReverse_u24((uint24_t)arg, bits), bits);
16571827}
16581828#endif
16591829
1660static inline uint32_t zig_bit_reverse_u32(uint32_t val, uint8_t bits) {
1830static inline uint32_t zig_bitReverse_u32(uint32_t arg, uint8_t bits) {
16611831 uint32_t full_res;
16621832#if zig_has_builtin(bitreverse32)
1663 full_res = __builtin_bitreverse32(val);
1833 full_res = __builtin_bitreverse32(arg);
16641834#else
1665 full_res = (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 0), 16) << 16 |
1666 (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 16), 16) >> 0;
1835 full_res = (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 0), 16) << 16 |
1836 (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 16), 16) >> 0;
16671837#endif
1668 return zig_wrap_u32(full_res >> (32 - bits), bits);
1838 return zig_u32_truncate_u32(full_res >> (32 - bits), bits);
16691839}
16701840
1671static inline int32_t zig_bit_reverse_i32(int32_t val, uint8_t bits) {
1672 return zig_wrap_i32((int32_t)zig_bit_reverse_u32((uint32_t)val, bits), bits);
1841static inline int32_t zig_bitReverse_i32(int32_t arg, uint8_t bits) {
1842 return zig_i32_truncate_i32((int32_t)zig_bitReverse_u32((uint32_t)arg, bits), bits);
16731843}
16741844
16751845#if defined(zig_ez80)
1676static inline uint32_t zig_bit_reverse_u48(uint48_t val, uint8_t bits) {
1846static inline uint32_t zig_bitReverse_u48(uint48_t arg, uint8_t bits) {
16771847 uint48_t full_res;
16781848#if zig_has_builtin(bitreverse48)
1679 full_res = __builtin_bitreverse48(val);
1849 full_res = __builtin_bitreverse48(arg);
16801850#else
1681 full_res = (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 0), 24) << 24 |
1682 (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 24), 24) >> 0;
1851 full_res = (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 0), 24) << 24 |
1852 (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 24), 24) >> 0;
16831853#endif
1684 return zig_wrap_u32(full_res >> (48 - bits), bits);
1854 return zig_u48_truncate_u48(full_res >> (48 - bits), bits);
16851855}
16861856
1687static inline int32_t zig_bit_reverse_i48(int48_t val, uint8_t bits) {
1688 return zig_wrap_i48((int48_t)zig_bit_reverse_u48((uint48_t)val, bits), bits);
1857static inline int32_t zig_bitReverse_i48(int48_t arg, uint8_t bits) {
1858 return zig_i48_truncate_i48((int48_t)zig_bitReverse_u48((uint48_t)arg, bits), bits);
16891859}
16901860#endif
16911861
1692static inline uint64_t zig_bit_reverse_u64(uint64_t val, uint8_t bits) {
1862static inline uint64_t zig_bitReverse_u64(uint64_t arg, uint8_t bits) {
16931863 uint64_t full_res;
16941864#if zig_has_builtin(bitreverse64)
1695 full_res = __builtin_bitreverse64(val);
1865 full_res = __builtin_bitreverse64(arg);
16961866#else
1697 full_res = (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 0), 32) << 32 |
1698 (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 32), 32) >> 0;
1867 full_res = (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 0), 32) << 32 |
1868 (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 32), 32) >> 0;
16991869#endif
1700 return zig_wrap_u64(full_res >> (64 - bits), bits);
1870 return zig_u64_truncate_u64(full_res >> (64 - bits), bits);
17011871}
17021872
1703static inline int64_t zig_bit_reverse_i64(int64_t val, uint8_t bits) {
1704 return zig_wrap_i64((int64_t)zig_bit_reverse_u64((uint64_t)val, bits), bits);
1873static inline int64_t zig_bitReverse_i64(int64_t arg, uint8_t bits) {
1874 return zig_i64_truncate_i64((int64_t)zig_bitReverse_u64((uint64_t)arg, bits), bits);
17051875}
17061876
1707#define zig_builtin_popcount_common(w) \
1708 static inline uint8_t zig_popcount_i##w(int##w##_t val, uint8_t bits) { \
1709 return zig_popcount_u##w((uint##w##_t)val, bits); \
1877#define zig_builtin_popCount_common(w) \
1878 static inline uint8_t zig_popCount_i##w(int##w##_t arg, uint8_t bits) { \
1879 return zig_popCount_u##w((uint##w##_t)arg, bits); \
17101880 }
1711#if zig_has_builtin(popcount) || defined(zig_gcc) || defined(zig_tinyc)
1712#define zig_builtin_popcount(w) \
1713 static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \
1881#if zig_has_builtin(popCount) || defined(zig_gcc) || defined(zig_tinyc)
1882#define zig_builtin_popCount(w) \
1883 static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \
17141884 (void)bits; \
1715 return zig_builtin##w(popcount, val); \
1885 return zig_builtin##w(popcount, arg); \
17161886 } \
17171887\
1718 zig_builtin_popcount_common(w)
1888 zig_builtin_popCount_common(w)
17191889#else
1720#define zig_builtin_popcount(w) \
1721 static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \
1890#define zig_builtin_popCount(w) \
1891 static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \
17221892 (void)bits; \
1723 uint##w##_t temp = val - ((val >> 1) & (UINT##w##_MAX / 3)); \
1893 uint##w##_t temp = arg - ((arg >> 1) & (UINT##w##_MAX / 3)); \
17241894 temp = (temp & (UINT##w##_MAX / 5)) + ((temp >> 2) & (UINT##w##_MAX / 5)); \
17251895 temp = (temp + (temp >> 4)) & (UINT##w##_MAX / 17); \
17261896 return temp * (UINT##w##_MAX / 255) >> (UINT8_C(w) - UINT8_C(8)); \
17271897 } \
17281898\
1729 zig_builtin_popcount_common(w)
1730#endif
1731zig_builtin_popcount(8)
1732zig_builtin_popcount(16)
1733#if defined(zig_ez80)
1734zig_builtin_popcount(24)
1899 zig_builtin_popCount_common(w)
17351900#endif
1736zig_builtin_popcount(32)
1901zig_builtin_popCount(8)
1902zig_builtin_popCount(16)
1903zig_builtin_popCount(32)
1904zig_builtin_popCount(64)
17371905#if defined(zig_ez80)
1738zig_builtin_popcount(48)
1906zig_builtin_popCount(24)
1907zig_builtin_popCount(48)
17391908#endif
1740zig_builtin_popcount(64)
17411909
17421910#define zig_builtin_ctz_common(w) \
1743 static inline uint8_t zig_ctz_i##w(int##w##_t val, uint8_t bits) { \
1744 return zig_ctz_u##w((uint##w##_t)val, bits); \
1911 static inline uint8_t zig_ctz_i##w(int##w##_t arg, uint8_t bits) { \
1912 return zig_ctz_u##w((uint##w##_t)arg, bits); \
17451913 }
17461914#if zig_has_builtin(ctz) || defined(zig_gcc) || defined(zig_tinyc)
17471915#define zig_builtin_ctz(w) \
1748 static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \
1749 if (val == 0) return bits; \
1750 return zig_builtin##w(ctz, val); \
1916 static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \
1917 if (arg == 0) return bits; \
1918 return zig_builtin##w(ctz, arg); \
17511919 } \
17521920\
17531921 zig_builtin_ctz_common(w)
17541922#else
17551923#define zig_builtin_ctz(w) \
1756 static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \
1757 return zig_popcount_u##w(zig_not_u##w(val, bits) & zig_subw_u##w(val, 1, bits), bits); \
1924 static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \
1925 return zig_popCount_u##w(zig_not_u##w(arg, bits) & zig_subw_u##w(arg, 1, bits), bits); \
17581926 } \
17591927\
17601928 zig_builtin_ctz_common(w)
17611929#endif
17621930zig_builtin_ctz(8)
17631931zig_builtin_ctz(16)
1764#if defined(zig_ez80)
1765zig_builtin_ctz(24)
1766#endif
17671932zig_builtin_ctz(32)
1933zig_builtin_ctz(64)
17681934#if defined(zig_ez80)
1935zig_builtin_ctz(24)
17691936zig_builtin_ctz(48)
17701937#endif
1771zig_builtin_ctz(64)
17721938
17731939#define zig_builtin_clz_common(w) \
1774 static inline uint8_t zig_clz_i##w(int##w##_t val, uint8_t bits) { \
1775 return zig_clz_u##w((uint##w##_t)val, bits); \
1940 static inline uint8_t zig_clz_i##w(int##w##_t arg, uint8_t bits) { \
1941 return zig_clz_u##w((uint##w##_t)arg, bits); \
17761942 }
17771943#if zig_has_builtin(clz) || defined(zig_gcc) || defined(zig_tinyc)
17781944#define zig_builtin_clz(w) \
1779 static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \
1780 if (val == 0) return bits; \
1781 return zig_builtin##w(clz, val) - (zig_bitSizeOf(zig_Builtin##w) - bits); \
1945 static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \
1946 if (arg == 0) return bits; \
1947 return zig_builtin##w(clz, arg) - (zig_bitSizeOf(zig_Builtin##w) - bits); \
17821948 } \
17831949\
17841950 zig_builtin_clz_common(w)
17851951#else
17861952#define zig_builtin_clz(w) \
1787 static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \
1788 return zig_ctz_u##w(zig_bit_reverse_u##w(val, bits), bits); \
1953 static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \
1954 return zig_ctz_u##w(zig_bitReverse_u##w(arg, bits), bits); \
17891955 } \
17901956\
17911957 zig_builtin_clz_common(w)
17921958#endif
17931959zig_builtin_clz(8)
17941960zig_builtin_clz(16)
1795#if defined(zig_ez80)
1796zig_builtin_clz(24)
1797#endif
17981961zig_builtin_clz(32)
1962zig_builtin_clz(64)
17991963#if defined(zig_ez80)
1964zig_builtin_clz(24)
18001965zig_builtin_clz(48)
18011966#endif
1802zig_builtin_clz(64)
18031967
18041968/* ======================== 128-bit Integer Support ========================= */
18051969
......@@ -1816,16 +1980,14 @@ zig_builtin_clz(64)
18161980typedef unsigned __int128 zig_u128;
18171981typedef signed __int128 zig_i128;
18181982
1819#define zig_make_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))
1820#define zig_make_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo))
1821#define zig_init_u128(hi, lo) zig_make_u128(hi, lo)
1822#define zig_init_i128(hi, lo) zig_make_i128(hi, lo)
1823#define zig_hi_u128(val) ((uint64_t)((val) >> 64))
1824#define zig_lo_u128(val) ((uint64_t)((val) >> 0))
1825#define zig_hi_i128(val) (( int64_t)((val) >> 64))
1826#define zig_lo_i128(val) ((uint64_t)((val) >> 0))
1827#define zig_bitCast_u128(val) ((zig_u128)(val))
1828#define zig_bitCast_i128(val) ((zig_i128)(val))
1983#define zig_init_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))
1984#define zig_init_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo))
1985#define zig_make_u128(hi, lo) zig_init_u128(hi, lo)
1986#define zig_make_i128(hi, lo) zig_init_i128(hi, lo)
1987#define zig_hi_u128(arg) ((uint64_t)((arg) >> 64))
1988#define zig_lo_u128(arg) ((uint64_t)((arg) >> 0))
1989#define zig_hi_i128(arg) (( int64_t)((arg) >> 64))
1990#define zig_lo_i128(arg) ((uint64_t)((arg) >> 0))
18291991#define zig_cmp_int128(Type) \
18301992 static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
18311993 return (lhs > rhs) - (lhs < rhs); \
......@@ -1835,32 +1997,49 @@ typedef signed __int128 zig_i128;
18351997 return lhs operator rhs; \
18361998 }
18371999
1838#else /* zig_has_int128 */
2000static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
2001 return lhs << rhs;
2002}
18392003
1840#if zig_little_endian
1841typedef struct { zig_align(16) uint64_t lo; uint64_t hi; } zig_u128;
1842typedef struct { zig_align(16) uint64_t lo; int64_t hi; } zig_i128;
2004static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
2005 return lhs >> rhs;
2006}
2007
2008static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {
2009 return lhs << rhs;
2010}
2011
2012static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
2013 // This works around a GCC miscompilation, but it has the side benefit of
2014 // emitting better code. It is behind the `#if` because it depends on
2015 // arithmetic right shift, which is implementation-defined in C, but should
2016 // be guaranteed on any GCC-compatible compiler.
2017#if defined(zig_gnuc)
2018 return lhs >> rhs;
18432019#else
1844typedef struct { zig_align(16) uint64_t hi; uint64_t lo; } zig_u128;
1845typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;
2020 zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0);
2021 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask;
18462022#endif
2023}
18472024
1848#define zig_make_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) })
1849#define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) })
2025#else /* zig_has_int128 */
18502026
1851#if defined(zig_msvc) /* MSVC doesn't allow struct literals in constant expressions */
1852#define zig_init_u128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1853#define zig_init_i128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1854#else /* But non-MSVC doesn't like the unprotected commas */
1855#define zig_init_u128(hi, lo) zig_make_u128(hi, lo)
1856#define zig_init_i128(hi, lo) zig_make_i128(hi, lo)
1857#endif
1858#define zig_hi_u128(val) ((val).hi)
1859#define zig_lo_u128(val) ((val).lo)
1860#define zig_hi_i128(val) ((val).hi)
1861#define zig_lo_i128(val) ((val).lo)
1862#define zig_bitCast_u128(val) zig_make_u128((uint64_t)(val).hi, (val).lo)
1863#define zig_bitCast_i128(val) zig_make_i128(( int64_t)(val).hi, (val).lo)
2027#if zig_little_endian
2028typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; uint64_t hi; } zig_u128;
2029typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; int64_t hi; } zig_i128;
2030#else
2031typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t hi; uint64_t lo; } zig_u128;
2032typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) int64_t hi; uint64_t lo; } zig_i128;
2033#endif
2034
2035#define zig_init_u128(hi, lo) { .h##i = hi, .l##o = lo }
2036#define zig_init_i128(hi, lo) { .h##i = hi, .l##o = lo }
2037#define zig_make_u128(hi, lo) (zig_u128)zig_init_u128(hi, lo)
2038#define zig_make_i128(hi, lo) (zig_i128)zig_init_i128(hi, lo)
2039#define zig_hi_u128(arg) (arg).hi
2040#define zig_lo_u128(arg) (arg).lo
2041#define zig_hi_i128(arg) (arg).hi
2042#define zig_lo_i128(arg) (arg).lo
18642043#define zig_cmp_int128(Type) \
18652044 static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
18662045 return (lhs.hi == rhs.hi) \
......@@ -1872,6 +2051,30 @@ typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;
18722051 return (zig_##Type){ .hi = lhs.hi operator rhs.hi, .lo = lhs.lo operator rhs.lo }; \
18732052 }
18742053
2054static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
2055 if (rhs == UINT8_C(0)) return lhs;
2056 if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
2057 return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
2058}
2059
2060static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
2061 if (rhs == UINT8_C(0)) return lhs;
2062 if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - UINT8_C(64)) };
2063 return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (UINT8_C(64) - rhs) | lhs.lo >> rhs };
2064}
2065
2066static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {
2067 if (rhs == UINT8_C(0)) return lhs;
2068 if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
2069 return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
2070}
2071
2072static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
2073 if (rhs == UINT8_C(0)) return lhs;
2074 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))) };
2075 return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) };
2076}
2077
18752078#endif /* zig_has_int128 */
18762079
18772080#define zig_minInt_u128 zig_make_u128(zig_minInt_u64, zig_minInt_u64)
......@@ -1891,42 +2094,177 @@ zig_bit_int128(i128, or, |)
18912094zig_bit_int128(u128, xor, ^)
18922095zig_bit_int128(i128, xor, ^)
18932096
1894static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs);
2097static inline uint8_t zig_u8_intCast_u128(zig_u128 arg) {
2098 return (uint8_t)zig_lo_u128(arg);
2099}
2100static inline uint8_t zig_u8_intCast_i128(zig_i128 arg) {
2101 return (uint8_t)zig_lo_i128(arg);
2102}
2103static inline int8_t zig_i8_intCast_i128(zig_i128 arg) {
2104 return (int8_t)zig_lo_i128(arg);
2105}
2106static inline int8_t zig_i8_intCast_u128(zig_u128 arg) {
2107 return (int8_t)zig_lo_u128(arg);
2108}
18952109
1896#if zig_has_int128
2110static inline uint16_t zig_u16_intCast_u128(zig_u128 arg) {
2111 return (uint16_t)zig_lo_u128(arg);
2112}
2113static inline uint16_t zig_u16_intCast_i128(zig_i128 arg) {
2114 return (uint16_t)zig_lo_i128(arg);
2115}
2116static inline int16_t zig_i16_intCast_i128(zig_i128 arg) {
2117 return (int16_t)zig_lo_i128(arg);
2118}
2119static inline int16_t zig_i16_intCast_u128(zig_u128 arg) {
2120 return (int16_t)zig_lo_u128(arg);
2121}
18972122
1898static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) {
1899 return val ^ zig_maxInt_u(128, bits);
2123static inline uint32_t zig_u32_intCast_u128(zig_u128 arg) {
2124 return (uint32_t)zig_lo_u128(arg);
2125}
2126static inline uint32_t zig_u32_intCast_i128(zig_i128 arg) {
2127 return (uint32_t)zig_lo_i128(arg);
2128}
2129static inline int32_t zig_i32_intCast_i128(zig_i128 arg) {
2130 return (int32_t)zig_lo_i128(arg);
2131}
2132static inline int32_t zig_i32_intCast_u128(zig_u128 arg) {
2133 return (int32_t)zig_lo_u128(arg);
19002134}
19012135
1902static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) {
1903 (void)bits;
1904 return ~val;
2136static inline uint64_t zig_u64_intCast_u128(zig_u128 arg) {
2137 return zig_lo_u128(arg);
2138}
2139static inline uint64_t zig_u64_intCast_i128(zig_i128 arg) {
2140 return zig_lo_i128(arg);
2141}
2142static inline int64_t zig_i64_intCast_i128(zig_i128 arg) {
2143 return (int64_t)zig_lo_i128(arg);
2144}
2145static inline int64_t zig_i64_intCast_u128(zig_u128 arg) {
2146 return (int64_t)zig_lo_u128(arg);
19052147}
19062148
1907static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
1908 return lhs >> rhs;
2149static inline zig_u128 zig_u128_intCast_u8(uint8_t arg) {
2150 return zig_make_u128(UINT8_C(0), arg);
2151}
2152static inline zig_u128 zig_u128_intCast_i8(int8_t arg) {
2153 return zig_make_u128(UINT8_C(0), (uint8_t)arg);
2154}
2155static inline zig_i128 zig_i128_intCast_i8(int8_t arg) {
2156 return zig_make_i128(zig_shr_i64(arg, 63), (uint8_t)arg);
2157}
2158static inline zig_i128 zig_i128_intCast_u8(uint8_t arg) {
2159 return zig_make_i128(INT8_C(0), arg);
19092160}
19102161
1911static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
1912 return lhs << rhs;
2162static inline zig_u128 zig_u128_intCast_u16(uint16_t arg) {
2163 return zig_make_u128(UINT16_C(0), arg);
2164}
2165static inline zig_u128 zig_u128_intCast_i16(int16_t arg) {
2166 return zig_make_u128(UINT16_C(0), (uint16_t)arg);
2167}
2168static inline zig_i128 zig_i128_intCast_i16(int16_t arg) {
2169 return zig_make_i128(zig_shr_i64(arg, 63), (uint16_t)arg);
2170}
2171static inline zig_i128 zig_i128_intCast_u16(uint16_t arg) {
2172 return zig_make_i128(INT16_C(0), arg);
19132173}
19142174
1915static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
1916 // This works around a GCC miscompilation, but it has the side benefit of
1917 // emitting better code. It is behind the `#if` because it depends on
1918 // arithmetic right shift, which is implementation-defined in C, but should
1919 // be guaranteed on any GCC-compatible compiler.
1920#if defined(zig_gnuc)
1921 return lhs >> rhs;
2175static inline zig_u128 zig_u128_intCast_u32(uint32_t arg) {
2176 return zig_make_u128(UINT32_C(0), arg);
2177}
2178static inline zig_u128 zig_u128_intCast_i32(int32_t arg) {
2179 return zig_make_u128(UINT32_C(0), (uint32_t)arg);
2180}
2181static inline zig_i128 zig_i128_intCast_i32(int32_t arg) {
2182 return zig_make_i128(zig_shr_i64(arg, 63), (uint32_t)arg);
2183}
2184static inline zig_i128 zig_i128_intCast_u32(uint32_t arg) {
2185 return zig_make_i128(INT32_C(0), arg);
2186}
2187
2188static inline zig_u128 zig_u128_intCast_u64(uint64_t arg) {
2189 return zig_make_u128(UINT64_C(0), arg);
2190}
2191static inline zig_u128 zig_u128_intCast_i64(int64_t arg) {
2192 return zig_make_u128(UINT64_C(0), (uint64_t)arg);
2193}
2194static inline zig_i128 zig_i128_intCast_i64(int64_t arg) {
2195 return zig_make_i128(zig_shr_i64(arg, 63), (uint64_t)arg);
2196}
2197static inline zig_i128 zig_i128_intCast_u64(uint64_t arg) {
2198 return zig_make_i128(INT64_C(0), arg);
2199}
2200
2201static inline zig_u128 zig_u128_intCast_u128(zig_u128 arg) {
2202 return arg;
2203}
2204static inline zig_u128 zig_u128_intCast_i128(zig_i128 arg) {
2205#if zig_has_int128
2206 return (zig_u128)arg;
19222207#else
1923 zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0);
1924 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask;
2208 return zig_make_u128(zig_u64_bitCast_i64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg));
2209#endif
2210}
2211static inline zig_i128 zig_i128_intCast_i128(zig_i128 arg) {
2212 return arg;
2213}
2214static inline zig_i128 zig_i128_intCast_u128(zig_u128 arg) {
2215#if zig_has_int128
2216 return (zig_i128)arg;
2217#else
2218 return zig_make_i128(zig_i64_bitCast_u64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg));
19252219#endif
19262220}
19272221
1928static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {
1929 return lhs << rhs;
2222#define zig_int128_cast_builtins(w) \
2223 static inline uint##w##_t zig_u##w##_truncate_u128(zig_u128 arg, uint8_t bits) { \
2224 return zig_u##w##_truncate_u##w((uint##w##_t)zig_lo_u128(arg), bits); \
2225 } \
2226\
2227 static inline int##w##_t zig_i##w##_truncate_i128(zig_i128 arg, uint8_t bits) { \
2228 return zig_i##w##_truncate_i##w((int##w##_t)zig_lo_i128(arg), bits); \
2229 }
2230zig_int128_cast_builtins(8)
2231zig_int128_cast_builtins(16)
2232zig_int128_cast_builtins(32)
2233zig_int128_cast_builtins(64)
2234
2235static inline zig_u128 zig_u128_truncate_u128(zig_u128 arg, uint8_t bits) {
2236 return zig_and_u128(arg, zig_maxInt_u(128, bits));
2237}
2238static inline zig_i128 zig_i128_truncate_i128(zig_i128 arg, uint8_t bits) {
2239 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));
2240 int64_t lo = zig_i64_truncate_i128(arg, bits);
2241 return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo);
2242}
2243
2244static inline zig_u128 zig_u128_bitCast_u128(zig_u128 arg, uint8_t bits) {
2245 (void)bits;
2246 return arg;
2247}
2248static inline zig_u128 zig_u128_bitCast_i128(zig_i128 arg, uint8_t bits) {
2249 return zig_u128_truncate_u128(zig_u128_intCast_i128(arg), bits);
2250}
2251static inline zig_i128 zig_i128_bitCast_i128(zig_i128 arg, uint8_t bits) {
2252 (void)bits;
2253 return arg;
2254}
2255static inline zig_i128 zig_i128_bitCast_u128(zig_u128 arg, uint8_t bits) {
2256 return zig_i128_truncate_i128(zig_i128_intCast_u128(arg), bits);
2257}
2258
2259#if zig_has_int128
2260
2261static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) {
2262 return arg ^ zig_maxInt_u(128, bits);
2263}
2264
2265static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) {
2266 (void)bits;
2267 return ~arg;
19302268}
19312269
19322270static 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) {
19532291 return lhs * rhs;
19542292}
19552293
1956static inline zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) {
2294static inline zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) {
19572295 return lhs / rhs;
19582296}
19592297
1960static inline zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) {
2298static inline zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) {
19612299 return lhs / rhs;
19622300}
19632301
......@@ -1971,36 +2309,14 @@ static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
19712309
19722310#else /* zig_has_int128 */
19732311
1974static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) {
1975 return (zig_u128){ .hi = zig_not_u64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) };
1976}
1977
1978static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) {
1979 return (zig_i128){ .hi = zig_not_i64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) };
1980}
1981
1982static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
1983 if (rhs == UINT8_C(0)) return lhs;
1984 if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - UINT8_C(64)) };
1985 return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (UINT8_C(64) - rhs) | lhs.lo >> rhs };
1986}
1987
1988static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
1989 if (rhs == UINT8_C(0)) return lhs;
1990 if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
1991 return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
1992}
1993
1994static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
1995 if (rhs == UINT8_C(0)) return lhs;
1996 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))) };
1997 return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) };
2312static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) {
2313 if (bits <= UINT8_C(64)) return (zig_u128){ .hi = UINT64_C(0), .lo = zig_not_u64(arg.lo, bits) };
2314 return (zig_u128){ .hi = zig_not_u64(arg.hi, bits - UINT8_C(64)), .lo = zig_not_u64(arg.lo, UINT8_C(64)) };
19982315}
19992316
2000static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {
2001 if (rhs == UINT8_C(0)) return lhs;
2002 if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
2003 return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
2317static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) {
2318 (void)bits;
2319 return (zig_i128){ .hi = ~arg.hi, .lo = ~arg.lo };
20042320}
20052321
20062322static 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) {
20272343 return res;
20282344}
20292345
2030zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs);
20312346static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {
2347 zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs);
20322348 return __multi3(lhs, rhs);
20332349}
20342350
20352351static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) {
2036 return zig_bitCast_u128(zig_mul_i128(zig_bitCast_i128(lhs), zig_bitCast_i128(rhs)));
2352 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));
20372353}
20382354
2039zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs);
2040static zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) {
2355static zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) {
2356 zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs);
20412357 return __udivti3(lhs, rhs);
20422358}
20432359
2044zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs);
2045static zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) {
2360static zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) {
2361 zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs);
20462362 return __divti3(lhs, rhs);
20472363}
20482364
2049zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs);
20502365static zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) {
2366 zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs);
20512367 return __umodti3(lhs, rhs);
20522368}
20532369
2054zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs);
20552370static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
2371 zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs);
20562372 return __modti3(lhs, rhs);
20572373}
20582374
20592375#endif /* zig_has_int128 */
20602376
2061#define zig_div_floor_u128 zig_div_trunc_u128
2377#define zig_divFloor_u128 zig_divTrunc_u128
20622378
2063static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) {
2379static inline zig_i128 zig_divFloor_i128(zig_i128 lhs, zig_i128 rhs) {
20642380 zig_i128 rem = zig_rem_i128(lhs, rhs);
20652381 int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0)
20662382 ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) : INT64_C(0);
2067 return zig_add_i128(zig_div_trunc_i128(lhs, rhs), zig_make_i128(mask, (uint64_t)mask));
2383 return zig_add_i128(zig_divTrunc_i128(lhs, rhs), zig_make_i128(mask, (uint64_t)mask));
20682384}
20692385
2070static inline zig_u128 zig_div_ceil_u128(zig_u128 lhs, zig_u128 rhs) {
2386static inline zig_u128 zig_divCeil_u128(zig_u128 lhs, zig_u128 rhs) {
20712387 zig_u128 rem = zig_rem_u128(lhs, rhs);
20722388 uint64_t mask = zig_or_u64(zig_hi_u128(rem), zig_lo_u128(rem)) != UINT64_C(0)
20732389 ? UINT64_C(1) : UINT64_C(0);
2074 return zig_add_u128(zig_div_trunc_u128(lhs, rhs), zig_make_u128(UINT64_C(0), mask));
2390 return zig_add_u128(zig_divTrunc_u128(lhs, rhs), zig_make_u128(UINT64_C(0), mask));
20752391}
20762392
2077static inline zig_i128 zig_div_ceil_i128(zig_i128 lhs, zig_i128 rhs) {
2393static inline zig_i128 zig_divCeil_i128(zig_i128 lhs, zig_i128 rhs) {
20782394 zig_i128 rem = zig_rem_i128(lhs, rhs);
20792395 int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0)
20802396 ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) + INT64_C(1)
20812397 : INT64_C(0);
2082 return zig_add_i128(zig_div_trunc_i128(lhs, rhs), zig_make_i128(INT64_C(0), (uint64_t)mask));
2398 return zig_add_i128(zig_divTrunc_i128(lhs, rhs), zig_make_i128(INT64_C(0), (uint64_t)mask));
20832399}
20842400
20852401#define zig_mod_u128 zig_rem_u128
......@@ -2107,51 +2423,41 @@ static inline zig_i128 zig_max_i128(zig_i128 lhs, zig_i128 rhs) {
21072423 return zig_cmp_i128(lhs, rhs) > INT32_C(0) ? lhs : rhs;
21082424}
21092425
2110static inline zig_u128 zig_wrap_u128(zig_u128 val, uint8_t bits) {
2111 return zig_and_u128(val, zig_maxInt_u(128, bits));
2112}
2113
2114static inline zig_i128 zig_wrap_i128(zig_i128 val, uint8_t bits) {
2115 if (bits > UINT8_C(64)) return zig_make_i128(zig_wrap_i64(zig_hi_i128(val), bits - UINT8_C(64)), zig_lo_i128(val));
2116 int64_t lo = zig_wrap_i64((int64_t)zig_lo_i128(val), bits);
2117 return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo);
2118}
2119
21202426static inline zig_u128 zig_shlw_u128(zig_u128 lhs, uint8_t rhs, uint8_t bits) {
2121 return zig_wrap_u128(zig_shl_u128(lhs, rhs), bits);
2427 return zig_u128_truncate_u128(zig_shl_u128(lhs, rhs), bits);
21222428}
21232429
21242430static inline zig_i128 zig_shlw_i128(zig_i128 lhs, uint8_t rhs, uint8_t bits) {
2125 return zig_wrap_i128(zig_bitCast_i128(zig_shl_u128(zig_bitCast_u128(lhs), rhs)), bits);
2431 return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_shl_u128(zig_u128_bitCast_i128(lhs, bits), rhs), bits), bits);
21262432}
21272433
21282434static inline zig_u128 zig_addw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2129 return zig_wrap_u128(zig_add_u128(lhs, rhs), bits);
2435 return zig_u128_truncate_u128(zig_add_u128(lhs, rhs), bits);
21302436}
21312437
21322438static inline zig_i128 zig_addw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2133 return zig_wrap_i128(zig_bitCast_i128(zig_add_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits);
2439 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);
21342440}
21352441
21362442static inline zig_u128 zig_subw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2137 return zig_wrap_u128(zig_sub_u128(lhs, rhs), bits);
2443 return zig_u128_truncate_u128(zig_sub_u128(lhs, rhs), bits);
21382444}
21392445
21402446static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2141 return zig_wrap_i128(zig_bitCast_i128(zig_sub_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits);
2447 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);
21422448}
21432449
21442450static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2145 return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits);
2451 return zig_u128_truncate_u128(zig_mul_u128(lhs, rhs), bits);
21462452}
21472453
21482454static inline zig_i128 zig_mulw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2149 return zig_wrap_i128(zig_bitCast_i128(zig_mul_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits);
2455 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);
21502456}
21512457
2152static inline zig_u128 zig_abs_i128(zig_i128 val) {
2153 zig_i128 tmp = zig_shr_i128(val, 127);
2154 return zig_bitCast_u128(zig_sub_i128(zig_xor_i128(val, tmp), tmp));
2458static inline zig_u128 zig_abs_i128(zig_i128 arg) {
2459 zig_u128 tmp = zig_u128_bitCast_i128(zig_shr_i128(arg, 127), UINT8_C(128));
2460 return zig_sub_u128(zig_xor_u128(zig_u128_bitCast_i128(arg, UINT8_C(128)), tmp), tmp);
21552461}
21562462
21572463#if zig_has_int128
......@@ -2160,7 +2466,7 @@ static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
21602466#if zig_has_builtin(add_overflow)
21612467 zig_u128 full_res;
21622468 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
2163 *res = zig_wrap_u128(full_res, bits);
2469 *res = zig_u128_truncate_u128(full_res, bits);
21642470 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
21652471#else
21662472 *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
21762482 zig_i128 full_res = (zig_i128)((zig_u128)lhs + (zig_u128)rhs);
21772483 bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0;
21782484#endif
2179 *res = zig_wrap_i128(full_res, bits);
2485 *res = zig_i128_truncate_i128(full_res, bits);
21802486 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
21812487}
21822488
......@@ -2184,7 +2490,7 @@ static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
21842490#if zig_has_builtin(sub_overflow)
21852491 zig_u128 full_res;
21862492 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
2187 *res = zig_wrap_u128(full_res, bits);
2493 *res = zig_u128_truncate_u128(full_res, bits);
21882494 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
21892495#else
21902496 *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
22002506 zig_i128 full_res = (zig_i128)((zig_u128)lhs - (zig_u128)rhs);
22012507 bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0;
22022508#endif
2203 *res = zig_wrap_i128(full_res, bits);
2509 *res = zig_i128_truncate_i128(full_res, bits);
22042510 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
22052511}
22062512
......@@ -2208,7 +2514,7 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
22082514#if zig_has_builtin(mul_overflow)
22092515 zig_u128 full_res;
22102516 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
2211 *res = zig_wrap_u128(full_res, bits);
2517 *res = zig_u128_truncate_u128(full_res, bits);
22122518 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
22132519#else
22142520 *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
22162522#endif
22172523}
22182524
2219zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
22202525static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2526 zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
22212527#if zig_has_builtin(mul_overflow)
22222528 zig_i128 full_res;
22232529 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
22262532 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);
22272533 bool overflow = overflow_int != 0;
22282534#endif
2229 *res = zig_wrap_i128(full_res, bits);
2535 *res = zig_i128_truncate_i128(full_res, bits);
22302536 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
22312537}
22322538
22332539#else /* zig_has_int128 */
22342540
22352541static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2236 uint64_t hi;
2237 bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - 64);
2238 return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
2542 if (bits <= UINT8_C(64)) {
2543 uint64_t lo;
2544 bool overflow = zig_addo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits);
2545 *res = zig_u128_intCast_u64(lo);
2546 return overflow;
2547 } else {
2548 uint64_t hi;
2549 bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64));
2550 return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64));
2551 }
22392552}
22402553
22412554static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2242 int64_t hi;
2243 bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - 64);
2244 return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
2555 if (bits <= UINT8_C(64)) {
2556 int64_t lo;
2557 bool overflow = zig_addo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits);
2558 *res = zig_i128_intCast_i64(lo);
2559 return overflow;
2560 } else {
2561 int64_t hi;
2562 bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64));
2563 return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64));
2564 }
22452565}
22462566
22472567static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2248 uint64_t hi;
2249 bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - 64);
2250 return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
2568 if (bits <= UINT8_C(64)) {
2569 uint64_t lo;
2570 bool overflow = zig_subo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits);
2571 *res = zig_u128_intCast_u64(lo);
2572 return overflow;
2573 } else {
2574 uint64_t hi;
2575 bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64));
2576 return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64));
2577 }
22512578}
22522579
22532580static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2254 int64_t hi;
2255 bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - 64);
2256 return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
2581 if (bits <= UINT8_C(64)) {
2582 int64_t lo;
2583 bool overflow = zig_subo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits);
2584 *res = zig_i128_intCast_i64(lo);
2585 return overflow;
2586 } else {
2587 int64_t hi;
2588 bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64));
2589 return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64));
2590 }
22572591}
22582592
22592593static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
22602594 *res = zig_mulw_u128(lhs, rhs, bits);
2261 return zig_cmp_u128(*res, zig_make_u128(0, 0)) != INT32_C(0) &&
2262 zig_cmp_u128(lhs, zig_div_trunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0);
2595 return zig_cmp_u128(rhs, zig_make_u128(0, 0)) != INT32_C(0) &&
2596 zig_cmp_u128(lhs, zig_divTrunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0);
22632597}
22642598
2265zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
22662599static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2600 zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
22672601 int overflow_int;
22682602 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);
22692603 bool overflow = overflow_int != 0 ||
22702604 zig_cmp_i128(full_res, zig_minInt_i(128, bits)) < INT32_C(0) ||
22712605 zig_cmp_i128(full_res, zig_maxInt_i(128, bits)) > INT32_C(0);
2272 *res = zig_wrap_i128(full_res, bits);
2606 *res = zig_i128_truncate_i128(full_res, bits);
22732607 return overflow;
22742608}
22752609
......@@ -2282,28 +2616,54 @@ static inline bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, uint8_t rhs, uint8
22822616
22832617static inline bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, uint8_t rhs, uint8_t bits) {
22842618 *res = zig_shlw_i128(lhs, rhs, bits);
2285 zig_i128 mask = zig_bitCast_i128(zig_shl_u128(zig_maxInt_u128, bits - rhs - UINT8_C(1)));
2619 zig_i128 mask = zig_i128_bitCast_u128(zig_shl_u128(zig_maxInt_u128, bits - rhs - UINT8_C(1)), bits);
22862620 return zig_cmp_i128(zig_and_i128(lhs, mask), zig_make_i128(0, 0)) != INT32_C(0) &&
22872621 zig_cmp_i128(zig_and_i128(lhs, mask), mask) != INT32_C(0);
22882622}
22892623
2290static inline zig_u128 zig_shls_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2624#define zig_int128_shls_builtins(rw) \
2625 static inline zig_u128 zig_shls_u128_u##rw(zig_u128 lhs, uint##rw##_t rhs, uint8_t bits) { \
2626 zig_u128 res; \
2627 if (rhs < bits && !zig_shlo_u128(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \
2628 switch (zig_cmp_u128(lhs, zig_make_u128(UINT64_C(0), UINT64_C(0)))) { \
2629 case 0: return zig_minInt_u(128, bits); \
2630 case 1: return zig_maxInt_u(128, bits); \
2631 default: zig_unreachable(); \
2632 } \
2633 } \
2634\
2635 static inline zig_i128 zig_shls_i128_u##rw(zig_i128 lhs, uint##rw##_t rhs, uint8_t bits) { \
2636 zig_i128 res; \
2637 if (rhs < bits && !zig_shlo_i128(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \
2638 switch (zig_cmp_i128(lhs, zig_make_i128(INT64_C(0), UINT64_C(0)))) { \
2639 case -1: return zig_minInt_i(128, bits); \
2640 case 0: return zig_make_i128(INT64_C(0), UINT64_C(0)); \
2641 case 1: return zig_maxInt_i(128, bits); \
2642 default: zig_unreachable(); \
2643 } \
2644 }
2645zig_int128_shls_builtins(8)
2646zig_int128_shls_builtins(16)
2647zig_int128_shls_builtins(32)
2648zig_int128_shls_builtins(64)
2649
2650static inline zig_u128 zig_shls_u128_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
22912651 zig_u128 res;
22922652 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;
22932653 switch (zig_cmp_u128(lhs, zig_make_u128(0, 0))) {
2294 case 0: return zig_make_u128(0, 0);
2295 case 1: return zig_maxInt_u(128, bits);
2654 case INT32_C(0): return zig_make_u128(0, 0);
2655 case INT32_C(1): return zig_maxInt_u(128, bits);
22962656 default: zig_unreachable();
22972657 }
22982658}
22992659
2300static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) {
2660static inline zig_i128 zig_shls_i128_u128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) {
23012661 zig_i128 res;
23022662 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;
23032663 switch (zig_cmp_i128(lhs, zig_make_i128(0, 0))) {
2304 case -1: return zig_minInt_i(128, bits);
2305 case 0: return zig_make_i128(0, 0);
2306 case 1: return zig_maxInt_i(128, bits);
2664 case -INT32_C(1): return zig_minInt_i(128, bits);
2665 case INT32_C(0): return zig_make_i128(0, 0);
2666 case INT32_C(1): return zig_maxInt_i(128, bits);
23072667 default: zig_unreachable();
23082668 }
23092669}
......@@ -2341,57 +2701,60 @@ static inline zig_i128 zig_muls_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
23412701 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);
23422702}
23432703
2344static inline uint8_t zig_clz_u128(zig_u128 val, uint8_t bits) {
2345 if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(val), bits);
2346 if (zig_hi_u128(val) != 0) return zig_clz_u64(zig_hi_u128(val), bits - UINT8_C(64));
2347 return zig_clz_u64(zig_lo_u128(val), UINT8_C(64)) + (bits - UINT8_C(64));
2704static inline uint8_t zig_clz_u128(zig_u128 arg, uint8_t bits) {
2705 if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(arg), bits);
2706 if (zig_hi_u128(arg) != 0) return zig_clz_u64(zig_hi_u128(arg), bits - UINT8_C(64));
2707 return zig_clz_u64(zig_lo_u128(arg), UINT8_C(64)) + (bits - UINT8_C(64));
23482708}
23492709
2350static inline uint8_t zig_clz_i128(zig_i128 val, uint8_t bits) {
2351 return zig_clz_u128(zig_bitCast_u128(val), bits);
2710static inline uint8_t zig_clz_i128(zig_i128 arg, uint8_t bits) {
2711 return zig_clz_u128(zig_u128_bitCast_i128(arg, bits), bits);
23522712}
23532713
2354static inline uint8_t zig_ctz_u128(zig_u128 val, uint8_t bits) {
2355 if (zig_lo_u128(val) != 0) return zig_ctz_u64(zig_lo_u128(val), UINT8_C(64));
2356 return zig_ctz_u64(zig_hi_u128(val), bits - UINT8_C(64)) + UINT8_C(64);
2714static inline uint8_t zig_ctz_u128(zig_u128 arg, uint8_t bits) {
2715 if (zig_lo_u128(arg) != 0) return zig_ctz_u64(zig_lo_u128(arg), UINT8_C(64));
2716 return zig_ctz_u64(zig_hi_u128(arg), bits - UINT8_C(64)) + UINT8_C(64);
23572717}
23582718
2359static inline uint8_t zig_ctz_i128(zig_i128 val, uint8_t bits) {
2360 return zig_ctz_u128(zig_bitCast_u128(val), bits);
2719static inline uint8_t zig_ctz_i128(zig_i128 arg, uint8_t bits) {
2720 return zig_ctz_u128(zig_u128_bitCast_i128(arg, bits), bits);
23612721}
23622722
2363static inline uint8_t zig_popcount_u128(zig_u128 val, uint8_t bits) {
2364 return zig_popcount_u64(zig_hi_u128(val), bits - UINT8_C(64)) +
2365 zig_popcount_u64(zig_lo_u128(val), UINT8_C(64));
2723static inline uint8_t zig_popCount_u128(zig_u128 arg, uint8_t bits) {
2724 return (bits > UINT8_C(64) ? zig_popCount_u64(zig_hi_u128(arg), bits - UINT8_C(64)) : UINT8_C(0)) +
2725 zig_popCount_u64(zig_lo_u128(arg), UINT8_C(64));
23662726}
23672727
2368static inline uint8_t zig_popcount_i128(zig_i128 val, uint8_t bits) {
2369 return zig_popcount_u128(zig_bitCast_u128(val), bits);
2728static inline uint8_t zig_popCount_i128(zig_i128 arg, uint8_t bits) {
2729 return zig_popCount_u128(zig_u128_bitCast_i128(arg, bits), bits);
23702730}
23712731
2372static inline zig_u128 zig_byte_swap_u128(zig_u128 val, uint8_t bits) {
2732static inline zig_u128 zig_byteSwap_u128(zig_u128 arg, uint8_t bits) {
23732733 zig_u128 full_res;
23742734#if zig_has_builtin(bswap128)
2375 full_res = __builtin_bswap128(val);
2735 full_res = __builtin_bswap128(arg);
23762736#else
2377 full_res = zig_make_u128(zig_byte_swap_u64(zig_lo_u128(val), UINT8_C(64)),
2378 zig_byte_swap_u64(zig_hi_u128(val), UINT8_C(64)));
2737 full_res = zig_make_u128(
2738 zig_byteSwap_u64(zig_lo_u128(arg), UINT8_C(64)),
2739 zig_byteSwap_u64(zig_hi_u128(arg), UINT8_C(64))
2740 );
23792741#endif
23802742 return zig_shr_u128(full_res, UINT8_C(128) - bits);
23812743}
23822744
2383static inline zig_i128 zig_byte_swap_i128(zig_i128 val, uint8_t bits) {
2384 return zig_bitCast_i128(zig_byte_swap_u128(zig_bitCast_u128(val), bits));
2745static inline zig_i128 zig_byteSwap_i128(zig_i128 arg, uint8_t bits) {
2746 return zig_i128_bitCast_u128(zig_byteSwap_u128(zig_u128_bitCast_i128(arg, bits), bits), bits);
23852747}
23862748
2387static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, uint8_t bits) {
2388 return zig_shr_u128(zig_make_u128(zig_bit_reverse_u64(zig_lo_u128(val), UINT8_C(64)),
2389 zig_bit_reverse_u64(zig_hi_u128(val), UINT8_C(64))),
2390 UINT8_C(128) - bits);
2749static inline zig_u128 zig_bitReverse_u128(zig_u128 arg, uint8_t bits) {
2750 return zig_shr_u128(zig_make_u128(
2751 zig_bitReverse_u64(zig_lo_u128(arg), UINT8_C(64)),
2752 zig_bitReverse_u64(zig_hi_u128(arg), UINT8_C(64))
2753 ), UINT8_C(128) - bits);
23912754}
23922755
2393static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) {
2394 return zig_bitCast_i128(zig_bit_reverse_u128(zig_bitCast_u128(val), bits));
2756static inline zig_i128 zig_bitReverse_i128(zig_i128 arg, uint8_t bits) {
2757 return zig_i128_bitCast_u128(zig_bitReverse_u128(zig_u128_bitCast_i128(arg, bits), bits), bits);
23952758}
23962759
23972760#if zig_has_int128
......@@ -2411,15 +2774,218 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) {
24112774/* ========================== Big Integer Support =========================== */
24122775
24132776static inline uint16_t zig_int_bytes(uint16_t bits) {
2414 uint16_t bytes = (bits + CHAR_BIT - 1) / CHAR_BIT;
2777 uint16_t bytes = (bits - UINT16_C(1)) / CHAR_BIT + UINT16_C(1);
24152778 uint16_t alignment = ZIG_TARGET_MAX_INT_ALIGNMENT;
2779
24162780 while (alignment / 2 >= bytes) alignment /= 2;
24172781 return (bytes + alignment - 1) / alignment * alignment;
24182782}
24192783
2420static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2784static inline void zig_minInt_big(void *res, bool is_signed, uint16_t bits) {
2785 uint8_t *res_bytes = res;
2786 uint16_t size = zig_int_bytes(bits);
2787 uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3));
2788 uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1);
2789 uint8_t sign_byte;
2790 uint8_t fill_byte;
2791
2792 if (is_signed) {
2793 int8_t signed_sign_byte = zig_minInt_i(8, remainder_bits);
2794
2795 sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8));
2796 fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8));
2797 } else {
2798 sign_byte = zig_minInt_u(8, remainder_bits);
2799 fill_byte = UINT8_C(0);
2800 }
2801
2802#if zig_little_endian
2803 memset(&res_bytes[0], zig_minInt_u8, byte_offset);
2804 res_bytes[byte_offset] = sign_byte;
2805 byte_offset += UINT16_C(1);
2806 memset(&res_bytes[byte_offset], fill_byte, size - byte_offset);
2807#else
2808 byte_offset = size - UINT16_C(1) - byte_offset;
2809 memset(&res_bytes[0], fill_byte, byte_offset);
2810 res_bytes[byte_offset] = sign_byte;
2811 byte_offset += UINT16_C(1);
2812 memset(&res_bytes[byte_offset], zig_minInt_u8, size - byte_offset);
2813#endif
2814}
2815
2816static inline void zig_maxInt_big(void *res, bool is_signed, uint16_t bits) {
2817 uint8_t *res_bytes = res;
2818 uint16_t size = zig_int_bytes(bits);
2819 uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3));
2820 uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1);
2821 uint8_t sign_byte;
2822 uint8_t fill_byte;
2823
2824 if (is_signed) {
2825 int8_t signed_sign_byte = zig_maxInt_i(8, remainder_bits);
2826
2827 sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8));
2828 fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8));
2829 } else {
2830 sign_byte = zig_maxInt_u(8, remainder_bits);
2831 fill_byte = UINT8_C(0);
2832 }
2833
2834#if zig_little_endian
2835 memset(&res_bytes[0], zig_maxInt_u8, byte_offset);
2836 res_bytes[byte_offset] = sign_byte;
2837 byte_offset += UINT16_C(1);
2838 memset(&res_bytes[byte_offset], fill_byte, size - byte_offset);
2839#else
2840 byte_offset = size - UINT16_C(1) - byte_offset;
2841 memset(&res_bytes[0], fill_byte, byte_offset);
2842 res_bytes[byte_offset] = sign_byte;
2843 byte_offset += UINT16_C(1);
2844 memset(&res_bytes[byte_offset], zig_maxInt_u8, size - byte_offset);
2845#endif
2846}
2847
2848static inline int8_t zig_signFill_big(const void *arg, bool is_signed, uint16_t bits) {
2849 const uint8_t *arg_bytes = arg;
2850 uint16_t byte_offset = 0;
2851
2852 if (!is_signed) return INT8_C(0);
2853#if zig_little_endian
2854 byte_offset = zig_int_bytes(bits) - 1;
2855#endif
2856 return zig_shr_i8(zig_i8_bitCast_u8(arg_bytes[byte_offset], UINT8_C(8)), UINT8_C(7));
2857}
2858
2859static 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) {
2860 uint8_t *res_bytes = res;
2861 const uint8_t *arg_bytes = arg;
2862 uint16_t res_size = zig_int_bytes(res_bits);
2863 uint16_t arg_size = zig_int_bytes(arg_bits);
2864 uint16_t copy_size = zig_min_u16(res_size, arg_size);
2865 uint8_t sign_fill = zig_u8_bitCast_i8(zig_signFill_big(arg, arg_is_signed, arg_bits), UINT8_C(8));
2866
2867#if zig_little_endian
2868 memcpy(&res_bytes[0], &arg_bytes[0], copy_size);
2869 memset(&res_bytes[copy_size], sign_fill, res_size - copy_size);
2870#else
2871 memset(&res_bytes[0], sign_fill, res_size - copy_size);
2872 memcpy(&res_bytes[res_size - copy_size], &arg_bytes[arg_size - copy_size], copy_size);
2873#endif
2874}
2875
2876static 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) {
2877 uint8_t *res_bytes = res;
2878 const uint8_t *arg_bytes = arg;
2879 uint16_t res_size = zig_int_bytes(res_bits);
2880
2881 if (res_is_signed != arg_is_signed) zig_unreachable();
2882 if (res_bits > arg_bits) zig_unreachable();
2883
2884 if (res_is_signed) {
2885 uint16_t arg_byte_offset = UINT16_C(0);
2886
2887#if zig_big_endian
2888 arg_byte_offset = zig_int_bytes(arg_bits) - res_size;
2889#endif
2890
2891 memcpy(&res_bytes[0], &arg_bytes[arg_byte_offset], res_size);
2892 } else {
2893 uint16_t res_byte_offset = zig_shr_u16(res_bits - UINT16_C(1), UINT8_C(3));
2894 uint16_t arg_byte_offset = res_byte_offset;
2895
2896#if zig_little_endian
2897 memcpy(&res_bytes[0], &arg_bytes[0], res_byte_offset);
2898#else
2899 res_byte_offset = res_size - UINT16_C(1) - res_byte_offset;
2900 arg_byte_offset = zig_int_bytes(arg_bits) - UINT16_C(1) - arg_byte_offset;
2901
2902 memset(&res_bytes[0], zig_minInt_u8, res_byte_offset);
2903#endif
2904
2905 res_bytes[res_byte_offset] = zig_u8_truncate_u8(
2906 arg_bytes[arg_byte_offset],
2907 zig_u8_truncate_u8(res_bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1)
2908 );
2909 res_byte_offset += UINT16_C(1);
2910 arg_byte_offset += UINT16_C(1);
2911
2912#if zig_little_endian
2913 memset(&res_bytes[res_byte_offset], zig_minInt_u8, res_size - res_byte_offset);
2914#else
2915 memcpy(&res_bytes[res_byte_offset], &arg_bytes[arg_byte_offset], res_size - res_byte_offset);
2916#endif
2917 }
2918}
2919
2920#define zig_big_casts(is, s, w, IntType) \
2921 static inline IntType zig_##s##w##_intCast_big(const void *arg, bool arg_is_signed, uint16_t arg_bits) { \
2922 IntType res; \
2923 zig_big_intCast_big(&res, arg, is, w, arg_is_signed, arg_bits); \
2924 return res; \
2925 } \
2926\
2927 static inline void zig_big_intCast_##s##w(void *res, IntType arg, bool res_is_signed, uint16_t res_bits) { \
2928 zig_big_intCast_big(res, &arg, res_is_signed, res_bits, is, w); \
2929 } \
2930\
2931 static inline IntType zig_##s##w##_truncate_big(const void *arg, uint8_t res_bits, bool arg_is_signed, uint16_t arg_bits) { \
2932 IntType res; \
2933 zig_big_truncate_big(&res, arg, is, res_bits, arg_is_signed, arg_bits); \
2934 return res; \
2935 } \
2936\
2937 static inline void zig_big_truncate_##s##w(void *res, IntType arg, bool res_is_signed, uint16_t res_bits) { \
2938 zig_big_truncate_big(res, &arg, res_is_signed, res_bits, is, w); \
2939 }
2940zig_big_casts(false, u, 8, uint8_t)
2941zig_big_casts(true , i, 8, int8_t)
2942zig_big_casts(false, u, 16, uint16_t)
2943zig_big_casts(true , i, 16, int16_t)
2944zig_big_casts(false, u, 32, uint32_t)
2945zig_big_casts(true , i, 32, int32_t)
2946zig_big_casts(false, u, 64, uint64_t)
2947zig_big_casts(true , i, 64, int64_t)
2948zig_big_casts(false, u, 128, zig_u128)
2949zig_big_casts(true , i, 128, zig_i128)
2950
2951static inline void zig_big_bitCast_big(void *res, const void *arg, bool res_is_signed, uint16_t bits) {
2952 uint8_t *res_bytes = res;
2953 const uint8_t *arg_bytes = arg;
2954 uint16_t size = zig_int_bytes(bits);
2955 uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3));
2956 uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1);
2957 uint8_t sign_byte;
2958 uint8_t fill_byte;
2959
2960#if zig_big_endian
2961 byte_offset = size - UINT16_C(1) - byte_offset;
2962#endif
2963
2964 if (res_is_signed) {
2965 int8_t signed_sign_byte = zig_i8_bitCast_u8(arg_bytes[byte_offset], remainder_bits);
2966
2967 sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8));
2968 fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8));
2969 } else {
2970 sign_byte = zig_u8_bitCast_u8(arg_bytes[byte_offset], remainder_bits);
2971 fill_byte = UINT8_C(0);
2972 }
2973
2974#if zig_little_endian
2975 memcpy(&res_bytes[0], &arg_bytes[0], byte_offset);
2976 res_bytes[byte_offset] = sign_byte;
2977 byte_offset += UINT16_C(1);
2978 memset(&res_bytes[byte_offset], fill_byte, size - byte_offset);
2979#else
2980 memset(&res_bytes[0], fill_byte, byte_offset);
2981 res_bytes[byte_offset] = sign_byte;
2982 byte_offset += UINT16_C(1);
2983 memcpy(&res_bytes[byte_offset], &arg_bytes[byte_offset], size - byte_offset);
2984#endif
2985}
2986
2987static inline int32_t zig_cmp_big_u8(const void *lhs, uint8_t rhs, bool is_signed, uint16_t bits) {
24212988 const uint8_t *lhs_bytes = lhs;
2422 const uint8_t *rhs_bytes = rhs;
24232989 uint16_t byte_offset = 0;
24242990 bool do_signed = is_signed;
24252991 uint16_t remaining_bytes = zig_int_bytes(bits);
......@@ -2429,6 +2995,7 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
24292995#endif
24302996
24312997 while (remaining_bytes >= 128 / CHAR_BIT) {
2998 uint8_t rhs_byte = remaining_bytes == 128 / CHAR_BIT ? rhs : UINT8_C(0);
24322999 int32_t limb_cmp;
24333000
24343001#if zig_little_endian
......@@ -2437,18 +3004,16 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
24373004
24383005 if (do_signed) {
24393006 zig_i128 lhs_limb;
2440 zig_i128 rhs_limb;
3007 zig_i128 rhs_limb = zig_i128_intCast_u8(rhs_byte);
24413008
24423009 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2443 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
24443010 limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb);
24453011 do_signed = false;
24463012 } else {
24473013 zig_u128 lhs_limb;
2448 zig_u128 rhs_limb;
3014 zig_u128 rhs_limb = zig_u128_intCast_u8(rhs_byte);
24493015
24503016 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2451 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
24523017 limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb);
24533018 }
24543019
......@@ -2461,24 +3026,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
24613026 }
24623027
24633028 while (remaining_bytes >= 64 / CHAR_BIT) {
3029 uint8_t rhs_byte = remaining_bytes == 64 / CHAR_BIT ? rhs : UINT8_C(0);
3030
24643031#if zig_little_endian
24653032 byte_offset -= 64 / CHAR_BIT;
24663033#endif
24673034
24683035 if (do_signed) {
24693036 int64_t lhs_limb;
2470 int64_t rhs_limb;
3037 int64_t rhs_limb = zig_i64_intCast_u8(rhs_byte);
24713038
24723039 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2473 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
24743040 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
24753041 do_signed = false;
24763042 } else {
24773043 uint64_t lhs_limb;
2478 uint64_t rhs_limb;
3044 uint64_t rhs_limb = zig_u64_intCast_u8(rhs_byte);
24793045
24803046 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2481 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
24823047 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
24833048 }
24843049
......@@ -2490,24 +3055,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
24903055 }
24913056
24923057 while (remaining_bytes >= 32 / CHAR_BIT) {
3058 uint8_t rhs_byte = remaining_bytes == 32 / CHAR_BIT ? rhs : UINT8_C(0);
3059
24933060#if zig_little_endian
24943061 byte_offset -= 32 / CHAR_BIT;
24953062#endif
24963063
24973064 if (do_signed) {
24983065 int32_t lhs_limb;
2499 int32_t rhs_limb;
3066 int32_t rhs_limb = zig_i32_intCast_u8(rhs_byte);
25003067
25013068 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2502 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
25033069 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
25043070 do_signed = false;
25053071 } else {
25063072 uint32_t lhs_limb;
2507 uint32_t rhs_limb;
3073 uint32_t rhs_limb = zig_u32_intCast_u8(rhs_byte);
25083074
25093075 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2510 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
25113076 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
25123077 }
25133078
......@@ -2519,24 +3084,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
25193084 }
25203085
25213086 while (remaining_bytes >= 16 / CHAR_BIT) {
3087 uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0);
3088
25223089#if zig_little_endian
25233090 byte_offset -= 16 / CHAR_BIT;
25243091#endif
25253092
25263093 if (do_signed) {
25273094 int16_t lhs_limb;
2528 int16_t rhs_limb;
3095 int16_t rhs_limb = zig_i16_intCast_u8(rhs_byte);
25293096
25303097 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2531 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
25323098 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
25333099 do_signed = false;
25343100 } else {
25353101 uint16_t lhs_limb;
2536 uint16_t rhs_limb;
3102 uint16_t rhs_limb = zig_u16_intCast_u8(rhs_byte);
25373103
25383104 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2539 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
25403105 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
25413106 }
25423107
......@@ -2548,24 +3113,26 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
25483113 }
25493114
25503115 while (remaining_bytes >= 8 / CHAR_BIT) {
3116 uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0);
3117
25513118#if zig_little_endian
25523119 byte_offset -= 8 / CHAR_BIT;
25533120#endif
25543121
25553122 if (do_signed) {
25563123 int8_t lhs_limb;
2557 int8_t rhs_limb;
3124 int16_t lhs_cmp_limb;
3125 int16_t rhs_cmp_limb = zig_i16_intCast_u8(rhs_byte);
25583126
25593127 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2560 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2561 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3128 lhs_cmp_limb = zig_i16_intCast_i8(lhs_limb);
3129 if (lhs_cmp_limb != rhs_cmp_limb) return (lhs_cmp_limb > rhs_cmp_limb) - (lhs_cmp_limb < rhs_cmp_limb);
25623130 do_signed = false;
25633131 } else {
25643132 uint8_t lhs_limb;
2565 uint8_t rhs_limb;
3133 uint8_t rhs_limb = rhs_byte;
25663134
25673135 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2568 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
25693136 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
25703137 }
25713138
......@@ -2579,148 +3146,472 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
25793146 return 0;
25803147}
25813148
2582static inline void zig_and_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2583 uint8_t *res_bytes = res;
3149static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
25843150 const uint8_t *lhs_bytes = lhs;
25853151 const uint8_t *rhs_bytes = rhs;
25863152 uint16_t byte_offset = 0;
3153 bool do_signed = is_signed;
25873154 uint16_t remaining_bytes = zig_int_bytes(bits);
2588 (void)is_signed;
3155
3156#if zig_little_endian
3157 byte_offset = remaining_bytes;
3158#endif
25893159
25903160 while (remaining_bytes >= 128 / CHAR_BIT) {
2591 zig_u128 res_limb;
2592 zig_u128 lhs_limb;
2593 zig_u128 rhs_limb;
3161 int32_t limb_cmp;
25943162
2595 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2596 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2597 res_limb = zig_and_u128(lhs_limb, rhs_limb);
2598 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3163#if zig_little_endian
3164 byte_offset -= 128 / CHAR_BIT;
3165#endif
3166
3167 if (do_signed) {
3168 zig_i128 lhs_limb;
3169 zig_i128 rhs_limb;
3170
3171 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3172 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3173 limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb);
3174 do_signed = false;
3175 } else {
3176 zig_u128 lhs_limb;
3177 zig_u128 rhs_limb;
3178
3179 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3180 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3181 limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb);
3182 }
25993183
3184 if (limb_cmp != 0) return limb_cmp;
26003185 remaining_bytes -= 128 / CHAR_BIT;
3186
3187#if zig_big_endian
26013188 byte_offset += 128 / CHAR_BIT;
3189#endif
26023190 }
26033191
26043192 while (remaining_bytes >= 64 / CHAR_BIT) {
2605 uint64_t res_limb;
2606 uint64_t lhs_limb;
2607 uint64_t rhs_limb;
3193#if zig_little_endian
3194 byte_offset -= 64 / CHAR_BIT;
3195#endif
26083196
2609 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2610 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2611 res_limb = zig_and_u64(lhs_limb, rhs_limb);
2612 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3197 if (do_signed) {
3198 int64_t lhs_limb;
3199 int64_t rhs_limb;
3200
3201 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3202 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3203 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3204 do_signed = false;
3205 } else {
3206 uint64_t lhs_limb;
3207 uint64_t rhs_limb;
3208
3209 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3210 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3211 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3212 }
26133213
26143214 remaining_bytes -= 64 / CHAR_BIT;
3215
3216#if zig_big_endian
26153217 byte_offset += 64 / CHAR_BIT;
3218#endif
26163219 }
26173220
26183221 while (remaining_bytes >= 32 / CHAR_BIT) {
2619 uint32_t res_limb;
2620 uint32_t lhs_limb;
2621 uint32_t rhs_limb;
3222#if zig_little_endian
3223 byte_offset -= 32 / CHAR_BIT;
3224#endif
26223225
2623 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2624 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2625 res_limb = zig_and_u32(lhs_limb, rhs_limb);
2626 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3226 if (do_signed) {
3227 int32_t lhs_limb;
3228 int32_t rhs_limb;
3229
3230 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3231 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3232 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3233 do_signed = false;
3234 } else {
3235 uint32_t lhs_limb;
3236 uint32_t rhs_limb;
3237
3238 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3239 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3240 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3241 }
26273242
26283243 remaining_bytes -= 32 / CHAR_BIT;
3244
3245#if zig_big_endian
26293246 byte_offset += 32 / CHAR_BIT;
3247#endif
26303248 }
26313249
26323250 while (remaining_bytes >= 16 / CHAR_BIT) {
2633 uint16_t res_limb;
2634 uint16_t lhs_limb;
2635 uint16_t rhs_limb;
3251#if zig_little_endian
3252 byte_offset -= 16 / CHAR_BIT;
3253#endif
26363254
2637 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2638 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2639 res_limb = zig_and_u16(lhs_limb, rhs_limb);
2640 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3255 if (do_signed) {
3256 int16_t lhs_limb;
3257 int16_t rhs_limb;
3258
3259 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3260 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3261 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3262 do_signed = false;
3263 } else {
3264 uint16_t lhs_limb;
3265 uint16_t rhs_limb;
3266
3267 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3268 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3269 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3270 }
26413271
26423272 remaining_bytes -= 16 / CHAR_BIT;
3273
3274#if zig_big_endian
26433275 byte_offset += 16 / CHAR_BIT;
3276#endif
26443277 }
26453278
26463279 while (remaining_bytes >= 8 / CHAR_BIT) {
2647 uint8_t res_limb;
2648 uint8_t lhs_limb;
2649 uint8_t rhs_limb;
3280#if zig_little_endian
3281 byte_offset -= 8 / CHAR_BIT;
3282#endif
26503283
2651 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2652 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2653 res_limb = zig_and_u8(lhs_limb, rhs_limb);
2654 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3284 if (do_signed) {
3285 int8_t lhs_limb;
3286 int8_t rhs_limb;
3287
3288 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3289 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3290 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3291 do_signed = false;
3292 } else {
3293 uint8_t lhs_limb;
3294 uint8_t rhs_limb;
3295
3296 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3297 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3298 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3299 }
26553300
26563301 remaining_bytes -= 8 / CHAR_BIT;
3302
3303#if zig_big_endian
26573304 byte_offset += 8 / CHAR_BIT;
3305#endif
26583306 }
3307
3308 return 0;
26593309}
26603310
2661static inline void zig_or_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3311static inline void zig_not_big(void *res, const void *arg, bool is_signed, uint16_t bits) {
26623312 uint8_t *res_bytes = res;
2663 const uint8_t *lhs_bytes = lhs;
2664 const uint8_t *rhs_bytes = rhs;
3313 const uint8_t *arg_bytes = arg;
26653314 uint16_t byte_offset = 0;
26663315 uint16_t remaining_bytes = zig_int_bytes(bits);
2667 (void)is_signed;
3316 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
3317
3318#if zig_big_endian
3319 byte_offset = remaining_bytes;
3320#endif
26683321
26693322 while (remaining_bytes >= 128 / CHAR_BIT) {
2670 zig_u128 res_limb;
2671 zig_u128 lhs_limb;
2672 zig_u128 rhs_limb;
3323 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
26733324
2674 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2675 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2676 res_limb = zig_or_u128(lhs_limb, rhs_limb);
2677 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3325#if zig_big_endian
3326 byte_offset -= 128 / CHAR_BIT;
3327#endif
3328
3329 if (remaining_bytes != 128 / CHAR_BIT || is_signed) {
3330 zig_i128 res_limb;
3331 zig_i128 arg_limb;
3332
3333 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3334 res_limb = zig_not_i128(arg_limb, limb_bits);
3335 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3336 } else {
3337 zig_u128 res_limb;
3338 zig_u128 arg_limb;
3339
3340 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3341 res_limb = zig_not_u128(arg_limb, limb_bits);
3342 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3343 }
26783344
26793345 remaining_bytes -= 128 / CHAR_BIT;
3346
3347#if zig_little_endian
26803348 byte_offset += 128 / CHAR_BIT;
3349#endif
26813350 }
26823351
26833352 while (remaining_bytes >= 64 / CHAR_BIT) {
2684 uint64_t res_limb;
2685 uint64_t lhs_limb;
2686 uint64_t rhs_limb;
3353 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
26873354
2688 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2689 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2690 res_limb = zig_or_u64(lhs_limb, rhs_limb);
2691 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3355#if zig_big_endian
3356 byte_offset -= 64 / CHAR_BIT;
3357#endif
3358
3359 if (remaining_bytes != 64 / CHAR_BIT || is_signed) {
3360 int64_t res_limb;
3361 int64_t arg_limb;
3362
3363 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3364 res_limb = zig_not_i64(arg_limb, limb_bits);
3365 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3366 } else {
3367 uint64_t res_limb;
3368 uint64_t arg_limb;
3369
3370 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3371 res_limb = zig_not_u64(arg_limb, limb_bits);
3372 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3373 }
26923374
26933375 remaining_bytes -= 64 / CHAR_BIT;
3376
3377#if zig_little_endian
26943378 byte_offset += 64 / CHAR_BIT;
3379#endif
26953380 }
26963381
26973382 while (remaining_bytes >= 32 / CHAR_BIT) {
2698 uint32_t res_limb;
2699 uint32_t lhs_limb;
2700 uint32_t rhs_limb;
3383 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
27013384
2702 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2703 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2704 res_limb = zig_or_u32(lhs_limb, rhs_limb);
2705 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3385#if zig_big_endian
3386 byte_offset -= 32 / CHAR_BIT;
3387#endif
3388
3389 if (remaining_bytes != 32 / CHAR_BIT || is_signed) {
3390 int32_t res_limb;
3391 int32_t arg_limb;
3392
3393 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3394 res_limb = zig_not_i32(arg_limb, limb_bits);
3395 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3396 } else {
3397 uint32_t res_limb;
3398 uint32_t arg_limb;
3399
3400 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3401 res_limb = zig_not_u32(arg_limb, limb_bits);
3402 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3403 }
27063404
27073405 remaining_bytes -= 32 / CHAR_BIT;
3406
3407#if zig_little_endian
27083408 byte_offset += 32 / CHAR_BIT;
3409#endif
27093410 }
27103411
27113412 while (remaining_bytes >= 16 / CHAR_BIT) {
2712 uint16_t res_limb;
2713 uint16_t lhs_limb;
2714 uint16_t rhs_limb;
3413 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
27153414
2716 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2717 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2718 res_limb = zig_or_u16(lhs_limb, rhs_limb);
2719 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3415#if zig_big_endian
3416 byte_offset -= 16 / CHAR_BIT;
3417#endif
27203418
2721 remaining_bytes -= 16 / CHAR_BIT;
2722 byte_offset += 16 / CHAR_BIT;
2723 }
3419 if (remaining_bytes != 16 / CHAR_BIT || is_signed) {
3420 int16_t res_limb;
3421 int16_t arg_limb;
3422
3423 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3424 res_limb = zig_not_i16(arg_limb, limb_bits);
3425 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3426 } else {
3427 uint16_t res_limb;
3428 uint16_t arg_limb;
3429
3430 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3431 res_limb = zig_not_u16(arg_limb, limb_bits);
3432 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3433 }
3434
3435 remaining_bytes -= 16 / CHAR_BIT;
3436
3437#if zig_little_endian
3438 byte_offset += 16 / CHAR_BIT;
3439#endif
3440 }
3441
3442 while (remaining_bytes >= 8 / CHAR_BIT) {
3443 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
3444
3445#if zig_big_endian
3446 byte_offset -= 8 / CHAR_BIT;
3447#endif
3448
3449 if (remaining_bytes != 8 / CHAR_BIT || is_signed) {
3450 int8_t res_limb;
3451 int8_t arg_limb;
3452
3453 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3454 res_limb = zig_not_i8(arg_limb, limb_bits);
3455 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3456 } else {
3457 uint8_t res_limb;
3458 uint8_t arg_limb;
3459
3460 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3461 res_limb = zig_not_u8(arg_limb, limb_bits);
3462 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3463 }
3464
3465 remaining_bytes -= 8 / CHAR_BIT;
3466
3467#if zig_little_endian
3468 byte_offset += 8 / CHAR_BIT;
3469#endif
3470 }
3471}
3472
3473static inline void zig_and_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3474 uint8_t *res_bytes = res;
3475 const uint8_t *lhs_bytes = lhs;
3476 const uint8_t *rhs_bytes = rhs;
3477 uint16_t byte_offset = 0;
3478 uint16_t remaining_bytes = zig_int_bytes(bits);
3479 (void)is_signed;
3480
3481 while (remaining_bytes >= 128 / CHAR_BIT) {
3482 zig_u128 res_limb;
3483 zig_u128 lhs_limb;
3484 zig_u128 rhs_limb;
3485
3486 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3487 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3488 res_limb = zig_and_u128(lhs_limb, rhs_limb);
3489 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3490
3491 remaining_bytes -= 128 / CHAR_BIT;
3492 byte_offset += 128 / CHAR_BIT;
3493 }
3494
3495 while (remaining_bytes >= 64 / CHAR_BIT) {
3496 uint64_t res_limb;
3497 uint64_t lhs_limb;
3498 uint64_t rhs_limb;
3499
3500 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3501 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3502 res_limb = zig_and_u64(lhs_limb, rhs_limb);
3503 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3504
3505 remaining_bytes -= 64 / CHAR_BIT;
3506 byte_offset += 64 / CHAR_BIT;
3507 }
3508
3509 while (remaining_bytes >= 32 / CHAR_BIT) {
3510 uint32_t res_limb;
3511 uint32_t lhs_limb;
3512 uint32_t rhs_limb;
3513
3514 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3515 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3516 res_limb = zig_and_u32(lhs_limb, rhs_limb);
3517 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3518
3519 remaining_bytes -= 32 / CHAR_BIT;
3520 byte_offset += 32 / CHAR_BIT;
3521 }
3522
3523 while (remaining_bytes >= 16 / CHAR_BIT) {
3524 uint16_t res_limb;
3525 uint16_t lhs_limb;
3526 uint16_t rhs_limb;
3527
3528 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3529 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3530 res_limb = zig_and_u16(lhs_limb, rhs_limb);
3531 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3532
3533 remaining_bytes -= 16 / CHAR_BIT;
3534 byte_offset += 16 / CHAR_BIT;
3535 }
3536
3537 while (remaining_bytes >= 8 / CHAR_BIT) {
3538 uint8_t res_limb;
3539 uint8_t lhs_limb;
3540 uint8_t rhs_limb;
3541
3542 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3543 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3544 res_limb = zig_and_u8(lhs_limb, rhs_limb);
3545 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3546
3547 remaining_bytes -= 8 / CHAR_BIT;
3548 byte_offset += 8 / CHAR_BIT;
3549 }
3550}
3551
3552static inline void zig_or_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3553 uint8_t *res_bytes = res;
3554 const uint8_t *lhs_bytes = lhs;
3555 const uint8_t *rhs_bytes = rhs;
3556 uint16_t byte_offset = 0;
3557 uint16_t remaining_bytes = zig_int_bytes(bits);
3558 (void)is_signed;
3559
3560 while (remaining_bytes >= 128 / CHAR_BIT) {
3561 zig_u128 res_limb;
3562 zig_u128 lhs_limb;
3563 zig_u128 rhs_limb;
3564
3565 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3566 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3567 res_limb = zig_or_u128(lhs_limb, rhs_limb);
3568 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3569
3570 remaining_bytes -= 128 / CHAR_BIT;
3571 byte_offset += 128 / CHAR_BIT;
3572 }
3573
3574 while (remaining_bytes >= 64 / CHAR_BIT) {
3575 uint64_t res_limb;
3576 uint64_t lhs_limb;
3577 uint64_t rhs_limb;
3578
3579 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3580 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3581 res_limb = zig_or_u64(lhs_limb, rhs_limb);
3582 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3583
3584 remaining_bytes -= 64 / CHAR_BIT;
3585 byte_offset += 64 / CHAR_BIT;
3586 }
3587
3588 while (remaining_bytes >= 32 / CHAR_BIT) {
3589 uint32_t res_limb;
3590 uint32_t lhs_limb;
3591 uint32_t rhs_limb;
3592
3593 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3594 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3595 res_limb = zig_or_u32(lhs_limb, rhs_limb);
3596 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3597
3598 remaining_bytes -= 32 / CHAR_BIT;
3599 byte_offset += 32 / CHAR_BIT;
3600 }
3601
3602 while (remaining_bytes >= 16 / CHAR_BIT) {
3603 uint16_t res_limb;
3604 uint16_t lhs_limb;
3605 uint16_t rhs_limb;
3606
3607 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3608 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3609 res_limb = zig_or_u16(lhs_limb, rhs_limb);
3610 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3611
3612 remaining_bytes -= 16 / CHAR_BIT;
3613 byte_offset += 16 / CHAR_BIT;
3614 }
27243615
27253616 while (remaining_bytes >= 8 / CHAR_BIT) {
27263617 uint8_t res_limb;
......@@ -2816,13 +3707,415 @@ static inline void zig_xor_big(void *res, const void *lhs, const void *rhs, bool
28163707 }
28173708}
28183709
3710static inline void zig_increment_big(void *res, bool is_signed, uint16_t bits) {
3711 uint8_t *res_bytes = res;
3712 uint16_t byte_offset = 0;
3713 uint16_t remaining_bytes = zig_int_bytes(bits);
3714 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
3715
3716#if zig_big_endian
3717 byte_offset = remaining_bytes;
3718#endif
3719
3720 while (remaining_bytes >= 128 / CHAR_BIT) {
3721 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
3722
3723#if zig_big_endian
3724 byte_offset -= 128 / CHAR_BIT;
3725#endif
3726
3727 {
3728 zig_u128 res_limb;
3729 bool limb_overflow;
3730
3731 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3732 limb_overflow = zig_addo_u128(&res_limb, res_limb, zig_make_u128(UINT64_C(0), UINT64_C(1)), limb_bits);
3733 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3734 if (!limb_overflow) return;
3735 }
3736
3737 remaining_bytes -= 128 / CHAR_BIT;
3738
3739#if zig_little_endian
3740 byte_offset += 128 / CHAR_BIT;
3741#endif
3742 }
3743
3744 while (remaining_bytes >= 64 / CHAR_BIT) {
3745 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
3746
3747#if zig_big_endian
3748 byte_offset -= 64 / CHAR_BIT;
3749#endif
3750
3751 {
3752 uint64_t res_limb;
3753 bool limb_overflow;
3754
3755 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3756 limb_overflow = zig_addo_u64(&res_limb, res_limb, UINT64_C(1), limb_bits);
3757 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3758 if (!limb_overflow) return;
3759 }
3760
3761 remaining_bytes -= 64 / CHAR_BIT;
3762
3763#if zig_little_endian
3764 byte_offset += 64 / CHAR_BIT;
3765#endif
3766 }
3767
3768 while (remaining_bytes >= 32 / CHAR_BIT) {
3769 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
3770
3771#if zig_big_endian
3772 byte_offset -= 32 / CHAR_BIT;
3773#endif
3774
3775 {
3776 uint32_t res_limb;
3777 bool limb_overflow;
3778
3779 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3780 limb_overflow = zig_addo_u32(&res_limb, res_limb, UINT32_C(1), limb_bits);
3781 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3782 if (!limb_overflow) return;
3783 }
3784
3785 remaining_bytes -= 32 / CHAR_BIT;
3786
3787#if zig_little_endian
3788 byte_offset += 32 / CHAR_BIT;
3789#endif
3790 }
3791
3792 while (remaining_bytes >= 16 / CHAR_BIT) {
3793 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
3794
3795#if zig_big_endian
3796 byte_offset -= 16 / CHAR_BIT;
3797#endif
3798
3799 {
3800 uint16_t res_limb;
3801 bool limb_overflow;
3802
3803 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3804 limb_overflow = zig_addo_u16(&res_limb, res_limb, UINT16_C(1), limb_bits);
3805 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3806 if (!limb_overflow) return;
3807 }
3808
3809 remaining_bytes -= 16 / CHAR_BIT;
3810
3811#if zig_little_endian
3812 byte_offset += 16 / CHAR_BIT;
3813#endif
3814 }
3815
3816 while (remaining_bytes >= 8 / CHAR_BIT) {
3817 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
3818
3819#if zig_big_endian
3820 byte_offset -= 8 / CHAR_BIT;
3821#endif
3822
3823 {
3824 uint8_t res_limb;
3825 bool limb_overflow;
3826
3827 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3828 limb_overflow = zig_addo_u8(&res_limb, res_limb, UINT8_C(1), limb_bits);
3829 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3830 if (!limb_overflow) return;
3831 }
3832
3833 remaining_bytes -= 8 / CHAR_BIT;
3834
3835#if zig_little_endian
3836 byte_offset += 8 / CHAR_BIT;
3837#endif
3838 }
3839}
3840
3841static inline void zig_decrement_big(void *res, bool is_signed, uint16_t bits) {
3842 uint8_t *res_bytes = res;
3843 uint16_t byte_offset = 0;
3844 uint16_t remaining_bytes = zig_int_bytes(bits);
3845 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
3846
3847#if zig_big_endian
3848 byte_offset = remaining_bytes;
3849#endif
3850
3851 while (remaining_bytes >= 128 / CHAR_BIT) {
3852 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
3853
3854#if zig_big_endian
3855 byte_offset -= 128 / CHAR_BIT;
3856#endif
3857
3858 {
3859 zig_u128 res_limb;
3860 bool limb_overflow;
3861
3862 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3863 limb_overflow = zig_subo_u128(&res_limb, res_limb, zig_make_u128(UINT64_C(0), UINT64_C(1)), limb_bits);
3864 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3865 if (!limb_overflow) return;
3866 }
3867
3868 remaining_bytes -= 128 / CHAR_BIT;
3869
3870#if zig_little_endian
3871 byte_offset += 128 / CHAR_BIT;
3872#endif
3873 }
3874
3875 while (remaining_bytes >= 64 / CHAR_BIT) {
3876 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
3877
3878#if zig_big_endian
3879 byte_offset -= 64 / CHAR_BIT;
3880#endif
3881
3882 {
3883 uint64_t res_limb;
3884 bool limb_overflow;
3885
3886 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3887 limb_overflow = zig_subo_u64(&res_limb, res_limb, UINT64_C(1), limb_bits);
3888 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3889 if (!limb_overflow) return;
3890 }
3891
3892 remaining_bytes -= 64 / CHAR_BIT;
3893
3894#if zig_little_endian
3895 byte_offset += 64 / CHAR_BIT;
3896#endif
3897 }
3898
3899 while (remaining_bytes >= 32 / CHAR_BIT) {
3900 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
3901
3902#if zig_big_endian
3903 byte_offset -= 32 / CHAR_BIT;
3904#endif
3905
3906 {
3907 uint32_t res_limb;
3908 bool limb_overflow;
3909
3910 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3911 limb_overflow = zig_subo_u32(&res_limb, res_limb, UINT32_C(1), limb_bits);
3912 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3913 if (!limb_overflow) return;
3914 }
3915
3916 remaining_bytes -= 32 / CHAR_BIT;
3917
3918#if zig_little_endian
3919 byte_offset += 32 / CHAR_BIT;
3920#endif
3921 }
3922
3923 while (remaining_bytes >= 16 / CHAR_BIT) {
3924 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
3925
3926#if zig_big_endian
3927 byte_offset -= 16 / CHAR_BIT;
3928#endif
3929
3930 {
3931 uint16_t res_limb;
3932 bool limb_overflow;
3933
3934 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3935 limb_overflow = zig_subo_u16(&res_limb, res_limb, UINT16_C(1), limb_bits);
3936 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3937 if (!limb_overflow) return;
3938 }
3939
3940 remaining_bytes -= 16 / CHAR_BIT;
3941
3942#if zig_little_endian
3943 byte_offset += 16 / CHAR_BIT;
3944#endif
3945 }
3946
3947 while (remaining_bytes >= 8 / CHAR_BIT) {
3948 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
3949
3950#if zig_big_endian
3951 byte_offset -= 8 / CHAR_BIT;
3952#endif
3953
3954 {
3955 uint8_t res_limb;
3956 bool limb_overflow;
3957
3958 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3959 limb_overflow = zig_subo_u8(&res_limb, res_limb, UINT8_C(1), limb_bits);
3960 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3961 if (!limb_overflow) return;
3962 }
3963
3964 remaining_bytes -= 8 / CHAR_BIT;
3965
3966#if zig_little_endian
3967 byte_offset += 8 / CHAR_BIT;
3968#endif
3969 }
3970}
3971
3972static inline void zig_abs_big(void *res, const void *arg, bool is_signed, uint16_t bits) {
3973 uint8_t *res_bytes = res;
3974 const uint8_t *arg_bytes = arg;
3975 uint16_t byte_offset = 0;
3976 uint16_t remaining_bytes = zig_int_bytes(bits);
3977 if (zig_signFill_big(arg, is_signed, bits) >= INT8_C(0)) {
3978 memcpy(res, arg, remaining_bytes);
3979 return;
3980 }
3981 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
3982 bool overflow = true;
3983
3984#if zig_big_endian
3985 byte_offset = remaining_bytes;
3986#endif
3987
3988 while (remaining_bytes >= 128 / CHAR_BIT) {
3989 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
3990
3991#if zig_big_endian
3992 byte_offset -= 128 / CHAR_BIT;
3993#endif
3994
3995 {
3996 zig_u128 res_limb;
3997 zig_u128 arg_limb;
3998
3999 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
4000 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);
4001 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
4002 }
4003
4004 remaining_bytes -= 128 / CHAR_BIT;
4005
4006#if zig_little_endian
4007 byte_offset += 128 / CHAR_BIT;
4008#endif
4009 }
4010
4011 while (remaining_bytes >= 64 / CHAR_BIT) {
4012 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
4013
4014#if zig_big_endian
4015 byte_offset -= 64 / CHAR_BIT;
4016#endif
4017
4018 {
4019 uint64_t res_limb;
4020 uint64_t arg_limb;
4021
4022 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
4023 overflow = zig_addo_u64(&res_limb, zig_not_u64(arg_limb, UINT8_C(64)), overflow ? UINT64_C(1) : UINT64_C(0), limb_bits);
4024 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
4025 }
4026
4027 remaining_bytes -= 64 / CHAR_BIT;
4028
4029#if zig_little_endian
4030 byte_offset += 64 / CHAR_BIT;
4031#endif
4032 }
4033
4034 while (remaining_bytes >= 32 / CHAR_BIT) {
4035 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
4036
4037#if zig_big_endian
4038 byte_offset -= 32 / CHAR_BIT;
4039#endif
4040
4041 {
4042 uint32_t res_limb;
4043 uint32_t arg_limb;
4044
4045 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
4046 overflow = zig_addo_u32(&res_limb, zig_not_u32(arg_limb, UINT8_C(32)), overflow ? UINT32_C(1) : UINT32_C(0), limb_bits);
4047 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
4048 }
4049
4050 remaining_bytes -= 32 / CHAR_BIT;
4051
4052#if zig_little_endian
4053 byte_offset += 32 / CHAR_BIT;
4054#endif
4055 }
4056
4057 while (remaining_bytes >= 16 / CHAR_BIT) {
4058 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
4059
4060#if zig_big_endian
4061 byte_offset -= 16 / CHAR_BIT;
4062#endif
4063
4064 {
4065 uint16_t res_limb;
4066 uint16_t arg_limb;
4067
4068 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
4069 overflow = zig_addo_u16(&res_limb, zig_not_u16(arg_limb, UINT8_C(16)), overflow ? UINT16_C(1) : UINT16_C(0), limb_bits);
4070 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
4071 }
4072
4073 remaining_bytes -= 16 / CHAR_BIT;
4074
4075#if zig_little_endian
4076 byte_offset += 16 / CHAR_BIT;
4077#endif
4078 }
4079
4080 while (remaining_bytes >= 8 / CHAR_BIT) {
4081 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
4082
4083#if zig_big_endian
4084 byte_offset -= 8 / CHAR_BIT;
4085#endif
4086
4087 {
4088 uint8_t res_limb;
4089 uint8_t arg_limb;
4090
4091 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
4092 overflow = zig_addo_u8(&res_limb, zig_not_u8(arg_limb, UINT8_C(8)), overflow ? UINT8_C(1) : UINT8_C(0), limb_bits);
4093 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
4094 }
4095
4096 remaining_bytes -= 8 / CHAR_BIT;
4097
4098#if zig_little_endian
4099 byte_offset += 8 / CHAR_BIT;
4100#endif
4101 }
4102}
4103
4104static inline void zig_min_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4105 memcpy(res, zig_cmp_big(lhs, rhs, is_signed, bits) < INT32_C(0) ? lhs : rhs, zig_int_bytes(bits));
4106}
4107
4108static inline void zig_max_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4109 memcpy(res, zig_cmp_big(lhs, rhs, is_signed, bits) >= INT32_C(0) ? lhs : rhs, zig_int_bytes(bits));
4110}
4111
28194112static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
28204113 uint8_t *res_bytes = res;
28214114 const uint8_t *lhs_bytes = lhs;
28224115 const uint8_t *rhs_bytes = rhs;
28234116 uint16_t byte_offset = 0;
28244117 uint16_t remaining_bytes = zig_int_bytes(bits);
2825 uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits);
4118 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
28264119 bool overflow = false;
28274120
28284121#if zig_big_endian
......@@ -3038,7 +4331,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
30384331 const uint8_t *rhs_bytes = rhs;
30394332 uint16_t byte_offset = 0;
30404333 uint16_t remaining_bytes = zig_int_bytes(bits);
3041 uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits);
4334 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
30424335 bool overflow = false;
30434336
30444337#if zig_big_endian
......@@ -3238,218 +4531,890 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
32384531 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
32394532 }
32404533
3241 remaining_bytes -= 8 / CHAR_BIT;
4534 remaining_bytes -= 8 / CHAR_BIT;
4535
4536#if zig_little_endian
4537 byte_offset += 8 / CHAR_BIT;
4538#endif
4539 }
4540
4541 return overflow;
4542}
4543
4544static inline void zig_add_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4545 if (zig_addo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow
4546}
4547
4548static inline void zig_addw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4549 (void)zig_addo_big(res, lhs, rhs, is_signed, bits);
4550}
4551
4552static inline void zig_adds_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4553 int8_t sat_sign = zig_signFill_big(lhs, is_signed, bits);
4554
4555 if (!zig_addo_big(res, lhs, rhs, is_signed, bits)) return;
4556 switch (sat_sign) {
4557 case -INT8_C(1): return zig_minInt_big(res, is_signed, bits);
4558 case INT8_C(0): return zig_maxInt_big(res, is_signed, bits);
4559 }
4560}
4561
4562static inline void zig_sub_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4563 if (zig_subo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow
4564}
4565
4566static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4567 (void)zig_subo_big(res, lhs, rhs, is_signed, bits);
4568}
4569
4570static inline void zig_subs_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4571 int8_t sat_sign = is_signed ? zig_signFill_big(lhs, is_signed, bits) : -INT8_C(1);
4572
4573 if (!zig_subo_big(res, lhs, rhs, is_signed, bits)) return;
4574 switch (sat_sign) {
4575 case -INT8_C(1): return zig_minInt_big(res, is_signed, bits);
4576 case INT8_C(0): return zig_maxInt_big(res, is_signed, bits);
4577 }
4578}
4579
4580static inline bool zig_mulo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4581 uint8_t *res_bytes = res;
4582 const uint8_t *lhs_bytes = lhs;
4583 const uint8_t *rhs_bytes = rhs;
4584 uint16_t size = zig_int_bytes(bits);
4585 uint16_t sign_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
4586 uint8_t lhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(lhs, is_signed, bits), UINT8_C(8));
4587 uint8_t rhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(rhs, is_signed, bits), UINT8_C(8));
4588 uint16_t lhs_byte_offset = sign_byte_offset;
4589 uint16_t lhs_end_byte_offset = UINT16_C(0);
4590 bool overflow = false;
4591
4592#if zig_big_endian
4593 lhs_byte_offset = size - lhs_byte_offset;
4594 lhs_end_byte_offset = size - lhs_end_byte_offset;
4595#endif
4596
4597 while (lhs_byte_offset != lhs_end_byte_offset) {
4598 uint16_t rhs_byte_offset = UINT16_C(0);
4599 uint16_t end_byte_offset = sign_byte_offset;
4600 uint16_t res_byte_offset;
4601 uint16_t lhs_byte;
4602 uint8_t res_byte = UINT8_C(0);
4603 uint16_t mul_res = UINT16_C(0);
4604 uint8_t carry = UINT8_C(0);
4605
4606#if zig_little_endian
4607 lhs_byte_offset -= UINT16_C(1);
4608#else
4609 rhs_byte_offset = size - rhs_byte_offset;
4610 end_byte_offset = size - end_byte_offset;
4611#endif
4612
4613 lhs_byte = zig_u16_intCast_u8(lhs_bytes[lhs_byte_offset]) ^ lhs_sign_fill;
4614
4615#if zig_big_endian
4616 lhs_byte_offset += UINT16_C(1);
4617#endif
4618
4619 res_byte_offset = lhs_byte_offset;
4620
4621 while (res_byte_offset != end_byte_offset) {
4622 bool res_byte_initialized = res_byte_offset != lhs_byte_offset;
4623
4624#if zig_big_endian
4625 rhs_byte_offset -= UINT16_C(1);
4626 res_byte_offset -= UINT16_C(1);
4627#endif
4628
4629 if (res_byte_initialized) res_byte = res_bytes[res_byte_offset];
4630 carry = zig_addo_u8(&res_byte, res_byte, carry, UINT8_C(8));
4631 carry += zig_addo_u8(&res_byte, res_byte, zig_u8_intCast_u16(
4632 zig_shr_u16(mul_res, UINT8_C(8))
4633 ), UINT8_C(8));
4634 mul_res = lhs_byte * zig_u16_intCast_u8(rhs_bytes[rhs_byte_offset] ^ rhs_sign_fill);
4635 carry += zig_addo_u8(&res_bytes[res_byte_offset], res_byte, zig_u8_truncate_u16(
4636 mul_res,
4637 UINT8_C(8)
4638 ), UINT8_C(8));
4639
4640#if zig_little_endian
4641 rhs_byte_offset += UINT16_C(1);
4642 res_byte_offset += UINT16_C(1);
4643#endif
4644 }
4645
4646 while (rhs_byte_offset != end_byte_offset) {
4647#if zig_big_endian
4648 rhs_byte_offset -= UINT16_C(1);
4649#endif
4650
4651 carry = zig_addo_u8(
4652 &res_byte,
4653 zig_u8_intCast_u16(zig_shr_u16(mul_res, UINT8_C(8))),
4654 carry,
4655 UINT8_C(8)
4656 );
4657 mul_res = lhs_byte * zig_u16_intCast_u8(rhs_bytes[rhs_byte_offset] ^ rhs_sign_fill);
4658 carry += zig_addo_u8(&res_byte, res_byte, zig_u8_truncate_u16(
4659 mul_res,
4660 UINT8_C(8)
4661 ), UINT8_C(8));
4662 overflow |= res_byte != UINT8_C(0);
4663
4664#if zig_little_endian
4665 rhs_byte_offset += UINT16_C(1);
4666#endif
4667 }
4668
4669 overflow |= zig_shr_u16(mul_res, UINT8_C(8)) != UINT16_C(0);
4670 overflow |= carry != UINT8_C(0);
4671 }
4672
4673#if zig_little_endian
4674 sign_byte_offset -= UINT64_C(1);
4675#else
4676 sign_byte_offset = size - sign_byte_offset;
4677#endif
4678
4679 if (lhs_sign_fill != rhs_sign_fill) {
4680 uint16_t byte_offset = UINT16_C(0);
4681 uint16_t end_byte_offset = sign_byte_offset;
4682 uint8_t res_byte;
4683 int8_t signed_res_byte;
4684 uint8_t carry = UINT8_C(0);
4685
4686#if zig_big_endian
4687 byte_offset = size - byte_offset;
4688 end_byte_offset += UINT16_C(1);
4689#endif
4690
4691 while (byte_offset != end_byte_offset) {
4692#if zig_big_endian
4693 byte_offset -= UINT16_C(1);
4694#endif
4695
4696 carry = zig_subo_u8(&res_byte, UINT8_C(0), carry, UINT8_C(8));
4697 carry += zig_subo_u8(&res_byte, res_byte, res_bytes[byte_offset], UINT8_C(8));
4698 carry += zig_subo_u8(
4699 &res_bytes[byte_offset],
4700 res_byte,
4701 (lhs_sign_fill == UINT8_C(0) ? lhs_bytes : rhs_bytes)[byte_offset],
4702 UINT8_C(8)
4703 );
4704
4705#if zig_little_endian
4706 byte_offset += UINT16_C(1);
4707#endif
4708 }
4709
4710#if zig_big_endian
4711 byte_offset -= UINT16_C(1);
4712#endif
4713
4714 signed_res_byte = zig_i8_bitCast_u8(res_bytes[byte_offset], UINT8_C(8));
4715 overflow |= signed_res_byte < INT8_C(0);
4716 overflow |= zig_subo_i8(&signed_res_byte, INT8_C(0), signed_res_byte, UINT8_C(8));
4717 overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_intCast_u8(carry), UINT8_C(8));
4718 overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8(
4719 (lhs_sign_fill == UINT8_C(0) ? lhs_bytes : rhs_bytes)[byte_offset],
4720 UINT8_C(8)
4721 ), UINT8_C(8));
4722 res_bytes[byte_offset] = zig_i8_bitCast_u8(signed_res_byte, UINT8_C(8));
4723 } else if (lhs_sign_fill != UINT8_C(0)) {
4724 uint16_t byte_offset = UINT16_C(0);
4725 uint16_t end_byte_offset = sign_byte_offset;
4726 uint8_t res_byte;
4727 int8_t signed_res_byte;
4728 uint8_t carry = UINT8_C(1);
4729
4730#if zig_big_endian
4731 byte_offset = size - byte_offset;
4732 end_byte_offset += UINT16_C(1);
4733#endif
4734
4735 while (byte_offset != end_byte_offset) {
4736#if zig_big_endian
4737 byte_offset -= UINT16_C(1);
4738#endif
4739
4740 carry = zig_subo_u8(&res_byte, res_bytes[byte_offset], carry, UINT8_C(8));
4741 carry += zig_subo_u8(&res_byte, res_byte, lhs_bytes[byte_offset], UINT8_C(8));
4742 carry += zig_subo_u8(&res_bytes[byte_offset], res_byte, rhs_bytes[byte_offset], UINT8_C(8));
4743
4744#if zig_little_endian
4745 byte_offset += UINT16_C(1);
4746#endif
4747 }
4748
4749#if zig_big_endian
4750 byte_offset -= UINT16_C(1);
4751#endif
4752
4753 signed_res_byte = zig_i8_bitCast_u8(res_bytes[byte_offset], UINT8_C(8));
4754 overflow |= signed_res_byte < INT8_C(0);
4755 overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_intCast_u8(carry), UINT8_C(8));
4756 overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8(
4757 lhs_bytes[byte_offset],
4758 UINT8_C(8)
4759 ), UINT8_C(8));
4760 overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8(
4761 rhs_bytes[byte_offset],
4762 UINT8_C(8)
4763 ), UINT8_C(8));
4764 res_bytes[byte_offset] = zig_i8_bitCast_u8(signed_res_byte, UINT8_C(8));
4765 } else if (is_signed) {
4766 int8_t signed_res_byte = zig_i8_bitCast_u8(res_bytes[sign_byte_offset], UINT8_C(8));
4767
4768 overflow |= signed_res_byte < INT8_C(0);
4769 }
4770
4771 {
4772 uint8_t truncate_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
4773 uint8_t fill_byte = UINT8_C(0);
4774
4775 if (is_signed) {
4776 int8_t sign_byte = zig_i8_bitCast_u8(res_bytes[sign_byte_offset], UINT8_C(8));
4777 int8_t truncated = zig_i8_truncate_i8(sign_byte, truncate_bits);
4778
4779 overflow |= sign_byte != truncated;
4780 res_bytes[sign_byte_offset] = zig_u8_bitCast_i8(truncated, UINT8_C(8));
4781 fill_byte = zig_u8_bitCast_i8(zig_shr_i8(truncated, UINT8_C(7)), UINT8_C(8));
4782 } else {
4783 uint8_t sign_byte = res_bytes[sign_byte_offset];
4784 uint8_t truncated = zig_u8_truncate_u8(sign_byte, truncate_bits);
4785
4786 overflow |= sign_byte != truncated;
4787 res_bytes[sign_byte_offset] = truncated;
4788 }
4789
4790#if zig_little_endian
4791 sign_byte_offset += UINT16_C(1);
4792 memset(&res_bytes[sign_byte_offset], fill_byte, size - sign_byte_offset);
4793#else
4794 memset(&res_bytes[0], fill_byte, sign_byte_offset);
4795#endif
4796 }
4797
4798 return overflow;
4799}
4800
4801static inline void zig_mul_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4802 if (zig_mulo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow
4803}
4804
4805static inline void zig_mulw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4806 (void)zig_mulo_big(res, lhs, rhs, is_signed, bits);
4807}
4808
4809static inline void zig_muls_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4810 int8_t sat_sign = zig_signFill_big(lhs, is_signed, bits) ^ zig_signFill_big(rhs, is_signed, bits);
4811
4812 if (!zig_mulo_big(res, lhs, rhs, is_signed, bits)) return;
4813 switch (sat_sign) {
4814 case -INT8_C(1): return zig_minInt_big(res, is_signed, bits);
4815 case INT8_C(0): return zig_maxInt_big(res, is_signed, bits);
4816 }
4817}
4818
4819static inline void zig_divTrunc_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) {
4820 if (is_signed) {
4821 zig_extern void __divei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits);
4822 __divei5(res, lhs, rhs, temp, bits);
4823 } else {
4824 zig_extern void __udivei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits);
4825 __udivei5(res, lhs, rhs, temp, bits);
4826 }
4827}
4828
4829static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) {
4830 if (is_signed) {
4831 zig_extern void __modei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits);
4832 __modei5(res, lhs, rhs, temp, bits);
4833 } else {
4834 zig_extern void __umodei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits);
4835 __umodei5(res, lhs, rhs, temp, bits);
4836 }
4837}
4838
4839static inline void zig_divFloor_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) {
4840 bool decrement = false;
4841
4842 if (is_signed) {
4843 zig_rem_big(res, lhs, rhs, temp, is_signed, bits);
4844 decrement = zig_u32_bitCast_i32(zig_xor_i32(
4845 zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits),
4846 zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32)
4847 ), UINT8_C(32)) > zig_u32_bitCast_i32(zig_minInt_i32, UINT8_C(32));
4848 }
4849 zig_divTrunc_big(res, lhs, rhs, temp, is_signed, bits);
4850 if (decrement) zig_decrement_big(res, is_signed, bits);
4851}
4852
4853static inline void zig_divCeil_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) {
4854 bool increment = false;
4855
4856 zig_rem_big(res, lhs, rhs, temp, is_signed, bits);
4857 increment = zig_xor_i32(
4858 zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits),
4859 zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32)
4860 ) > INT32_C(0);
4861 zig_divTrunc_big(res, lhs, rhs, temp, is_signed, bits);
4862 if (increment) zig_increment_big(res, is_signed, bits);
4863}
4864
4865static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) {
4866 bool fixup = false;
4867
4868 zig_rem_big(res, lhs, rhs, temp, is_signed, bits);
4869 if (is_signed && zig_u32_bitCast_i32(zig_xor_i32(
4870 zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits),
4871 zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32)
4872 ), UINT8_C(32)) > zig_u32_bitCast_i32(zig_minInt_i32, UINT8_C(32))) zig_add_big(res, res, rhs, is_signed, bits);
4873}
4874
4875static inline void zig_shr_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) {
4876 uint8_t *res_bytes = res;
4877 const uint8_t *lhs_bytes = lhs;
4878 uint16_t size = zig_int_bytes(bits);
4879 uint16_t res_byte_offset = UINT16_C(0);
4880 uint16_t lhs_byte_offset = zig_shr_u16(rhs, UINT8_C(3));
4881 uint16_t end_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
4882 uint8_t lhs_prev_byte;
4883 uint8_t byte_shift = zig_u8_truncate_u16(rhs, UINT8_C(3));
4884
4885#if zig_big_endian
4886 res_byte_offset = size - res_byte_offset;
4887 lhs_byte_offset = size - lhs_byte_offset;
4888 end_byte_offset = size - end_byte_offset;
4889#endif
4890
4891 {
4892#if zig_big_endian
4893 lhs_byte_offset -= UINT16_C(1);
4894#endif
4895
4896 lhs_prev_byte = lhs_bytes[lhs_byte_offset];
4897
4898#if zig_little_endian
4899 lhs_byte_offset += UINT16_C(1);
4900#endif
4901 }
4902
4903 while (lhs_byte_offset != end_byte_offset) {
4904#if zig_big_endian
4905 res_byte_offset -= UINT16_C(1);
4906 lhs_byte_offset -= UINT16_C(1);
4907#endif
4908
4909 {
4910 uint8_t lhs_byte = lhs_bytes[lhs_byte_offset];
4911
4912 res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16(
4913 zig_shl_u16(zig_u16_intCast_u8(lhs_byte), UINT8_C(8)),
4914 zig_u16_intCast_u8(lhs_prev_byte)
4915 ), byte_shift));
4916 lhs_prev_byte = lhs_byte;
4917 }
4918
4919#if zig_little_endian
4920 res_byte_offset += UINT16_C(1);
4921 lhs_byte_offset += UINT16_C(1);
4922#endif
4923 }
4924
4925 {
4926 uint8_t lhs_sign_fill = UINT8_C(0);
4927
4928#if zig_big_endian
4929 res_byte_offset -= UINT16_C(1);
4930#endif
4931
4932 if (is_signed) {
4933 int8_t signed_byte = zig_i8_bitCast_u8(lhs_prev_byte, UINT8_C(8));
4934
4935 res_bytes[res_byte_offset] = zig_shr_i8(signed_byte, byte_shift);
4936 lhs_sign_fill = zig_u8_bitCast_i8(zig_shr_i8(signed_byte, UINT8_C(7)), UINT8_C(8));
4937 } else {
4938 res_bytes[res_byte_offset] = zig_shr_u8(lhs_prev_byte, byte_shift);
4939 }
4940
4941#if zig_little_endian
4942 res_byte_offset += UINT16_C(1);
4943 memset(&res_bytes[res_byte_offset], lhs_sign_fill, size - res_byte_offset);
4944#else
4945 memset(&res_bytes[0], lhs_sign_fill, res_byte_offset);
4946#endif
4947 }
4948}
4949
4950static inline bool zig_shlo_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) {
4951 uint8_t *res_bytes = res;
4952 const uint8_t *lhs_bytes = lhs;
4953 uint8_t lhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(lhs, is_signed, bits), UINT8_C(8));
4954 uint16_t size = zig_int_bytes(bits);
4955 uint16_t res_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
4956 uint16_t lhs_byte_offset = UINT16_C(0);
4957 uint16_t end_byte_offset = res_byte_offset - UINT16_C(1) - zig_shr_u16(rhs, UINT8_C(3));
4958 uint8_t lhs_prev_byte = lhs_sign_fill;
4959 uint8_t byte_shift = UINT8_C(8) - zig_u8_truncate_u16(rhs, UINT8_C(3));
4960 bool overflow = false;
4961
4962#if zig_little_endian
4963 lhs_byte_offset = size - lhs_byte_offset;
4964#else
4965 res_byte_offset = size - res_byte_offset;
4966 end_byte_offset = size - end_byte_offset;
4967#endif
4968
4969 while (lhs_byte_offset != end_byte_offset) {
4970#if zig_little_endian
4971 lhs_byte_offset -= UINT16_C(1);
4972#endif
4973
4974 overflow |= lhs_prev_byte != lhs_sign_fill;
4975 lhs_prev_byte = lhs_bytes[lhs_byte_offset];
4976
4977#if zig_big_endian
4978 lhs_byte_offset += UINT16_C(1);
4979#endif
4980 }
4981
4982#if zig_little_endian
4983 end_byte_offset = UINT16_C(0);
4984#else
4985 end_byte_offset = size;
4986#endif
4987
4988 {
4989 bool lhs_more_bytes = lhs_byte_offset != end_byte_offset;
4990
4991#if zig_little_endian
4992 if (lhs_more_bytes) lhs_byte_offset -= UINT16_C(1);
4993#endif
4994
4995 {
4996 uint8_t lhs_byte = UINT8_C(0);
4997
4998 if (lhs_more_bytes) lhs_byte = lhs_bytes[lhs_byte_offset];
4999
5000 if (is_signed) {
5001 int16_t shifted = zig_shr_i16(zig_or_i16(
5002 zig_shl_i16(zig_i16_intCast_u8(lhs_prev_byte), UINT8_C(8)),
5003 zig_i16_intCast_u8(lhs_byte)
5004 ), byte_shift);
5005 int8_t truncated = zig_i8_truncate_i16(
5006 shifted,
5007 zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1)
5008 );
5009 uint8_t fill = zig_u8_bitCast_i8(zig_shr_i8(truncated, UINT8_C(7)), UINT8_C(8));
5010
5011 overflow |= zig_i16_intCast_i8(truncated) != shifted;
5012#if zig_little_endian
5013 memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset);
5014 res_byte_offset -= UINT16_C(1);
5015#else
5016 memset(&res_bytes[0], fill, res_byte_offset);
5017#endif
5018 res_bytes[res_byte_offset] = zig_u8_bitCast_i8(truncated, UINT8_C(8));
5019 } else {
5020 uint16_t shifted = zig_shr_u16(zig_or_u16(
5021 zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)),
5022 zig_u16_intCast_u8(lhs_byte)
5023 ), byte_shift);
5024 uint8_t truncated = zig_u8_truncate_u16(
5025 shifted,
5026 zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1)
5027 );
5028
5029 overflow |= zig_u16_intCast_u8(truncated) != shifted;
5030#if zig_little_endian
5031 memset(&res_bytes[res_byte_offset], zig_minInt_u8, size - res_byte_offset);
5032 res_byte_offset -= UINT16_C(1);
5033#else
5034 memset(&res_bytes[0], zig_minInt_u8, res_byte_offset);
5035#endif
5036 res_bytes[res_byte_offset] = truncated;
5037 }
5038
5039 lhs_prev_byte = lhs_byte;
5040 }
5041
5042#if zig_big_endian
5043 res_byte_offset += UINT16_C(1);
5044 if (lhs_more_bytes) lhs_byte_offset += UINT16_C(1);
5045#endif
5046 }
5047
5048 while (lhs_byte_offset != end_byte_offset) {
5049#if zig_little_endian
5050 res_byte_offset -= UINT16_C(1);
5051 lhs_byte_offset -= UINT16_C(1);
5052#endif
5053
5054 {
5055 uint8_t lhs_byte = lhs_bytes[lhs_byte_offset];
5056
5057 res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16(
5058 zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)),
5059 zig_u16_intCast_u8(lhs_byte)
5060 ), byte_shift));
5061 lhs_prev_byte = lhs_byte;
5062 }
5063
5064#if zig_big_endian
5065 res_byte_offset += UINT16_C(1);
5066 lhs_byte_offset += UINT16_C(1);
5067#endif
5068 }
5069
5070 {
5071#if zig_little_endian
5072 res_byte_offset -= UINT16_C(1);
5073#endif
5074
5075 res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(
5076 zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)),
5077 byte_shift
5078 ));
5079
5080#if zig_big_endian
5081 res_byte_offset += UINT16_C(1);
5082#endif
5083 }
5084
5085#if zig_little_endian
5086 memset(&res_bytes[0], zig_minInt_u8, res_byte_offset);
5087#else
5088 memset(&res_bytes[res_byte_offset], zig_minInt_u8, size - res_byte_offset);
5089#endif
5090
5091 return overflow;
5092}
5093
5094static inline void zig_shl_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) {
5095 if (zig_shlo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: left shift overflowed bits
5096}
5097
5098static inline void zig_shlw_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) {
5099 (void)zig_shlo_big(res, lhs, rhs, is_signed, bits);
5100}
5101
5102#define zig_big_shls_builtin(w) \
5103 static inline uint##w##_t zig_shls_u##w##_big(uint##w##_t lhs, const void *rhs, \
5104 uint8_t lhs_bits, bool rhs_is_signed, uint16_t rhs_bits) { \
5105 uint##w##_t res; \
5106 const uint8_t *rhs_bytes = rhs; \
5107 if (zig_cmp_big_u8(rhs, lhs_bits, rhs_is_signed, rhs_bits) < INT32_C(0) && \
5108 !zig_shlo_u##w(&res, lhs, rhs_bytes[0], lhs_bits)) return res; \
5109 return lhs == INT##w##_C(0) ? zig_minInt_u(w, lhs_bits) : zig_maxInt_u(w, lhs_bits); \
5110 } \
5111\
5112 static inline int##w##_t zig_shls_i##w##_big(int##w##_t lhs, const void *rhs, \
5113 uint8_t lhs_bits, bool rhs_is_signed, uint16_t rhs_bits) { \
5114 int##w##_t res; \
5115 const uint8_t *rhs_bytes = rhs; \
5116 if (zig_cmp_big_u8(rhs, lhs_bits, rhs_is_signed, rhs_bits) < INT32_C(0) && \
5117 !zig_shlo_i##w(&res, lhs, rhs_bytes[0], lhs_bits)) return res; \
5118 return lhs == INT##w##_C(0) ? INT##w##_C(0) : \
5119 lhs < INT##w##_C(0) ? zig_minInt_i(w, lhs_bits) : zig_maxInt_i(w, lhs_bits); \
5120 } \
5121\
5122 static inline void zig_shls_big_u##w(void *res, const void *lhs, uint##w##_t rhs, bool is_signed, uint16_t bits) { \
5123 const uint8_t *lhs_bytes = lhs; \
5124 if (rhs < bits && !zig_shlo_big(res, lhs, zig_u16_intCast_u##w(rhs), is_signed, bits)) return; \
5125 switch (zig_cmp_big_u8(lhs, UINT8_C(0), is_signed, bits)) { \
5126 case -INT32_C(1): return zig_minInt_big(res, is_signed, bits); \
5127 case INT32_C(0): return zig_minInt_big(res, false, bits); \
5128 case INT32_C(1): return zig_maxInt_big(res, is_signed, bits); \
5129 default: zig_unreachable(); \
5130 } \
5131 }
5132zig_big_shls_builtin(8)
5133zig_big_shls_builtin(16)
5134zig_big_shls_builtin(32)
5135zig_big_shls_builtin(64)
5136
5137static inline void zig_byteSwap_big(void *res, const void *arg, bool is_signed, uint16_t bits) {
5138 uint8_t *res_bytes = res;
5139 const uint8_t *arg_bytes = arg;
5140 uint16_t res_byte_offset = UINT16_C(0);
5141 uint16_t arg_byte_offset = bits / CHAR_BIT;
5142 uint16_t end_byte_offset = UINT16_C(1);
5143 uint16_t size = zig_int_bytes(bits);
5144
5145#if zig_big_endian
5146 res_byte_offset = size - res_byte_offset;
5147 arg_byte_offset = size - arg_byte_offset;
5148 end_byte_offset = size - end_byte_offset;
5149#endif
5150
5151 while (arg_byte_offset != end_byte_offset) {
5152#if zig_little_endian
5153 arg_byte_offset -= UINT16_C(1);
5154#else
5155 res_byte_offset -= UINT16_C(1);
5156#endif
5157
5158 res_bytes[res_byte_offset] = arg_bytes[arg_byte_offset];
32425159
32435160#if zig_little_endian
3244 byte_offset += 8 / CHAR_BIT;
5161 res_byte_offset += UINT16_C(1);
5162#else
5163 arg_byte_offset += UINT16_C(1);
32455164#endif
32465165 }
32475166
3248 return overflow;
3249}
5167 {
5168#if zig_little_endian
5169 arg_byte_offset -= UINT16_C(1);
5170#else
5171 res_byte_offset -= UINT16_C(1);
5172#endif
32505173
3251static inline void zig_addw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3252 (void)zig_addo_big(res, lhs, rhs, is_signed, bits);
3253}
5174 {
5175 uint8_t byte = arg_bytes[arg_byte_offset];
5176 uint8_t fill = is_signed
5177 ? zig_u8_bitCast_i8(zig_shr_i8(zig_i8_bitCast_u8(byte, UINT8_C(8)), UINT8_C(7)), UINT8_C(8))
5178 : UINT8_C(0);
32545179
3255static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3256 (void)zig_subo_big(res, lhs, rhs, is_signed, bits);
3257}
5180 res_bytes[res_byte_offset] = byte;
32585181
3259zig_extern void __udivei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits);
3260static inline void zig_div_trunc_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3261 if (!is_signed) {
3262 __udivei4(res, lhs, rhs, bits);
3263 return;
5182#if zig_little_endian
5183 res_byte_offset += UINT16_C(1);
5184 memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset);
5185#else
5186 memset(&res_bytes[0], fill, res_byte_offset);
5187#endif
5188 }
32645189 }
3265
3266 zig_trap();
32675190}
32685191
3269static inline void zig_div_floor_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3270 if (!is_signed) {
3271 zig_div_trunc_big(res, lhs, rhs, is_signed, bits);
3272 return;
3273 }
5192static inline void zig_bitReverse_big(void *res, const void *arg, bool is_signed, uint16_t bits) {
5193 uint8_t *res_bytes = res;
5194 const uint8_t *arg_bytes = arg;
5195 uint16_t size = zig_int_bytes(bits);
5196 uint16_t res_byte_offset = UINT16_C(0);
5197 uint16_t arg_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
5198 uint16_t end_byte_offset = UINT16_C(0);
5199 uint8_t arg_prev_byte;
5200 uint8_t byte_shift = zig_u8_intCast_u16(zig_subw_u16(UINT16_C(0), bits, UINT8_C(3)));
32745201
3275 zig_trap();
3276}
5202#if zig_big_endian
5203 res_byte_offset = size - res_byte_offset;
5204 arg_byte_offset = size - arg_byte_offset;
5205 end_byte_offset = size - end_byte_offset;
5206#endif
32775207
3278static inline void zig_div_ceil_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3279 zig_trap();
3280}
5208 {
5209#if zig_little_endian
5210 arg_byte_offset -= UINT16_C(1);
5211#endif
32815212
3282zig_extern void __umodei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits);
3283static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3284 if (!is_signed) {
3285 __umodei4(res, lhs, rhs, bits);
3286 return;
5213 arg_prev_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8));
5214
5215#if zig_big_endian
5216 arg_byte_offset += UINT16_C(1);
5217#endif
32875218 }
32885219
3289 zig_trap();
3290}
5220 while (arg_byte_offset != end_byte_offset) {
5221#if zig_big_endian
5222 res_byte_offset -= UINT16_C(1);
5223#else
5224 arg_byte_offset -= UINT16_C(1);
5225#endif
32915226
3292static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3293 if (!is_signed) {
3294 zig_rem_big(res, lhs, rhs, is_signed, bits);
3295 return;
5227 {
5228 uint8_t arg_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8));
5229
5230 res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16(
5231 zig_shl_u16(zig_u16_intCast_u8(arg_byte), UINT8_C(8)),
5232 zig_u16_intCast_u8(arg_prev_byte)
5233 ), byte_shift));
5234 arg_prev_byte = arg_byte;
5235 }
5236
5237#if zig_little_endian
5238 res_byte_offset += UINT16_C(1);
5239#else
5240 arg_byte_offset += UINT16_C(1);
5241#endif
32965242 }
32975243
3298 zig_trap();
5244 {
5245 uint8_t arg_sign_fill = UINT8_C(0);
5246
5247#if zig_big_endian
5248 res_byte_offset -= UINT16_C(1);
5249#endif
5250
5251 if (is_signed) {
5252 int8_t signed_byte = zig_i8_bitCast_u8(arg_prev_byte, UINT8_C(8));
5253
5254 res_bytes[res_byte_offset] = zig_shr_i8(signed_byte, byte_shift);
5255 arg_sign_fill = zig_u8_bitCast_i8(zig_shr_i8(signed_byte, UINT8_C(7)), UINT8_C(8));
5256 } else {
5257 res_bytes[res_byte_offset] = zig_shr_u8(arg_prev_byte, byte_shift);
5258 }
5259
5260#if zig_little_endian
5261 res_byte_offset += UINT16_C(1);
5262 memset(&res_bytes[res_byte_offset], arg_sign_fill, size - res_byte_offset);
5263#else
5264 memset(&res_bytes[0], arg_sign_fill, res_byte_offset);
5265#endif
5266 }
32995267}
33005268
3301static inline uint16_t zig_clz_big(const void *val, bool is_signed, uint16_t bits) {
3302 const uint8_t *val_bytes = val;
5269static inline uint16_t zig_popCount_big(const void *arg, bool is_signed, uint16_t bits) {
5270 const uint8_t *arg_bytes = arg;
33035271 uint16_t byte_offset = 0;
3304 uint16_t remaining_bytes = zig_int_bytes(bits);
3305 uint16_t skip_bits = remaining_bytes * 8 - bits;
3306 uint16_t total_lz = 0;
3307 uint16_t limb_lz;
5272 uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
5273 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
5274 uint16_t total_pc = 0;
33085275 (void)is_signed;
33095276
3310#if zig_little_endian
3311 byte_offset = remaining_bytes;
5277#if zig_big_endian
5278 byte_offset = zig_int_bytes(bits);
33125279#endif
33135280
33145281 while (remaining_bytes >= 128 / CHAR_BIT) {
3315#if zig_little_endian
5282 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
5283
5284#if zig_big_endian
33165285 byte_offset -= 128 / CHAR_BIT;
33175286#endif
33185287
33195288 {
3320 zig_u128 val_limb;
5289 zig_u128 arg_limb;
33215290
3322 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3323 limb_lz = zig_clz_u128(val_limb, 128 - skip_bits);
5291 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5292 total_pc += zig_popCount_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits);
33245293 }
33255294
3326 total_lz += limb_lz;
3327 if (limb_lz < 128 - skip_bits) return total_lz;
3328 skip_bits = 0;
33295295 remaining_bytes -= 128 / CHAR_BIT;
33305296
3331#if zig_big_endian
5297#if zig_little_endian
33325298 byte_offset += 128 / CHAR_BIT;
33335299#endif
33345300 }
33355301
33365302 while (remaining_bytes >= 64 / CHAR_BIT) {
3337#if zig_little_endian
5303 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
5304
5305#if zig_big_endian
33385306 byte_offset -= 64 / CHAR_BIT;
33395307#endif
33405308
33415309 {
3342 uint64_t val_limb;
5310 uint64_t arg_limb;
33435311
3344 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3345 limb_lz = zig_clz_u64(val_limb, 64 - skip_bits);
5312 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5313 total_pc += zig_popCount_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits);
33465314 }
33475315
3348 total_lz += limb_lz;
3349 if (limb_lz < 64 - skip_bits) return total_lz;
3350 skip_bits = 0;
33515316 remaining_bytes -= 64 / CHAR_BIT;
33525317
3353#if zig_big_endian
5318#if zig_little_endian
33545319 byte_offset += 64 / CHAR_BIT;
33555320#endif
33565321 }
33575322
33585323 while (remaining_bytes >= 32 / CHAR_BIT) {
3359#if zig_little_endian
5324 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
5325
5326#if zig_big_endian
33605327 byte_offset -= 32 / CHAR_BIT;
33615328#endif
33625329
33635330 {
3364 uint32_t val_limb;
5331 uint32_t arg_limb;
33655332
3366 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3367 limb_lz = zig_clz_u32(val_limb, 32 - skip_bits);
5333 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5334 total_pc += zig_popCount_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits);
33685335 }
33695336
3370 total_lz += limb_lz;
3371 if (limb_lz < 32 - skip_bits) return total_lz;
3372 skip_bits = 0;
33735337 remaining_bytes -= 32 / CHAR_BIT;
33745338
3375#if zig_big_endian
5339#if zig_little_endian
33765340 byte_offset += 32 / CHAR_BIT;
33775341#endif
33785342 }
33795343
33805344 while (remaining_bytes >= 16 / CHAR_BIT) {
3381#if zig_little_endian
5345 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
5346
5347#if zig_big_endian
33825348 byte_offset -= 16 / CHAR_BIT;
33835349#endif
33845350
33855351 {
3386 uint16_t val_limb;
5352 uint16_t arg_limb;
33875353
3388 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3389 limb_lz = zig_clz_u16(val_limb, 16 - skip_bits);
5354 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5355 total_pc += zig_popCount_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits);
33905356 }
33915357
3392 total_lz += limb_lz;
3393 if (limb_lz < 16 - skip_bits) return total_lz;
3394 skip_bits = 0;
33955358 remaining_bytes -= 16 / CHAR_BIT;
33965359
3397#if zig_big_endian
5360#if zig_little_endian
33985361 byte_offset += 16 / CHAR_BIT;
33995362#endif
34005363 }
34015364
34025365 while (remaining_bytes >= 8 / CHAR_BIT) {
3403#if zig_little_endian
5366 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
5367
5368#if zig_big_endian
34045369 byte_offset -= 8 / CHAR_BIT;
34055370#endif
34065371
34075372 {
3408 uint8_t val_limb;
5373 uint8_t arg_limb;
34095374
3410 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3411 limb_lz = zig_clz_u8(val_limb, 8 - skip_bits);
5375 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5376 total_pc += zig_popCount_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits);
34125377 }
34135378
3414 total_lz += limb_lz;
3415 if (limb_lz < 8 - skip_bits) return total_lz;
3416 skip_bits = 0;
34175379 remaining_bytes -= 8 / CHAR_BIT;
34185380
3419#if zig_big_endian
5381#if zig_little_endian
34205382 byte_offset += 8 / CHAR_BIT;
34215383#endif
34225384 }
34235385
3424 return total_lz;
5386 return total_pc;
34255387}
34265388
3427static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bits) {
3428 const uint8_t *val_bytes = val;
3429 uint16_t byte_offset = 0;
3430 uint16_t remaining_bytes = zig_int_bytes(bits);
3431 uint16_t total_tz = 0;
5389static inline uint16_t zig_ctz_big(const void *arg, bool is_signed, uint16_t bits) {
5390 const uint8_t *arg_bytes = arg;
5391 uint16_t byte_offset = UINT16_C(0);
5392 uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
5393 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
5394 uint16_t total_tz = UINT16_C(0);
34325395 uint16_t limb_tz;
34335396 (void)is_signed;
34345397
34355398#if zig_big_endian
3436 byte_offset = remaining_bytes;
5399 byte_offset = zig_int_bytes(bits);
34375400#endif
34385401
34395402 while (remaining_bytes >= 128 / CHAR_BIT) {
5403 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
5404
34405405#if zig_big_endian
34415406 byte_offset -= 128 / CHAR_BIT;
34425407#endif
34435408
34445409 {
3445 zig_u128 val_limb;
5410 zig_u128 arg_limb;
34465411
3447 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3448 limb_tz = zig_ctz_u128(val_limb, 128);
5412 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5413 limb_tz = zig_ctz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits);
34495414 }
34505415
34515416 total_tz += limb_tz;
3452 if (limb_tz < 128) return total_tz;
5417 if (limb_tz < limb_bits) return total_tz;
34535418 remaining_bytes -= 128 / CHAR_BIT;
34545419
34555420#if zig_little_endian
......@@ -3458,19 +5423,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
34585423 }
34595424
34605425 while (remaining_bytes >= 64 / CHAR_BIT) {
5426 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
5427
34615428#if zig_big_endian
34625429 byte_offset -= 64 / CHAR_BIT;
34635430#endif
34645431
34655432 {
3466 uint64_t val_limb;
5433 uint64_t arg_limb;
34675434
3468 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3469 limb_tz = zig_ctz_u64(val_limb, 64);
5435 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5436 limb_tz = zig_ctz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits);
34705437 }
34715438
34725439 total_tz += limb_tz;
3473 if (limb_tz < 64) return total_tz;
5440 if (limb_tz < limb_bits) return total_tz;
34745441 remaining_bytes -= 64 / CHAR_BIT;
34755442
34765443#if zig_little_endian
......@@ -3479,19 +5446,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
34795446 }
34805447
34815448 while (remaining_bytes >= 32 / CHAR_BIT) {
5449 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
5450
34825451#if zig_big_endian
34835452 byte_offset -= 32 / CHAR_BIT;
34845453#endif
34855454
34865455 {
3487 uint32_t val_limb;
5456 uint32_t arg_limb;
34885457
3489 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3490 limb_tz = zig_ctz_u32(val_limb, 32);
5458 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5459 limb_tz = zig_ctz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits);
34915460 }
34925461
34935462 total_tz += limb_tz;
3494 if (limb_tz < 32) return total_tz;
5463 if (limb_tz < limb_bits) return total_tz;
34955464 remaining_bytes -= 32 / CHAR_BIT;
34965465
34975466#if zig_little_endian
......@@ -3500,19 +5469,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
35005469 }
35015470
35025471 while (remaining_bytes >= 16 / CHAR_BIT) {
5472 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
5473
35035474#if zig_big_endian
35045475 byte_offset -= 16 / CHAR_BIT;
35055476#endif
35065477
35075478 {
3508 uint16_t val_limb;
5479 uint16_t arg_limb;
35095480
3510 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3511 limb_tz = zig_ctz_u16(val_limb, 16);
5481 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5482 limb_tz = zig_ctz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits);
35125483 }
35135484
35145485 total_tz += limb_tz;
3515 if (limb_tz < 16) return total_tz;
5486 if (limb_tz < limb_bits) return total_tz;
35165487 remaining_bytes -= 16 / CHAR_BIT;
35175488
35185489#if zig_little_endian
......@@ -3521,19 +5492,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
35215492 }
35225493
35235494 while (remaining_bytes >= 8 / CHAR_BIT) {
5495 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
5496
35245497#if zig_big_endian
35255498 byte_offset -= 8 / CHAR_BIT;
35265499#endif
35275500
35285501 {
3529 uint8_t val_limb;
5502 uint8_t arg_limb;
35305503
3531 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3532 limb_tz = zig_ctz_u8(val_limb, 8);
5504 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5505 limb_tz = zig_ctz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits);
35335506 }
35345507
35355508 total_tz += limb_tz;
3536 if (limb_tz < 8) return total_tz;
5509 if (limb_tz < limb_bits) return total_tz;
35375510 remaining_bytes -= 8 / CHAR_BIT;
35385511
35395512#if zig_little_endian
......@@ -3544,113 +5517,141 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
35445517 return total_tz;
35455518}
35465519
3547static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_t bits) {
3548 const uint8_t *val_bytes = val;
3549 uint16_t byte_offset = 0;
3550 uint16_t remaining_bytes = zig_int_bytes(bits);
3551 uint16_t total_pc = 0;
5520static inline uint16_t zig_clz_big(const void *arg, bool is_signed, uint16_t bits) {
5521 const uint8_t *arg_bytes = arg;
5522 uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
5523 uint16_t remaining_bytes = byte_offset;
5524 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
5525 bool sign_limb = true;
5526 uint16_t total_lz = UINT16_C(0);
5527 uint16_t limb_lz;
35525528 (void)is_signed;
35535529
35545530#if zig_big_endian
3555 byte_offset = remaining_bytes;
5531 byte_offset = zig_int_bytes(bits) - remaining_bytes;
35565532#endif
35575533
35585534 while (remaining_bytes >= 128 / CHAR_BIT) {
3559#if zig_big_endian
5535 uint8_t limb_bits = UINT8_C(128) - (sign_limb ? top_bits : UINT8_C(0));
5536
5537#if zig_little_endian
35605538 byte_offset -= 128 / CHAR_BIT;
35615539#endif
35625540
35635541 {
3564 zig_u128 val_limb;
5542 zig_u128 arg_limb;
35655543
3566 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3567 total_pc += zig_popcount_u128(val_limb, 128);
5544 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5545 limb_lz = zig_clz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits);
35685546 }
35695547
5548 total_lz += limb_lz;
5549 if (limb_lz < limb_bits) return total_lz;
5550 sign_limb = false;
35705551 remaining_bytes -= 128 / CHAR_BIT;
35715552
3572#if zig_little_endian
5553#if zig_big_endian
35735554 byte_offset += 128 / CHAR_BIT;
35745555#endif
35755556 }
35765557
35775558 while (remaining_bytes >= 64 / CHAR_BIT) {
3578#if zig_big_endian
5559 uint8_t limb_bits = UINT8_C(64) - (sign_limb ? top_bits : UINT8_C(0));
5560
5561#if zig_little_endian
35795562 byte_offset -= 64 / CHAR_BIT;
35805563#endif
35815564
35825565 {
3583 uint64_t val_limb;
5566 uint64_t arg_limb;
35845567
3585 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3586 total_pc += zig_popcount_u64(val_limb, 64);
5568 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5569 limb_lz = zig_clz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits);
35875570 }
35885571
5572 total_lz += limb_lz;
5573 if (limb_lz < limb_bits) return total_lz;
5574 sign_limb = false;
35895575 remaining_bytes -= 64 / CHAR_BIT;
35905576
3591#if zig_little_endian
5577#if zig_big_endian
35925578 byte_offset += 64 / CHAR_BIT;
35935579#endif
35945580 }
35955581
35965582 while (remaining_bytes >= 32 / CHAR_BIT) {
3597#if zig_big_endian
5583 uint8_t limb_bits = UINT8_C(32) - (sign_limb ? top_bits : UINT8_C(0));
5584
5585#if zig_little_endian
35985586 byte_offset -= 32 / CHAR_BIT;
35995587#endif
36005588
36015589 {
3602 uint32_t val_limb;
5590 uint32_t arg_limb;
36035591
3604 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3605 total_pc += zig_popcount_u32(val_limb, 32);
5592 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5593 limb_lz = zig_clz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits);
36065594 }
36075595
5596 total_lz += limb_lz;
5597 if (limb_lz < limb_bits) return total_lz;
5598 sign_limb = false;
36085599 remaining_bytes -= 32 / CHAR_BIT;
36095600
3610#if zig_little_endian
5601#if zig_big_endian
36115602 byte_offset += 32 / CHAR_BIT;
36125603#endif
36135604 }
36145605
36155606 while (remaining_bytes >= 16 / CHAR_BIT) {
3616#if zig_big_endian
5607 uint8_t limb_bits = UINT8_C(16) - (sign_limb ? top_bits : UINT8_C(0));
5608
5609#if zig_little_endian
36175610 byte_offset -= 16 / CHAR_BIT;
36185611#endif
36195612
36205613 {
3621 uint16_t val_limb;
5614 uint16_t arg_limb;
36225615
3623 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3624 total_pc = zig_popcount_u16(val_limb, 16);
5616 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5617 limb_lz = zig_clz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits);
36255618 }
36265619
5620 total_lz += limb_lz;
5621 if (limb_lz < limb_bits) return total_lz;
5622 sign_limb = false;
36275623 remaining_bytes -= 16 / CHAR_BIT;
36285624
3629#if zig_little_endian
5625#if zig_big_endian
36305626 byte_offset += 16 / CHAR_BIT;
36315627#endif
36325628 }
36335629
36345630 while (remaining_bytes >= 8 / CHAR_BIT) {
3635#if zig_big_endian
5631 uint8_t limb_bits = UINT8_C(8) - (sign_limb ? top_bits : UINT8_C(0));
5632
5633#if zig_little_endian
36365634 byte_offset -= 8 / CHAR_BIT;
36375635#endif
36385636
36395637 {
3640 uint8_t val_limb;
5638 uint8_t arg_limb;
36415639
3642 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3643 total_pc = zig_popcount_u8(val_limb, 8);
5640 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5641 limb_lz = zig_clz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits);
36445642 }
36455643
5644 total_lz += limb_lz;
5645 if (limb_lz < limb_bits) return total_lz;
5646 sign_limb = false;
36465647 remaining_bytes -= 8 / CHAR_BIT;
36475648
3648#if zig_little_endian
5649#if zig_big_endian
36495650 byte_offset += 8 / CHAR_BIT;
36505651#endif
36515652 }
36525653
3653 return total_pc;
5654 return total_lz;
36545655}
36555656
36565657/* ========================= Floating Point Support ========================= */
......@@ -3687,29 +5688,29 @@ long double __cdecl nanl(char const* input);
36875688#define zig_make_special_f80(sign, name, arg, repr) sign zig_make_f80 (__builtin_##name, )(arg)
36885689#define zig_make_special_f128(sign, name, arg, repr) sign zig_make_f128(__builtin_##name, )(arg)
36895690#else
3690#define zig_make_special_f16(sign, name, arg, repr) zig_bitCast_f16 (repr)
3691#define zig_make_special_f32(sign, name, arg, repr) zig_bitCast_f32 (repr)
3692#define zig_make_special_f64(sign, name, arg, repr) zig_bitCast_f64 (repr)
3693#define zig_make_special_f80(sign, name, arg, repr) zig_bitCast_f80 (repr)
3694#define zig_make_special_f128(sign, name, arg, repr) zig_bitCast_f128(repr)
5691#define zig_make_special_f16(sign, name, arg, repr) zig_f16_bitCast_u16 (repr)
5692#define zig_make_special_f32(sign, name, arg, repr) zig_f32_bitCast_u32 (repr)
5693#define zig_make_special_f64(sign, name, arg, repr) zig_f64_bitCast_u64 (repr)
5694#define zig_make_special_f80(sign, name, arg, repr) zig_f80_bitCast_u128(repr)
5695#define zig_make_special_f128(sign, name, arg, repr) zig_f128_bitCast_u128(repr)
36955696#endif
36965697
36975698#define zig_has_f16 1
36985699#define zig_libc_name_f16(name) __##name##h
36995700#define zig_init_special_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr)
3700#if FLT_MANT_DIG == 11
5701#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT_MANT_DIG == 11
37015702typedef float zig_f16;
37025703#define zig_make_f16(fp, repr) fp##f
3703#elif DBL_MANT_DIG == 11
5704#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && DBL_MANT_DIG == 11
37045705typedef double zig_f16;
37055706#define zig_make_f16(fp, repr) fp
3706#elif LDBL_MANT_DIG == 11
5707#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && LDBL_MANT_DIG == 11
37075708typedef long double zig_f16;
37085709#define zig_make_f16(fp, repr) fp##l
3709#elif FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gcc))
5710#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gcc))
37105711typedef _Float16 zig_f16;
37115712#define zig_make_f16(fp, repr) fp##f16
3712#elif defined(__SIZEOF_FP16__)
5713#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && defined(__SIZEOF_FP16__)
37135714typedef __fp16 zig_f16;
37145715#define zig_make_f16(fp, repr) fp##f16
37155716#else
......@@ -3723,11 +5724,6 @@ typedef uint16_t zig_f16;
37235724#undef zig_init_special_f16
37245725#define zig_init_special_f16(sign, name, arg, repr) repr
37255726#endif
3726#if defined(zig_darwin) && defined(zig_x86)
3727typedef uint16_t zig_compiler_rt_f16;
3728#else
3729typedef zig_f16 zig_compiler_rt_f16;
3730#endif
37315727
37325728#define zig_has_f32 1
37335729#define zig_libc_name_f32(name) name##f
......@@ -3736,16 +5732,16 @@ typedef zig_f16 zig_compiler_rt_f16;
37365732#else
37375733#define zig_init_special_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr)
37385734#endif
3739#if FLT_MANT_DIG == 24
5735#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT_MANT_DIG == 24
37405736typedef float zig_f32;
37415737#define zig_make_f32(fp, repr) fp##f
3742#elif DBL_MANT_DIG == 24
5738#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && DBL_MANT_DIG == 24
37435739typedef double zig_f32;
37445740#define zig_make_f32(fp, repr) fp
3745#elif LDBL_MANT_DIG == 24
5741#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && LDBL_MANT_DIG == 24
37465742typedef long double zig_f32;
37475743#define zig_make_f32(fp, repr) fp##l
3748#elif FLT32_MANT_DIG == 24
5744#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT32_MANT_DIG == 24
37495745typedef _Float32 zig_f32;
37505746#define zig_make_f32(fp, repr) fp##f32
37515747#else
......@@ -3768,19 +5764,19 @@ typedef uint32_t zig_f32;
37685764#else
37695765#define zig_init_special_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr)
37705766#endif
3771#if FLT_MANT_DIG == 53
5767#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT_MANT_DIG == 53
37725768typedef float zig_f64;
37735769#define zig_make_f64(fp, repr) fp##f
3774#elif DBL_MANT_DIG == 53
5770#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && DBL_MANT_DIG == 53
37755771typedef double zig_f64;
37765772#define zig_make_f64(fp, repr) fp
3777#elif LDBL_MANT_DIG == 53
5773#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && LDBL_MANT_DIG == 53
37785774typedef long double zig_f64;
37795775#define zig_make_f64(fp, repr) fp##l
3780#elif FLT64_MANT_DIG == 53
5776#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT64_MANT_DIG == 53
37815777typedef _Float64 zig_f64;
37825778#define zig_make_f64(fp, repr) fp##f64
3783#elif FLT32X_MANT_DIG == 53
5779#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT32X_MANT_DIG == 53
37845780typedef _Float32x zig_f64;
37855781#define zig_make_f64(fp, repr) fp##f32x
37865782#else
......@@ -3798,7 +5794,14 @@ typedef uint64_t zig_f64;
37985794#define zig_has_f80 1
37995795#define zig_libc_name_f80(name) __##name##x
38005796#define zig_init_special_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr)
3801#if FLT_MANT_DIG == 64
5797#ifdef ZIG_TARGET_SOFT_COMPILER_RT_F80_ABI
5798#undef zig_has_f80
5799typedef struct { uint64_t mantissa; uint16_t exponent; } zig_f80;
5800#define zig_init_repr_f80(mantissa, exponent) { .mant##issa = mantissa, .expo##nent = exponent }
5801#define zig_make_repr_f80(mantissa, exponent) (zig_f80)zig_init_repr_f80(mantissa, exponent)
5802#define zig_mantissa_repr_f80(arg) (arg).mantissa
5803#define zig_exponent_repr_f80(arg) (arg).exponent
5804#elif FLT_MANT_DIG == 64
38025805typedef float zig_f80;
38035806#define zig_make_f80(fp, repr) fp##f
38045807#elif DBL_MANT_DIG == 64
......@@ -3818,68 +5821,91 @@ typedef __float80 zig_f80;
38185821#define zig_make_f80(fp, repr) fp##l
38195822#else
38205823#undef zig_has_f80
3821#define zig_has_f80 0
3822#define zig_repr_f80 u128
38235824typedef zig_u128 zig_f80;
5825#define zig_init_repr_f80(mantissa, exponent) zig_init_u128(exponent, mantissa)
5826#define zig_make_repr_f80(mantissa, exponent) zig_make_u128(exponent, mantissa)
5827#define zig_mantissa_repr_f80(arg) zig_lo_u128(arg)
5828#define zig_exponent_repr_f80(arg) (uint16_t)zig_hi_u128(arg)
5829#endif
5830#ifndef zig_has_f80
5831#define zig_has_f80 0
38245832#define zig_make_f80(fp, repr) repr
5833#ifndef zig_make_repr_f80
5834#define zig_make_repr_f80(mantissa, exponent) (zig_f80)zig_init_repr_f80(mantissa, exponent)
5835#endif
38255836#undef zig_make_special_f80
38265837#define zig_make_special_f80(sign, name, arg, repr) repr
38275838#undef zig_init_special_f80
38285839#define zig_init_special_f80(sign, name, arg, repr) repr
38295840#endif
38305841
3831#if defined(zig_gcc) && defined(zig_x86)
3832#define zig_f128_has_miscompilations 1
3833#else
3834#define zig_f128_has_miscompilations 0
3835#endif
3836
38375842#define zig_has_f128 1
3838#define zig_libc_name_f128(name) name##q
5843#define zig_libc_name_f128(name) name##f128
38395844#define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr)
3840#if !zig_f128_has_miscompilations && FLT_MANT_DIG == 113
5845#ifdef ZIG_TARGET_SOFT_COMPILER_RT_F128_ABI
5846#undef zig_has_f128
5847#if zig_little_endian
5848typedef struct { uint64_t lo, hi; } zig_f128;
5849#else
5850typedef struct { uint64_t hi, lo; } zig_f128;
5851#endif
5852#define zig_init_repr_f128(hi, lo) { .h##i = hi, .l##o = lo }
5853#define zig_lo_repr_f128(arg) (arg).lo
5854#define zig_hi_repr_f128(arg) (arg).hi
5855#elif FLT_MANT_DIG == 113
38415856typedef float zig_f128;
38425857#define zig_make_f128(fp, repr) fp##f
3843#elif !zig_f128_has_miscompilations && DBL_MANT_DIG == 113
5858#elif DBL_MANT_DIG == 113
38445859typedef double zig_f128;
38455860#define zig_make_f128(fp, repr) fp
3846#elif !zig_f128_has_miscompilations && LDBL_MANT_DIG == 113
5861#elif LDBL_MANT_DIG == 113
38475862typedef long double zig_f128;
38485863#define zig_make_f128(fp, repr) fp##l
3849#elif !zig_f128_has_miscompilations && FLT128_MANT_DIG == 113
5864#elif FLT128_MANT_DIG == 113
38505865typedef _Float128 zig_f128;
38515866#define zig_make_f128(fp, repr) fp##f128
3852#elif !zig_f128_has_miscompilations && FLT64X_MANT_DIG == 113
5867#elif FLT64X_MANT_DIG == 113
38535868typedef _Float64x zig_f128;
38545869#define zig_make_f128(fp, repr) fp##f64x
3855#elif !zig_f128_has_miscompilations && defined(__SIZEOF_FLOAT128__)
5870#elif defined(__SIZEOF_FLOAT128__)
38565871typedef __float128 zig_f128;
38575872#define zig_make_f128(fp, repr) fp##q
38585873#undef zig_make_special_f128
38595874#define zig_make_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg)
38605875#else
38615876#undef zig_has_f128
3862#define zig_has_f128 0
3863#undef zig_make_special_f128
3864#undef zig_init_special_f128
3865#if defined(zig_darwin) || defined(zig_aarch64)
3866typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_v2u64;
3867zig_basic_operator(zig_v2u64, xor_v2u64, ^)
3868#define zig_repr_f128 v2u64
3869typedef zig_v2u64 zig_f128;
3870#define zig_make_f128_zig_make_u128(hi, lo) (zig_f128){ lo, hi }
3871#define zig_make_f128_zig_init_u128 zig_make_f128_zig_make_u128
3872#define zig_make_f128(fp, repr) zig_make_f128_##repr
3873#define zig_make_special_f128(sign, name, arg, repr) zig_make_f128_##repr
3874#define zig_init_special_f128(sign, name, arg, repr) zig_make_f128_##repr
3875#else
3876#define zig_repr_f128 u128
5877#if defined(zig_x86_64) && defined(ZIG_TARGET_ABI_MSVC)
5878#if defined(zig_msvc) && !defined(__clang__)
5879#include <emmintrin.h>
5880typedef __m128i zig_f128;
5881#define zig_init_repr_f128(hi, lo) { .m128i_u64 = { lo, hi } }
5882#define zig_lo_repr_f128(arg) (arg).m128i_u64[0]
5883#define zig_hi_repr_f128(arg) (arg).m128i_u64[1]
5884#else
5885typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_f128;
5886#define zig_init_repr_f128(hi, lo) { lo, hi }
5887#define zig_lo_repr_f128(arg) (arg)[0]
5888#define zig_hi_repr_f128(arg) (arg)[1]
5889#endif
5890#else
38775891typedef zig_u128 zig_f128;
5892#define zig_init_repr_f128(hi, lo) zig_init_u128(hi, lo)
5893#define zig_make_repr_f128(hi, lo) zig_make_u128(hi, lo)
5894#define zig_lo_repr_f128(arg) zig_lo_u128(arg)
5895#define zig_hi_repr_f128(arg) zig_hi_u128(arg)
5896#endif
5897#endif
5898#ifndef zig_has_f128
5899#define zig_has_f128 0
38785900#define zig_make_f128(fp, repr) repr
5901#ifndef zig_make_repr_f128
5902#define zig_make_repr_f128(hi, lo) (zig_f128)zig_init_repr_f128(hi, lo)
5903#endif
5904#undef zig_make_special_f128
38795905#define zig_make_special_f128(sign, name, arg, repr) repr
5906#undef zig_init_special_f128
38805907#define zig_init_special_f128(sign, name, arg, repr) repr
38815908#endif
3882#endif
38835909
38845910#if !defined(zig_msvc) && defined(ZIG_TARGET_ABI_MSVC)
38855911/* Emulate msvc abi on a gnu compiler */
......@@ -3892,84 +5918,141 @@ typedef zig_f128 zig_c_longdouble;
38925918typedef long double zig_c_longdouble;
38935919#endif
38945920
3895#define zig_bitCast_float(Type, ReprType) \
3896 static inline zig_##Type zig_bitCast_##Type(ReprType repr) { \
3897 zig_##Type result; \
3898 memcpy(&result, &repr, sizeof(result)); \
3899 return result; \
5921#if __AVR__
5922typedef signed char zig_FloatCompareResult;
5923#elif defined(zig_aarch64)
5924typedef signed int zig_FloatCompareResult;
5925#elif __SIZEOF_LONG__ >= __SIZEOF_POINTER__
5926typedef signed long zig_FloatCompareResult;
5927#else
5928typedef signed long long zig_FloatCompareResult;
5929#endif
5930
5931#define zig_bitCast_float(w, iw, UnsignedReprType, SignedReprType) \
5932 static inline zig_f##w zig_f##w##_bitCast_u##iw(UnsignedReprType arg) { \
5933 zig_f##w res; \
5934 memcpy(&res, &arg, sizeof(zig_f##w)); \
5935 return res; \
5936 } \
5937 static inline zig_f##w zig_f##w##_bitCast_i##iw(SignedReprType arg) { \
5938 zig_f##w res; \
5939 memcpy(&res, &arg, sizeof(zig_f##w)); \
5940 return res; \
5941 } \
5942 static inline UnsignedReprType zig_u##iw##_bitCast_f##w(zig_f##w arg) { \
5943 UnsignedReprType res; \
5944 memcpy(&res, &arg, sizeof(zig_f##w)); \
5945 return zig_u##iw##_truncate_u##iw(res, w); \
5946 } \
5947 static inline SignedReprType zig_i##iw##_bitCast_f##w(zig_f##w arg) { \
5948 SignedReprType res; \
5949 memcpy(&res, &arg, sizeof(zig_f##w)); \
5950 return zig_i##iw##_truncate_i##iw(res, w); \
39005951 }
3901zig_bitCast_float(f16, uint16_t)
3902zig_bitCast_float(f32, uint32_t)
3903zig_bitCast_float(f64, uint64_t)
3904zig_bitCast_float(f80, zig_u128)
3905zig_bitCast_float(f128, zig_u128)
5952zig_bitCast_float(16, 16, uint16_t, int16_t)
5953zig_bitCast_float(32, 32, uint32_t, int32_t)
5954zig_bitCast_float(64, 64, uint64_t, int64_t)
5955#if zig_has_f80
5956zig_bitCast_float(80, 128, zig_u128, zig_i128)
5957#else
5958static inline zig_f80 zig_f80_bitCast_u128(zig_u128 arg) {
5959 return zig_make_repr_f80(zig_lo_u128(arg), (uint16_t)zig_hi_u128(arg));
5960}
5961static inline zig_f80 zig_f80_bitCast_i128(zig_i128 arg) {
5962 return zig_make_repr_f80(zig_lo_i128(arg), (uint16_t)zig_hi_i128(arg));
5963}
5964static inline zig_u128 zig_u128_bitCast_f80(zig_f80 arg) {
5965 return zig_make_u128(zig_exponent_repr_f80(arg), zig_mantissa_repr_f80(arg));
5966}
5967static inline zig_i128 zig_i128_bitCast_f80(zig_f80 arg) {
5968 return zig_make_i128((int16_t)zig_exponent_repr_f80(arg), zig_mantissa_repr_f80(arg));
5969}
5970#endif
5971static inline zig_f80 zig_f80_bitCast_big(const void *arg) {
5972 return zig_f80_bitCast_u128(zig_u128_truncate_big(arg, UINT8_C(80), false, UINT16_C(80)));
5973}
5974static inline void zig_big_bitCast_f80(void *res, zig_f80 arg, bool res_is_signed, uint16_t res_bits) {
5975 if (res_is_signed) {
5976 zig_big_truncate_i128(res, zig_i128_bitCast_f80(arg), res_is_signed, res_bits);
5977 } else {
5978 zig_big_truncate_u128(res, zig_u128_bitCast_f80(arg), res_is_signed, res_bits);
5979 }
5980}
5981#if zig_has_f128
5982zig_bitCast_float(128, 128, zig_u128, zig_i128)
5983#else
5984static inline zig_f128 zig_f128_bitCast_u128(zig_u128 arg) {
5985 return zig_make_repr_f128(zig_hi_u128(arg), zig_lo_u128(arg));
5986}
5987static inline zig_f128 zig_f128_bitCast_i128(zig_i128 arg) {
5988 return zig_make_repr_f128((uint64_t)zig_hi_i128(arg), zig_lo_i128(arg));
5989}
5990static inline zig_u128 zig_u128_bitCast_f128(zig_f128 arg) {
5991 return zig_make_u128(zig_hi_repr_f128(arg), zig_lo_repr_f128(arg));
5992}
5993static inline zig_i128 zig_i128_bitCast_f128(zig_f128 arg) {
5994 return zig_make_i128((int64_t)zig_hi_repr_f128(arg), zig_lo_repr_f128(arg));
5995}
5996#endif
39065997
3907#define zig_convert_builtin(ExternResType, ResType, operation, ExternArgType, ArgType, version) \
3908 zig_extern ExternResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
3909 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ExternArgType); \
5998#define zig_convert_float_00(ResType, operation, ArgType, version) \
5999 zig_extern ResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
6000 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ArgType arg); \
6001 return zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
6002 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(arg)
6003#define zig_convert_float_01(ResType, operation, ArgType, version) \
6004 zig_convert_float_00(ResType, operation, ArgType, version)
6005#define zig_convert_float_10(ResType, operation, ArgType, version) \
6006 zig_convert_float_00(ResType, operation, ArgType, version)
6007#define zig_convert_float_11(ResType, operation, ArgType, version) \
6008 return (ResType)arg
6009#define zig_convert_float(res_when, ResType, operation, arg_when, ArgType, version) \
39106010 static inline ResType zig_expand_concat(zig_expand_concat(zig_##operation, \
39116011 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType)(ArgType arg) { \
3912 ResType res; \
3913 ExternResType extern_res; \
3914 ExternArgType extern_arg; \
3915 memcpy(&extern_arg, &arg, sizeof(extern_arg)); \
3916 extern_res = zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
3917 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(extern_arg); \
3918 memcpy(&res, &extern_res, sizeof(res)); \
3919 return extern_res; \
3920 }
3921zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f32, zig_f32, 2)
3922zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f64, zig_f64, 2)
3923zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f80, zig_f80, 2)
3924zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f128, zig_f128, 2)
3925zig_convert_builtin(zig_f32, zig_f32, extend, zig_compiler_rt_f16, zig_f16, 2)
3926zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f80, zig_f80, 2)
3927zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f128, zig_f128, 2)
3928zig_convert_builtin(zig_f64, zig_f64, extend, zig_compiler_rt_f16, zig_f16, 2)
3929zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f80, zig_f80, 2)
3930zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f128, zig_f128, 2)
3931zig_convert_builtin(zig_f80, zig_f80, extend, zig_f16, zig_f16, 2)
3932zig_convert_builtin(zig_f80, zig_f80, extend, zig_f32, zig_f32, 2)
3933zig_convert_builtin(zig_f80, zig_f80, extend, zig_f64, zig_f64, 2)
3934zig_convert_builtin(zig_f80, zig_f80, trunc, zig_f128, zig_f128, 2)
3935zig_convert_builtin(zig_f128, zig_f128, extend, zig_f16, zig_f16, 2)
3936zig_convert_builtin(zig_f128, zig_f128, extend, zig_f32, zig_f32, 2)
3937zig_convert_builtin(zig_f128, zig_f128, extend, zig_f64, zig_f64, 2)
3938zig_convert_builtin(zig_f128, zig_f128, extend, zig_f80, zig_f80, 2)
3939
3940#ifdef __ARM_EABI__
3941
3942zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_d2f(zig_f64);
3943static inline zig_f32 zig_truncdfsf(zig_f64 arg) { return __aeabi_d2f(arg); }
3944
3945zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_f2d(zig_f32);
3946static inline zig_f64 zig_extendsfdf(zig_f32 arg) { return __aeabi_f2d(arg); }
3947
3948#else /* __ARM_EABI__ */
3949
3950zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f64, zig_f64, 2)
3951zig_convert_builtin(zig_f64, zig_f64, extend, zig_f32, zig_f32, 2)
3952
3953#endif /* __ARM_EABI__ */
3954
3955#define zig_float_negate_builtin_0(w, c, sb) \
3956 zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, c sb))
3957#define zig_float_negate_builtin_1(w, c, sb) -arg
3958#define zig_float_negate_builtin(w, c, sb) \
6012 zig_expand_concat(zig_expand_concat(zig_convert_float_, zig_has_##res_when), \
6013 zig_has_##arg_when)(ResType, operation, ArgType, version); \
6014 }
6015
6016#define zig_convert_floats(SmallType, BigType) \
6017 zig_convert_float(SmallType, zig_##SmallType, trunc, BigType, zig_##BigType, 2) \
6018 zig_convert_float(BigType, zig_##BigType, extend, SmallType, zig_##SmallType, 2)
6019zig_convert_floats(f16, f32)
6020zig_convert_floats(f16, f64)
6021zig_convert_floats(f16, f80)
6022zig_convert_floats(f16, f128)
6023zig_convert_floats(f32, f64)
6024zig_convert_floats(f32, f80)
6025zig_convert_floats(f32, f128)
6026zig_convert_floats(f64, f80)
6027zig_convert_floats(f64, f128)
6028zig_convert_floats(f80, f128)
6029
6030#define zig_float_negate_builtin_0(w, sb) \
6031 zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, sb))
6032#define zig_float_negate_builtin_1(w, sb) -arg
6033#define zig_float_negate_builtin(w, sb) \
39596034 static inline zig_f##w zig_neg_f##w(zig_f##w arg) { \
3960 return zig_expand_concat(zig_float_negate_builtin_, zig_has_f##w)(w, c, sb); \
6035 return zig_expand_concat(zig_float_negate_builtin_, zig_has_f##w)(w, sb); \
39616036 }
3962zig_float_negate_builtin(16, , UINT16_C(1) << 15 )
3963zig_float_negate_builtin(32, , UINT32_C(1) << 31 )
3964zig_float_negate_builtin(64, , UINT64_C(1) << 63 )
3965zig_float_negate_builtin(80, zig_make_u128, (UINT64_C(1) << 15, UINT64_C(0)))
3966zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))
6037zig_float_negate_builtin(16, UINT16_C(1) << 15)
6038zig_float_negate_builtin(32, UINT32_C(1) << 31)
6039zig_float_negate_builtin(64, UINT64_C(1) << 63)
6040
6041#undef zig_float_negate_builtin_0
6042#define zig_float_negate_builtin_0(w, sb) \
6043 zig_make_repr_f##w(zig_mantissa_repr_f##w(arg), zig_xor_u16(zig_exponent_repr_f##w(arg), sb))
6044zig_float_negate_builtin(80, UINT16_C(1) << 15)
6045
6046#undef zig_float_negate_builtin_0
6047#define zig_float_negate_builtin_0(w, sb) \
6048 zig_make_repr_f##w(zig_xor_u64(zig_hi_repr_f##w(arg), sb), zig_lo_repr_f##w(arg))
6049zig_float_negate_builtin(128, UINT64_C(1) << 63)
39676050
39686051#define zig_float_less_builtin_0(Type, operation) \
3969 zig_extern int32_t zig_expand_concat(zig_expand_concat(__##operation, \
6052 zig_extern zig_FloatCompareResult zig_expand_concat(zig_expand_concat(__##operation, \
39706053 zig_compiler_rt_abbrev_zig_##Type), 2)(zig_##Type, zig_##Type); \
39716054 static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
3972 return zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 2)(lhs, rhs); \
6055 return (int32_t)zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 2)(lhs, rhs); \
39736056 }
39746057#define zig_float_less_builtin_1(Type, operation) \
39756058 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)))
39946077 return lhs operator rhs; \
39956078 }
39966079
6080#define zig_float_builtins(w) \
6081 zig_common_float_builtins(w) \
6082 zig_convert_float(f##w, zig_f##w, float, int128, zig_i128, ) \
6083 zig_convert_float(f##w, zig_f##w, floatun, int128, zig_u128, )
39976084#define zig_common_float_builtins(w) \
3998 zig_convert_builtin( int64_t, int64_t, fix, zig_f##w, zig_f##w, ) \
3999 zig_convert_builtin(zig_i128, zig_i128, fix, zig_f##w, zig_f##w, ) \
4000 zig_convert_builtin(zig_u128, zig_u128, fixuns, zig_f##w, zig_f##w, ) \
4001 zig_convert_builtin(zig_f##w, zig_f##w, float, int64_t, int64_t, ) \
4002 zig_convert_builtin(zig_f##w, zig_f##w, float, zig_i128, zig_i128, ) \
4003 zig_convert_builtin(zig_f##w, zig_f##w, floatun, zig_u128, zig_u128, ) \
6085 zig_convert_float(always, int32_t, fix, f##w, zig_f##w, ) \
6086 zig_convert_float(always, int64_t, fix, f##w, zig_f##w, ) \
6087 zig_convert_float(int128, zig_i128, fix, f##w, zig_f##w, ) \
6088 zig_convert_float(always, uint32_t, fixuns, f##w, zig_f##w, ) \
6089 zig_convert_float(always, uint64_t, fixuns, f##w, zig_f##w, ) \
6090 zig_convert_float(int128, zig_u128, fixuns, f##w, zig_f##w, ) \
6091 zig_convert_float(f##w, zig_f##w, float, always, int32_t, ) \
6092 zig_convert_float(f##w, zig_f##w, float, always, int64_t, ) \
6093 zig_convert_float(f##w, zig_f##w, floatun, always, uint32_t, ) \
6094 zig_convert_float(f##w, zig_f##w, floatun, always, uint64_t, ) \
6095\
6096 static inline void zig_expand_concat(zig_expand_concat(zig_fix, \
6097 zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \
6098 zig_extern void zig_expand_concat(zig_expand_concat(__fix, \
6099 zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \
6100 zig_expand_concat(zig_expand_concat(__fix, \
6101 zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \
6102 } \
6103\
6104 static inline void zig_expand_concat(zig_expand_concat(zig_fixuns, \
6105 zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \
6106 zig_extern void zig_expand_concat(zig_expand_concat(__fixuns, \
6107 zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \
6108 zig_expand_concat(zig_expand_concat(__fixuns, \
6109 zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \
6110 } \
6111\
6112 static inline zig_f##w zig_expand_concat(zig_floatei, \
6113 zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \
6114 zig_extern zig_f##w zig_expand_concat(__floatei, \
6115 zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \
6116 return zig_expand_concat(__floatei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \
6117 } \
6118\
6119 static inline zig_f##w zig_expand_concat(zig_floatunei, \
6120 zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \
6121 zig_extern zig_f##w zig_expand_concat(__floatunei, \
6122 zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \
6123 return zig_expand_concat(__floatunei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \
6124 } \
6125\
40046126 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, cmp) \
40056127 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, ne) \
40066128 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)))
40316153 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)) \
40326154 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)) \
40336155\
4034 static inline zig_f##w zig_div_trunc_f##w(zig_f##w lhs, zig_f##w rhs) { \
6156 static inline zig_f##w zig_divTrunc_f##w(zig_f##w lhs, zig_f##w rhs) { \
40356157 return zig_trunc_f##w(zig_div_f##w(lhs, rhs)); \
40366158 } \
40376159\
4038 static inline zig_f##w zig_div_floor_f##w(zig_f##w lhs, zig_f##w rhs) { \
6160 static inline zig_f##w zig_divFloor_f##w(zig_f##w lhs, zig_f##w rhs) { \
40396161 return zig_floor_f##w(zig_div_f##w(lhs, rhs)); \
40406162 } \
40416163\
4042 static inline zig_f##w zig_div_ceil_f##w(zig_f##w lhs, zig_f##w rhs) { \
6164 static inline zig_f##w zig_divCeil_f##w(zig_f##w lhs, zig_f##w rhs) { \
40436165 return zig_ceil_f##w(zig_div_f##w(lhs, rhs)); \
40446166 } \
40456167\
40466168 static inline zig_f##w zig_mod_f##w(zig_f##w lhs, zig_f##w rhs) { \
4047 return zig_sub_f##w(lhs, zig_mul_f##w(zig_div_floor_f##w(lhs, rhs), rhs)); \
6169 return zig_sub_f##w(lhs, zig_mul_f##w(zig_divFloor_f##w(lhs, rhs), rhs)); \
40486170 }
4049zig_common_float_builtins(16)
4050zig_common_float_builtins(32)
4051zig_common_float_builtins(64)
4052zig_common_float_builtins(80)
4053zig_common_float_builtins(128)
4054
4055#define zig_float_builtins(w) \
4056 zig_convert_builtin( int32_t, int32_t, fix, zig_f##w, zig_f##w, ) \
4057 zig_convert_builtin(uint32_t, uint32_t, fixuns, zig_f##w, zig_f##w, ) \
4058 zig_convert_builtin(uint64_t, uint64_t, fixuns, zig_f##w, zig_f##w, ) \
4059 zig_convert_builtin(zig_f##w, zig_f##w, float, int32_t, int32_t, ) \
4060 zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint32_t, uint32_t, ) \
4061 zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint64_t, uint64_t, )
40626171zig_float_builtins(16)
4063zig_float_builtins(80)
4064zig_float_builtins(128)
4065
4066#ifdef __ARM_EABI__
4067
4068zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_f2iz(zig_f32);
4069static inline int32_t zig_fixsfsi(zig_f32 arg) { return __aeabi_f2iz(arg); }
4070
4071zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_f2uiz(zig_f32);
4072static inline uint32_t zig_fixunssfsi(zig_f32 arg) { return __aeabi_f2uiz(arg); }
4073
4074zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_f2ulz(zig_f32);
4075static inline uint64_t zig_fixunssfdi(zig_f32 arg) { return __aeabi_f2ulz(arg); }
4076
4077zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_i2f(int32_t);
4078static inline zig_f32 zig_floatsisf(int32_t arg) { return __aeabi_i2f(arg); }
4079
4080zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ui2f(uint32_t);
4081static inline zig_f32 zig_floatunsisf(uint32_t arg) { return __aeabi_ui2f(arg); }
4082
4083zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ul2f(uint64_t);
4084static inline zig_f32 zig_floatundisf(uint64_t arg) { return __aeabi_ul2f(arg); }
4085
4086zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_d2iz(zig_f64);
4087static inline int32_t zig_fixdfsi(zig_f64 arg) { return __aeabi_d2iz(arg); }
4088
4089zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_d2uiz(zig_f64);
4090static inline uint32_t zig_fixunsdfsi(zig_f64 arg) { return __aeabi_d2uiz(arg); }
4091
4092zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_d2ulz(zig_f64);
4093static inline uint64_t zig_fixunsdfdi(zig_f64 arg) { return __aeabi_d2ulz(arg); }
4094
4095zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_i2d(int32_t);
4096static inline zig_f64 zig_floatsidf(int32_t arg) { return __aeabi_i2d(arg); }
4097
4098zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ui2d(uint32_t);
4099static inline zig_f64 zig_floatunsidf(uint32_t arg) { return __aeabi_ui2d(arg); }
4100
4101zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ul2d(uint64_t);
4102static inline zig_f64 zig_floatundidf(uint64_t arg) { return __aeabi_ul2d(arg); }
4103
4104#else /* __ARM_EABI__ */
4105
41066172zig_float_builtins(32)
41076173zig_float_builtins(64)
4108
4109#endif /* __ARM_EABI__ */
6174zig_float_builtins(80)
6175#if defined(zig_x86_32)
6176zig_common_float_builtins(128)
6177static inline zig_f128 zig_floattitf(zig_i128 arg) {
6178 extern zig_f128 __floattitf(zig_f128 arg);
6179 return __floattitf(zig_f128_bitCast_i128(arg));
6180}
6181static inline zig_f128 zig_floatuntitf(zig_u128 arg) {
6182 extern zig_f128 __floatuntitf(zig_f128 arg);
6183 return __floatuntitf(zig_f128_bitCast_u128(arg));
6184}
6185#elif defined(zig_x86_64) && defined(zig_windows)
6186zig_common_float_builtins(128)
6187static inline zig_f128 zig_floattitf(zig_i128 arg) {
6188 extern zig_f128 __floattitf(zig_i128 arg);
6189 return __floattitf(arg);
6190}
6191static inline zig_f128 zig_floatuntitf(zig_u128 arg) {
6192 extern zig_f128 __floatuntitf(uint64_t arg_lo, uint64_t arg_hi);
6193 return __floatuntitf(zig_lo_u128(arg), zig_hi_u128(arg));
6194}
6195#else
6196zig_float_builtins(128)
6197#endif
41106198
41116199/* ============================ Atomics Support ============================= */
41126200
......@@ -4410,19 +6498,19 @@ typedef int zig_memory_order;
44106498 } \
44116499 static inline void zig_msvc_atomic_store_##ZigType(Type volatile* obj, Type value) { \
44126500 (void)_InterlockedExchange##suffix((SigType volatile*)obj, (SigType)value); \
4413 } \
6501 } \
44146502 static inline Type zig_msvc_atomic_load_zig_memory_order_relaxed_##ZigType(Type volatile* obj) { \
44156503 return __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
44166504 } \
44176505 static inline Type zig_msvc_atomic_load_zig_memory_order_acquire_##ZigType(Type volatile* obj) { \
4418 Type val = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
6506 Type value = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
44196507 _ReadWriteBarrier(); \
4420 return val; \
6508 return value; \
44216509 } \
44226510 static inline Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##ZigType(Type volatile* obj) { \
4423 Type val = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
6511 Type value = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
44246512 _ReadWriteBarrier(); \
4425 return val; \
6513 return value; \
44266514 }
44276515
44286516zig_msvc_atomics( u8, uint8_t, char, 8, 8)
......@@ -4465,14 +6553,14 @@ zig_msvc_atomics(i64, int64_t, __int64, 64, 64)
44656553 zig_##Type result; \
44666554 SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
44676555 _ReadWriteBarrier(); \
4468 memcpy(&result, &initial, sizeof(result)); \
6556 memcpy(&result, &initial, sizeof(result)); \
44696557 return result; \
44706558 } \
44716559 static inline zig_##Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##Type(zig_##Type volatile* obj) { \
44726560 zig_##Type result; \
44736561 SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
44746562 _ReadWriteBarrier(); \
4475 memcpy(&result, &initial, sizeof(result)); \
6563 memcpy(&result, &initial, sizeof(result)); \
44766564 return result; \
44776565 }
44786566
......@@ -4502,9 +6590,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p32(void volat
45026590}
45036591
45046592static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p32(void volatile* obj) {
4505 void* val = (void*)__iso_volatile_load32(obj);
6593 void* value = (void*)__iso_volatile_load32(obj);
45066594 _ReadWriteBarrier();
4507 return val;
6595 return value;
45086596}
45096597
45106598static 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
45326620}
45336621
45346622static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p64(void volatile* obj) {
4535 void* val = (void*)__iso_volatile_load64(obj);
6623 void* value = (void*)__iso_volatile_load64(obj);
45366624 _ReadWriteBarrier();
4537 return val;
6625 return value;
45386626}
45396627
45406628static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p64(void volatile* obj) {
src/Air.zig+1-1
......@@ -1907,7 +1907,7 @@ pub const NullTerminatedString = enum(u32) {
19071907 pub fn toSlice(nts: NullTerminatedString, air: Air) [:0]const u8 {
19081908 if (nts == .none) return "";
19091909 const bytes = std.mem.sliceAsBytes(air.extra.items[@backingInt(nts)..]);
1910 return bytes[0..std.mem.indexOfScalar(u8, bytes, 0).? :0];
1910 return bytes[0..std.mem.findScalar(u8, bytes, 0).? :0];
19111911 }
19121912};
19131913
src/Air/Legalize.zig+8-1
......@@ -2906,12 +2906,18 @@ fn packedAggregateInitBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Erro
29062906 const orig_ty_pl = l.air_instructions.items(.data)[@backingInt(orig_inst)].ty_pl;
29072907 const agg_ty = orig_ty_pl.ty.toType();
29082908 const agg_field_count = agg_ty.structFieldCount(zcu);
2909 var opv_field_count: u32 = 0;
2910 for (0..agg_field_count) |field_idx| {
2911 const field_ty = agg_ty.fieldType(field_idx, zcu);
2912 const field_bits: u16 = @intCast(field_ty.bitSize(zcu));
2913 if (field_bits == 0) opv_field_count += 1;
2914 }
29092915
29102916 var bfa_buf: [4 * 32 + 2]Air.Inst.Index = undefined;
29112917 var bfa_state: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), gpa);
29122918 const bfa = bfa_state.allocator();
29132919
2914 const inst_buf = try bfa.alloc(Air.Inst.Index, 4 * agg_field_count + 2);
2920 const inst_buf = try bfa.alloc(Air.Inst.Index, 4 * (agg_field_count - opv_field_count) + 2);
29152921 defer bfa.free(inst_buf);
29162922
29172923 var main_block: Block = .init(inst_buf);
......@@ -2927,6 +2933,7 @@ fn packedAggregateInitBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Erro
29272933 field_idx -= 1;
29282934 const field_ty = agg_ty.fieldType(field_idx, zcu);
29292935 const field_bits: u16 = @intCast(field_ty.bitSize(zcu));
2936 if (field_bits == 0) continue;
29302937 assert(field_bits < num_bits);
29312938 const field_uint_ty = try pt.intType(.unsigned, field_bits);
29322939 const field_bit_size_ref: Air.Inst.Ref = .fromValue(try pt.intValue(shift_ty, field_bits));
src/Air/Liveness.zig+3-3
......@@ -351,7 +351,7 @@ const Analysis = struct {
351351 extra: std.ArrayList(u32),
352352
353353 fn addExtra(a: *Analysis, extra: anytype) Allocator.Error!u32 {
354 const field_count = std.meta.fieldNames(@TypeOf(extra)).len;
354 const field_count = @typeInfo(@TypeOf(extra)).@"struct".field_names.len;
355355 try a.extra.ensureUnusedCapacity(a.gpa, field_count);
356356 return addExtraAssumeCapacity(a, extra);
357357 }
......@@ -1012,7 +1012,7 @@ fn analyzeInstBlock(
10121012 const block_scope = data.block_scopes.get(inst).?;
10131013 const num_deaths = data.live_set.count() - block_scope.live_set.count();
10141014
1015 try a.extra.ensureUnusedCapacity(gpa, num_deaths + std.meta.fieldNames(Block).len);
1015 try a.extra.ensureUnusedCapacity(gpa, num_deaths + @typeInfo(Block).@"struct".field_names.len);
10161016 const extra_index = a.addExtraAssumeCapacity(Block{
10171017 .death_count = num_deaths,
10181018 });
......@@ -1275,7 +1275,7 @@ fn analyzeInstCondBr(
12751275 // Write the mirrored deaths to `extra`
12761276 const then_death_count = @as(u32, @intCast(then_mirrored_deaths.items.len));
12771277 const else_death_count = @as(u32, @intCast(else_mirrored_deaths.items.len));
1278 try a.extra.ensureUnusedCapacity(gpa, std.meta.fieldNames(CondBr).len + then_death_count + else_death_count);
1278 try a.extra.ensureUnusedCapacity(gpa, @typeInfo(CondBr).@"struct".field_names.len + then_death_count + else_death_count);
12791279 const extra_index = a.addExtraAssumeCapacity(CondBr{
12801280 .then_death_count = then_death_count,
12811281 .else_death_count = else_death_count,
src/Builtin.zig+8-2
......@@ -7,7 +7,7 @@ is_test: bool,
77single_threaded: bool,
88link_libc: bool,
99link_libcpp: bool,
10optimize_mode: std.lang.OptimizeMode,
10optimize_mode: std.lang.Optimize,
1111error_tracing: bool,
1212valgrind: bool,
1313sanitize_thread: bool,
......@@ -64,7 +64,9 @@ pub fn append(opts: @This(), buffer: *std.array_list.Managed(u8)) Allocator.Erro
6464 \\pub const unwind_tables: std.lang.UnwindTables = .{f};
6565 \\pub const is_test = {};
6666 \\pub const single_threaded = {};
67 \\/// Deprecated; to be removed in 0.18.0. Use `target.abi` instead.
6768 \\pub const abi: std.Target.Abi = .{f};
69 \\/// Deprecated; to be removed in 0.18.0. Use `target.cpu` instead.
6870 \\pub const cpu: std.Target.Cpu = .{{
6971 \\ .arch = .{f},
7072 \\ .model = &std.Target.{f}.cpu.{f},
......@@ -95,6 +97,7 @@ pub fn append(opts: @This(), buffer: *std.array_list.Managed(u8)) Allocator.Erro
9597 try buffer.print(
9698 \\ }}),
9799 \\}};
100 \\/// Deprecated; to be removed in 0.18.0. Use `target.os` instead.
98101 \\pub const os: std.Target.Os = .{{
99102 \\ .tag = .{f},
100103 \\ .version_range = .{{
......@@ -238,8 +241,11 @@ pub fn append(opts: @This(), buffer: *std.array_list.Managed(u8)) Allocator.Erro
238241 const link_libc = opts.link_libc;
239242
240243 try buffer.print(
244 \\/// Deprecated; to be removed in 0.18.0. Use `target.ofmt` instead.
241245 \\pub const object_format: std.Target.ObjectFormat = .{f};
242 \\pub const mode: std.lang.OptimizeMode = .{f};
246 \\/// Deprecated, to be removed after 0.18.0
247 \\pub const mode = optimize;
248 \\pub const optimize: std.lang.Optimize = .{f};
243249 \\pub const link_libc = {};
244250 \\pub const link_libcpp = {};
245251 \\pub const have_error_return_tracing = {};
src/Compilation.zig+63-37
......@@ -172,7 +172,7 @@ verbose_link: bool,
172172link_depfile: ?[]const u8,
173173disable_c_depfile: bool,
174174stack_report: bool,
175debug_compiler_runtime_libs: ?std.lang.OptimizeMode,
175debug_compiler_runtime_libs: ?std.lang.Optimize,
176176debug_compile_errors: bool,
177177/// Do not check this field directly. Instead, use the `debugIncremental` wrapper function.
178178debug_incremental: bool,
......@@ -1232,7 +1232,6 @@ pub const cache_helpers = struct {
12321232 hh.add(mod.sanitize_thread);
12331233 hh.add(mod.fuzz);
12341234 hh.add(mod.unwind_tables);
1235 hh.add(mod.structured_cfg);
12361235 hh.add(mod.no_builtin);
12371236 hh.addListOfBytes(mod.cc_argv);
12381237 }
......@@ -1506,7 +1505,7 @@ pub const CreateOptions = struct {
15061505 verbose_llvm_bc: ?[]const u8 = null,
15071506 link_depfile: ?[]const u8 = null,
15081507 verbose_llvm_cpu_features: bool = false,
1509 debug_compiler_runtime_libs: ?std.lang.OptimizeMode = null,
1508 debug_compiler_runtime_libs: ?std.lang.Optimize = null,
15101509 debug_compile_errors: bool = false,
15111510 debug_incremental: bool = false,
15121511 /// Normally when you create a `Compilation`, Zig will automatically build
......@@ -2134,6 +2133,9 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
21342133 comp.config.any_fuzz = any_fuzz;
21352134
21362135 if (opt_zcu) |zcu| {
2136 // Finish initializing the `zcu` after the fields on `comp` have been initialized.
2137 zcu.initAfterCompilation();
2138
21372139 // Populate `zcu.module_roots`.
21382140 const active = zcu.acquire();
21392141 defer active.release();
......@@ -2160,7 +2162,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
21602162 .framework_dirs = options.framework_dirs,
21612163 .rpath_list = options.rpath_list,
21622164 .symbol_wrap_set = options.symbol_wrap_set,
2163 .repro = options.linker_repro orelse (options.root_mod.optimize_mode != .Debug),
2165 .repro = options.linker_repro orelse (options.root_mod.optimize_mode != .debug),
21642166 .allow_shlib_undefined = options.linker_allow_shlib_undefined,
21652167 .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false,
21662168 .compress_debug_sections = options.linker_compress_debug_sections orelse .none,
......@@ -2911,7 +2913,20 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
29112913 // The linker progress node is set up here instead of in `performAllTheWork`, because
29122914 // we also want it around during `flush`.
29132915 if (comp.bin_file) |lf| {
2914 comp.link_prog_node = main_progress_node.start("Linking", 0);
2916 // mirrors logic in `Compilation.flush`:
2917 // Always: linker flush
2918 var initial_estimated_total: usize = 1;
2919 const llvm = if (comp.zcu) |zcu| zcu.llvm_object != null else false;
2920 // For llvm: "LLVM Emit Object" and "Parse Object" with the zcu object
2921 if (llvm) {
2922 initial_estimated_total += 2;
2923 }
2924 // Prelink
2925 if (!lf.post_prelink or llvm) {
2926 initial_estimated_total += 1;
2927 }
2928
2929 comp.link_prog_node = main_progress_node.start("Linking", initial_estimated_total);
29152930 lf.startProgress(comp.link_prog_node);
29162931 }
29172932 defer if (comp.bin_file) |lf| {
......@@ -3189,8 +3204,8 @@ fn flush(comp: *Compilation, arena: Allocator) (Io.Cancelable || Allocator.Error
31893204 break :p try p.toStringZ(arena);
31903205 },
31913206
3192 .is_debug = comp.root_mod.optimize_mode == .Debug,
3193 .is_small = comp.root_mod.optimize_mode == .ReleaseSmall,
3207 .is_debug = comp.root_mod.optimize_mode == .debug,
3208 .is_small = comp.root_mod.optimize_mode == .small,
31943209 .time_report = if (comp.time_report) |*p| p else null,
31953210 .sanitize_thread = comp.config.any_sanitize_thread,
31963211 .fuzz = comp.config.any_fuzz,
......@@ -3660,11 +3675,11 @@ pub fn saveState(comp: *Compilation) !void {
36603675 addBuf(&bufs, @ptrCast(wasm.object_relocations_table.values()));
36613676 addBuf(&bufs, @ptrCast(wasm.object_comdat_symbols.items(.kind)));
36623677 addBuf(&bufs, @ptrCast(wasm.object_comdat_symbols.items(.index)));
3663 addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.tag)));
3664 addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.offset)));
3678 addBuf(&bufs, @ptrCast(wasm.zcu_relocations.items(.tag)));
3679 addBuf(&bufs, @ptrCast(wasm.zcu_relocations.items(.offset)));
36653680 // TODO handle the union safety field
3666 //addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.pointee)));
3667 addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.addend)));
3681 //addBuf(&bufs, @ptrCast(wasm.zcu_relocations.items(.pointee)));
3682 addBuf(&bufs, @ptrCast(wasm.zcu_relocations.items(.addend)));
36683683 addBuf(&bufs, @ptrCast(wasm.uav_fixups.items));
36693684 addBuf(&bufs, @ptrCast(wasm.nav_fixups.items));
36703685 addBuf(&bufs, @ptrCast(wasm.func_table_fixups.items));
......@@ -4061,7 +4076,14 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle {
40614076 ref = refs.get(r.referencer).?;
40624077 }
40634078 }
4064 @panic("referenced transitive analysis errors, but none actually emitted");
4079 if (comp.debugIncremental()) {
4080 std.debug.print("skipping compiler panic to allow incremental debug server usage", .{});
4081 try bundle.addRootErrorMessage(.{
4082 .msg = try bundle.addString("compiler bug: referenced transitive analysis errors, but none actually emitted"),
4083 });
4084 } else {
4085 @panic("referenced transitive analysis errors, but none actually emitted");
4086 }
40654087 }
40664088 };
40674089
......@@ -4744,7 +4766,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU
47444766 defer arena_allocator.deinit();
47454767 const arena = arena_allocator.allocator();
47464768
4747 const optimize_mode = std.lang.OptimizeMode.ReleaseSmall;
4769 const optimize_mode: std.lang.Optimize = .small;
47484770 const output_mode = std.lang.OutputMode.Exe;
47494771 const resolved_target: Module.ResolvedTarget = .{
47504772 .result = std.zig.system.resolveTargetQuery(io, .{
......@@ -5910,8 +5932,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
59105932 // them being defined matches the behavior of how MSVC calls rc.exe which is the more
59115933 // relevant behavior in this case.
59125934 switch (rc_src.owner.optimize_mode) {
5913 .Debug, .ReleaseSafe => {},
5914 .ReleaseFast, .ReleaseSmall => try argv.append("-DNDEBUG"),
5935 .debug, .safe => {},
5936 .fast, .small => try argv.append("-DNDEBUG"),
59155937 }
59165938 try argv.appendSlice(rc_src.extra_flags);
59175939 try argv.appendSlice(&.{ "--", rc_src.src_path, out_res_path });
......@@ -6006,26 +6028,30 @@ fn spawnZigRc(
60066028 multi_reader.init(gpa, io, multi_reader_buffer.toStreams(), &.{ child.stdout.?, child.stderr.? });
60076029 defer multi_reader.deinit();
60086030
6009 const stdout = multi_reader.fileReader(0);
6010 const MessageHeader = std.zig.Server.Message.Header;
6031 const stdout = multi_reader.reader(0);
60116032
60126033 var eos_err: error{EndOfStream}!void = {};
60136034
6035 var client: std.zig.Client = .{
6036 .in = stdout,
6037 .out = undefined,
6038 };
6039
60146040 while (true) {
6015 const header = stdout.interface.takeStruct(MessageHeader, .little) catch |err| switch (err) {
6016 error.EndOfStream => break,
6017 error.ReadFailed => return stdout.err.?,
6018 };
6019 const body = stdout.interface.take(header.bytes_len) catch |err| switch (err) {
6041 const header = client.receiveMessageWithMultiReader(&multi_reader, .none) catch |err| switch (err) {
6042 error.Timeout => unreachable,
60206043 error.EndOfStream => |e| {
6044 if (client.in.bufferedLen() == 0) break;
60216045 // Better to report the crash with stderr below, but we set
60226046 // this in case the child exits successfully while violating
60236047 // this protocol.
60246048 eos_err = e;
60256049 break;
60266050 },
6027 error.ReadFailed => return stdout.err.?,
6051 else => |e| return e,
60286052 };
6053 const body = client.in.take(header.bytes_len) catch unreachable;
6054
60296055 switch (header.tag) {
60306056 // We expect exactly one ErrorBundle, and if any error_bundle header is
60316057 // sent then it's a fatal error.
......@@ -6178,11 +6204,11 @@ fn addCommonCCArgs(
61786204 // LLVM IR files don't support these flags.
61796205 if (ext != .ll and ext != .bc) {
61806206 switch (mod.optimize_mode) {
6181 .Debug => {},
6182 .ReleaseSafe => {
6207 .debug => {},
6208 .safe => {
61836209 try argv.append("-D_FORTIFY_SOURCE=2");
61846210 },
6185 .ReleaseFast, .ReleaseSmall => {
6211 .fast, .small => {
61866212 try argv.append("-DNDEBUG");
61876213 },
61886214 }
......@@ -6333,7 +6359,7 @@ fn addCommonCCArgs(
63336359 }
63346360 }
63356361
6336 if (mod.optimize_mode != .Debug) {
6362 if (mod.optimize_mode != .debug) {
63376363 try argv.append("-Werror=date-time");
63386364 }
63396365 },
......@@ -6412,18 +6438,18 @@ fn addCommonCCArgs(
64126438 }
64136439
64146440 switch (mod.optimize_mode) {
6415 .Debug => {
6441 .debug => {
64166442 // Clang has -Og for compatibility with GCC, but currently it is just equivalent
64176443 // to -O1. Besides potentially impairing debugging, -O1/-Og significantly
64186444 // increases compile times.
64196445 try argv.append("-O0");
64206446 },
6421 .ReleaseSafe => {
6447 .safe => {
64226448 // See the comment in the BuildModeFastRelease case for why we pass -O2 rather
64236449 // than -O3 here.
64246450 try argv.append("-O2");
64256451 },
6426 .ReleaseFast => {
6452 .fast => {
64276453 // Here we pass -O2 rather than -O3 because, although we do the equivalent of
64286454 // -O3 in Zig code, the justification for the difference here is that Zig
64296455 // has better detection and prevention of undefined behavior, so -O3 is safer for
......@@ -6431,7 +6457,7 @@ fn addCommonCCArgs(
64316457 // running in -O2 and thus the -O3 path has been tested less.
64326458 try argv.append("-O2");
64336459 },
6434 .ReleaseSmall => {
6460 .small => {
64356461 try argv.append("-Os");
64366462 },
64376463 }
......@@ -6641,6 +6667,8 @@ pub fn addCCArgs(
66416667
66426668 // Only compiled files support these flags.
66436669 switch (ext) {
6670 .assembly,
6671 .assembly_with_cpp,
66446672 .c,
66456673 .h,
66466674 .cpp,
......@@ -7254,7 +7282,6 @@ fn buildOutputFromZig(
72547282 .unwind_tables = comp.root_mod.unwind_tables,
72557283 .pic = comp.root_mod.pic,
72567284 .optimize_mode = optimize_mode,
7257 .structured_cfg = comp.root_mod.structured_cfg,
72587285 .no_builtin = true,
72597286 .code_model = comp.root_mod.code_model,
72607287 .error_tracing = false,
......@@ -7403,7 +7430,6 @@ pub fn build_crt_file(
74037430 // Some CRT objects (e.g. musl's rcrt1.o and Scrt1.o) are opinionated about PIC.
74047431 .pic = options.pic orelse comp.root_mod.pic,
74057432 .optimize_mode = comp.compilerRtOptMode(),
7406 .structured_cfg = comp.root_mod.structured_cfg,
74077433 // Some libcs (e.g. musl) are opinionated about -fno-builtin.
74087434 .no_builtin = options.no_builtin orelse comp.root_mod.no_builtin,
74097435 .code_model = comp.root_mod.code_model,
......@@ -7557,15 +7583,15 @@ pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void {
75577583
75587584/// This decides the optimization mode for all zig-provided libraries, including
75597585/// compiler-rt, libcxx, libc, libunwind, etc.
7560pub fn compilerRtOptMode(comp: Compilation) std.lang.OptimizeMode {
7586pub fn compilerRtOptMode(comp: Compilation) std.lang.Optimize {
75617587 if (comp.debug_compiler_runtime_libs) |mode| {
75627588 return mode;
75637589 }
75647590 const target = &comp.root_mod.resolved_target.result;
75657591 switch (comp.root_mod.optimize_mode) {
7566 .Debug, .ReleaseSafe => return target_util.defaultCompilerRtOptimizeMode(target),
7567 .ReleaseFast => return .ReleaseFast,
7568 .ReleaseSmall => return .ReleaseSmall,
7592 .debug, .safe => return target_util.defaultCompilerRtOptimizeMode(target),
7593 .fast => return .fast,
7594 .small => return .small,
75697595 }
75707596}
75717597
src/Compilation/Config.zig+7-7
......@@ -59,7 +59,7 @@ export_memory: bool,
5959shared_memory: bool,
6060is_test: bool,
6161debug_format: DebugFormat,
62root_optimize_mode: std.lang.OptimizeMode,
62root_optimize_mode: std.lang.Optimize,
6363root_strip: bool,
6464root_error_tracing: bool,
6565dll_export_fns: bool,
......@@ -80,7 +80,7 @@ pub const Options = struct {
8080 is_test: bool,
8181 have_zcu: bool,
8282 emit_bin: bool,
83 root_optimize_mode: ?std.lang.OptimizeMode = null,
83 root_optimize_mode: ?std.lang.Optimize = null,
8484 root_strip: ?bool = null,
8585 root_error_tracing: ?bool = null,
8686 link_mode: ?std.lang.LinkMode = null,
......@@ -196,7 +196,7 @@ pub fn resolve(options: Options) ResolveError!Config {
196196 break :b options.use_lib_llvm orelse true;
197197 };
198198
199 const root_optimize_mode = options.root_optimize_mode orelse .Debug;
199 const root_optimize_mode = options.root_optimize_mode orelse .debug;
200200
201201 // Make a decision on whether to use Clang or Aro for translate-c and compiling C files.
202202 const c_frontend: CFrontend = b: {
......@@ -357,7 +357,7 @@ pub fn resolve(options: Options) ResolveError!Config {
357357 if (!use_lib_llvm and options.emit_bin) break :b false;
358358
359359 // Prefer LLVM for release builds.
360 if (root_optimize_mode != .Debug) break :b true;
360 if (root_optimize_mode != .debug) break :b true;
361361
362362 // load_dynamic_library standalone test not passing on this combination
363363 // https://github.com/ziglang/zig/issues/24080
......@@ -486,7 +486,7 @@ pub fn resolve(options: Options) ResolveError!Config {
486486
487487 const root_strip = b: {
488488 if (options.root_strip) |x| break :b x;
489 if (root_optimize_mode == .ReleaseSmall) break :b true;
489 if (root_optimize_mode == .small) break :b true;
490490 if (!target_util.hasDebugInfo(target)) break :b true;
491491 break :b false;
492492 };
......@@ -512,8 +512,8 @@ pub fn resolve(options: Options) ResolveError!Config {
512512 if (root_strip) break :b false;
513513 if (!backend_supports_error_tracing) break :b false;
514514 break :b switch (root_optimize_mode) {
515 .Debug => true,
516 .ReleaseSafe, .ReleaseFast, .ReleaseSmall => false,
515 .debug => true,
516 .safe, .fast, .small => false,
517517 };
518518 };
519519
src/IncrementalDebugServer.zig+24-11
......@@ -130,7 +130,7 @@ fn serveStream(
130130 try stream_writer.writeAll("zig> ");
131131 const untrimmed = try stream_reader.takeSentinel('\n');
132132 const cmd_and_arg = std.mem.trim(u8, untrimmed, " \t\r\n");
133 const cmd: []const u8, const arg: []const u8 = if (std.mem.indexOfScalar(u8, cmd_and_arg, ' ')) |i|
133 const cmd: []const u8, const arg: []const u8 = if (std.mem.findScalar(u8, cmd_and_arg, ' ')) |i|
134134 .{ cmd_and_arg[0..i], cmd_and_arg[i + 1 ..] }
135135 else
136136 .{ cmd_and_arg, "" };
......@@ -244,7 +244,7 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const
244244 const ty: Type = .fromInterned(type_ip_index);
245245 const ty_name = ty.containerTypeName(ip).toSlice(ip);
246246 const success = switch (@as(u2, @intFromBool(anchor_start)) << 1 | @intFromBool(anchor_end)) {
247 0b00 => std.mem.indexOf(u8, ty_name, query) != null,
247 0b00 => std.mem.find(u8, ty_name, query) != null,
248248 0b01 => std.mem.endsWith(u8, ty_name, query),
249249 0b10 => std.mem.startsWith(u8, ty_name, query),
250250 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
265265 const nav = ip.getNav(nav_index);
266266 const nav_fqn = nav.fqn.toSlice(ip);
267267 const success = switch (@as(u2, @intFromBool(anchor_start)) << 1 | @intFromBool(anchor_end)) {
268 0b00 => std.mem.indexOf(u8, nav_fqn, query) != null,
268 0b00 => std.mem.find(u8, nav_fqn, query) != null,
269269 0b01 => std.mem.endsWith(u8, nav_fqn, query),
270270 0b10 => std.mem.startsWith(u8, nav_fqn, query),
271271 0b11 => std.mem.eql(u8, nav_fqn, query),
......@@ -286,21 +286,34 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const
286286 const referencer = (ref orelse break :ref "<analysis root>").referencer;
287287 break :ref printAnalUnit(referencer, &ref_str_buf);
288288 };
289 const has_err: []const u8 = err: {
290 if (zcu.failed_analysis.contains(unit)) break :err "true";
291 if (zcu.transitive_failed_analysis.contains(unit)) break :err "true (transitive)";
292 break :err "false";
293 };
294289 try w.print(
295290 \\last update generation: {d}
296291 \\current referencer: {s}
297 \\has error: {s}
298292 \\
299293 , .{
300294 unit_info.last_update_gen,
301295 ref_str,
302 has_err,
303296 });
297 if (zcu.failed_analysis.get(unit)) |err_msg| {
298 try w.print("analysis result: failure ({q})\n", .{err_msg.msg});
299 } else if (zcu.transitive_failed_analysis.get(unit)) |reason| {
300 switch (reason) {
301 .astgen_error => try w.writeAll("analysis result: transitive failure (astgen error)\n"),
302 .dependency_loop => try w.writeAll("analysis result: transitive failure (dependency loop)\n"),
303 .lost_tracking => try w.writeAll("analysis result: transitive failure (lost tracking for zir inst)\n"),
304 .failed_unit => |other_unit| {
305 var buf: [32]u8 = undefined;
306 try w.print("analysis result: transitive failure (failed unit: {s})\n", .{printAnalUnit(other_unit, &buf)});
307 },
308 .func_nav_val_changed => |func_index| try w.print("analysis result: transitive failure (owner nav of func '{d}' changed value)\n", .{@backingInt(func_index)}),
309 }
310 } else {
311 try w.writeAll("analysis result: success\n");
312 }
313 if (unit.unwrap() == .func) {
314 const nav_id = zcu.intern_pool.indexToKey(unit.unwrap().func).func.owner_nav;
315 try w.print("owner nav: {d}\n", .{@backingInt(nav_id)});
316 }
304317 } else if (std.mem.eql(u8, cmd_str, "unit_dependencies")) {
305318 const unit = parseAnalUnit(arg_str) orelse return w.writeAll("malformed anal unit");
306319 const unit_info = zcu.incremental_debug_state.units.get(unit) orelse return w.writeAll("unknown anal unit");
......@@ -365,7 +378,7 @@ fn parseIndex(str: []const u8) ?u32 {
365378 return std.fmt.parseInt(u32, str, 10) catch null;
366379}
367380fn parseAnalUnit(str: []const u8) ?AnalUnit {
368 const split_idx = std.mem.indexOfScalar(u8, str, ' ') orelse return null;
381 const split_idx = std.mem.findScalar(u8, str, ' ') orelse return null;
369382 const kind = str[0..split_idx];
370383 const idx_str = str[split_idx + 1 ..];
371384 if (std.mem.eql(u8, kind, "comptime")) {
src/InternPool.zig+30-30
......@@ -1737,7 +1737,7 @@ pub const String = enum(u32) {
17371737 }
17381738
17391739 pub fn toNullTerminatedString(string: String, len: u64, ip: *const InternPool) NullTerminatedString {
1740 assert(std.mem.indexOfScalar(u8, string.toSlice(len, ip), 0) == null);
1740 assert(std.mem.findScalar(u8, string.toSlice(len, ip), 0) == null);
17411741 assert(string.at(len, ip) == 0);
17421742 return @fromBackingInt(@intCast(@backingInt(string)));
17431743 }
......@@ -1864,7 +1864,7 @@ pub const NullTerminatedString = enum(u32) {
18641864 pub fn toUnsigned(string: NullTerminatedString, ip: *const InternPool) ?u32 {
18651865 const slice = string.toSlice(ip);
18661866 if (slice.len > 1 and slice[0] == '0') return null;
1867 if (std.mem.indexOfScalar(u8, slice, '_')) |_| return null;
1867 if (std.mem.findScalar(u8, slice, '_')) |_| return null;
18681868 return std.fmt.parseUnsigned(u32, slice, 10) catch null;
18691869 }
18701870
......@@ -4193,7 +4193,7 @@ pub const Index = enum(u32) {
41934193 };
41944194 }
41954195
4196 /// This function is used in the debugger pretty formatters in tools/ to fetch the
4196 /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the
41974197 /// Tag to encoding mapping to facilitate fancy debug printing for this type.
41984198 fn dbHelper(self: *Index, tag_to_encoding_map: *struct {
41994199 const DataIsIndex = struct { data: Index };
......@@ -4219,26 +4219,17 @@ pub const Index = enum(u32) {
42194219 type_inferred_error_set: DataIsIndex,
42204220 simple_type: void,
42214221 type_function: struct {
4222 const @"data.flags.has_comptime_bits" = opaque {};
4223 const @"data.flags.has_noalias_bits" = opaque {};
4224 const @"data.flags.cc.extraLen()" = opaque {};
42254222 const @"data.params_len" = opaque {};
42264223 data: *Tag.TypeFunction,
4227 @"trailing.comptime_bits.len": *@"data.flags.has_comptime_bits",
4228 @"trailing.noalias_bits.len": *@"data.flags.has_noalias_bits",
4229 @"trailing.cc_bits.len": *@"data.flags.cc.extraLen()",
42304224 @"trailing.param_types.len": *@"data.params_len",
4231 trailing: struct { comptime_bits: []u32, noalias_bits: []u32, cc_bits: []u32, param_types: []Index },
4225 trailing: struct { param_types: []Index },
42324226 },
42334227 type_tuple: struct {
42344228 const @"data.fields_len" = opaque {};
42354229 data: *TypeTuple,
42364230 @"trailing.types.len": *@"data.fields_len",
42374231 @"trailing.values.len": *@"data.fields_len",
4238 trailing: struct {
4239 types: []Index,
4240 values: []Index,
4241 },
4232 trailing: struct { types: []Index, values: []Index },
42424233 },
42434234
42444235 type_struct: struct { data: *Tag.TypeStruct },
......@@ -4350,7 +4341,7 @@ pub const Index = enum(u32) {
43504341 const encoding = @field(Tag.encodings, tag_name);
43514342 if (@hasField(@TypeOf(encoding), "trailing")) {
43524343 const trailing_info = @typeInfo(encoding.trailing).@"struct";
4353 for (trailing_info.field_names, trailing_info.field_types) |field_name, field_type| {
4344 for (trailing_info.field_names, trailing_info.field_types) |trailing_field_name, trailing_field_type| {
43544345 struct {
43554346 fn checkConfig(name: []const u8) void {
43564347 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) {
43594350 }
43604351 fn checkField(name: []const u8, Type: type) void {
43614352 switch (@typeInfo(Type)) {
4362 .int => {},
4363 .@"enum" => {},
4364 .@"struct" => |info| assert(info.layout == .@"packed"),
4353 .int, .@"enum" => return,
4354 .@"struct" => |info| switch (info.layout) {
4355 .auto => unreachable,
4356 .@"extern" => {
4357 for (info.field_names, info.field_types) |field_name, field_type| checkField(name ++ "." ++ field_name, field_type);
4358 return;
4359 },
4360 .@"packed" => return,
4361 },
43654362 .optional => |info| {
43664363 checkConfig(name ++ ".?");
43674364 checkField(name ++ ".?", info.child);
4365 return;
43684366 },
4369 .pointer => |info| {
4370 assert(info.size == .slice);
4367 .pointer => |info| if (info.size == .slice) {
43714368 checkConfig(name ++ ".len");
43724369 checkField(name ++ "[0]", info.child);
4370 return;
43734371 },
4374 else => @compileError("unsupported type: " ++ @typeName(Tag) ++ ".encodings." ++ tag_name ++ "." ++ name ++ ": " ++ @typeName(Type)),
4372 else => {},
43754373 }
4374 @compileError("unsupported type: " ++ @typeName(Tag) ++ ".encodings." ++ tag_name ++ "." ++ name ++ ": " ++ @typeName(Type));
43764375 }
4377 }.checkField("trailing." ++ field_name, field_type);
4376 }.checkField("trailing." ++ trailing_field_name, trailing_field_type);
43784377 }
43794378 }
43804379 },
......@@ -5186,17 +5185,18 @@ pub const Tag = enum(u8) {
51865185 .trailing = struct {
51875186 param_comptime_bits: ?[]u32,
51885187 param_noalias_bits: ?[]u32,
5189 param_cc_bits: ?[]u32,
5190 param_type: []Index,
5188 spirv_kernel_options: ?extern struct { x: u32, y: u32, z: u32 },
5189 spirv_mesh_options: ?extern struct { max_primitives: u32, max_vertices: u32 },
5190 param_types: []Index,
51915191 },
51925192 .config = .{
51935193 .@"trailing.param_comptime_bits.?" = .@"payload.flags.has_comptime_bits",
51945194 .@"trailing.param_comptime_bits.?.len" = .@"(payload.params_len + 31) / 32",
51955195 .@"trailing.param_noalias_bits.?" = .@"payload.flags.has_noalias_bits",
51965196 .@"trailing.param_noalias_bits.?.len" = .@"(payload.params_len + 31) / 32",
5197 .@"trailing.param_cc_bits.?" = .@"payload.flags.cc.extraLen() != 0",
5198 .@"trailing.param_cc_bits.?.len" = .@"payload.flags.cc.extraLen()",
5199 .@"trailing.param_type.len" = .@"payload.params_len",
5197 .@"trailing.spirv_kernel_options.?" = .@"payload.flags.cc.tag == .spirv_kernel or payload.flags.cc.tag == .spirv_task",
5198 .@"trailing.spirv_mesh_options.?" = .@"payload.flags.cc.tag == .spirv_mesh",
5199 .@"trailing.param_types.len" = .@"payload.params_len",
52005200 },
52015201 },
52025202
......@@ -5225,7 +5225,7 @@ pub const Tag = enum(u8) {
52255225 .@"trailing.field_defaults.?" = .@"payload.flags.any_field_defaults",
52265226 .@"trailing.field_defaults.?.len" = .@"payload.fields_len",
52275227 .@"trailing.field_aligns.?" = .@"payload.flags.any_field_aligns",
5228 .@"trailing.field_aligns.?.len" = .@"payload.fields_len",
5228 .@"trailing.field_aligns.?.len" = .@"(payload.fields_len + 3) / 4",
52295229 .@"trailing.field_is_comptime_bits.?" = .@"payload.flags.any_comptime_fields",
52305230 .@"trailing.field_is_comptime_bits.?.len" = .@"(payload.fields_len + 31) / 32",
52315231 .@"trailing.field_runtime_order.?" = .@"payload.flags.layout == .auto",
......@@ -5254,7 +5254,7 @@ pub const Tag = enum(u8) {
52545254 .@"trailing.captures.?.len" = .@"trailing.captures_len.?",
52555255 .@"trailing.field_types.len" = .@"payload.fields_len",
52565256 .@"trailing.field_aligns.?" = .@"payloads.flags.any_field_aligns",
5257 .@"trailing.field_aligns.?.len" = .@"payload.fields_len",
5257 .@"trailing.field_aligns.?.len" = .@"(payload.fields_len + 3) / 4",
52585258 },
52595259 },
52605260 .type_union_packed_auto = union_packed_encoding,
......@@ -11428,7 +11428,7 @@ pub fn getOrPutTrailingString(
1142811428 .tid = tid,
1142911429 .index = strings.mutate.len - 1,
1143011430 }).wrap(ip))));
11431 const has_embedded_null = std.mem.indexOfScalar(u8, key, 0) != null;
11431 const has_embedded_null = std.mem.findScalar(u8, key, 0) != null;
1143211432 switch (embedded_nulls) {
1143311433 .no_embedded_nulls => assert(!has_embedded_null),
1143411434 .maybe_embedded_nulls => if (has_embedded_null) {
src/Module.zig+9-26
......@@ -26,7 +26,7 @@ fully_qualified_name: []const u8,
2626deps: Deps = .{},
2727
2828resolved_target: ResolvedTarget,
29optimize_mode: std.lang.OptimizeMode,
29optimize_mode: std.lang.Optimize,
3030code_model: std.lang.CodeModel,
3131single_threaded: bool,
3232error_tracing: bool,
......@@ -42,8 +42,6 @@ sanitize_thread: bool,
4242fuzz: bool,
4343unwind_tables: std.lang.UnwindTables,
4444cc_argv: []const []const u8,
45/// (SPIR-V) whether to generate a structured control flow graph or not
46structured_cfg: bool,
4745no_builtin: bool,
4846
4947pub const Deps = std.array_hash_map.String(*Module);
......@@ -67,7 +65,7 @@ pub const CreateOptions = struct {
6765 pub const Inherited = struct {
6866 /// If this is null then `parent` must be non-null.
6967 resolved_target: ?ResolvedTarget = null,
70 optimize_mode: ?std.lang.OptimizeMode = null,
68 optimize_mode: ?std.lang.Optimize = null,
7169 code_model: ?std.lang.CodeModel = null,
7270 single_threaded: ?bool = null,
7371 error_tracing: ?bool = null,
......@@ -85,7 +83,6 @@ pub const CreateOptions = struct {
8583 sanitize_c: ?std.zig.SanitizeC = null,
8684 sanitize_thread: ?bool = null,
8785 fuzz: ?bool = null,
88 structured_cfg: ?bool = null,
8986 no_builtin: ?bool = null,
9087 };
9188};
......@@ -144,7 +141,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {
144141 if (options.inherited.valgrind) |x| break :b x;
145142 if (options.parent) |p| break :b p.valgrind;
146143 if (strip) break :b false;
147 break :b optimize_mode == .Debug;
144 break :b optimize_mode == .debug;
148145 };
149146
150147 const single_threaded = b: {
......@@ -212,7 +209,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {
212209 const omit_frame_pointer = b: {
213210 if (options.inherited.omit_frame_pointer) |x| break :b x;
214211 if (options.parent) |p| break :b p.omit_frame_pointer;
215 if (optimize_mode == .ReleaseSmall) {
212 if (optimize_mode == .small) {
216213 // On x86, in most cases, keeping the frame pointer usually results in smaller binary size.
217214 // This has to do with how instructions for memory access via the stack base pointer register (when keeping the frame pointer)
218215 // are smaller than instructions for memory access via the stack pointer register (when omitting the frame pointer).
......@@ -251,21 +248,21 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {
251248 };
252249
253250 const is_safe_mode = switch (optimize_mode) {
254 .Debug, .ReleaseSafe => true,
255 .ReleaseFast, .ReleaseSmall => false,
251 .debug, .safe => true,
252 .fast, .small => false,
256253 };
257254
258255 const sanitize_c: std.zig.SanitizeC = b: {
259256 if (options.inherited.sanitize_c) |x| break :b x;
260257 if (options.parent) |p| break :b p.sanitize_c;
261258 break :b switch (optimize_mode) {
262 .Debug => .full,
259 .debug => .full,
263260 // It's recommended to use the minimal runtime in production
264261 // environments due to the security implications of the full runtime.
265262 // The minimal runtime doesn't provide much benefit over simply
266263 // trapping, however, so we do that instead.
267 .ReleaseSafe => .trap,
268 .ReleaseFast, .ReleaseSmall => .off,
264 .safe => .trap,
265 .fast, .small => .off,
269266 };
270267 };
271268
......@@ -320,17 +317,6 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {
320317 break :sp target_util.default_stack_protector_buffer_size;
321318 };
322319
323 const structured_cfg = b: {
324 if (options.inherited.structured_cfg) |x| break :b x;
325 if (options.parent) |p| break :b p.structured_cfg;
326 // We always want a structured control flow in shaders. This option is
327 // only relevant for OpenCL kernels.
328 break :b switch (target.os.tag) {
329 .opencl => false,
330 else => true,
331 };
332 };
333
334320 const no_builtin = b: {
335321 if (options.inherited.no_builtin) |x| break :b x;
336322 if (options.parent) |p| break :b p.no_builtin;
......@@ -411,7 +397,6 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {
411397 .fuzz = fuzz,
412398 .unwind_tables = unwind_tables,
413399 .cc_argv = options.cc_argv,
414 .structured_cfg = structured_cfg,
415400 .no_builtin = no_builtin,
416401 };
417402 return mod;
......@@ -450,7 +435,6 @@ pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*M
450435 .fuzz = undefined,
451436 .unwind_tables = undefined,
452437 .cc_argv = undefined,
453 .structured_cfg = undefined,
454438 .no_builtin = undefined,
455439 };
456440 return mod;
......@@ -489,7 +473,6 @@ pub fn createBuiltin(arena: Allocator, opts: Builtin, dirs: std.zig.Directories)
489473 .stack_protector = 0,
490474 .red_zone = false,
491475 .sanitize_c = .off,
492 .structured_cfg = false,
493476 .no_builtin = false,
494477 };
495478 return new;
src/RangeSet.zig+18-23
......@@ -1,6 +1,6 @@
11const RangeSet = @This();
22
3ranges: std.MultiArrayList(Range),
3list: std.MultiArrayList(Range),
44
55pub const Range = struct {
66 first: Value,
......@@ -8,41 +8,36 @@ pub const Range = struct {
88 src: LazySrcLoc,
99};
1010
11pub const empty: RangeSet = .{ .ranges = .empty };
11pub const empty: RangeSet = .{ .list = .empty };
1212
1313pub fn deinit(self: *RangeSet, allocator: Allocator) void {
14 self.ranges.deinit(allocator);
14 self.list.deinit(allocator);
1515 self.* = undefined;
1616}
1717
18pub fn ensureUnusedCapacity(self: *RangeSet, allocator: Allocator, additional_count: usize) Allocator.Error!void {
19 return self.ranges.ensureUnusedCapacity(allocator, additional_count);
18pub fn ensureUnusedCapacity(set: *RangeSet, allocator: Allocator, additional_count: usize) Allocator.Error!void {
19 return set.list.ensureUnusedCapacity(allocator, additional_count);
2020}
2121
22pub fn addAssumeCapacity(set: *RangeSet, new: Range, ty: Type, zcu: *Zcu) ?LazySrcLoc {
22pub fn addAssumeCapacity(set: *RangeSet, new: Range, ty: Type, zcu: *Zcu) ?Range {
2323 assert(new.first.typeOf(zcu).eql(ty));
2424 assert(new.last.typeOf(zcu).eql(ty));
2525 assert(new.first.compareScalar(.lte, new.last, ty, zcu));
2626
27 const idx = std.sort.lowerBound(Value, set.ranges.items(.last), @as(SearchCtx, .{
27 const idx = std.sort.lowerBound(Value, set.list.items(.last), @as(SearchCtx, .{
2828 .val = new.first,
2929 .zcu = zcu,
3030 }), compare);
3131
32 if (idx != set.ranges.len and // `new.first` is *not* greater than all `old.last`
33 new.last.compareScalar(.gte, set.ranges.items(.first)[idx], ty, zcu))
32 if (idx != set.list.len and // `new.first` is *not* greater than all `old.last`
33 new.last.compareScalar(.gte, set.list.items(.first)[idx], ty, zcu))
3434 {
35 return set.ranges.items(.src)[idx]; // `new` overlaps with existing range.
35 return set.list.get(idx); // `new` overlaps with existing range.
3636 }
37 set.ranges.insertAssumeCapacity(idx, new);
37 set.list.insertAssumeCapacity(idx, new);
3838 return null;
3939}
4040
41pub fn add(set: *RangeSet, allocator: Allocator, new: Range, ty: Type, zcu: *Zcu) Allocator.Error!?LazySrcLoc {
42 try set.ensureUnusedCapacity(allocator, 1);
43 return set.addAssumeCapacity(new, ty, zcu);
44}
45
4641pub fn spans(
4742 set: *RangeSet,
4843 allocator: Allocator,
......@@ -53,13 +48,13 @@ pub fn spans(
5348) Allocator.Error!bool {
5449 assert(first.typeOf(zcu).eql(ty));
5550 assert(last.typeOf(zcu).eql(ty));
56 if (set.ranges.len == 0) return false;
51 if (set.list.len == 0) return false;
5752
58 assert(std.sort.isSorted(Value, set.ranges.items(.first), @as(SortCtx, .{ .ty = ty, .zcu = zcu }), lessThan));
59 assert(std.sort.isSorted(Value, set.ranges.items(.last), @as(SortCtx, .{ .ty = ty, .zcu = zcu }), lessThan));
53 assert(std.sort.isSorted(Value, set.list.items(.first), @as(SortCtx, .{ .ty = ty, .zcu = zcu }), lessThan));
54 assert(std.sort.isSorted(Value, set.list.items(.last), @as(SortCtx, .{ .ty = ty, .zcu = zcu }), lessThan));
6055
61 if (!set.ranges.items(.first)[0].eql(first, ty, zcu) or
62 !set.ranges.items(.last)[set.ranges.len - 1].eql(last, ty, zcu))
56 if (!set.list.items(.first)[0].eql(first, ty, zcu) or
57 !set.list.items(.last)[set.list.len - 1].eql(last, ty, zcu))
6358 {
6459 return false;
6560 }
......@@ -75,8 +70,8 @@ pub fn spans(
7570
7671 // look for gaps
7772 for (
78 set.ranges.items(.first)[1..],
79 set.ranges.items(.last)[0 .. set.ranges.len - 1],
73 set.list.items(.first)[1..],
74 set.list.items(.last)[0 .. set.list.len - 1],
8075 ) |cur_first, prev_last| {
8176 // prev_last + 1 == cur_first
8277 counter.copy(prev_last.toBigInt(&space, zcu));
src/Sema.zig+551-262
......@@ -532,20 +532,20 @@ pub const Block = struct {
532532
533533 fn wantSafeTypes(block: *const Block) bool {
534534 return block.want_safety orelse switch (block.ownerModule().optimize_mode) {
535 .Debug => true,
536 .ReleaseSafe => true,
537 .ReleaseFast => false,
538 .ReleaseSmall => false,
535 .debug => true,
536 .safe => true,
537 .fast => false,
538 .small => false,
539539 };
540540 }
541541
542542 fn wantSafety(block: *const Block) bool {
543543 if (block.isComptime()) return false; // runtime safety checks are pointless in comptime blocks
544544 return block.want_safety orelse switch (block.ownerModule().optimize_mode) {
545 .Debug => true,
546 .ReleaseSafe => true,
547 .ReleaseFast => false,
548 .ReleaseSmall => false,
545 .debug => true,
546 .safe => true,
547 .fast => false,
548 .small => false,
549549 };
550550 }
551551
......@@ -1472,7 +1472,7 @@ fn analyzeBodyInner(
14721472 i += 1;
14731473 continue;
14741474 },
1475 .astgen_error => return error.AnalysisFail,
1475 .astgen_error => return sema.failTransitive(.astgen_error),
14761476 .float_op_result_ty => try sema.zirFloatOpResultType(block, extended),
14771477 };
14781478 },
......@@ -2247,7 +2247,7 @@ fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) ?Value {
22472247 .inferred_alloc_comptime => unreachable, // assertion failure
22482248 else => {},
22492249 }
2250 // LLVM fails to eliminate this `classify` call in ReleaseFast, which hurts performance, so
2250 // LLVM fails to eliminate this `classify` call in -Ofast, which hurts performance, so
22512251 // we must explicitly check for `std.debug.runtime_safety`.
22522252 if (std.debug.runtime_safety) switch (sema.typeOf(inst).classify(zcu)) {
22532253 .no_possible_value => unreachable, // values of this type do not exist
......@@ -2352,6 +2352,10 @@ pub fn failWithUseOfUndef(sema: *Sema, block: *Block, src: LazySrcLoc, vector_in
23522352 });
23532353}
23542354
2355pub fn failWithUndefSliceLen(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError {
2356 return sema.fail(block, src, "use of slice with undefined length here causes illegal behavior", .{});
2357}
2358
23552359pub fn failWithDivideByZero(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError {
23562360 return sema.fail(block, src, "division by zero here causes illegal behavior", .{});
23572361}
......@@ -2697,13 +2701,15 @@ fn failWithTypeMismatch(sema: *Sema, block: *Block, src: LazySrcLoc, expected: T
26972701 });
26982702}
26992703
2700pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg) error{ AnalysisFail, OutOfMemory } {
2704pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg) SemaError {
27012705 @branchHint(.cold);
27022706 const zcu = sema.pt.zcu;
27032707 const comp = zcu.comp;
27042708 const gpa = comp.gpa;
27052709 const io = comp.io;
27062710
2711 assert(sema.err == null);
2712
27072713 if (build_options.enable_debug_extensions and comp.debug_compile_errors) {
27082714 var wip_errors: std.zig.ErrorBundle.Wip = undefined;
27092715 wip_errors.init(gpa) catch @panic("out of memory");
......@@ -2729,17 +2735,11 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg
27292735
27302736 err_msg.reference_trace_root = sema.owner.toOptional();
27312737
2732 const gop = try zcu.failed_analysis.getOrPut(gpa, sema.owner);
2733 if (gop.found_existing) {
2734 // If there are multiple errors for the same Decl, prefer the first one added.
2735 sema.err = null;
2736 err_msg.destroy(gpa);
2737 } else {
2738 sema.err = err_msg;
2739 gop.value_ptr.* = err_msg;
2740 }
2738 try zcu.failed_analysis.putNoClobber(gpa, sema.owner, err_msg);
2739 assert(!zcu.transitive_failed_analysis.contains(sema.owner));
27412740
2742 return error.AnalysisFail;
2741 sema.err = err_msg;
2742 return error.AlreadyReported;
27432743}
27442744
27452745/// Given an ErrorMsg, modify its message and source location to the given values, turning the
......@@ -3117,9 +3117,14 @@ fn zirRefDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
31173117 try sema.validateDeref(block, src, operand, operand_ty);
31183118
31193119 const ptr_info = operand_ty.ptrInfo(zcu);
3120 return switch (ptr_info.flags.size) {
3121 .many, .slice => unreachable, // cannot be dereferenced
3122 .c => single_ptr: {
3120 return single_ptr: switch (ptr_info.flags.size) {
3121 .many => unreachable, // cannot be dereferenced directly
3122 .slice => {
3123 const slice_val = sema.resolveValue(operand).?;
3124 const slice = zcu.intern_pool.indexToKey(slice_val.toIntern()).slice;
3125 break :single_ptr .fromValue(try pt.sliceToArrayPtr(slice));
3126 },
3127 .c => {
31233128 const single_ptr_ty = try pt.ptrType(p: {
31243129 var p = ptr_info;
31253130 p.flags.size = .one;
......@@ -3153,18 +3158,26 @@ fn validateDeref(
31533158) CompileError!void {
31543159 const pt = sema.pt;
31553160 const zcu = pt.zcu;
3161 const ip = &zcu.intern_pool;
31563162 if (ty.zigTypeTag(zcu) != .pointer) {
31573163 return sema.fail(block, src, "cannot dereference non-pointer type '{f}'", .{ty.fmt(pt)});
3158 } else switch (ty.ptrSize(zcu)) {
3159 .one, .c => {},
3164 }
3165 const size = ty.ptrSize(zcu);
3166 switch (size) {
31603167 .many => return sema.fail(block, src, "index syntax required for unknown-length pointer type '{f}'", .{ty.fmt(pt)}),
3161 .slice => return sema.fail(block, src, "index syntax required for slice type '{f}'", .{ty.fmt(pt)}),
3168 .one, .c, .slice => {},
31623169 }
31633170 if (sema.resolveValue(ref)) |val| {
31643171 // Error for deref of undef pointer, unless the pointee is OPV in which case it's legal.
31653172 if (val.isUndef(zcu) and ty.childType(zcu).classify(zcu) != .one_possible_value) {
31663173 return sema.fail(block, src, "cannot dereference undefined value", .{});
31673174 }
3175 // We need a defined slice length for the array type the slice should be dereferenced to.
3176 if (size == .slice and ip.indexToKey(val.toIntern()).slice.len == .undef_usize) {
3177 return sema.fail(block, src, "cannot dereference slice with undefined length", .{});
3178 }
3179 } else if (size == .slice) {
3180 return sema.fail(block, src, "index syntax required to access runtime-known slice", .{});
31683181 }
31693182}
31703183
......@@ -3186,10 +3199,12 @@ fn ensureResultUsed(
31863199 const zcu = pt.zcu;
31873200 switch (ty.zigTypeTag(zcu)) {
31883201 .void, .noreturn => return,
3189 .error_set => return sema.fail(block, src, "error set is ignored", .{}),
3202 .error_set => {
3203 return sema.fail(block, src, "error set of type '{f}' is ignored", .{ty.fmt(pt)});
3204 },
31903205 .error_union => {
31913206 const msg = msg: {
3192 const msg = try sema.errMsg(src, "error union is ignored", .{});
3207 const msg = try sema.errMsg(src, "error union of type '{f}' is ignored", .{ty.fmt(pt)});
31933208 errdefer msg.destroy(sema.gpa);
31943209 try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{});
31953210 break :msg msg;
......@@ -4745,11 +4760,14 @@ fn failWithBadMemberAccess(
47454760 .@"enum" => "enum",
47464761 else => unreachable,
47474762 };
4748 if (agg_ty.typeDeclInst(zcu)) |inst| if ((inst.resolve(ip) orelse return error.AnalysisFail) == .main_struct_inst) {
4749 return sema.fail(block, field_src, "root source file struct '{f}' has no member named '{f}'", .{
4750 agg_ty.fmt(pt), field_name.fmt(ip),
4751 });
4752 };
4763 if (agg_ty.typeDeclInst(zcu)) |inst| {
4764 const inst_index = inst.resolve(ip) orelse return sema.failTransitive(.{ .lost_tracking = inst });
4765 if (inst_index == .main_struct_inst) {
4766 return sema.fail(block, field_src, "root source file struct '{f}' has no member named '{f}'", .{
4767 agg_ty.fmt(pt), field_name.fmt(ip),
4768 });
4769 }
4770 }
47534771
47544772 return sema.fail(block, field_src, "{s} '{f}' has no member named '{f}'", .{
47554773 kw_name, agg_ty.fmt(pt), field_name.fmt(ip),
......@@ -5997,7 +6015,14 @@ fn lookupInNamespace(
59976015 const pt = sema.pt;
59986016 const zcu = pt.zcu;
59996017
6000 try pt.ensureNamespaceUpToDate(namespace_index);
6018 pt.ensureNamespaceUpToDate(namespace_index) catch |err| switch (err) {
6019 error.LostZirContainerDecl => {
6020 const namespace = zcu.namespacePtr(namespace_index);
6021 const ns_ty: Type = .fromInterned(namespace.owner_type);
6022 return sema.failTransitive(.{ .lost_tracking = ns_ty.typeDeclInstAllowGeneratedTag(zcu).? });
6023 },
6024 else => |e| return e,
6025 };
60016026
60026027 const namespace = zcu.namespacePtr(namespace_index);
60036028
......@@ -6062,7 +6087,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref
60626087 const stack_trace_ty = try sema.getStdLangType(block.nodeOffset(.zero), .StackTrace);
60636088 const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls);
60646089 const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) {
6065 error.AnalysisFail => @panic("std.lang.StackTrace is corrupt"),
6090 error.AlreadyReported => @panic("std.lang.StackTrace is corrupt"),
60666091 error.ComptimeReturn, error.ComptimeBreak => unreachable,
60676092 error.OutOfMemory, error.Canceled => |e| return e,
60686093 };
......@@ -6724,7 +6749,9 @@ fn analyzeCall(
67246749 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: {
67256750 const info = ip.indexToKey(f.toIntern()).func;
67266751 const nav = ip.getNav(info.owner_nav);
6727 const resolved_func_inst = info.zir_body_inst.resolveFull(ip) orelse return error.AnalysisFail;
6752 const resolved_func_inst = info.zir_body_inst.resolveFull(ip) orelse {
6753 return sema.failTransitive(.{ .lost_tracking = info.zir_body_inst });
6754 };
67286755 const file = zcu.fileByIndex(resolved_func_inst.file);
67296756 const zir_info = file.zir.?.getFnInfo(resolved_func_inst.inst);
67306757 break :b .{ nav, file.zir.?, info.zir_body_inst, resolved_func_inst.inst, zir_info };
......@@ -8355,7 +8382,10 @@ fn zirFunc(
83558382 const cc: std.lang.CallingConvention = if (has_body) cc: {
83568383 const func_decl_nav = sema.owner.unwrap().nav_val;
83578384 const fn_is_exported = exported: {
8358 const decl_inst = ip.getNav(func_decl_nav).analysis.?.zir_index.resolve(ip) orelse return error.AnalysisFail;
8385 const decl_ti = ip.getNav(func_decl_nav).analysis.?.zir_index;
8386 const decl_inst = decl_ti.resolve(ip) orelse {
8387 return sema.failTransitive(.{ .lost_tracking = decl_ti });
8388 };
83598389 const zir_decl = sema.code.getDeclaration(decl_inst);
83608390 break :exported zir_decl.linkage == .@"export";
83618391 };
......@@ -8501,6 +8531,7 @@ const calling_conventions_supporting_var_args = [_]std.lang.CallingConvention.Ta
85018531 .x86_64_win,
85028532 .x86_sysv,
85038533 .x86_win,
8534 .x86_mingw,
85048535 .aarch64_aapcs,
85058536 .aarch64_aapcs_darwin,
85068537 .aarch64_aapcs_win,
......@@ -10760,7 +10791,7 @@ fn finishSwitchBr(
1076010791 .@"enum" => if (else_is_named_only or
1076110792 !item_ty.isNonexhaustiveEnum(zcu) or tagged_union_originally)
1076210793 {
10763 try branch_hints.ensureUnusedCapacity(gpa, @intCast(validated_switch.seen_enum_fields.len));
10794 try branch_hints.ensureUnusedCapacity(gpa, @intCast(validated_switch.seen.enum_fields.len));
1076410795 break :check_enumerable .{ undefined, undefined };
1076510796 },
1076610797 .error_set => if (!operand_ty.isAnyError(zcu)) {
......@@ -10881,13 +10912,13 @@ fn finishSwitchBr(
1088110912 try branch_hints.append(gpa, prong_hint);
1088210913
1088310914 try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".field_names.len +
10884 (validated_switch.seen_enum_fields.len + 1 - zir_switch.totalItemsLen()) + // +1 because totalItemsLen includes the _
10915 (validated_switch.seen.enum_fields.len + 1 - zir_switch.totalItemsLen()) + // +1 because totalItemsLen includes the _
1088510916 case_block.instructions.items.len);
1088610917 const extra_case = cases_extra.addManyAsArrayAssumeCapacity(
1088710918 @typeInfo(Air.SwitchBr.Case).@"struct".field_names.len,
1088810919 );
1088910920 var items_len: u32 = 0;
10890 for (validated_switch.seen_enum_fields, 0..) |seen_field, field_i| {
10921 for (validated_switch.seen.enum_fields, 0..) |seen_field, field_i| {
1089110922 if (seen_field != null) continue;
1089210923 const item_val = try pt.enumValueFieldIndex(item_ty, @intCast(field_i));
1089310924 const item_ref: Air.Inst.Ref = .fromValue(item_val);
......@@ -10920,7 +10951,7 @@ fn finishSwitchBr(
1092010951 }
1092110952 if (tagged_union_originally) {
1092210953 const union_obj = zcu.typeToUnion(operand_ty).?;
10923 for (validated_switch.seen_enum_fields, 0..) |seen_field, field_i| {
10954 for (validated_switch.seen.enum_fields, 0..) |seen_field, field_i| {
1092410955 if (seen_field != null) continue;
1092510956 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_i]);
1092610957 if (!field_ty.isNoReturn(zcu)) break :analyze_body true;
......@@ -11004,17 +11035,21 @@ fn finishSwitchBr(
1100411035}
1100511036
1100611037const ValidatedSwitchBlock = struct {
11007 seen_enum_fields: []const ?LazySrcLoc,
11008 seen_errors: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, LazySrcLoc),
11009 seen_ranges: std.MultiArrayList(RangeSet.Range).Slice,
11010 true_src: ?LazySrcLoc,
11011 false_src: ?LazySrcLoc,
11012 void_src: ?LazySrcLoc,
11013
11038 seen: Seen,
1101411039 case_vals: []const Air.Inst.Ref,
1101511040 else_case: Zir.UnwrappedSwitchBlock.Case.Else,
1101611041 else_err_ty: ?Type,
1101711042
11043 const Seen = struct {
11044 enum_fields: []?LazySrcLoc,
11045 errors: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, LazySrcLoc),
11046 sparse_values: std.AutoHashMapUnmanaged(InternPool.Index, LazySrcLoc),
11047 ranges: RangeSet,
11048 true_src: ?LazySrcLoc,
11049 false_src: ?LazySrcLoc,
11050 void_src: ?LazySrcLoc,
11051 };
11052
1101811053 fn iterateUnhandledItems(
1101911054 validated_switch: *const ValidatedSwitchBlock,
1102011055 /// May be `undefined` if `item_ty` isn't an `error_set`.
......@@ -11023,28 +11058,26 @@ const ValidatedSwitchBlock = struct {
1102311058 min_int: Value,
1102411059 ) UnhandledIterator {
1102511060 return .{
11061 .error_names = error_names,
11062 .seen = &validated_switch.seen,
11063
1102611064 .next_idx = 0,
1102711065 .next_val = min_int,
11028 .error_names = error_names,
11029 .seen_enum_fields = validated_switch.seen_enum_fields,
11030 .seen_errors = &validated_switch.seen_errors,
11031 .seen_ranges = validated_switch.seen_ranges,
11032 .seen_true = validated_switch.true_src != null,
11033 .seen_false = validated_switch.false_src != null,
11034 .seen_void = validated_switch.void_src != null,
11066 .handled_true = validated_switch.seen.true_src != null,
11067 .handled_false = validated_switch.seen.false_src != null,
11068 .handled_void = validated_switch.seen.void_src != null,
1103511069 };
1103611070 }
1103711071
1103811072 const UnhandledIterator = struct {
11073 error_names: InternPool.NullTerminatedString.Slice,
11074 seen: *const Seen,
11075
1103911076 next_idx: u32,
1104011077 next_val: ?Value,
11041 error_names: InternPool.NullTerminatedString.Slice,
11042 seen_enum_fields: []const ?LazySrcLoc,
11043 seen_errors: *const std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, LazySrcLoc),
11044 seen_ranges: std.MultiArrayList(RangeSet.Range).Slice,
11045 seen_true: bool,
11046 seen_false: bool,
11047 seen_void: bool,
11078 handled_true: bool,
11079 handled_false: bool,
11080 handled_void: bool,
1104811081
1104911082 fn next(it: *UnhandledIterator, sema: *Sema, item_ty: Type) CompileError!?Value {
1105011083 const pt = sema.pt;
......@@ -11052,7 +11085,7 @@ const ValidatedSwitchBlock = struct {
1105211085 const ip = &zcu.intern_pool;
1105311086 switch (item_ty.zigTypeTag(zcu)) {
1105411087 .@"enum" => {
11055 for (it.seen_enum_fields[it.next_idx..], it.next_idx..) |seen_field, field_i| {
11088 for (it.seen.enum_fields[it.next_idx..], it.next_idx..) |seen_field, field_i| {
1105611089 if (seen_field != null) continue;
1105711090 it.next_idx = @intCast(field_i + 1);
1105811091 return try pt.enumValueFieldIndex(item_ty, @intCast(field_i));
......@@ -11061,7 +11094,7 @@ const ValidatedSwitchBlock = struct {
1106111094 },
1106211095 .error_set => {
1106311096 for (it.error_names.get(ip)[it.next_idx..], it.next_idx..) |err_name, name_i| {
11064 if (it.seen_errors.contains(err_name)) continue;
11097 if (it.seen.errors.contains(err_name)) continue;
1106511098 it.next_idx = @intCast(name_i + 1);
1106611099 return .fromInterned(try pt.intern(.{ .err = .{
1106711100 .ty = item_ty.toIntern(),
......@@ -11077,14 +11110,14 @@ const ValidatedSwitchBlock = struct {
1107711110 .@"union", .@"struct" => item_ty.backingIntType(zcu),
1107811111 else => unreachable,
1107911112 };
11080 while (it.next_idx < it.seen_ranges.len and
11081 cur_val.eql(it.seen_ranges.items(.first)[it.next_idx], int_ty, zcu))
11113 while (it.next_idx < it.seen.ranges.list.len and
11114 cur_val.eql(it.seen.ranges.list.items(.first)[it.next_idx], int_ty, zcu))
1108211115 {
1108311116 defer it.next_idx += 1;
1108411117 const incr = try arith.incrementDefinedInt(
1108511118 sema,
1108611119 int_ty,
11087 it.seen_ranges.items(.last)[it.next_idx],
11120 it.seen.ranges.list.items(.last)[it.next_idx],
1108811121 );
1108911122 if (incr.overflow) {
1109011123 it.next_val = null;
......@@ -11101,19 +11134,19 @@ const ValidatedSwitchBlock = struct {
1110111134 };
1110211135 },
1110311136 .bool => {
11104 if (!it.seen_true) {
11105 it.seen_true = true;
11137 if (!it.handled_true) {
11138 it.handled_true = true;
1110611139 return .true;
1110711140 }
11108 if (!it.seen_false) {
11109 it.seen_false = true;
11141 if (!it.handled_false) {
11142 it.handled_false = true;
1111011143 return .false;
1111111144 }
1111211145 return null;
1111311146 },
1111411147 .void => {
11115 if (!it.seen_void) {
11116 it.seen_void = true;
11148 if (!it.handled_void) {
11149 it.handled_void = true;
1111711150 return .void;
1111811151 }
1111911152 return null;
......@@ -11186,14 +11219,8 @@ fn validateSwitchBlock(
1118611219 operand_ty.assertHasLayout(zcu);
1118711220 const union_obj = ip.loadUnionType(operand_ty.toIntern());
1118811221 switch (union_obj.tag_usage) {
11189 .tagged => {
11190 break :item_ty .fromInterned(union_obj.enum_tag_type);
11191 },
11192 .none => {
11193 if (union_obj.layout == .@"packed") {
11194 break :item_ty operand_ty;
11195 }
11196 },
11222 .tagged => break :item_ty .fromInterned(union_obj.enum_tag_type),
11223 .none => if (union_obj.layout == .@"packed") break :item_ty operand_ty,
1119711224 .safety => {},
1119811225 }
1119911226 return sema.failWithOwnedErrorMsg(block, msg: {
......@@ -11208,27 +11235,47 @@ fn validateSwitchBlock(
1120811235
1120911236 .@"struct" => {
1121011237 operand_ty.assertHasLayout(zcu);
11211 const layout = operand_ty.containerLayout(zcu);
11212 if (layout == .@"packed") {
11213 break :item_ty operand_ty;
11214 }
11238 if (operand_ty.containerLayout(zcu) == .@"packed") break :item_ty operand_ty;
1121511239 return sema.failWithOwnedErrorMsg(block, msg: {
11216 const msg = try sema.errMsg(operand_src, "switch on struct with {t} layout", .{layout});
11240 const msg = try sema.errMsg(operand_src, "switch on non-packed struct", .{});
1121711241 errdefer msg.destroy(sema.gpa);
11218 if (operand_ty.srcLocOrNull(zcu)) |struct_src| {
11219 try sema.errNote(struct_src, msg, "consider 'packed struct' here", .{});
11220 }
11242 try sema.addDeclaredHereNote(msg, operand_ty);
1122111243 break :msg msg;
1122211244 });
1122311245 },
1122411246
11225 .pointer => {
11226 if (!operand_ty.isSlice(zcu)) {
11227 break :item_ty operand_ty;
11228 }
11229 },
11247 .pointer => if (!operand_ty.isSlice(zcu)) break :item_ty operand_ty,
1123011248
11231 else => {},
11249 .optional => return sema.failWithOwnedErrorMsg(block, msg: {
11250 const msg = try sema.errMsg(operand_src, "switch on optional type '{f}'", .{
11251 operand_ty.fmt(pt),
11252 });
11253 errdefer msg.destroy(gpa);
11254 try sema.errNote(operand_src, msg, "consider using '.?', 'orelse', or 'if'", .{});
11255 break :msg msg;
11256 }),
11257
11258 .error_union => return sema.failWithOwnedErrorMsg(block, msg: {
11259 const msg = try sema.errMsg(operand_src, "switch on error union type '{f}'", .{
11260 operand_ty.fmt(pt),
11261 });
11262 errdefer msg.destroy(gpa);
11263 try sema.errNote(operand_src, msg, "consider using 'try', 'catch', or 'if'", .{});
11264 break :msg msg;
11265 }),
11266
11267 .noreturn,
11268 .float,
11269 .comptime_float,
11270 .array,
11271 .vector,
11272 .undefined,
11273 .null,
11274 .@"opaque",
11275 .frame,
11276 .@"anyframe",
11277 .spirv,
11278 => {},
1123211279 }
1123311280 return sema.fail(block, operand_src, "switch on type '{f}'", .{operand_ty.fmt(pt)});
1123411281 };
......@@ -11253,13 +11300,15 @@ fn validateSwitchBlock(
1125311300 var case_vals: std.ArrayList(Air.Inst.Ref) = try .initCapacity(arena, zir_switch.item_infos.len);
1125411301
1125511302 // Duplicate checking variables later also used for `inline else`.
11256 var seen_enum_fields: []?LazySrcLoc = &.{};
11257 var seen_errors: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, LazySrcLoc) = .empty;
11258 var seen_sparse_values: std.AutoHashMapUnmanaged(InternPool.Index, LazySrcLoc) = .empty;
11259 var range_set: RangeSet = .empty;
11260 var true_src: ?LazySrcLoc = null;
11261 var false_src: ?LazySrcLoc = null;
11262 var void_src: ?LazySrcLoc = null;
11303 var seen: ValidatedSwitchBlock.Seen = .{
11304 .enum_fields = &.{},
11305 .errors = .empty,
11306 .sparse_values = .empty,
11307 .ranges = .empty,
11308 .true_src = null,
11309 .false_src = null,
11310 .void_src = null,
11311 };
1126311312
1126411313 var else_err_ty: ?Type = null;
1126511314
......@@ -11267,20 +11316,20 @@ fn validateSwitchBlock(
1126711316
1126811317 switch (item_ty.zigTypeTag(zcu)) {
1126911318 .@"enum" => {
11270 seen_enum_fields = try arena.alloc(?LazySrcLoc, item_ty.enumFieldCount(zcu));
11271 @memset(seen_enum_fields, null);
11272 // `range_set` is used for non-exhaustive enum values that do not
11319 seen.enum_fields = try arena.alloc(?LazySrcLoc, item_ty.enumFieldCount(zcu));
11320 @memset(seen.enum_fields, null);
11321 // `seen.ranges` is used for non-exhaustive enum values that do not
1127311322 // correspond to any tags. Since this is rare, we only allocate on
1127411323 // demand in `validateSwitchItem`.
1127511324 },
1127611325 .error_set => {
11277 try seen_errors.ensureUnusedCapacity(arena, zir_switch.totalItemsLen());
11326 try seen.errors.ensureUnusedCapacity(arena, zir_switch.totalItemsLen());
1127811327 },
1127911328 .int, .comptime_int, .@"union", .@"struct" => {
11280 try range_set.ensureUnusedCapacity(arena, zir_switch.totalItemsLen());
11329 try seen.ranges.ensureUnusedCapacity(arena, zir_switch.totalItemsLen());
1128111330 },
1128211331 .enum_literal, .@"fn", .pointer, .type => {
11283 try seen_sparse_values.ensureUnusedCapacity(arena, zir_switch.totalItemsLen());
11332 try seen.sparse_values.ensureUnusedCapacity(arena, zir_switch.totalItemsLen());
1128411333 },
1128511334 .bool, .void => {},
1128611335
......@@ -11323,7 +11372,7 @@ fn validateSwitchBlock(
1132311372 case_vals.appendAssumeCapacity(.none);
1132411373 } else {
1132511374 const item, extra_index = try sema.resolveSwitchItem(block, item_src, item_ty, item_info, extra_index, switch_inst, prong_info.is_comptime_unreach);
11326 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);
11375 try sema.validateSwitchItemOrRange(block, item_src, item.val, null, item_ty, &seen);
1132711376 case_vals.appendAssumeCapacity(item.ref);
1132811377 }
1132911378 }
......@@ -11338,7 +11387,7 @@ fn validateSwitchBlock(
1133811387 const last_src = block.src(.{ .switch_case_item_range_last = range_offset });
1133911388 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);
1134011389 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);
11341 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);
11390 try sema.validateSwitchItemOrRange(block, range_src, first_item.val, last_item.val, item_ty, &seen);
1134211391 case_vals.appendSliceAssumeCapacity(&.{ first_item.ref, last_item.ref });
1134311392 }
1134411393 }
......@@ -11369,13 +11418,13 @@ fn validateSwitchBlock(
1136911418 // Validate for missing special prongs.
1137011419 switch (item_ty.zigTypeTag(zcu)) {
1137111420 .@"enum" => {
11372 const all_tags_handled = for (seen_enum_fields) |seen_src| {
11421 const all_tags_handled = for (seen.enum_fields) |seen_src| {
1137311422 if (seen_src == null) break false;
1137411423 } else true;
1137511424
1137611425 if (has_else) {
1137711426 if (all_tags_handled) {
11378 if (item_ty.isNonexhaustiveEnum(zcu)) {
11427 if (operand_ty.isNonexhaustiveEnum(zcu)) {
1137911428 if (has_under) return sema.fail(
1138011429 block,
1138111430 else_prong_src,
......@@ -11397,7 +11446,7 @@ fn validateSwitchBlock(
1139711446 .{},
1139811447 );
1139911448 errdefer msg.destroy(sema.gpa);
11400 for (seen_enum_fields, 0..) |seen_src, i| {
11449 for (seen.enum_fields, 0..) |seen_src, i| {
1140111450 if (seen_src != null) continue;
1140211451
1140311452 const field_name = item_ty.enumFieldName(i, zcu);
......@@ -11449,7 +11498,7 @@ fn validateSwitchBlock(
1144911498
1145011499 var seen_errors_from_set: u32 = 0;
1145111500 for (error_names.get(ip)) |error_name| {
11452 if (seen_errors.contains(error_name)) {
11501 if (seen.errors.contains(error_name)) {
1145311502 seen_errors_from_set += 1;
1145411503 } else if (!has_else) {
1145511504 const msg = maybe_msg orelse blk: {
......@@ -11491,7 +11540,7 @@ fn validateSwitchBlock(
1149111540 var names: InferredErrorSet.NameMap = .{};
1149211541 try names.ensureUnusedCapacity(sema.arena, error_names.len);
1149311542 for (error_names.get(ip)) |error_name| {
11494 if (seen_errors.contains(error_name)) continue;
11543 if (seen.errors.contains(error_name)) continue;
1149511544 names.putAssumeCapacityNoClobber(error_name, {});
1149611545 }
1149711546 // No need to keep the hash map metadata correct; here we
......@@ -11509,7 +11558,7 @@ fn validateSwitchBlock(
1150911558 };
1151011559 const min_int = try int_ty.minInt(pt, int_ty);
1151111560 const max_int = try int_ty.maxInt(pt, int_ty);
11512 if (try range_set.spans(arena, min_int, max_int, int_ty, zcu)) {
11561 if (try seen.ranges.spans(arena, min_int, max_int, int_ty, zcu)) {
1151311562 if (has_else) {
1151411563 return sema.fail(
1151511564 block,
......@@ -11542,8 +11591,8 @@ fn validateSwitchBlock(
1154211591 },
1154311592 .bool, .void => |type_tag| {
1154411593 const all_values_handled = switch (type_tag) {
11545 .bool => true_src != null and false_src != null,
11546 .void => void_src != null,
11594 .bool => seen.true_src != null and seen.false_src != null,
11595 .void => seen.void_src != null,
1154711596 else => unreachable,
1154811597 };
1154911598 if (has_else) {
......@@ -11570,13 +11619,7 @@ fn validateSwitchBlock(
1157011619 }
1157111620
1157211621 return .{
11573 .seen_enum_fields = seen_enum_fields,
11574 .seen_errors = seen_errors,
11575 .seen_ranges = range_set.ranges.slice(),
11576 .true_src = true_src,
11577 .false_src = false_src,
11578 .void_src = void_src,
11579
11622 .seen = seen,
1158011623 .case_vals = case_vals.items,
1158111624 .else_case = else_case,
1158211625 .else_err_ty = else_err_ty,
......@@ -11754,7 +11797,7 @@ fn resolveSwitchBlock(
1175411797 .{ else_case.index, else_case.body, else_case.capture, else_case.has_tag_capture, else_case.is_inline };
1175511798 if (err_set) try sema.maybeErrorUnwrapComptime(child_block, body, cond_ref);
1175611799 if (tagged_union_originally) {
11757 for (validated_switch.seen_enum_fields, 0..) |maybe_seen, field_i| {
11800 for (validated_switch.seen.enum_fields, 0..) |maybe_seen, field_i| {
1175811801 if (maybe_seen != null) continue;
1175911802 if (!operand_ty.unionFieldTypeByIndex(field_i, zcu).isNoReturn(zcu)) break;
1176011803 } else {
......@@ -12276,10 +12319,11 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
1227612319 dummy_captures,
1227712320 .{ .override = item_srcs },
1227812321 ) catch |err| switch (err) {
12279 error.AnalysisFail => {
12280 const msg = sema.err orelse return error.AnalysisFail;
12281 try sema.reparentOwnedErrorMsg(capture_src, msg, "capture group with incompatible types", .{});
12282 return error.AnalysisFail;
12322 error.AlreadyReported => |e| {
12323 if (sema.err) |msg| {
12324 try sema.reparentOwnedErrorMsg(capture_src, msg, "capture group with incompatible types", .{});
12325 }
12326 return e;
1228312327 },
1228412328 else => |e| return e,
1228512329 };
......@@ -12315,11 +12359,12 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
1231512359 dummy_captures,
1231612360 .{ .override = item_srcs },
1231712361 ) catch |err| switch (err) {
12318 error.AnalysisFail => {
12319 const msg = sema.err orelse return error.AnalysisFail;
12320 try sema.errNote(capture_src, msg, "this coercion is only possible when capturing by value", .{});
12321 try sema.reparentOwnedErrorMsg(capture_src, msg, "capture group with incompatible types", .{});
12322 return error.AnalysisFail;
12362 error.AlreadyReported => |e| {
12363 if (sema.err) |msg| {
12364 try sema.errNote(capture_src, msg, "this coercion is only possible when capturing by value", .{});
12365 try sema.reparentOwnedErrorMsg(capture_src, msg, "capture group with incompatible types", .{});
12366 }
12367 return e;
1232312368 },
1232412369 else => |e| return e,
1232512370 };
......@@ -12559,13 +12604,7 @@ fn validateSwitchItemOrRange(
1255912604 item_val: Value,
1256012605 opt_last_val: ?Value,
1256112606 item_ty: Type,
12562 seen_enum_fields: []?LazySrcLoc,
12563 seen_errors: *std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, LazySrcLoc),
12564 seen_sparse_values: *std.AutoHashMapUnmanaged(InternPool.Index, LazySrcLoc),
12565 range_set: *RangeSet,
12566 true_src: *?LazySrcLoc,
12567 false_src: *?LazySrcLoc,
12568 void_src: *?LazySrcLoc,
12607 seen: *ValidatedSwitchBlock.Seen,
1256912608) CompileError!void {
1257012609 const pt = sema.pt;
1257112610 const zcu = pt.zcu;
......@@ -12574,88 +12613,117 @@ fn validateSwitchItemOrRange(
1257412613 .@"enum" => {
1257512614 const int = ip.indexToKey(item_val.toIntern()).enum_tag.int;
1257612615 if (ip.loadEnumType(item_ty.toIntern()).tagValueIndex(ip, int)) |field_index| {
12577 const maybe_prev_src = seen_enum_fields[field_index];
12578 seen_enum_fields[field_index] = item_src;
12616 const maybe_prev_src = seen.enum_fields[field_index];
12617 seen.enum_fields[field_index] = item_src;
1257912618 break :maybe_prev_src maybe_prev_src;
1258012619 } else {
12581 break :maybe_prev_src try range_set.add(sema.arena, .{
12620 try seen.ranges.ensureUnusedCapacity(sema.arena, 1);
12621 break :maybe_prev_src if (seen.ranges.addAssumeCapacity(.{
1258212622 .first = .fromInterned(int),
1258312623 .last = .fromInterned(int),
1258412624 .src = item_src,
12585 }, .fromInterned(ip.typeOf(int)), zcu);
12625 }, .fromInterned(ip.typeOf(int)), zcu)) |prev| prev.src else null;
1258612626 }
1258712627 },
1258812628 .error_set => {
1258912629 const error_name = ip.indexToKey(item_val.toIntern()).err.name;
12590 break :maybe_prev_src if (seen_errors.fetchPutAssumeCapacity(error_name, item_src)) |prev|
12630 break :maybe_prev_src if (seen.errors.fetchPutAssumeCapacity(error_name, item_src)) |prev|
1259112631 prev.value
1259212632 else
1259312633 null;
1259412634 },
1259512635 .int, .comptime_int => {
12596 if (opt_last_val) |last_val| {
12597 const first_val = item_val;
12636 const first_val = item_val;
12637 const last_val: Value = last_val: {
12638 const last_val = opt_last_val orelse break :last_val item_val;
1259812639 if (try first_val.compareAll(.gt, last_val, item_ty, pt)) {
1259912640 return sema.fail(block, item_src, "range start value is greater than the end value", .{});
1260012641 }
12601 break :maybe_prev_src range_set.addAssumeCapacity(.{
12602 .first = first_val,
12603 .last = last_val,
12604 .src = item_src,
12605 }, item_ty, zcu);
12606 } else {
12607 break :maybe_prev_src range_set.addAssumeCapacity(.{
12608 .first = item_val,
12609 .last = item_val,
12610 .src = item_src,
12611 }, item_ty, zcu);
12642 break :last_val last_val;
12643 };
12644 if (seen.ranges.addAssumeCapacity(.{
12645 .first = first_val,
12646 .last = last_val,
12647 .src = item_src,
12648 }, item_ty, zcu)) |prev_range| {
12649 const overlap_start = first_val.numberMax(prev_range.first, zcu);
12650 const overlap_end = last_val.numberMin(prev_range.last, zcu);
12651 if (overlap_start.eql(overlap_end, item_ty, zcu)) {
12652 return sema.failWithOwnedErrorMsg(block, msg: {
12653 const msg = try sema.errMsg(item_src, "duplicate switch value '{f}'", .{
12654 overlap_start.fmtValueSema(pt, sema),
12655 });
12656 errdefer msg.destroy(sema.gpa);
12657 if (prev_range.first.eql(prev_range.last, item_ty, zcu)) {
12658 try sema.errNote(prev_range.src, msg, "previous value here", .{});
12659 } else {
12660 try sema.errNote(prev_range.src, msg, "previous value inside range here", .{});
12661 }
12662 break :msg msg;
12663 });
12664 }
12665 assert(!prev_range.first.eql(prev_range.last, item_ty, zcu));
12666 return sema.failWithOwnedErrorMsg(block, msg: {
12667 const msg = try sema.errMsg(item_src, "duplicate switch ranges", .{});
12668 errdefer msg.destroy(sema.gpa);
12669 if (first_val.eql(prev_range.first, item_ty, zcu) and
12670 last_val.eql(prev_range.last, item_ty, zcu))
12671 {
12672 try sema.errNote(prev_range.src, msg, "previous range here", .{});
12673 } else {
12674 try sema.errNote(prev_range.src, msg, "overlaps with previous range here", .{});
12675 try sema.errNote(prev_range.src, msg, "ranges overlap from '{f}' to '{f}'", .{
12676 overlap_start.fmtValueSema(pt, sema), overlap_end.fmtValueSema(pt, sema),
12677 });
12678 }
12679 break :msg msg;
12680 });
1261212681 }
12682 break :maybe_prev_src null;
1261312683 },
1261412684 .@"union", .@"struct" => {
1261512685 const backing_int_val = ip.indexToKey(item_val.toIntern()).bitpack.backing_int_val;
12616 break :maybe_prev_src range_set.addAssumeCapacity(.{
12686 break :maybe_prev_src if (seen.ranges.addAssumeCapacity(.{
1261712687 .first = .fromInterned(backing_int_val),
1261812688 .last = .fromInterned(backing_int_val),
1261912689 .src = item_src,
12620 }, item_ty.backingIntType(zcu), zcu);
12690 }, item_ty.backingIntType(zcu), zcu)) |prev| prev.src else null;
1262112691 },
1262212692 .enum_literal, .@"fn", .pointer, .type => {
12623 break :maybe_prev_src if (seen_sparse_values.fetchPutAssumeCapacity(item_val.toIntern(), item_src)) |prev|
12693 break :maybe_prev_src if (seen.sparse_values.fetchPutAssumeCapacity(item_val.toIntern(), item_src)) |prev|
1262412694 prev.value
1262512695 else
1262612696 null;
1262712697 },
1262812698 .bool => {
1262912699 if (item_val.toBool()) {
12630 if (true_src.*) |prev_src| break :maybe_prev_src prev_src;
12631 true_src.* = item_src;
12700 if (seen.true_src) |prev_src| break :maybe_prev_src prev_src;
12701 seen.true_src = item_src;
1263212702 } else {
12633 if (false_src.*) |prev_src| break :maybe_prev_src prev_src;
12634 false_src.* = item_src;
12703 if (seen.false_src) |prev_src| break :maybe_prev_src prev_src;
12704 seen.false_src = item_src;
1263512705 }
1263612706 break :maybe_prev_src null;
1263712707 },
1263812708 .void => {
12639 if (void_src.*) |prev_src| break :maybe_prev_src prev_src;
12640 void_src.* = item_src;
12709 if (seen.void_src) |prev_src| break :maybe_prev_src prev_src;
12710 seen.void_src = item_src;
1264112711 break :maybe_prev_src null;
1264212712 },
1264312713 else => unreachable, // should have already checked for invalid types
1264412714 };
1264512715 if (maybe_prev_src) |prev_src| {
1264612716 return sema.failWithOwnedErrorMsg(block, msg: {
12647 const msg = try sema.errMsg(
12648 item_src,
12649 "duplicate switch value",
12650 .{},
12651 );
12717 const msg = try sema.errMsg(item_src, "duplicate switch value '{f}'", .{
12718 item_val.fmtValueSema(pt, sema),
12719 });
1265212720 errdefer msg.destroy(sema.gpa);
12653 try sema.errNote(
12654 prev_src,
12655 msg,
12656 "previous value here",
12657 .{},
12658 );
12721 try sema.errNote(prev_src, msg, "previous value here", .{});
12722 if (item_ty.zigTypeTag(zcu) == .type) {
12723 try sema.addDeclaredHereNote(msg, item_val.toType());
12724 } else {
12725 try sema.addDeclaredHereNote(msg, item_ty);
12726 }
1265912727 break :msg msg;
1266012728 });
1266112729 }
......@@ -17171,7 +17239,14 @@ fn typeInfoNamespaceDecls(
1717117239 const ip = &zcu.intern_pool;
1717217240
1717317241 const namespace_index = opt_namespace_index.unwrap() orelse return;
17174 try pt.ensureNamespaceUpToDate(namespace_index);
17242 pt.ensureNamespaceUpToDate(namespace_index) catch |err| switch (err) {
17243 error.LostZirContainerDecl => {
17244 const namespace = zcu.namespacePtr(namespace_index);
17245 const ns_ty: Type = .fromInterned(namespace.owner_type);
17246 return sema.failTransitive(.{ .lost_tracking = ns_ty.typeDeclInstAllowGeneratedTag(zcu).? });
17247 },
17248 else => |e| return e,
17249 };
1717517250 const namespace = zcu.namespacePtr(namespace_index);
1717617251
1717717252 const gop = try seen_namespaces.getOrPut(namespace);
......@@ -17897,11 +17972,12 @@ fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1789717972 }
1789817973 // TODO Add compile error for @optimizeFor occurring too late in a scope.
1789917974 sema.analyzeUnreachable(block, src, true) catch |err| switch (err) {
17900 error.AnalysisFail => {
17901 const msg = sema.err orelse return err;
17902 if (!mem.eql(u8, msg.msg, "runtime safety check not allowed in naked function")) return err;
17903 try sema.errNote(src, msg, "the end of a naked function is implicitly unreachable", .{});
17904 return err;
17975 error.AlreadyReported => |e| {
17976 if (sema.err) |msg| {
17977 if (!mem.eql(u8, msg.msg, "runtime safety check not allowed in naked function")) return err;
17978 try sema.errNote(src, msg, "the end of a naked function is implicitly unreachable", .{});
17979 }
17980 return e;
1790517981 },
1790617982 else => |e| return e,
1790717983 };
......@@ -18317,11 +18393,16 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1831718393
1831818394 const elem_ty = blk: {
1831918395 const air_inst = sema.resolveInst(extra.data.elem_type);
18320 const ty = sema.analyzeAsType(block, elem_ty_src, .type, air_inst) catch |err| {
18321 if (err == error.AnalysisFail and sema.err != null and sema.typeOf(air_inst).isSinglePointer(zcu)) {
18322 try sema.errNote(elem_ty_src, sema.err.?, "use '.*' to dereference pointer", .{});
18323 }
18324 return err;
18396 const ty = sema.analyzeAsType(block, elem_ty_src, .type, air_inst) catch |err| switch (err) {
18397 error.AlreadyReported => |e| {
18398 if (sema.err) |msg| {
18399 if (sema.typeOf(air_inst).isSinglePointer(zcu)) {
18400 try sema.errNote(elem_ty_src, msg, "use '.*' to dereference pointer", .{});
18401 }
18402 }
18403 return e;
18404 },
18405 else => |e| return e,
1832518406 };
1832618407 assert(!ty.isGenericPoison());
1832718408 break :blk ty;
......@@ -21103,7 +21184,10 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
2110321184 const dest_scalar_ty = dest_ty.scalarType(zcu);
2110421185 const operand_scalar_ty = operand_ty.scalarType(zcu);
2110521186
21106 _ = try sema.checkIntType(block, src, dest_scalar_ty);
21187 switch (dest_scalar_ty.zigTypeTag(zcu)) {
21188 .comptime_int, .int => {},
21189 else => return sema.fail(block, src, "expected integer result type, found '{f}'", .{dest_scalar_ty.fmt(pt)}),
21190 }
2110721191 try sema.checkFloatType(block, operand_src, operand_scalar_ty);
2110821192
2110921193 if (sema.resolveValue(operand)) |operand_val| {
......@@ -21279,7 +21363,10 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
2127921363 const dest_scalar_ty = dest_ty.scalarType(zcu);
2128021364 const operand_scalar_ty = operand_ty.scalarType(zcu);
2128121365
21282 try sema.checkFloatType(block, src, dest_scalar_ty);
21366 switch (dest_scalar_ty.zigTypeTag(zcu)) {
21367 .comptime_float, .float => {},
21368 else => return sema.fail(block, src, "expected float result type, found '{f}'", .{dest_scalar_ty.fmt(pt)}),
21369 }
2128321370 _ = try sema.checkIntType(block, operand_src, operand_scalar_ty);
2128421371
2128521372 if (sema.resolveValue(operand)) |operand_val| {
......@@ -21594,16 +21681,16 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
2159421681 const is_zero = try block.addBinOp(.cmp_eq, err_int_inst, zero_err);
2159521682 if (result == .disjoint) {
2159621683 // Error must be zero.
21597 try sema.addSafetyCheck(block, src, is_zero, .invalid_error_code);
21684 try sema.addSafetyCheckCall(block, src, is_zero, .@"panic.unexpectedErrorCode", &.{err_code_inst});
2159821685 } else {
2159921686 // Error must be in destination set or zero.
2160021687 const has_value = try block.addTyOp(.error_set_has_value, dest_err_ty, err_int_inst);
2160121688 const ok = try block.addBinOp(.bit_or, has_value, is_zero);
21602 try sema.addSafetyCheck(block, src, ok, .invalid_error_code);
21689 try sema.addSafetyCheckCall(block, src, ok, .@"panic.unexpectedErrorCode", &.{err_code_inst});
2160321690 }
2160421691 } else {
2160521692 const ok = try block.addTyOp(.error_set_has_value, dest_err_ty, err_int_inst);
21606 try sema.addSafetyCheck(block, src, ok, .invalid_error_code);
21693 try sema.addSafetyCheckCall(block, src, ok, .@"panic.unexpectedErrorCode", &.{err_code_inst});
2160721694 }
2160821695 }
2160921696
......@@ -23460,7 +23547,9 @@ fn analyzeShuffle(
2346023547 // `InternPool.Index` values using the known operands.
2346123548 for (mask_shuffle_two, mask_ip_index) |in, *out| {
2346223549 const val: Value = switch (in.unwrap()) {
23463 .undef => try pt.undefValue(elem_ty),
23550 // Special case zero bit types: there is no undefined value for OPV elements.
23551 // Only affects the case where `!a_rt and !b_rt` since `a_coerced` and `b_coerced`'s types are also OPV for OPV elements.
23552 .undef => try elem_ty.onePossibleValue(pt) orelse try pt.undefValue(elem_ty),
2346423553 .a_elem => |idx| try maybe_a_val.?.elemValue(pt, idx),
2346523554 .b_elem => |idx| try maybe_b_val.?.elemValue(pt, idx),
2346623555 };
......@@ -23509,6 +23598,9 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
2350923598 const a = try sema.coerce(block, vec_ty, sema.resolveInst(extra.a), a_src);
2351023599 const b = try sema.coerce(block, vec_ty, sema.resolveInst(extra.b), b_src);
2351123600
23601 // special case zero bit types
23602 if (try vec_ty.onePossibleValue(pt)) |opv| return .fromValue(opv);
23603
2351223604 const maybe_pred = sema.resolveValue(pred);
2351323605 const maybe_a = sema.resolveValue(a);
2351423606 const maybe_b = sema.resolveValue(b);
......@@ -24873,7 +24965,10 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2487324965 } else cc: {
2487424966 if (has_body) {
2487524967 const func_decl_nav = sema.owner.unwrap().nav_val;
24876 const func_decl_inst = ip.getNav(func_decl_nav).analysis.?.zir_index.resolve(&zcu.intern_pool) orelse return error.AnalysisFail;
24968 const func_decl_ti = ip.getNav(func_decl_nav).analysis.?.zir_index;
24969 const func_decl_inst = func_decl_ti.resolve(&zcu.intern_pool) orelse {
24970 return sema.failTransitive(.{ .lost_tracking = func_decl_ti });
24971 };
2487724972 const zir_decl = sema.code.getDeclaration(func_decl_inst);
2487824973 if (zir_decl.linkage == .@"export") {
2487924974 break :cc target.cCallingConvention() orelse {
......@@ -25458,10 +25553,10 @@ fn zirRoundOpType(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDa
2545825553 return .generic_poison_type;
2545925554 };
2546025555
25461 const float_ty = dest_ty.optEuBaseType(zcu);
25462 switch (float_ty.scalarType(zcu).zigTypeTag(zcu)) {
25463 .float, .comptime_float => return .fromType(float_ty),
25464 else => return .comptime_float_type,
25556 const dest_base_ty = dest_ty.optEuBaseType(zcu);
25557 switch (dest_base_ty.scalarType(zcu).zigTypeTag(zcu)) {
25558 .float, .comptime_float => return .fromType(dest_base_ty),
25559 else => return .generic_poison_type,
2546525560 }
2546625561}
2546725562
......@@ -25640,7 +25735,6 @@ pub fn explainWhyTypeIsNotExtern(
2564025735
2564125736 .@"opaque",
2564225737 .bool,
25643 .float,
2564425738 .@"anyframe",
2564525739 => unreachable, // these *are* allowed
2564625740
......@@ -25649,6 +25743,7 @@ pub fn explainWhyTypeIsNotExtern(
2564925743 try sema.errNote(src_loc, msg, "SPIR-V runtime arrays must be the last field of an extern struct", .{});
2565025744 },
2565125745
25746 .float => try sema.errNote(src_loc, msg, "'{f}' is not extern compatible on this target", .{ty.fmt(pt)}),
2565225747 .pointer => if (ty.isSlice(zcu)) {
2565325748 try sema.errNote(src_loc, msg, "slices have no guaranteed in-memory representation", .{});
2565425749 } else {
......@@ -28174,9 +28269,94 @@ fn coerceExtra(
2817428269 },
2817528270 else => {},
2817628271 },
28177 .one => {},
28272 // []T to *[n]T
28273 .one => slice_to_array_ptr: {
28274 if (!inst_ty.isSlice(zcu)) break :slice_to_array_ptr;
28275 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :slice_to_array_ptr;
28276 const array_ty: Type = .fromInterned(dest_info.child);
28277 if (array_ty.zigTypeTag(zcu) != .array) break :slice_to_array_ptr;
28278 const inst_val = maybe_inst_val orelse {
28279 if (!opts.report_err) return error.NotCoercible;
28280 return sema.fail(
28281 block,
28282 inst_src,
28283 "coercion from slice to array pointer type '{f}' requires length to be known at compile-time",
28284 .{dest_ty.fmt(pt)},
28285 );
28286 };
28287
28288 const slice: InternPool.Key.Slice = slice: {
28289 switch (ip.indexToKey(inst_val.toIntern())) {
28290 .undef => {},
28291 .slice => |slice| if (slice.len != .undef_usize) break :slice slice,
28292 else => unreachable,
28293 }
28294 if (!opts.report_err) return error.NotCoercible;
28295 return sema.failWithOwnedErrorMsg(block, msg: {
28296 const msg = try sema.errMsg(inst_src, "slice with undefined length cannot cast into array pointer type '{f}'", .{
28297 dest_ty.fmt(pt),
28298 });
28299 errdefer msg.destroy(gpa);
28300 try sema.errNote(inst_src, msg, "length of slice must be defined and match length of array type", .{});
28301 break :msg msg;
28302 });
28303 };
28304 const slice_len = Value.fromInterned(slice.len).toUnsignedInt(zcu);
28305 if (array_ty.arrayLen(zcu) != slice_len) {
28306 if (!opts.report_err) return error.NotCoercible;
28307 return sema.failWithOwnedErrorMsg(block, msg: {
28308 const msg = try sema.errMsg(inst_src, "slice of length {d} cannot cast into array pointer type '{f}'", .{
28309 slice_len, dest_ty.fmt(pt),
28310 });
28311 errdefer msg.destroy(gpa);
28312 try sema.errNote(inst_src, msg, "length of slice must match length of array type", .{});
28313 break :msg msg;
28314 });
28315 }
28316
28317 const inst_elem_ty = inst_ty.childType(zcu);
28318 const dest_elem_ty = array_ty.childType(zcu);
28319 const dest_is_mut = !dest_info.flags.is_const;
28320 switch (try sema.coerceInMemoryAllowed(block, dest_elem_ty, inst_elem_ty, dest_is_mut, target, dest_ty_src, inst_src, null)) {
28321 .ok => {},
28322 else => |elem_res| {
28323 in_memory_result = .{ .ptr_child = .{
28324 .child = try elem_res.dupe(sema.arena),
28325 .actual = inst_elem_ty,
28326 .wanted = dest_elem_ty,
28327 } };
28328 break :slice_to_array_ptr;
28329 },
28330 }
28331
28332 if (array_ty.sentinel(zcu)) |array_sentinel| {
28333 if (inst_ty.sentinel(zcu)) |slice_sentinel| {
28334 if (array_sentinel.toIntern() !=
28335 (try pt.getCoerced(slice_sentinel, dest_elem_ty)).toIntern())
28336 {
28337 in_memory_result = .{ .ptr_sentinel = .{
28338 .actual = slice_sentinel,
28339 .wanted = array_sentinel,
28340 .ty = dest_elem_ty,
28341 } };
28342 break :slice_to_array_ptr;
28343 }
28344 } else {
28345 in_memory_result = .{ .ptr_sentinel = .{
28346 .actual = .@"unreachable",
28347 .wanted = array_sentinel,
28348 .ty = dest_elem_ty,
28349 } };
28350 break :slice_to_array_ptr;
28351 }
28352 }
28353
28354 const array_ptr = try pt.sliceToArrayPtr(slice);
28355 return sema.coerceCompatiblePtrs(block, dest_ty, .fromValue(array_ptr), inst_src);
28356 },
2817828357 .slice => to_slice: {
2817928358 if (inst_ty.zigTypeTag(zcu) == .array) {
28359 if (!opts.report_err) return error.NotCoercible;
2818028360 return sema.fail(
2818128361 block,
2818228362 inst_src,
......@@ -28204,6 +28384,7 @@ fn coerceExtra(
2820428384
2820528385 // pointer to tuple to slice
2820628386 if (!dest_info.flags.is_const) {
28387 if (!opts.report_err) return error.NotCoercible;
2820728388 const err_msg = err_msg: {
2820828389 const err_msg = try sema.errMsg(inst_src, "cannot cast pointer to tuple to '{f}'", .{dest_ty.fmt(pt)});
2820928390 errdefer err_msg.destroy(sema.gpa);
......@@ -28299,6 +28480,7 @@ fn coerceExtra(
2829928480 if (maybe_inst_val) |val| {
2830028481 const result_val = try val.floatCast(dest_ty, pt);
2830128482 if (!val.eql(try result_val.floatCast(inst_ty, pt), inst_ty, zcu)) {
28483 if (!opts.report_err) return error.NotCoercible;
2830228484 return sema.fail(
2830328485 block,
2830428486 inst_src,
......@@ -28356,12 +28538,15 @@ fn coerceExtra(
2835628538 break :fits result_big_int.toConst().eql(operand_big_int);
2835728539 },
2835828540 };
28359 if (!fits) return sema.fail(
28360 block,
28361 inst_src,
28362 "type '{f}' cannot represent integer value '{f}'",
28363 .{ dest_ty.fmt(pt), val.fmtValue(pt) },
28364 );
28541 if (!fits) {
28542 if (!opts.report_err) return error.NotCoercible;
28543 return sema.fail(
28544 block,
28545 inst_src,
28546 "type '{f}' cannot represent integer value '{f}'",
28547 .{ dest_ty.fmt(pt), val.fmtValue(pt) },
28548 );
28549 }
2836528550 return .fromValue(result_val);
2836628551 },
2836728552 else => {},
......@@ -28372,6 +28557,7 @@ fn coerceExtra(
2837228557 const val = sema.resolveValue(inst).?;
2837328558 const string = zcu.intern_pool.indexToKey(val.toIntern()).enum_literal;
2837428559 const field_index = dest_ty.enumFieldIndex(string, zcu) orelse {
28560 if (!opts.report_err) return error.NotCoercible;
2837528561 return sema.fail(block, inst_src, "no field named '{f}' in enum '{f}'", .{
2837628562 string.fmt(&zcu.intern_pool), dest_ty.fmt(pt),
2837728563 });
......@@ -29622,7 +29808,7 @@ fn coerceVarArgParam(
2962229808 .array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}),
2962329809 .float => float: {
2962429810 const target = zcu.getTarget();
29625 const double_bits = target.cTypeBitSize(.double);
29811 const double_bits = target.cTypeBitSize(.double) orelse break :float inst;
2962629812 const inst_bits = uncasted_ty.floatBits(target);
2962729813 if (inst_bits >= double_bits) break :float inst;
2962829814 switch (double_bits) {
......@@ -29638,21 +29824,21 @@ fn coerceVarArgParam(
2963829824 if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) {
2963929825 .signed => .int,
2964029826 .unsigned => .uint,
29641 })) break :int try sema.coerce(block, switch (uncasted_info.signedness) {
29827 }) orelse break :int inst) break :int try sema.coerce(block, switch (uncasted_info.signedness) {
2964229828 .signed => .c_int,
2964329829 .unsigned => .c_uint,
2964429830 }, inst, inst_src);
2964529831 if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) {
2964629832 .signed => .long,
2964729833 .unsigned => .ulong,
29648 })) break :int try sema.coerce(block, switch (uncasted_info.signedness) {
29834 }).?) break :int try sema.coerce(block, switch (uncasted_info.signedness) {
2964929835 .signed => .c_long,
2965029836 .unsigned => .c_ulong,
2965129837 }, inst, inst_src);
2965229838 if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) {
2965329839 .signed => .longlong,
2965429840 .unsigned => .ulonglong,
29655 })) break :int try sema.coerce(block, switch (uncasted_info.signedness) {
29841 }).?) break :int try sema.coerce(block, switch (uncasted_info.signedness) {
2965629842 .signed => .c_longlong,
2965729843 .unsigned => .c_ulonglong,
2965829844 }, inst, inst_src);
......@@ -30048,6 +30234,19 @@ fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_resul
3004830234 } };
3004930235 return false;
3005030236 }
30237
30238 if (inst_info.packed_offset.host_size != dest_info.packed_offset.host_size or
30239 inst_info.packed_offset.bit_offset != dest_info.packed_offset.bit_offset)
30240 {
30241 in_memory_result.* = .{ .ptr_bit_range = .{
30242 .actual_host = inst_info.packed_offset.host_size,
30243 .wanted_host = dest_info.packed_offset.host_size,
30244 .actual_offset = inst_info.packed_offset.bit_offset,
30245 .wanted_offset = dest_info.packed_offset.bit_offset,
30246 } };
30247 return false;
30248 }
30249
3005130250 if (inst_info.flags.alignment == .none and dest_info.flags.alignment == .none) return true;
3005230251 if (len0) return true;
3005330252
......@@ -30068,19 +30267,6 @@ fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_resul
3006830267 } };
3006930268 return false;
3007030269 }
30071
30072 if (inst_info.packed_offset.host_size != dest_info.packed_offset.host_size or
30073 inst_info.packed_offset.bit_offset != dest_info.packed_offset.bit_offset)
30074 {
30075 in_memory_result.* = .{ .ptr_bit_range = .{
30076 .actual_host = inst_info.packed_offset.host_size,
30077 .wanted_host = dest_info.packed_offset.host_size,
30078 .actual_offset = inst_info.packed_offset.bit_offset,
30079 .wanted_offset = dest_info.packed_offset.bit_offset,
30080 } };
30081 return false;
30082 }
30083
3008430270 return true;
3008530271}
3008630272
......@@ -30606,7 +30792,10 @@ fn ensureMemoizedStateResolved(sema: *Sema, src: LazySrcLoc, stage: InternPool.M
3060630792 if (pt.zcu.analysis_in_progress.contains(unit)) {
3060730793 return sema.failWithDependencyLoop(unit, &reason);
3060830794 }
30609 try pt.ensureMemoizedStateUpToDate(stage, &reason);
30795 pt.ensureMemoizedStateUpToDate(stage, &reason) catch |err| switch (err) {
30796 error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = unit }),
30797 else => |e| return e,
30798 };
3061030799}
3061130800
3061230801pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: InternPool.Nav.Index, kind: enum { type, fully }) CompileError!void {
......@@ -30642,9 +30831,15 @@ pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index:
3064230831 switch (kind) {
3064330832 .type => {
3064430833 try zcu.ensureNavValAnalysisQueued(nav_index);
30645 return pt.ensureNavTypeUpToDate(nav_index, &reason);
30834 return pt.ensureNavTypeUpToDate(nav_index, &reason) catch |err| switch (err) {
30835 error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = anal_unit }),
30836 else => |e| return e,
30837 };
30838 },
30839 .fully => return pt.ensureNavValUpToDate(nav_index, &reason) catch |err| switch (err) {
30840 error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = anal_unit }),
30841 else => |e| return e,
3064630842 },
30647 .fully => return pt.ensureNavValUpToDate(nav_index, &reason),
3064830843 }
3064930844}
3065030845
......@@ -30856,7 +31051,18 @@ fn analyzeLoad(
3085631051 const comptime_only = switch (elem_ty.classify(zcu)) {
3085731052 .no_possible_value => switch (elem_ty.zigTypeTag(zcu)) {
3085831053 .@"opaque" => return sema.fail(block, src, "cannot load opaque type '{f}'", .{elem_ty.fmt(pt)}),
30859 else => return sema.fail(block, src, "cannot load uninstantiable type '{f}'", .{elem_ty.fmt(pt)}),
31054 else => {
31055 // Loading an uninstantiable type always invokes Illegal Behavior.
31056 if (block.isComptime()) {
31057 return sema.fail(block, src, "cannot load uninstantiable type '{f}'", .{elem_ty.fmt(pt)});
31058 } else if (block.wantSafety()) {
31059 try sema.safetyPanic(block, src, .load_uninstantiable_type);
31060 return .unreachable_value;
31061 } else {
31062 _ = try block.addNoOp(.unreach);
31063 return .unreachable_value;
31064 }
31065 },
3086031066 },
3086131067 .one_possible_value => return .fromValue((try elem_ty.onePossibleValue(pt)).?),
3086231068 .runtime => false,
......@@ -30864,8 +31070,11 @@ fn analyzeLoad(
3086431070 };
3086531071
3086631072 if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {
30867 if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| {
30868 return Air.internedToRef(elem_val.toIntern());
31073 if (switch (ptr_ty.ptrSize(zcu)) {
31074 .slice => try sema.maybeDerefSliceAsArray(block, src, ptr_val),
31075 else => try sema.pointerDeref(block, src, ptr_val, ptr_ty),
31076 }) |elem_val| {
31077 return .fromValue(elem_val);
3086931078 }
3087031079 }
3087131080
......@@ -33707,7 +33916,10 @@ fn ensureFuncIesResolved(
3370733916 return sema.failWithDependencyLoop(.wrap(.{ .func = func_index }), &reason);
3370833917 }
3370933918
33710 try pt.ensureFuncBodyUpToDate(func_index, &reason);
33919 pt.ensureFuncBodyUpToDate(func_index, &reason) catch |err| switch (err) {
33920 error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = .wrap(.{ .func = func_index }) }),
33921 else => |e| return e,
33922 };
3371133923}
3371233924
3371333925pub fn resolveInferredErrorSetPtr(
......@@ -33821,7 +34033,7 @@ pub fn getTmpAir(sema: Sema) Air {
3382134033}
3382234034
3382334035pub fn addExtra(sema: *Sema, extra: anytype) Allocator.Error!u32 {
33824 const field_count = std.meta.fieldNames(@TypeOf(extra)).len;
34036 const field_count = @typeInfo(@TypeOf(extra)).@"struct".field_names.len;
3382534037 try sema.air_extra.ensureUnusedCapacity(sema.gpa, field_count);
3382634038 return sema.addExtraAssumeCapacity(extra);
3382734039}
......@@ -34536,7 +34748,6 @@ fn maybeDerefSliceAsArray(
3453634748) CompileError!?Value {
3453734749 const pt = sema.pt;
3453834750 const zcu = pt.zcu;
34539 const ip = &zcu.intern_pool;
3454034751 const slice_ty = slice_val.typeOf(zcu);
3454134752 assert(slice_ty.zigTypeTag(zcu) == .pointer);
3454234753 switch (slice_ty.ptrInfo(zcu).flags.size) {
......@@ -34544,26 +34755,14 @@ fn maybeDerefSliceAsArray(
3454434755 .one => return sema.pointerDeref(block, src, slice_val, slice_ty),
3454534756 .many, .c => unreachable,
3454634757 }
34547 const slice = switch (ip.indexToKey(slice_val.toIntern())) {
34758 const slice = switch (zcu.intern_pool.indexToKey(slice_val.toIntern())) {
3454834759 .undef => return sema.failWithUseOfUndef(block, src, null),
3454934760 .slice => |slice| slice,
3455034761 else => unreachable,
3455134762 };
34552 const elem_ty = Type.fromInterned(slice.ty).childType(zcu);
34553 const len = Value.fromInterned(slice.len).toUnsignedInt(zcu);
34554 const array_ty = try pt.arrayType(.{
34555 .child = elem_ty.toIntern(),
34556 .len = len,
34557 });
34558 const ptr_ty = try pt.ptrType(p: {
34559 var p = Type.fromInterned(slice.ty).ptrInfo(zcu);
34560 p.flags.size = .one;
34561 p.child = array_ty.toIntern();
34562 p.sentinel = .none;
34563 break :p p;
34564 });
34565 const casted_ptr = try pt.getCoerced(Value.fromInterned(slice.ptr), ptr_ty);
34566 return sema.pointerDeref(block, src, casted_ptr, ptr_ty);
34763 if (slice.len == .undef_usize) return sema.failWithUndefSliceLen(block, src);
34764 const casted_ptr = try pt.sliceToArrayPtr(slice);
34765 return sema.pointerDeref(block, src, casted_ptr, casted_ptr.typeOf(zcu));
3456734766}
3456834767
3456934768fn analyzeUnreachable(sema: *Sema, block: *Block, src: LazySrcLoc, safety_check: bool) !void {
......@@ -34668,7 +34867,7 @@ pub fn resolveNavPtrModifiers(
3466834867 const linksection_body = zir_decl.linksection_body orelse break :ls .none;
3466934868 const linksection_ref = try sema.resolveInlineBody(block, linksection_body, decl_inst);
3467034869 const bytes = try sema.toConstString(block, section_src, linksection_ref, .{ .simple = .@"linksection" });
34671 if (std.mem.indexOfScalar(u8, bytes, 0) != null) {
34870 if (std.mem.findScalar(u8, bytes, 0) != null) {
3467234871 return sema.fail(block, section_src, "linksection cannot contain null bytes", .{});
3467334872 } else if (bytes.len == 0) {
3467434873 return sema.fail(block, section_src, "linksection cannot be empty", .{});
......@@ -34843,7 +35042,9 @@ fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.StdLangDecl) CompileError!Typ
3484335042 }),
3484435043
3484535044 // `fn (anyerror) noreturn`
34846 .@"panic.unwrapError" => try pt.funcType(.{
35045 .@"panic.unwrapError",
35046 .@"panic.unexpectedErrorCode",
35047 => try pt.funcType(.{
3484735048 .param_types = &.{.anyerror_type},
3484835049 .return_type = .noreturn_type,
3484935050 }),
......@@ -34882,12 +35083,60 @@ fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.StdLangDecl) CompileError!Typ
3488235083 .@"panic.copyLenMismatch",
3488335084 .@"panic.memcpyAlias",
3488435085 .@"panic.noreturnReturned",
35086 .@"panic.loadUninstantiableType",
3488535087 => try pt.funcType(.{
3488635088 .param_types = &.{},
3488735089 .return_type = .noreturn_type,
3488835090 }),
3488935091
34890 else => unreachable,
35092 .StackTrace,
35093 .CallingConvention,
35094 .SourceLocation,
35095 .Signedness,
35096 .AddressSpace,
35097 .VaList,
35098 .CallModifier,
35099 .AtomicOrder,
35100 .AtomicRmwOp,
35101 .ReduceOp,
35102 .FloatMode,
35103 .PrefetchOptions,
35104 .ExportOptions,
35105 .ExternOptions,
35106 .BranchHint,
35107 .assembly,
35108 .@"assembly.Clobbers",
35109 .Type,
35110 .@"Type.Fn",
35111 .@"Type.Fn.ParamAttributes",
35112 .@"Type.Fn.Attributes",
35113 .@"Type.Int",
35114 .@"Type.Float",
35115 .@"Type.Pointer",
35116 .@"Type.Pointer.Size",
35117 .@"Type.Pointer.Attributes",
35118 .@"Type.Array",
35119 .@"Type.Vector",
35120 .@"Type.Optional",
35121 .@"Type.ErrorUnion",
35122 .@"Type.ErrorSet",
35123 .@"Type.Enum",
35124 .@"Type.Enum.Mode",
35125 .@"Type.Union",
35126 .@"Type.Union.FieldAttributes",
35127 .@"Type.Struct",
35128 .@"Type.Struct.FieldAttributes",
35129 .@"Type.ContainerLayout",
35130 .@"Type.Opaque",
35131 .@"Type.Spirv",
35132 .@"Type.Spirv.Image",
35133 .@"Type.Spirv.Image.Usage",
35134 .@"Type.Spirv.Image.Format",
35135 .@"Type.Spirv.Image.Dimensionality",
35136 .@"Type.Spirv.Image.Depth",
35137 .@"Type.Spirv.Image.Access",
35138 .panic,
35139 => unreachable, // not a function (`decl.kind() != .func`)
3489135140 };
3489235141}
3489335142
......@@ -34926,7 +35175,9 @@ pub fn setTypeName(
3492635175 },
3492735176 .parent => wip.setName(ip, block.type_name_ctx, sema.owner.unwrap().nav_val.toOptional()),
3492835177 .func => {
34929 const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse return error.AnalysisFail);
35178 const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse {
35179 return sema.failTransitive(.{ .lost_tracking = ip.funcZirBodyInst(sema.func_index) });
35180 });
3493035181 const zir_tags = sema.code.instructions.items(.tag);
3493135182
3493235183 var aw: std.Io.Writer.Allocating = .init(gpa);
......@@ -35042,7 +35293,10 @@ fn zirStructDecl(
3504235293 };
3504335294
3504435295 try sema.addTypeReferenceEntry(src, ty);
35045 try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu));
35296 pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)) catch |err| switch (err) {
35297 error.LostZirContainerDecl => unreachable, // we literally just tracked it
35298 else => |e| return e,
35299 };
3504635300
3504735301 return .fromType(ty);
3504835302}
......@@ -35115,7 +35369,10 @@ fn zirUnionDecl(
3511535369 };
3511635370
3511735371 try sema.addTypeReferenceEntry(src, ty);
35118 try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu));
35372 pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)) catch |err| switch (err) {
35373 error.LostZirContainerDecl => unreachable, // we literally just tracked it
35374 else => |e| return e,
35375 };
3511935376
3512035377 return .fromType(ty);
3512135378}
......@@ -35167,7 +35424,10 @@ fn zirEnumDecl(
3516735424 };
3516835425
3516935426 try sema.addTypeReferenceEntry(src, ty);
35170 try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu));
35427 pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)) catch |err| switch (err) {
35428 error.LostZirContainerDecl => unreachable, // we literally just tracked it
35429 else => |e| return e,
35430 };
3517135431
3517235432 return .fromType(ty);
3517335433}
......@@ -35216,7 +35476,10 @@ fn zirOpaqueDecl(
3521635476 };
3521735477
3521835478 try sema.addTypeReferenceEntry(src, ty);
35219 try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu));
35479 pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)) catch |err| switch (err) {
35480 error.LostZirContainerDecl => unreachable, // we literally just tracked it
35481 else => |e| return e,
35482 };
3522035483
3522135484 return .fromType(ty);
3522235485}
......@@ -35257,5 +35520,31 @@ pub fn failWithDependencyLoop(
3525735520 }
3525835521
3525935522 // A dependency loop error will be reported. Mark us all as transitive failures.
35260 return error.AnalysisFail;
35523 return sema.failTransitive(.dependency_loop);
35524}
35525
35526/// Marks the owner of `sema` as having failed semantic failed *without* an error message, and
35527/// returns failure. This function is suitable to call when any one of the following is true:
35528///
35529/// * `sema.owner` is guaranteed to be unreferenced on this update, for instance because it uses a
35530/// dead `InternPool.TrackedInst`.
35531///
35532/// * There is guaranteed to be a compile error if this unit is referenced. In practice, this means
35533/// that either there is an error elsewhere in the pipeline (e.g. AstGen), or we depend on another
35534/// `AnalUnit` which has itself failed.
35535pub fn failTransitive(sema: *Sema, reason: Zcu.TransitiveFailureReason) SemaError {
35536 assert(sema.err == null);
35537 const zcu = sema.pt.zcu;
35538 const unit = sema.owner;
35539
35540 log.debug("transitive failure analyzing '{f}' ({t})", .{ zcu.fmtAnalUnit(unit), reason });
35541
35542 assert(!zcu.failed_analysis.contains(unit));
35543 try zcu.transitive_failed_analysis.putNoClobber(
35544 zcu.comp.gpa,
35545 unit,
35546 if (build_options.enable_debug_extensions) reason,
35547 );
35548
35549 return error.AlreadyReported;
3526135550}
src/Sema/LowerZon.zig+2-2
......@@ -320,7 +320,7 @@ fn failUnsupportedResultType(
320320 self: *LowerZon,
321321 ty: Type,
322322 opt_note: ?[]const u8,
323) error{ AnalysisFail, OutOfMemory } {
323) Zcu.SemaError {
324324 @branchHint(.cold);
325325 const sema = self.sema;
326326 const gpa = sema.gpa;
......@@ -338,7 +338,7 @@ fn fail(
338338 node: Zoir.Node.Index,
339339 comptime format: []const u8,
340340 args: anytype,
341) error{ AnalysisFail, OutOfMemory } {
341) Zcu.SemaError {
342342 @branchHint(.cold);
343343 const err_msg = try Zcu.ErrorMsg.create(self.sema.pt.zcu.gpa, self.nodeSrc(node), format, args);
344344 try self.sema.pt.zcu.errNote(self.import_loc, err_msg, "imported here", .{});
src/Sema/type_resolution.zig+22-8
......@@ -116,7 +116,10 @@ fn ensureLayoutResolvedInner(sema: *Sema, ty: Type, orig_ty: Type, reason: *cons
116116 if (zcu.analysis_in_progress.contains(.wrap(.{ .type_layout = ty.toIntern() }))) {
117117 return sema.failWithDependencyLoop(.wrap(.{ .type_layout = ty.toIntern() }), reason);
118118 }
119 try pt.ensureTypeLayoutUpToDate(ty, reason);
119 pt.ensureTypeLayoutUpToDate(ty, reason) catch |err| switch (err) {
120 error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = .wrap(.{ .type_layout = ty.toIntern() }) }),
121 else => |e| return e,
122 };
120123 },
121124
122125 // values, not types
......@@ -166,7 +169,10 @@ pub fn ensureStructDefaultsResolved(sema: *Sema, ty: Type, src: LazySrcLoc) Sema
166169 return sema.failWithDependencyLoop(.wrap(.{ .struct_defaults = ty.toIntern() }), &reason);
167170 }
168171
169 try pt.ensureStructDefaultsUpToDate(ty, &reason);
172 pt.ensureStructDefaultsUpToDate(ty, &reason) catch |err| switch (err) {
173 error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = .wrap(.{ .struct_defaults = ty.toIntern() }) }),
174 else => |e| return e,
175 };
170176}
171177
172178/// 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 {
188194
189195 const struct_obj = ip.loadStructType(struct_ty.toIntern());
190196 assert(struct_obj.want_layout);
191 const zir_index = struct_obj.zir_index.resolve(ip) orelse return error.AnalysisFail;
197 const zir_index = struct_obj.zir_index.resolve(ip) orelse {
198 return sema.failTransitive(.{ .lost_tracking = struct_obj.zir_index });
199 };
192200
193201 var block: Block = .{
194202 .parent = null,
......@@ -364,7 +372,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
364372 const a = struct_obj.field_aligns.get(ip)[field_idx];
365373 if (a != .none) break :a a;
366374 }
367 break :a field_ty.defaultStructFieldAlignment(struct_obj.layout, zcu);
375 break :a field_ty.abiAlignment(zcu);
368376 };
369377 align_out.* = field_align;
370378 if (struct_obj.field_is_comptime_bits.get(ip, field_idx)) {
......@@ -606,7 +614,7 @@ pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void {
606614 struct_ty.assertHasLayout(zcu);
607615 const layout_unit: InternPool.AnalUnit = .wrap(.{ .type_layout = struct_ty.toIntern() });
608616 if (zcu.failed_analysis.contains(layout_unit) or zcu.transitive_failed_analysis.contains(layout_unit)) {
609 return error.AnalysisFail;
617 return sema.failTransitive(.{ .failed_unit = layout_unit });
610618 }
611619
612620 const struct_obj = ip.loadStructType(struct_ty.toIntern());
......@@ -656,7 +664,9 @@ fn resolveStructDefaultsInner(
656664 assert(struct_obj.field_defaults.len > 0);
657665
658666 // We'll need to map the struct decl instruction to provide result types
659 const zir_index = struct_obj.zir_index.resolve(ip) orelse return error.AnalysisFail;
667 const zir_index = struct_obj.zir_index.resolve(ip) orelse {
668 return sema.failTransitive(.{ .lost_tracking = struct_obj.zir_index });
669 };
660670 try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index});
661671
662672 const field_types = struct_obj.field_types.get(ip);
......@@ -713,7 +723,9 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void {
713723
714724 const union_obj = ip.loadUnionType(union_ty.toIntern());
715725 assert(union_obj.want_layout);
716 const zir_index = union_obj.zir_index.resolve(ip) orelse return error.AnalysisFail;
726 const zir_index = union_obj.zir_index.resolve(ip) orelse {
727 return sema.failTransitive(.{ .lost_tracking = union_obj.zir_index });
728 };
717729
718730 var block: Block = .{
719731 .parent = null,
......@@ -1212,7 +1224,9 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void {
12121224 };
12131225
12141226 const tracked_inst = enum_obj.zir_index.unwrap() orelse maybe_parent_union_obj.?.zir_index;
1215 const zir_index = tracked_inst.resolve(ip) orelse return error.AnalysisFail;
1227 const zir_index = tracked_inst.resolve(ip) orelse {
1228 return sema.failTransitive(.{ .lost_tracking = tracked_inst });
1229 };
12161230
12171231 var block: Block = .{
12181232 .parent = null,
src/Type.zig+107-86
......@@ -957,12 +957,27 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment {
957957 if (vector_type.len == 0) return .@"1";
958958 switch (zcu.comp.getZigBackend()) {
959959 else => {
960 const elem_bits: u32 = @intCast(Type.fromInterned(vector_type.child).bitSize(zcu));
960 const elem_ty: Type = .fromInterned(vector_type.child);
961 switch (if (elem_ty.isRuntimeFloat())
962 std.zig.target.compilerRtFloatAbi(target, elem_ty.floatBits(target))
963 else
964 .hard) {
965 .hard => {},
966 .soft => return elem_ty.abiAlignment(zcu),
967 }
968 const elem_bits: u32 = @intCast(elem_ty.bitSize(zcu));
961969 if (elem_bits == 0) return .@"1";
962970 const bytes = ((elem_bits * vector_type.len) + 7) / 8;
963 return .fromByteUnits(std.math.ceilPowerOfTwoAssert(u32, bytes));
971 const arch = target.cpu.arch;
972 return .fromByteUnits(std.math.ceilPowerOfTwoAssert(
973 u32,
974 if (arch.isArm() or arch.isAARCH64() or arch == .s390x)
975 @min(bytes, target.stackAlignment())
976 else
977 bytes,
978 ));
964979 },
965 .stage2_c, .stage2_wasm => return Type.fromInterned(vector_type.child).defaultStructFieldAlignment(.auto, zcu),
980 .stage2_c, .stage2_wasm => return Type.fromInterned(vector_type.child).abiAlignment(zcu),
966981 .stage2_x86_64 => {
967982 if (vector_type.child == .bool_type) {
968983 if (vector_type.len > 256 and target.cpu.has(.x86, .avx512f)) return .@"64";
......@@ -1018,19 +1033,33 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment {
10181033 .c_ulonglong => cTypeAlign(target, .ulonglong),
10191034 .c_longdouble => cTypeAlign(target, .longdouble),
10201035
1021 .f16 => .@"2",
1022 .f32 => if (target.os.tag == .opengl) .@"4" else cTypeAlign(target, .float),
1023 .f64 => if (target.os.tag == .opengl) .@"8" else switch (target.cTypeBitSize(.double)) {
1024 64 => cTypeAlign(target, .double),
1025 else => .@"8",
1026 },
1027 .f80 => switch (target.cTypeBitSize(.longdouble)) {
1028 80 => cTypeAlign(target, .longdouble),
1029 else => Type.u80.abiAlignment(zcu),
1030 },
1031 .f128 => switch (target.cTypeBitSize(.longdouble)) {
1032 128 => cTypeAlign(target, .longdouble),
1033 else => .@"16",
1036 .f16 => .fromByteUnits(std.zig.target.intAlignment(target, 16)), // repr: u16
1037 .f32 => if (target.cTypeBitSize(.float) == 32)
1038 cTypeAlign(target, .float) // abi: c_float,
1039 else
1040 .fromByteUnits(std.zig.target.intAlignment(target, 32)), // repr: u32,
1041 .f64 => if (target.cTypeBitSize(.double) == 64)
1042 cTypeAlign(target, .double) // abi: c_double,
1043 else
1044 .fromByteUnits(std.zig.target.intAlignment(target, 64)), // repr: u64,
1045 .f80 => if (target.cTypeBitSize(.longdouble) == 80)
1046 cTypeAlign(target, .longdouble) // abi: c_longdouble,
1047 else
1048 .fromByteUnits(switch (std.zig.target.compilerRtFloatAbi(target, 80)) {
1049 .hard => std.zig.target.intAlignment(target, 80), // repr: u80,
1050 .soft => @max(
1051 std.zig.target.intAlignment(target, 64), // mantissa: u64,
1052 std.zig.target.intAlignment(target, 16), // exponent: u16,
1053 ),
1054 }),
1055 .f128 => if (target.cTypeBitSize(.longdouble) == 128)
1056 cTypeAlign(target, .longdouble) // abi: c_longdouble,
1057 else switch (std.zig.target.compilerRtFloatAbi(target, 128)) {
1058 .hard => if (target.cpu.arch.isX86())
1059 .@"16" // abi: c___float128,
1060 else
1061 .fromByteUnits(std.zig.target.intAlignment(target, 128)), // repr: u128,
1062 .soft => .fromByteUnits(std.zig.target.intAlignment(target, 64)), // lo: u64, hi: u64,
10341063 },
10351064
10361065 .generic_poison => unreachable,
......@@ -1111,7 +1140,13 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 {
11111140 .vector_type => |vec| {
11121141 const elem_ty: Type = .fromInterned(vec.child);
11131142 const bytes = switch (zcu.comp.getZigBackend()) {
1114 else => @divCeil(vec.len * elem_ty.bitSize(zcu), 8),
1143 else => switch (if (elem_ty.isRuntimeFloat())
1144 std.zig.target.compilerRtFloatAbi(target, elem_ty.floatBits(target))
1145 else
1146 .hard) {
1147 .hard => @divCeil(vec.len * elem_ty.bitSize(zcu), 8),
1148 .soft => vec.len * elem_ty.abiSize(zcu),
1149 },
11151150 .stage2_c, .stage2_wasm => vec.len * elem_ty.abiSize(zcu),
11161151 .stage2_x86_64 => switch (elem_ty.toIntern()) {
11171152 .bool_type => @divCeil(vec.len, 8),
......@@ -1167,25 +1202,44 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 {
11671202 .anyerror, .adhoc_inferred_error_set => errorAbiSize(zcu),
11681203 .usize, .isize => ptrAbiSize(target),
11691204
1170 .c_char => target.cTypeByteSize(.char),
1171 .c_short => target.cTypeByteSize(.short),
1172 .c_ushort => target.cTypeByteSize(.ushort),
1173 .c_int => target.cTypeByteSize(.int),
1174 .c_uint => target.cTypeByteSize(.uint),
1175 .c_long => target.cTypeByteSize(.long),
1176 .c_ulong => target.cTypeByteSize(.ulong),
1177 .c_longlong => target.cTypeByteSize(.longlong),
1178 .c_ulonglong => target.cTypeByteSize(.ulonglong),
1179 .c_longdouble => target.cTypeByteSize(.longdouble),
1180
1181 .f16 => 2,
1182 .f32 => 4,
1183 .f64 => 8,
1184 .f80 => switch (target.cTypeBitSize(.longdouble)) {
1185 80 => target.cTypeByteSize(.longdouble),
1186 else => Type.u80.abiSize(zcu),
1205 .c_char => target.cTypeByteSize(.char).?,
1206 .c_short => target.cTypeByteSize(.short).?,
1207 .c_ushort => target.cTypeByteSize(.ushort).?,
1208 .c_int => target.cTypeByteSize(.int).?,
1209 .c_uint => target.cTypeByteSize(.uint).?,
1210 .c_long => target.cTypeByteSize(.long).?,
1211 .c_ulong => target.cTypeByteSize(.ulong).?,
1212 .c_longlong => target.cTypeByteSize(.longlong).?,
1213 .c_ulonglong => target.cTypeByteSize(.ulonglong).?,
1214 .c_longdouble => target.cTypeByteSize(.longdouble).?,
1215
1216 .f16 => std.zig.target.intByteSize(target, 16), // repr: u16
1217 .f32 => if (target.cTypeBitSize(.float) == 32)
1218 target.cTypeByteSize(.float).? // abi: c_float,
1219 else
1220 std.zig.target.intByteSize(target, 32), // repr: u32,
1221 .f64 => if (target.cTypeBitSize(.double) == 64)
1222 target.cTypeByteSize(.double).? // abi: c_double,
1223 else
1224 std.zig.target.intByteSize(target, 64), // repr: u64,
1225 .f80 => if (target.cTypeBitSize(.longdouble) == 80)
1226 target.cTypeByteSize(.longdouble).? // abi: c_longdouble,
1227 else switch (std.zig.target.compilerRtFloatAbi(target, 80)) {
1228 .hard => std.zig.target.intByteSize(target, 80), // repr: u80,
1229 .soft => ty.abiAlignment(zcu).forward(
1230 std.zig.target.intByteSize(target, 64) + // mantissa: u64,
1231 std.zig.target.intByteSize(target, 16), // exponent: u16
1232 ),
1233 },
1234 .f128 => if (target.cTypeBitSize(.longdouble) == 128)
1235 target.cTypeByteSize(.longdouble).? // abi: c_longdouble,
1236 else switch (std.zig.target.compilerRtFloatAbi(target, 128)) {
1237 .hard => if (target.cpu.arch.isX86())
1238 16 // abi: c___float128,
1239 else
1240 std.zig.target.intByteSize(target, 128), // repr: u128,
1241 .soft => std.zig.target.intByteSize(target, 64) * 2, // lo: u64, hi: u64,
11871242 },
1188 .f128 => 16,
11891243
11901244 .anyopaque => unreachable,
11911245 .generic_poison => unreachable,
......@@ -1733,7 +1787,7 @@ pub fn isInt(self: Type, zcu: *const Zcu) bool {
17331787/// Returns true if and only if the type is a fixed-width, signed integer.
17341788pub fn isSignedInt(ty: Type, zcu: *const Zcu) bool {
17351789 return switch (ty.toIntern()) {
1736 .c_char_type => zcu.getTarget().cCharSignedness() == .signed,
1790 .c_char_type => zcu.getTarget().cCharSignedness().? == .signed,
17371791 .isize_type, .c_short_type, .c_int_type, .c_long_type, .c_longlong_type => true,
17381792 else => switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
17391793 .int_type => |int_type| int_type.signedness == .signed,
......@@ -1745,7 +1799,7 @@ pub fn isSignedInt(ty: Type, zcu: *const Zcu) bool {
17451799/// Returns true if and only if the type is a fixed-width, unsigned integer.
17461800pub fn isUnsignedInt(ty: Type, zcu: *const Zcu) bool {
17471801 return switch (ty.toIntern()) {
1748 .c_char_type => zcu.getTarget().cCharSignedness() == .unsigned,
1802 .c_char_type => zcu.getTarget().cCharSignedness().? == .unsigned,
17491803 .usize_type, .c_ushort_type, .c_uint_type, .c_ulong_type, .c_ulonglong_type => true,
17501804 else => switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
17511805 .int_type => |int_type| int_type.signedness == .unsigned,
......@@ -1776,15 +1830,15 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType {
17761830 },
17771831 .usize_type => return .{ .signedness = .unsigned, .bits = target.ptrBitWidth() },
17781832 .isize_type => return .{ .signedness = .signed, .bits = target.ptrBitWidth() },
1779 .c_char_type => return .{ .signedness = zcu.getTarget().cCharSignedness(), .bits = target.cTypeBitSize(.char) },
1780 .c_short_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.short) },
1781 .c_ushort_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ushort) },
1782 .c_int_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.int) },
1783 .c_uint_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.uint) },
1784 .c_long_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.long) },
1785 .c_ulong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulong) },
1786 .c_longlong_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.longlong) },
1787 .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulonglong) },
1833 .c_char_type => return .{ .signedness = target.cCharSignedness().?, .bits = target.cTypeBitSize(.char).? },
1834 .c_short_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.short).? },
1835 .c_ushort_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ushort).? },
1836 .c_int_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.int).? },
1837 .c_uint_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.uint).? },
1838 .c_long_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.long).? },
1839 .c_ulong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulong).? },
1840 .c_longlong_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.longlong).? },
1841 .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulonglong).? },
17881842 else => switch (ip.indexToKey(ty.toIntern())) {
17891843 .int_type => |int_type| return int_type,
17901844 .struct_type => {
......@@ -1882,7 +1936,7 @@ pub fn floatBits(ty: Type, target: *const Target) u16 {
18821936 .f64_type => 64,
18831937 .f80_type => 80,
18841938 .f128_type, .comptime_float_type => 128,
1885 .c_longdouble_type => target.cTypeBitSize(.longdouble),
1939 .c_longdouble_type => target.cTypeBitSize(.longdouble).?,
18861940
18871941 else => unreachable,
18881942 };
......@@ -2147,13 +2201,6 @@ pub fn isVector(ty: Type, zcu: *const Zcu) bool {
21472201 return ty.zigTypeTag(zcu) == .vector;
21482202}
21492203
2150/// Returns 0 if not a vector, otherwise returns @bitSizeOf(Element) * vector_len.
2151pub fn totalVectorBits(ty: Type, zcu: *Zcu) u64 {
2152 if (!ty.isVector(zcu)) return 0;
2153 const v = zcu.intern_pool.indexToKey(ty.toIntern()).vector_type;
2154 return v.len * Type.fromInterned(v.child).bitSize(zcu);
2155}
2156
21572204pub fn isArrayOrVector(ty: Type, zcu: *const Zcu) bool {
21582205 return switch (ty.zigTypeTag(zcu)) {
21592206 .array, .vector => true,
......@@ -2416,34 +2463,6 @@ pub fn explicitFieldAlignment(ty: Type, index: usize, zcu: *const Zcu) Alignment
24162463 };
24172464}
24182465
2419/// Returns the alignment a struct field of type `field_ty` will be given if no alignment is
2420/// explicitly specified. However, in an `extern struct`, a higher alignment may be available due
2421/// to the struct's full layout (i.e. a field might coincidentally be more aligned).
2422///
2423/// Asserts that the layout of `field_ty` is resolved. Asserts that `layout` is not `.@"packed"`.
2424pub fn defaultStructFieldAlignment(
2425 field_ty: Type,
2426 layout: std.lang.Type.ContainerLayout,
2427 zcu: *const Zcu,
2428) Alignment {
2429 const overalign_big_int = switch (layout) {
2430 .@"packed" => unreachable,
2431 .auto => zcu.getTarget().ofmt == .c,
2432 .@"extern" => true,
2433 };
2434 const abi_align = field_ty.abiAlignment(zcu);
2435 assert(abi_align != .none);
2436 // We check for anything over 64 here, because the C backend will lower e.g. u64 to a 128-bit
2437 // integer, which has 16-byte alignment.
2438 if (overalign_big_int and
2439 ((field_ty.isAbiInt(zcu) and field_ty.intInfo(zcu).bits > 64) or
2440 (field_ty.toIntern() == .f80_type and zcu.getTarget().cTypeBitSize(.longdouble) != 80)))
2441 {
2442 return abi_align.maxStrict(if (zcu.getTarget().cpu.arch == .s390x) .@"8" else .@"16");
2443 }
2444 return abi_align;
2445}
2446
24472466pub fn structFieldDefaultValue(ty: Type, index: usize, zcu: *const Zcu) ?Value {
24482467 const ip = &zcu.intern_pool;
24492468 switch (ip.indexToKey(ty.toIntern())) {
......@@ -2961,8 +2980,7 @@ pub fn fieldPtrType(ptr_ty: Type, field_index: u32, pt: Zcu.PerThread) Allocator
29612980 }
29622981 const actual_field_align = switch (field_align) {
29632982 .none => switch (ip.indexToKey(aggregate_ty.toIntern())) {
2964 .tuple_type, .union_type => field_ty.abiAlignment(zcu),
2965 .struct_type => field_ty.defaultStructFieldAlignment(.auto, zcu),
2983 .struct_type, .tuple_type, .union_type => field_ty.abiAlignment(zcu),
29662984 .ptr_type => Type.usize.abiAlignment(zcu),
29672985 else => unreachable,
29682986 },
......@@ -3122,7 +3140,6 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool
31223140
31233141 .@"opaque",
31243142 .bool,
3125 .float,
31263143 .@"anyframe",
31273144 => true,
31283145
......@@ -3144,6 +3161,10 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool
31443161 24, 48 => zcu.getTarget().cpu.arch == .ez80,
31453162 else => false,
31463163 },
3164 .float => switch (ty.floatBits(zcu.getTarget())) {
3165 else => true,
3166 80 => zcu.getTarget().cTypeBitSize(.longdouble) == 80,
3167 },
31473168 .@"fn" => {
31483169 if (position != .other) return false;
31493170 return validateExternCallconv(ty.fnCallingConvention(zcu));
......@@ -3600,5 +3621,5 @@ pub fn smallestUnsignedBits(max: u64) u16 {
36003621pub const packed_struct_layout_version = 2;
36013622
36023623fn cTypeAlign(target: *const Target, c_type: Target.CType) Alignment {
3603 return Alignment.fromByteUnits(target.cTypeAlignment(c_type));
3624 return .fromByteUnits(target.cTypeAlignment(c_type).?);
36043625}
src/Value.zig+2-7
......@@ -611,12 +611,7 @@ pub fn toFloat(val: Value, comptime T: type, zcu: *const Zcu) T {
611611 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {
612612 .int => |int| switch (int.storage) {
613613 .big_int => |big_int| big_int.toFloat(T, .nearest_even)[0],
614 inline .u64, .i64 => |x| {
615 if (T == f80) {
616 @panic("TODO we can't lower this properly on non-x86 llvm backend yet");
617 }
618 return @floatFromInt(x);
619 },
614 inline .u64, .i64 => |x| @floatFromInt(x),
620615 },
621616 .float => |float| switch (float.storage) {
622617 inline else => |x| @floatCast(x),
......@@ -959,7 +954,7 @@ pub fn anyScalarIsZero(val: Value, zcu: *Zcu) bool {
959954 .bytes => |str| {
960955 const len = Type.fromInterned(agg.ty).vectorLen(zcu);
961956 const slice = str.toSlice(len, &zcu.intern_pool);
962 return std.mem.indexOfScalar(u8, slice, 0) != null;
957 return std.mem.findScalar(u8, slice, 0) != null;
963958 },
964959 .elems => |elems| {
965960 for (elems) |elem| {
src/Zcu.zig+41-29
......@@ -182,7 +182,10 @@ analysis_in_progress: std.array_hash_map.Auto(AnalUnit, ?*const DependencyReason
182182/// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator.
183183failed_analysis: std.array_hash_map.Auto(AnalUnit, *ErrorMsg) = .empty,
184184/// This `AnalUnit` failed semantic analysis because it required analysis of another `AnalUnit` which itself failed.
185transitive_failed_analysis: std.array_hash_map.Auto(AnalUnit, void) = .empty,
185transitive_failed_analysis: std.array_hash_map.Auto(
186 AnalUnit,
187 if (build_options.enable_debug_extensions) TransitiveFailureReason else void,
188) = .empty,
186189/// This `Nav` succeeded analysis, but failed codegen.
187190/// This may be a simple "value" `Nav`, or it may be a function.
188191/// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator.
......@@ -351,6 +354,18 @@ pub const DependencyReason = struct {
351354 type_layout_reason: Sema.type_resolution.LayoutResolveReason,
352355};
353356
357/// These are not required for anything, but when the compiler is built with debug extensions, we
358/// store these in `Zcu.transitive_failed_analysis` and surface them in the incremental debug server
359/// (see `src/IncrementalDebugServer.zig`) because they are a useful debugging aid for bugs in
360/// incremental compilation.
361pub const TransitiveFailureReason = union(enum) {
362 astgen_error,
363 dependency_loop,
364 lost_tracking: InternPool.TrackedInst.Index,
365 failed_unit: AnalUnit,
366 func_nav_val_changed: InternPool.Index,
367};
368
354369pub const IncrementalDebugState = struct {
355370 /// All container types in the ZCU, even dead ones.
356371 /// Value is the generation the type was created on.
......@@ -488,6 +503,7 @@ pub const StdLangDecl = enum {
488503 @"panic.castToNull",
489504 @"panic.incorrectAlignment",
490505 @"panic.invalidErrorCode",
506 @"panic.unexpectedErrorCode",
491507 @"panic.integerOutOfBounds",
492508 @"panic.integerOverflow",
493509 @"panic.shlOverflow",
......@@ -502,6 +518,7 @@ pub const StdLangDecl = enum {
502518 @"panic.copyLenMismatch",
503519 @"panic.memcpyAlias",
504520 @"panic.noreturnReturned",
521 @"panic.loadUninstantiableType",
505522
506523 VaList,
507524
......@@ -577,6 +594,7 @@ pub const StdLangDecl = enum {
577594 .@"panic.castToNull",
578595 .@"panic.incorrectAlignment",
579596 .@"panic.invalidErrorCode",
597 .@"panic.unexpectedErrorCode",
580598 .@"panic.integerOutOfBounds",
581599 .@"panic.integerOverflow",
582600 .@"panic.shlOverflow",
......@@ -591,6 +609,7 @@ pub const StdLangDecl = enum {
591609 .@"panic.copyLenMismatch",
592610 .@"panic.memcpyAlias",
593611 .@"panic.noreturnReturned",
612 .@"panic.loadUninstantiableType",
594613 => .func,
595614 };
596615 }
......@@ -633,7 +652,7 @@ pub const StdLangDecl = enum {
633652 return switch (decl) {
634653 inline else => |tag| {
635654 const name = @tagName(tag);
636 const split = (comptime std.mem.lastIndexOfScalar(u8, name, '.')) orelse return .{ .direct = name };
655 const split = (comptime std.mem.findScalarLast(u8, name, '.')) orelse return .{ .direct = name };
637656 const parent = @field(StdLangDecl, name[0..split]);
638657 comptime assert(@backingInt(parent) < @backingInt(tag)); // dependencies ordered correctly
639658 return .{ .nested = .{ parent, name[split + 1 ..] } };
......@@ -664,6 +683,7 @@ pub const SimplePanicId = enum {
664683 copy_len_mismatch,
665684 memcpy_alias,
666685 noreturn_returned,
686 load_uninstantiable_type,
667687
668688 pub fn toStdLangDecl(id: SimplePanicId) StdLangDecl {
669689 return switch (id) {
......@@ -687,6 +707,7 @@ pub const SimplePanicId = enum {
687707 .copy_len_mismatch => .@"panic.copyLenMismatch",
688708 .memcpy_alias => .@"panic.memcpyAlias",
689709 .noreturn_returned => .@"panic.noreturnReturned",
710 .load_uninstantiable_type => .@"panic.loadUninstantiableType",
690711 // zig fmt: on
691712 };
692713 }
......@@ -2808,13 +2829,13 @@ pub const LazySrcLoc = struct {
28082829 }
28092830};
28102831
2811pub const SemaError = error{ OutOfMemory, Canceled, AnalysisFail };
2832pub const SemaError = error{ OutOfMemory, Canceled, AlreadyReported };
28122833pub const CompileError = error{
28132834 OutOfMemory,
28142835 /// The compilation update is no longer desired.
28152836 Canceled,
28162837 /// When this is returned, the compile error for the failure has already been recorded.
2817 AnalysisFail,
2838 AlreadyReported,
28182839 /// In a comptime scope, a return instruction was encountered. This error is only seen when
28192840 /// doing a comptime function call.
28202841 ComptimeReturn,
......@@ -2825,6 +2846,11 @@ pub const CompileError = error{
28252846
28262847pub fn init(zcu: *Zcu, gpa: Allocator, io: Io, thread_count: usize) !void {
28272848 try zcu.intern_pool.init(gpa, io, thread_count);
2849}
2850
2851/// It is valid to not call this function before `deinit` in error paths.
2852/// Requires the fields on `zcu.comp` to already be initialized.
2853pub fn initAfterCompilation(zcu: *Zcu) void {
28282854 zcu.initTracyPlots();
28292855}
28302856
......@@ -4273,7 +4299,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.array_hash_map.Auto(Ana
42734299 const fqn_slice = nav.fqn.toSlice(ip);
42744300 if (comp.test_filters.len > 0) {
42754301 for (comp.test_filters) |test_filter| {
4276 if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break;
4302 if (std.mem.find(u8, fqn_slice, test_filter) != null) break;
42774303 } else break :a false;
42784304 }
42794305 break :a true;
......@@ -4597,6 +4623,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)
45974623 .x86_64_regcall_v3_sysv,
45984624 .x86_64_regcall_v4_win,
45994625 .x86_64_interrupt,
4626 .x86_64_preserve_none,
46004627 .x86_fastcall,
46014628 .x86_thiscall,
46024629 .x86_vectorcall,
......@@ -4605,6 +4632,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)
46054632 .x86_interrupt,
46064633 .aarch64_vfabi,
46074634 .aarch64_vfabi_sve,
4635 .aarch64_preserve_none,
46084636 .arm_aapcs,
46094637 .csky_interrupt,
46104638 .riscv64_lp64_v,
......@@ -4612,43 +4640,26 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)
46124640 .m68k_rtd,
46134641 .m68k_interrupt,
46144642 .msp430_interrupt,
4615 => |opts| opts.incoming_stack_alignment == null,
4616
46174643 .arm_aapcs_vfp,
4618 => |opts| opts.incoming_stack_alignment == null,
4619
46204644 .arc_interrupt,
4621 => |opts| opts.incoming_stack_alignment == null,
4622
46234645 .arm_interrupt,
4624 => |opts| opts.incoming_stack_alignment == null,
4625
46264646 .microblaze_interrupt,
4627 => |opts| opts.incoming_stack_alignment == null,
4628
46294647 .mips_interrupt,
46304648 .mips64_interrupt,
4631 => |opts| opts.incoming_stack_alignment == null,
4632
46334649 .riscv32_interrupt,
46344650 .riscv64_interrupt,
4635 => |opts| opts.incoming_stack_alignment == null,
4636
46374651 .sh_interrupt,
4638 => |opts| opts.incoming_stack_alignment == null,
4652 .avr_interrupt,
4653 .avr_signal,
4654 .ez80_tiflags,
4655 .naked,
4656 => true, // incoming stack alignment supported
46394657
46404658 .x86_sysv,
46414659 .x86_win,
4660 .x86_mingw,
46424661 .x86_stdcall,
4643 => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0,
4644
4645 .avr_interrupt,
4646 .avr_signal,
4647 => true,
4648
4649 .ez80_tiflags => true,
4650
4651 .naked => true,
4662 => |opts| opts.register_params == 0, // incoming stack alignment supported
46524663
46534664 else => false,
46544665 };
......@@ -4673,6 +4684,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)
46734684 .stage2_x86 => switch (cc) {
46744685 .x86_sysv,
46754686 .x86_win,
4687 .x86_mingw,
46764688 => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0,
46774689 .naked => true,
46784690 else => false,
src/Zcu/PerThread.zig+96-93
......@@ -320,7 +320,7 @@ pub fn update(
320320 // Zig compilation pipeline. It selects some `AnalUnit` which we know needs to be analyzed,
321321 // and analyzes it, which may in turn discover more `AnalUnit`s which we need to analyze.
322322 while (try zcu.findOutdatedToAnalyze()) |unit| {
323 const maybe_err: Zcu.SemaError!void = switch (unit.unwrap()) {
323 const maybe_err: UpdateUnitError!void = switch (unit.unwrap()) {
324324 .@"comptime" => |cu| pt.ensureComptimeUnitUpToDate(cu),
325325 .nav_ty => |nav| pt.ensureNavTypeUpToDate(nav, null),
326326 .nav_val => |nav| pt.ensureNavValUpToDate(nav, null),
......@@ -332,7 +332,7 @@ pub fn update(
332332 error.Canceled,
333333 => |e| return e,
334334
335 error.AnalysisFail => {}, // already reported
335 error.AnalysisFail => {},
336336 };
337337 break :res pt.ensureStructDefaultsUpToDate(.fromInterned(ty), null);
338338 },
......@@ -344,7 +344,7 @@ pub fn update(
344344 error.Canceled,
345345 => |e| return e,
346346
347 error.AnalysisFail => {}, // already reported
347 error.AnalysisFail => {},
348348 };
349349 }
350350}
......@@ -455,7 +455,7 @@ fn detectEmbedFileUpdate(comp: *Compilation, tid: Zcu.PerThread.Id, ef_index: Zc
455455
456456/// Ensures that `file` has up-to-date ZIR. If not, loads the ZIR cache or runs
457457/// AstGen as needed. Also updates `file.status`. Does not assume that `file.mod`
458/// is populated. Does not return `error.AnalysisFail` on AstGen failures.
458/// is populated. Returns success even if the file has AstGen errors.
459459pub fn updateFile(
460460 pt: Zcu.PerThread,
461461 file_index: Zcu.File.Index,
......@@ -876,6 +876,7 @@ fn updateZirRefs(pt: Zcu.PerThread) (Io.Cancelable || Allocator.Error)!void {
876876 const old_line = old_zir.getDeclaration(old_inst).src_line;
877877 const new_line = new_zir.getDeclaration(new_inst).src_line;
878878 if (old_line != new_line) {
879 comp.link_prog_node.increaseEstimatedTotalItems(1);
879880 try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .debug_update_line_number = tracked_inst_index });
880881 }
881882 },
......@@ -1035,6 +1036,11 @@ pub fn ensureFilePopulated(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Alloc
10351036 zcu.setFileRootType(file_index, wip.finish(ip, new_namespace_index));
10361037}
10371038
1039const UpdateUnitError = Allocator.Error || Io.Cancelable || error{
1040 /// Semantic analysis of this `AnalUnit` failed.
1041 AnalysisFail,
1042};
1043
10381044/// Ensures that all memoized state on `Zcu` is up-to-date, performing re-analysis if necessary.
10391045/// Returns `error.AnalysisFail` if an analysis error is encountered; the caller is free to ignore
10401046/// this, since the error is already registered, but it must not use the value of memoized fields.
......@@ -1043,7 +1049,7 @@ pub fn ensureMemoizedStateUpToDate(
10431049 stage: InternPool.MemoizedStateStage,
10441050 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
10451051 reason: ?*const Zcu.DependencyReason,
1046) Zcu.SemaError!void {
1052) UpdateUnitError!void {
10471053 const zcu = pt.zcu;
10481054 const gpa = zcu.gpa;
10491055
......@@ -1077,15 +1083,7 @@ pub fn ensureMemoizedStateUpToDate(
10771083 const any_changed: bool, const new_failed: bool = if (pt.analyzeMemoizedState(stage, reason)) |any_changed|
10781084 .{ any_changed or prev_failed, false }
10791085 else |err| switch (err) {
1080 error.AnalysisFail => res: {
1081 if (!zcu.failed_analysis.contains(unit)) {
1082 // If this unit caused the error, it would have an entry in `failed_analysis`.
1083 // Since it does not, this must be a transitive failure.
1084 try zcu.transitive_failed_analysis.put(gpa, unit, {});
1085 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(unit)});
1086 }
1087 break :res .{ !prev_failed, true };
1088 },
1086 error.AlreadyReported => .{ !prev_failed, true },
10891087 error.OutOfMemory => {
10901088 // TODO: same as for `ensureComptimeUnitUpToDate` etc
10911089 return error.OutOfMemory;
......@@ -1153,7 +1151,7 @@ fn analyzeMemoizedState(
11531151/// Ensures that the state of the given `ComptimeUnit` is fully up-to-date, performing re-analysis
11541152/// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is
11551153/// free to ignore this, since the error is already registered.
1156pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.SemaError!void {
1154pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) UpdateUnitError!void {
11571155 const zcu = pt.zcu;
11581156 const gpa = zcu.gpa;
11591157
......@@ -1194,15 +1192,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU
11941192 defer unit_tracking.end(zcu);
11951193
11961194 return pt.analyzeComptimeUnit(cu_id) catch |err| switch (err) {
1197 error.AnalysisFail => {
1198 if (!zcu.failed_analysis.contains(anal_unit)) {
1199 // If this unit caused the error, it would have an entry in `failed_analysis`.
1200 // Since it does not, this must be a transitive failure.
1201 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
1202 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
1203 }
1204 return error.AnalysisFail;
1205 },
1195 error.AlreadyReported => return error.AnalysisFail,
12061196 error.OutOfMemory => {
12071197 // TODO: it's unclear how to gracefully handle this.
12081198 // To report the error cleanly, we need to add a message to `failed_analysis` and a
......@@ -1220,8 +1210,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU
12201210
12211211/// Re-analyzes a `ComptimeUnit`. The unit has already been determined to be out-of-date, and old
12221212/// side effects (exports/references/etc) have been dropped. If semantic analysis fails, this
1223/// function will return `error.AnalysisFail`, and it is the caller's reponsibility to add an entry
1224/// to `transitive_failed_analysis` if necessary.
1213/// function will return `error.AlreadyReported`.
12251214fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.CompileError!void {
12261215 const zcu = pt.zcu;
12271216 const ip = &zcu.intern_pool;
......@@ -1238,7 +1227,14 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu
12381227 defer tracy_trace.end();
12391228 tracy_trace.addTextFmt("cu_id={d}", .{cu_id});
12401229
1241 const inst_resolved = comptime_unit.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
1230 const inst_resolved = comptime_unit.zir_index.resolveFull(ip) orelse {
1231 try zcu.transitive_failed_analysis.putNoClobber(
1232 gpa,
1233 anal_unit,
1234 if (build_options.enable_debug_extensions) .{ .lost_tracking = comptime_unit.zir_index },
1235 );
1236 return error.AlreadyReported;
1237 };
12421238 const file = zcu.fileByIndex(inst_resolved.file);
12431239 const zir = file.zir.?;
12441240
......@@ -1313,7 +1309,7 @@ pub fn ensureTypeLayoutUpToDate(
13131309 ty: Type,
13141310 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
13151311 reason: ?*const Zcu.DependencyReason,
1316) Zcu.SemaError!void {
1312) UpdateUnitError!void {
13171313 const zcu = pt.zcu;
13181314 const ip = &zcu.intern_pool;
13191315 const comp = zcu.comp;
......@@ -1398,15 +1394,7 @@ pub fn ensureTypeLayoutUpToDate(
13981394 const new_failed: bool = if (result) failed: {
13991395 break :failed false;
14001396 } else |err| switch (err) {
1401 error.AnalysisFail => failed: {
1402 if (!zcu.failed_analysis.contains(anal_unit)) {
1403 // If this unit caused the error, it would have an entry in `failed_analysis`.
1404 // Since it does not, this must be a transitive failure.
1405 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
1406 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
1407 }
1408 break :failed true;
1409 },
1397 error.AlreadyReported => true,
14101398 error.OutOfMemory,
14111399 error.Canceled,
14121400 => |e| return e,
......@@ -1441,7 +1429,7 @@ pub fn ensureStructDefaultsUpToDate(
14411429 ty: Type,
14421430 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
14431431 reason: ?*const Zcu.DependencyReason,
1444) Zcu.SemaError!void {
1432) UpdateUnitError!void {
14451433 const zcu = pt.zcu;
14461434 const ip = &zcu.intern_pool;
14471435 const comp = zcu.comp;
......@@ -1512,15 +1500,7 @@ pub fn ensureStructDefaultsUpToDate(
15121500 const new_failed: bool = if (Sema.type_resolution.resolveStructDefaults(&sema, ty)) failed: {
15131501 break :failed false;
15141502 } else |err| switch (err) {
1515 error.AnalysisFail => failed: {
1516 if (!zcu.failed_analysis.contains(anal_unit)) {
1517 // If this unit caused the error, it would have an entry in `failed_analysis`.
1518 // Since it does not, this must be a transitive failure.
1519 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
1520 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
1521 }
1522 break :failed true;
1523 },
1503 error.AlreadyReported => true,
15241504 error.OutOfMemory,
15251505 error.Canceled,
15261506 => |e| return e,
......@@ -1546,7 +1526,7 @@ pub fn ensureNavValUpToDate(
15461526 nav_id: InternPool.Nav.Index,
15471527 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
15481528 reason: ?*const Zcu.DependencyReason,
1549) Zcu.SemaError!void {
1529) UpdateUnitError!void {
15501530 const zcu = pt.zcu;
15511531 const gpa = zcu.gpa;
15521532 const ip = &zcu.intern_pool;
......@@ -1593,15 +1573,7 @@ pub fn ensureNavValUpToDate(
15931573 false,
15941574 };
15951575 } else |err| switch (err) {
1596 error.AnalysisFail => res: {
1597 if (!zcu.failed_analysis.contains(anal_unit)) {
1598 // If this unit caused the error, it would have an entry in `failed_analysis`.
1599 // Since it does not, this must be a transitive failure.
1600 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
1601 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
1602 }
1603 break :res .{ !prev_failed, true };
1604 },
1576 error.AlreadyReported => .{ !prev_failed, true },
16051577 error.OutOfMemory => {
16061578 // TODO: it's unclear how to gracefully handle this.
16071579 // To report the error cleanly, we need to add a message to `failed_analysis` and a
......@@ -1654,7 +1626,14 @@ fn analyzeNavVal(
16541626 tracy_trace.addText(old_nav.fqn.toSlice(ip));
16551627 tracy_trace.addTextFmt("nav_id={d}", .{nav_id});
16561628
1657 const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
1629 const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse {
1630 try zcu.transitive_failed_analysis.putNoClobber(
1631 gpa,
1632 anal_unit,
1633 if (build_options.enable_debug_extensions) .{ .lost_tracking = old_nav.analysis.?.zir_index },
1634 );
1635 return error.AlreadyReported;
1636 };
16581637 const file = zcu.fileByIndex(inst_resolved.file);
16591638 const zir = file.zir.?;
16601639 const zir_decl = zir.getDeclaration(inst_resolved.inst);
......@@ -1915,7 +1894,7 @@ pub fn ensureNavTypeUpToDate(
19151894 nav_id: InternPool.Nav.Index,
19161895 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
19171896 reason: ?*const Zcu.DependencyReason,
1918) Zcu.SemaError!void {
1897) UpdateUnitError!void {
19191898 const zcu = pt.zcu;
19201899 const gpa = zcu.gpa;
19211900 const ip = &zcu.intern_pool;
......@@ -1962,15 +1941,7 @@ pub fn ensureNavTypeUpToDate(
19621941 false,
19631942 };
19641943 } else |err| switch (err) {
1965 error.AnalysisFail => res: {
1966 if (!zcu.failed_analysis.contains(anal_unit)) {
1967 // If this unit caused the error, it would have an entry in `failed_analysis`.
1968 // Since it does not, this must be a transitive failure.
1969 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
1970 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
1971 }
1972 break :res .{ !prev_failed, true };
1973 },
1944 error.AlreadyReported => .{ !prev_failed, true },
19741945 error.OutOfMemory => {
19751946 // TODO: it's unclear how to gracefully handle this.
19761947 // To report the error cleanly, we need to add a message to `failed_analysis` and a
......@@ -2023,7 +1994,14 @@ fn analyzeNavType(
20231994 tracy_trace.addText(old_nav.fqn.toSlice(ip));
20241995 tracy_trace.addTextFmt("nav_id={d}", .{nav_id});
20251996
2026 const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
1997 const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse {
1998 try zcu.transitive_failed_analysis.putNoClobber(
1999 gpa,
2000 anal_unit,
2001 if (build_options.enable_debug_extensions) .{ .lost_tracking = old_nav.analysis.?.zir_index },
2002 );
2003 return error.AlreadyReported;
2004 };
20272005 const file = zcu.fileByIndex(inst_resolved.file);
20282006 const zir = file.zir.?;
20292007
......@@ -2159,7 +2137,7 @@ pub fn ensureFuncBodyUpToDate(
21592137 func_index: InternPool.Index,
21602138 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
21612139 reason: ?*const Zcu.DependencyReason,
2162) Zcu.SemaError!void {
2140) UpdateUnitError!void {
21632141 dev.check(.sema);
21642142
21652143 const zcu = pt.zcu;
......@@ -2203,18 +2181,10 @@ pub fn ensureFuncBodyUpToDate(
22032181 const ies_outdated, const new_failed = if (pt.analyzeFuncBody(func_index, reason)) |result|
22042182 .{ prev_failed or result.ies_outdated, false }
22052183 else |err| switch (err) {
2206 error.AnalysisFail => res: {
2207 if (!zcu.failed_analysis.contains(anal_unit)) {
2208 // If this function caused the error, it would have an entry in `failed_analysis`.
2209 // Since it does not, this must be a transitive failure.
2210 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
2211 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
2212 }
2213 // We consider the IES to be outdated if the function previously succeeded analysis; in this case,
2214 // we need to re-analyze dependants to ensure they hit a transitive error here, rather than reporting
2215 // a different error later (which may now be invalid).
2216 break :res .{ !prev_failed, true };
2217 },
2184 // We consider the IES to be outdated if the function previously succeeded analysis; in this case,
2185 // we need to re-analyze dependants to ensure they hit a transitive error here, rather than reporting
2186 // a different error later (which may now be invalid).
2187 error.AlreadyReported => .{ !prev_failed, true },
22182188 error.OutOfMemory => {
22192189 // TODO: it's unclear how to gracefully handle this.
22202190 // To report the error cleanly, we need to add a message to `failed_analysis` and a
......@@ -3206,7 +3176,7 @@ const ScanDeclIter = struct {
32063176 if (is_named and comp.test_filters.len > 0) {
32073177 const fqn_slice = fqn.toSlice(ip);
32083178 for (comp.test_filters) |test_filter| {
3209 if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break;
3179 if (std.mem.find(u8, fqn_slice, test_filter) != null) break;
32103180 } else break :a false;
32113181 }
32123182 try zcu.test_functions.put(gpa, nav, {});
......@@ -3292,9 +3262,7 @@ fn analyzeFuncBodyInner(
32923262 defer sema.deinit();
32933263
32943264 // Every runtime function has a dependency on the source of the Decl it originates from.
3295 // It also depends on the value of its owner Decl.
32963265 try sema.declareDependency(.{ .src_hash = decl_analysis.zir_index });
3297 try sema.declareDependency(.{ .nav_val = func.owner_nav });
32983266
32993267 // Make sure that the declaration `Nav` still refers to this function (or its generic owner).
33003268 // This will not be the case if the incremental update has changed a function type or turned a
......@@ -3305,15 +3273,23 @@ fn analyzeFuncBodyInner(
33053273 // If we *are* still owned by the right NAV, this analysis updates `zir_body_inst` if necessary.
33063274
33073275 if (func.generic_owner == .none) {
3308 try pt.ensureNavValUpToDate(func.owner_nav, reason);
3276 try sema.declareDependency(.{ .nav_val = func.owner_nav });
3277 pt.ensureNavValUpToDate(func.owner_nav, reason) catch |err| switch (err) {
3278 error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = .wrap(.{ .nav_val = func.owner_nav }) }),
3279 else => |e| return e,
3280 };
33093281 if (ip.getNav(func.owner_nav).resolved.?.value != func_index) {
3310 return error.AnalysisFail;
3282 return sema.failTransitive(.{ .func_nav_val_changed = func_index });
33113283 }
33123284 } else {
33133285 const go_nav = zcu.funcInfo(func.generic_owner).owner_nav;
3314 try pt.ensureNavValUpToDate(go_nav, reason);
3286 try sema.declareDependency(.{ .nav_val = go_nav });
3287 pt.ensureNavValUpToDate(go_nav, reason) catch |err| switch (err) {
3288 error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = .wrap(.{ .nav_val = go_nav }) }),
3289 else => |e| return e,
3290 };
33153291 if (ip.getNav(go_nav).resolved.?.value != func.generic_owner) {
3316 return error.AnalysisFail;
3292 return sema.failTransitive(.{ .func_nav_val_changed = func.generic_owner });
33173293 }
33183294 }
33193295
......@@ -3343,7 +3319,9 @@ fn analyzeFuncBodyInner(
33433319 };
33443320 defer inner_block.instructions.deinit(gpa);
33453321
3346 const fn_info = sema.code.getFnInfo(func.zirBodyInstUnordered(ip).resolve(ip) orelse return error.AnalysisFail);
3322 const fn_info = sema.code.getFnInfo(func.zirBodyInstUnordered(ip).resolve(ip) orelse {
3323 return sema.failTransitive(.{ .lost_tracking = func.zirBodyInstUnordered(ip) });
3324 });
33473325
33483326 // Here we are performing "runtime semantic analysis" for a function body, which means
33493327 // we must map the parameter ZIR instructions to `arg` AIR instructions.
......@@ -3520,6 +3498,25 @@ pub fn getErrorValueFromSlice(pt: Zcu.PerThread, name: []const u8) Allocator.Err
35203498 return pt.getErrorValue(try pt.zcu.intern_pool.getOrPutString(gpa, io, name));
35213499}
35223500
3501/// Asserts that `slice.len` is *not* undef.
3502pub fn sliceToArrayPtr(pt: Zcu.PerThread, slice: InternPool.Key.Slice) Allocator.Error!Value {
3503 const zcu = pt.zcu;
3504 const slice_info = Type.fromInterned(slice.ty).ptrInfo(zcu);
3505 const array_ty = try pt.arrayType(.{
3506 .len = Value.fromInterned(slice.len).toUnsignedInt(zcu),
3507 .child = slice_info.child,
3508 .sentinel = slice_info.sentinel,
3509 });
3510 const ptr_ty = try pt.ptrType(ptr_info: {
3511 var ptr_info = slice_info;
3512 ptr_info.flags.size = .one;
3513 ptr_info.child = array_ty.toIntern();
3514 ptr_info.sentinel = .none;
3515 break :ptr_info ptr_info;
3516 });
3517 return pt.getCoerced(.fromInterned(slice.ptr), ptr_ty);
3518}
3519
35233520/// Removes any entry from `Zcu.failed_files` associated with `file`. Acquires `Compilation.mutex` as needed.
35243521/// `file.zir` must be unchanged from the last update, as it is used to determine if there is such an entry.
35253522fn lockAndClearFileCompileError(pt: Zcu.PerThread, file_index: Zcu.File.Index, file: *Zcu.File) void {
......@@ -4377,12 +4374,18 @@ pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) (Io.Cancelable |
43774374 return result.index;
43784375}
43794376
4377const UpdateNamespaceError = Allocator.Error || Io.Cancelable || error{
4378 /// This namespace refers to a ZIR container declaration which no longer exists, so any code
4379 /// referencing it is guaranteed to be unreferenced on this update.
4380 LostZirContainerDecl,
4381};
4382
43804383/// Given a namespace, re-scan its declarations from the type definition if they have not
43814384/// yet been re-scanned on this update.
4382/// If the type declaration instruction has been lost, returns `error.AnalysisFail`.
4385/// If the type declaration instruction has been lost, returns `error.LostZirContainerDecl`.
43834386/// This will effectively short-circuit the caller, which will be semantic analysis of a
43844387/// guaranteed-unreferenced `AnalUnit`, to trigger a transitive analysis error.
4385pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace.Index) Zcu.SemaError!void {
4388pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace.Index) UpdateNamespaceError!void {
43864389 const zcu = pt.zcu;
43874390 const ip = &zcu.intern_pool;
43884391 const namespace = zcu.namespacePtr(namespace_index);
......@@ -4409,7 +4412,7 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace
44094412
44104413 // Namespace outdated -- re-scan the type if necessary.
44114414
4412 const inst_info = key.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
4415 const inst_info = key.zir_index.resolveFull(ip) orelse return error.LostZirContainerDecl;
44134416 const file = zcu.fileByIndex(inst_info.file);
44144417 const zir = &file.zir.?;
44154418
src/codegen.zig+196-30
......@@ -767,11 +767,9 @@ fn lowerNavRef(
767767 offset: u64,
768768) (Error || std.Io.Writer.Error)!void {
769769 const zcu = pt.zcu;
770 const gpa = zcu.gpa;
771770 const ip = &zcu.intern_pool;
772771 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;
773772 const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8);
774 const is_obj = lf.comp.config.output_mode == .Obj;
775773 const nav_ty = Type.fromInterned(ip.getNav(nav_index).resolved.?.type);
776774
777775 if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) and ip.getNav(nav_index).getExtern(ip) == null) {
......@@ -786,34 +784,7 @@ fn lowerNavRef(
786784 dev.check(link.File.Tag.wasm.devFeature());
787785 const wasm = lf.cast(.wasm).?;
788786 assert(reloc_parent == .none);
789 if (nav_ty.zigTypeTag(zcu) == .@"fn") {
790 const gop = try wasm.zcu_indirect_function_set.getOrPut(gpa, nav_index);
791 if (!gop.found_existing) gop.value_ptr.* = {};
792 if (is_obj) {
793 @panic("TODO add out_reloc for this");
794 } else {
795 try wasm.func_table_fixups.append(gpa, .{
796 .table_index = @fromBackingInt(@intCast(gop.index)),
797 .offset = @intCast(w.end),
798 });
799 }
800 } else {
801 if (is_obj) {
802 try wasm.out_relocs.append(gpa, .{
803 .offset = @intCast(w.end),
804 .pointee = .{ .symbol_index = try wasm.navSymbolIndex(nav_index) },
805 .tag = if (ptr_width_bytes == 4) .memory_addr_i32 else .memory_addr_i64,
806 .addend = @intCast(offset),
807 });
808 } else {
809 try wasm.nav_fixups.ensureUnusedCapacity(gpa, 1);
810 wasm.nav_fixups.appendAssumeCapacity(.{
811 .navs_exe_index = try wasm.refNavExe(nav_index),
812 .offset = @intCast(w.end),
813 .addend = @intCast(offset),
814 });
815 }
816 }
787 try wasm.addNavReloc(w.end, nav_index, nav_ty, @intCast(offset));
817788 try w.splatByteAll(0, ptr_width_bytes);
818789 return;
819790 },
......@@ -1124,6 +1095,201 @@ pub fn fieldOffset(ptr_agg_ty: Type, ptr_field_ty: Type, field_index: u32, zcu:
11241095 };
11251096}
11261097
1098pub const FlattenedItem = struct { offset: u64, type: ?Type };
1099pub fn flattenType(items_buf: []FlattenedItem, ty: Type, zcu: *Zcu, opts: struct {
1100 offset: u64 = 0,
1101 allow_arrays: bool = true,
1102 fn increaseOffset(opts: @This(), offset: u64) @This() {
1103 return .{
1104 .offset = opts.offset + offset,
1105 .allow_arrays = opts.allow_arrays,
1106 };
1107 }
1108}) ?[]FlattenedItem {
1109 const ip = &zcu.intern_pool;
1110 switch (ip.indexToKey(ty.toIntern())) {
1111 .int_type => |int_type| {
1112 if (int_type.bits == 0) return items_buf[0..0];
1113 if (items_buf.len < 1) return null;
1114 const items = items_buf[0..1];
1115 items.* = .{.{ .offset = opts.offset, .type = ty }};
1116 return items;
1117 },
1118 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1119 .one, .many, .c => {
1120 if (items_buf.len < 1) return null;
1121 const items = items_buf[0..1];
1122 items.* = .{.{ .offset = opts.offset, .type = ty }};
1123 return items;
1124 },
1125 .slice => {
1126 if (items_buf.len < 2) return null;
1127 const items = items_buf[0..2];
1128 const ptr_field_ty = ty.slicePtrFieldType(zcu);
1129 items.* = .{
1130 .{ .offset = opts.offset, .type = ptr_field_ty },
1131 .{ .offset = opts.offset + ptr_field_ty.abiSize(zcu), .type = .usize },
1132 };
1133 return items;
1134 },
1135 },
1136 .array_type => |array_type| {
1137 const len = array_type.lenIncludingSentinel();
1138 if (len == 0) return items_buf[0..0];
1139 const elem_ty: Type = .fromInterned(array_type.child);
1140 const elem_items = flattenType(items_buf, elem_ty, zcu, opts) orelse return null;
1141 if (elem_items.len == 0) return items_buf[0..0];
1142 if (!opts.allow_arrays) return null;
1143 const items_len, const items_overflow = @mulWithOverflow(elem_items.len, len);
1144 if (items_overflow != 0 or items_buf.len < items_len) return null;
1145 var items_index = elem_items.len;
1146 const elem_size = elem_ty.abiSize(zcu);
1147 var elem_offset: u64 = elem_size;
1148 while (items_index != items_len) : ({
1149 items_index += elem_items.len;
1150 elem_offset += elem_size;
1151 }) for (items_buf[items_index..][0..elem_items.len], elem_items) |*item, elem_item| {
1152 item.* = .{ .offset = elem_offset + elem_item.offset, .type = elem_item.type };
1153 };
1154 return items_buf[0..@intCast(items_len)];
1155 },
1156 .vector_type => |vector_type| {
1157 if (vector_type.len == 0) return items_buf[0..0];
1158 if (items_buf.len < 1) return null;
1159 const items = items_buf[0..1];
1160 items.* = .{.{ .offset = opts.offset, .type = ty }};
1161 return items;
1162 },
1163 .opt_type, .error_union_type => return null,
1164 .simple_type => |simple_type| switch (simple_type) {
1165 .f16,
1166 .f32,
1167 .f64,
1168 .f80,
1169 .f128,
1170 .usize,
1171 .isize,
1172 .c_char,
1173 .c_short,
1174 .c_ushort,
1175 .c_int,
1176 .c_uint,
1177 .c_long,
1178 .c_ulong,
1179 .c_longlong,
1180 .c_ulonglong,
1181 .c_longdouble,
1182 .bool,
1183 .anyerror,
1184 => {
1185 if (items_buf.len < 1) return null;
1186 const items = items_buf[0..1];
1187 items.* = .{.{ .offset = opts.offset, .type = ty }};
1188 return items;
1189 },
1190 .anyopaque, .noreturn => return null,
1191 .void,
1192 .type,
1193 .comptime_int,
1194 .comptime_float,
1195 .null,
1196 .undefined,
1197 .enum_literal,
1198 => return items_buf[0..0],
1199 .adhoc_inferred_error_set, .generic_poison => unreachable,
1200 },
1201 .struct_type => {
1202 const loaded_struct = ip.loadStructType(ty.toIntern());
1203 switch (loaded_struct.layout) {
1204 .auto, .@"extern" => {},
1205 .@"packed" => return flattenType(items_buf, .fromInterned(
1206 loaded_struct.packed_backing_int_type,
1207 ), zcu, opts),
1208 }
1209 var items_len: usize = 0;
1210 var offset: u64 = 0;
1211 var field_it = loaded_struct.iterateRuntimeOrder(ip);
1212 while (field_it.next()) |field_index| {
1213 const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
1214 const field_offset = loaded_struct.field_offsets.get(ip)[field_index];
1215 if (field_offset - offset > 0 and
1216 (items_len == 0 or items_buf[items_len - 1].type != null))
1217 {
1218 if (items_len == items_buf.len) return null;
1219 items_buf[items_len] = .{ .offset = offset, .type = null };
1220 items_len += 1;
1221 }
1222 items_len += (flattenType(items_buf[items_len..], field_ty, zcu, opts.increaseOffset(
1223 field_offset,
1224 )) orelse return null).len;
1225 offset = field_offset + field_ty.abiSize(zcu);
1226 }
1227 if (ty.abiSize(zcu) - offset > 0 and
1228 (items_len == 0 or items_buf[items_len - 1].type != null))
1229 {
1230 if (items_len == items_buf.len) return null;
1231 items_buf[items_len] = .{ .offset = offset, .type = null };
1232 items_len += 1;
1233 }
1234 return items_buf[0..items_len];
1235 },
1236 .tuple_type => |tuple_type| {
1237 if (items_buf.len < tuple_type.types.len) return null;
1238 var items_len: usize = 0;
1239 var offset: u64 = 0;
1240 for (tuple_type.types.get(ip)) |field_ty_ip| {
1241 const field_ty: Type = .fromInterned(field_ty_ip);
1242 offset = field_ty.abiAlignment(zcu).forward(offset);
1243 items_len += (flattenType(items_buf[items_len..], field_ty, zcu, opts.increaseOffset(
1244 offset,
1245 )) orelse return null).len;
1246 offset += field_ty.abiSize(zcu);
1247 }
1248 return items_buf[0..items_len];
1249 },
1250 .union_type => {
1251 const loaded_union = ip.loadUnionType(ty.toIntern());
1252 return switch (loaded_union.layout) {
1253 .auto, .@"extern" => return null,
1254 .@"packed" => return flattenType(items_buf, .fromInterned(
1255 loaded_union.packed_backing_int_type,
1256 ), zcu, opts),
1257 };
1258 },
1259 .opaque_type, .spirv_type, .func_type => return null,
1260 .enum_type => return flattenType(items_buf, .fromInterned(
1261 ip.loadEnumType(ty.toIntern()).int_tag_type,
1262 ), zcu, opts),
1263 .error_set_type, .inferred_error_set_type => {
1264 if (items_buf.len < 1) return null;
1265 const items = items_buf[0..1];
1266 items.* = .{.{ .offset = opts.offset, .type = ty }};
1267 return items;
1268 },
1269 .anyframe_type,
1270 // values, not types
1271 .undef,
1272 .simple_value,
1273 .@"extern",
1274 .func,
1275 .int,
1276 .err,
1277 .error_union,
1278 .enum_literal,
1279 .enum_tag,
1280 .float,
1281 .ptr,
1282 .slice,
1283 .opt,
1284 .aggregate,
1285 .un,
1286 .bitpack,
1287 // memoization, not types
1288 .memoized_call,
1289 => unreachable,
1290 }
1291}
1292
11271293test {
11281294 _ = aarch64;
11291295}
src/codegen/aarch64/Assemble.zig+1-1
......@@ -163,7 +163,7 @@ const matchers = matchers: {
163163 arg.* = zonCast(param_type.?, instruction.encode[encode_index], symbols);
164164 return @call(.auto, encode, args);
165165 } else if (pattern_token[0] == '<') {
166 const symbol_name = comptime pattern_token[1 .. std.mem.indexOfScalarPos(u8, pattern_token, 1, '|') orelse
166 const symbol_name = comptime pattern_token[1 .. std.mem.findScalarPos(u8, pattern_token, 1, '|') orelse
167167 pattern_token.len - 1];
168168 const symbol = @field(Symbol, symbol_name);
169169 const symbol_ptr = &@field(symbols, symbol_name);
src/codegen/aarch64/Mir.zig+2-2
......@@ -70,8 +70,8 @@ pub fn emit(
7070
7171 const func_align = switch (nav.resolved.?.@"align") {
7272 .none => switch (mod.optimize_mode) {
73 .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),
74 .ReleaseSmall => target_util.minFunctionAlignment(target),
73 .debug, .safe, .fast => target_util.defaultFunctionAlignment(target),
74 .small => target_util.minFunctionAlignment(target),
7575 },
7676 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
7777 };
src/codegen/aarch64/Select.zig+23-27
......@@ -2099,7 +2099,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
20992099 32 => "truncf",
21002100 64 => "trunc",
21012101 80 => "__truncx",
2102 128 => "truncq",
2102 128 => "truncf128",
21032103 },
21042104 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
21052105 });
......@@ -2113,7 +2113,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
21132113 32 => "floorf",
21142114 64 => "floor",
21152115 80 => "__floorx",
2116 128 => "floorq",
2116 128 => "floorf128",
21172117 },
21182118 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
21192119 });
......@@ -2431,7 +2431,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
24312431 32 => "fmodf",
24322432 64 => "fmod",
24332433 80 => "__fmodx",
2434 128 => "fmodq",
2434 128 => "fmodf128",
24352435 },
24362436 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
24372437 });
......@@ -2599,7 +2599,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
25992599 32 => "fmaxf",
26002600 64 => "fmax",
26012601 80 => "__fmaxx",
2602 128 => "fmaxq",
2602 128 => "fmaxf128",
26032603 },
26042604 .min => switch (bits) {
26052605 else => unreachable,
......@@ -2607,7 +2607,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
26072607 32 => "fminf",
26082608 64 => "fmin",
26092609 80 => "__fminx",
2610 128 => "fminq",
2610 128 => "fminf128",
26112611 },
26122612 },
26132613 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
......@@ -2856,7 +2856,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
28562856 const remaining_source = std.mem.span(as.source);
28572857 return isel.fail("unable to assemble: '{s}'", .{std.mem.trim(
28582858 u8,
2859 as.source[0 .. std.mem.indexOfScalar(u8, remaining_source, '\n') orelse remaining_source.len],
2859 as.source[0 .. std.mem.findScalar(u8, remaining_source, '\n') orelse remaining_source.len],
28602860 &std.ascii.whitespace,
28612861 )});
28622862 },
......@@ -4055,7 +4055,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
40554055 32 => "sqrtf",
40564056 64 => "sqrt",
40574057 80 => "__sqrtx",
4058 128 => "sqrtq",
4058 128 => "sqrtf128",
40594059 },
40604060 .floor => switch (bits) {
40614061 else => unreachable,
......@@ -4063,7 +4063,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
40634063 32 => "floorf",
40644064 64 => "floor",
40654065 80 => "__floorx",
4066 128 => "floorq",
4066 128 => "floorf128",
40674067 },
40684068 .ceil => switch (bits) {
40694069 else => unreachable,
......@@ -4071,7 +4071,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
40714071 32 => "ceilf",
40724072 64 => "ceil",
40734073 80 => "__ceilx",
4074 128 => "ceilq",
4074 128 => "ceilf128",
40754075 },
40764076 .round => switch (bits) {
40774077 else => unreachable,
......@@ -4079,7 +4079,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
40794079 32 => "roundf",
40804080 64 => "round",
40814081 80 => "__roundx",
4082 128 => "roundq",
4082 128 => "roundf128",
40834083 },
40844084 .trunc_float => switch (bits) {
40854085 else => unreachable,
......@@ -4087,7 +4087,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
40874087 32 => "truncf",
40884088 64 => "trunc",
40894089 80 => "__truncx",
4090 128 => "truncq",
4090 128 => "truncf128",
40914091 },
40924092 },
40934093 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
......@@ -4147,7 +4147,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
41474147 32 => "sinf",
41484148 64 => "sin",
41494149 80 => "__sinx",
4150 128 => "sinq",
4150 128 => "sinf128",
41514151 },
41524152 .cos => switch (bits) {
41534153 else => unreachable,
......@@ -4155,7 +4155,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
41554155 32 => "cosf",
41564156 64 => "cos",
41574157 80 => "__cosx",
4158 128 => "cosq",
4158 128 => "cosf128",
41594159 },
41604160 .tan => switch (bits) {
41614161 else => unreachable,
......@@ -4163,7 +4163,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
41634163 32 => "tanf",
41644164 64 => "tan",
41654165 80 => "__tanx",
4166 128 => "tanq",
4166 128 => "tanf128",
41674167 },
41684168 .exp => switch (bits) {
41694169 else => unreachable,
......@@ -4171,7 +4171,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
41714171 32 => "expf",
41724172 64 => "exp",
41734173 80 => "__expx",
4174 128 => "expq",
4174 128 => "expf128",
41754175 },
41764176 .exp2 => switch (bits) {
41774177 else => unreachable,
......@@ -4179,7 +4179,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
41794179 32 => "exp2f",
41804180 64 => "exp2",
41814181 80 => "__exp2x",
4182 128 => "exp2q",
4182 128 => "exp2f128",
41834183 },
41844184 .log => switch (bits) {
41854185 else => unreachable,
......@@ -4187,7 +4187,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
41874187 32 => "logf",
41884188 64 => "log",
41894189 80 => "__logx",
4190 128 => "logq",
4190 128 => "logf128",
41914191 },
41924192 .log2 => switch (bits) {
41934193 else => unreachable,
......@@ -4195,7 +4195,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
41954195 32 => "log2f",
41964196 64 => "log2",
41974197 80 => "__log2x",
4198 128 => "log2q",
4198 128 => "log2f128",
41994199 },
42004200 .log10 => switch (bits) {
42014201 else => unreachable,
......@@ -4203,7 +4203,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
42034203 32 => "log10f",
42044204 64 => "log10",
42054205 80 => "__log10x",
4206 128 => "log10q",
4206 128 => "log10f128",
42074207 },
42084208 },
42094209 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
......@@ -7118,7 +7118,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
71187118 32 => "fmaf",
71197119 64 => "fma",
71207120 80 => "__fmax",
7121 128 => "fmaq",
7121 128 => "fmaf128",
71227122 },
71237123 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
71247124 });
......@@ -12176,9 +12176,7 @@ pub const CallAbiIterator = struct {
1217612176 const loaded_struct = ip.loadStructType(ty.toIntern());
1217712177 switch (loaded_struct.layout) {
1217812178 .auto, .@"extern" => {},
12179 .@"packed" => continue :type_key .{
12180 .int_type = ip.indexToKey(loaded_struct.packed_backing_int_type).int_type,
12181 },
12179 .@"packed" => continue :type_key ip.indexToKey(loaded_struct.packed_backing_int_type),
1218212180 }
1218312181 const size = wip_vi.size(isel);
1218412182 if (size <= 16 * 4) homogeneous_aggregate: {
......@@ -12300,9 +12298,7 @@ pub const CallAbiIterator = struct {
1230012298 }
1230112299 },
1230212300 .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque },
12303 .enum_type => continue :type_key .{
12304 .int_type = ip.indexToKey(ip.loadEnumType(ty.toIntern()).int_tag_type).int_type,
12305 },
12301 .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).int_tag_type),
1230612302 .error_set_type,
1230712303 .inferred_error_set_type,
1230812304 => continue :type_key .{ .simple_type = .anyerror },
......@@ -12388,7 +12384,7 @@ pub const CallAbiIterator = struct {
1238812384 .f32 => .single,
1238912385 .f64 => .double,
1239012386 .f128 => .quad,
12391 .c_longdouble => switch (zcu.getTarget().cTypeBitSize(.longdouble)) {
12387 .c_longdouble => switch (zcu.getTarget().cTypeBitSize(.longdouble).?) {
1239212388 else => unreachable,
1239312389 64 => .double,
1239412390 80 => null,
src/codegen/aarch64/abi.zig+7-2
......@@ -1,4 +1,4 @@
1const assert = @import("std").debug.assert;
1const assert = std.debug.assert;
22const std = @import("std");
33const InternPool = @import("../../InternPool.zig");
44const Type = @import("../../Type.zig");
......@@ -35,7 +35,12 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class {
3535 if (bit_size > 64) return .double_integer;
3636 return .integer;
3737 },
38 .int, .@"enum", .error_set, .float, .bool => return .byval,
38 .int, .@"enum", .error_set, .bool => return .byval,
39 .float => return switch (ty.floatBits(zcu.getTarget())) {
40 else => unreachable,
41 16, 32, 64, 128 => .byval,
42 80 => .double_integer,
43 },
3944 .vector => {
4045 const bit_size = ty.bitSize(zcu);
4146 // TODO is this controlled by a cpu feature?
src/codegen/arm/abi.zig+9-7
......@@ -39,7 +39,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
3939 const float_count = countFloats(ty, zcu, &maybe_float_bits);
4040 if (float_count <= byval_float_count) return .byval;
4141
42 if (ty.abiAlignment(zcu).compare(.gt, .@"32")) {
42 if (ty.abiAlignment(zcu).compare(.gt, .@"4")) {
4343 return Class.arrSize(bit_size, 64);
4444 }
4545
......@@ -62,7 +62,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
6262 const float_count = countFloats(ty, zcu, &maybe_float_bits);
6363 if (float_count <= byval_float_count) return .byval;
6464
65 if (union_obj.alignment.compareStrict(.gt, .@"32")) {
65 if (union_obj.alignment.compareStrict(.gt, .@"4")) {
6666 return Class.arrSize(bit_size, 64);
6767 }
6868
......@@ -73,14 +73,16 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
7373 }
7474 return Class.arrSize(bit_size, 32);
7575 },
76 .bool, .float => return .byval,
76 .bool => return .byval,
7777 .int => {
78 // TODO this is incorrect for _BitInt(128) but implementing
79 // this correctly makes implementing compiler-rt impossible.
80 // const bit_size = ty.bitSize(zcu);
81 // if (bit_size > 64) return .memory;
78 if (ctx == .ret and ty.intInfo(zcu).bits > 64) return .memory;
8279 return .byval;
8380 },
81 .float => return switch (ty.floatBits(zcu.getTarget())) {
82 else => unreachable,
83 16, 32, 64 => .byval,
84 80, 128 => .{ .i64_array = 2 },
85 },
8486 .@"enum", .error_set => {
8587 const bit_size = ty.bitSize(zcu);
8688 if (bit_size > 64) return .memory;
src/codegen/c.zig+751-610
......@@ -164,7 +164,8 @@ const BlockData = struct {
164164
165165const LocalType = struct {
166166 type: Type,
167 alignment: Alignment,
167 alignment: Alignment = .none,
168 array_len: u2 = 1,
168169};
169170
170171const LocalIndex = u16;
......@@ -184,13 +185,11 @@ const ValueRenderLocation = enum {
184185 }
185186};
186187
187const BuiltinInfo = enum { none, bits };
188const BuiltinInfo = enum { none, bits, bits_none, big_temp_bits };
188189
189190const reserved_idents = std.StaticStringMap(void).initComptime(.{
190191 // C language
191 .{ "alignas", {
192 @setEvalBranchQuota(4000);
193 } },
192 .{ "alignas", {} },
194193 .{ "alignof", {} },
195194 .{ "asm", {} },
196195 .{ "atomic_bool", {} },
......@@ -302,7 +301,100 @@ const reserved_idents = std.StaticStringMap(void).initComptime(.{
302301 // stddef.h
303302 .{ "offsetof", {} },
304303
304 // math.h (only symbols exported by compiler-rt)
305 .{ "ceil", {} },
306 .{ "ceilf", {} },
307 .{ "ceilf128", {} },
308 .{ "ceill", {} },
309 .{ "cos", {} },
310 .{ "cosf", {} },
311 .{ "cosf128", {} },
312 .{ "cosl", {} },
313 .{ "exp", {} },
314 .{ "exp2", {} },
315 .{ "exp2f", {} },
316 .{ "exp2f128", {} },
317 .{ "exp2l", {} },
318 .{ "expf", {} },
319 .{ "expf128", {} },
320 .{ "expl", {} },
321 .{ "fabs", {} },
322 .{ "fabsf", {} },
323 .{ "fabsf128", {} },
324 .{ "fabsl", {} },
325 .{ "floor", {} },
326 .{ "floorf", {} },
327 .{ "floorf128", {} },
328 .{ "floorl", {} },
329 .{ "fma", {} },
330 .{ "fmaf", {} },
331 .{ "fmaf128", {} },
332 .{ "fmal", {} },
333 .{ "fmax", {} },
334 .{ "fmaxf", {} },
335 .{ "fmaxf128", {} },
336 .{ "fmaxl", {} },
337 .{ "fmin", {} },
338 .{ "fminf", {} },
339 .{ "fminf128", {} },
340 .{ "fminl", {} },
341 .{ "fmod", {} },
342 .{ "fmodf", {} },
343 .{ "fmodf128", {} },
344 .{ "fmodl", {} },
345 .{ "log", {} },
346 .{ "log10", {} },
347 .{ "log10f", {} },
348 .{ "log10f128", {} },
349 .{ "log10l", {} },
350 .{ "log2", {} },
351 .{ "log2f", {} },
352 .{ "log2f128", {} },
353 .{ "log2l", {} },
354 .{ "logf", {} },
355 .{ "logf128", {} },
356 .{ "logl", {} },
357 .{ "round", {} },
358 .{ "roundf", {} },
359 .{ "roundf128", {} },
360 .{ "roundl", {} },
361 .{ "sin", {} },
362 .{ "sincos", {} },
363 .{ "sincosf", {} },
364 .{ "sincosf128", {} },
365 .{ "sincosl", {} },
366 .{ "sinf", {} },
367 .{ "sinf128", {} },
368 .{ "sinl", {} },
369 .{ "sqrt", {} },
370 .{ "sqrtf", {} },
371 .{ "sqrtf128", {} },
372 .{ "sqrtl", {} },
373 .{ "tan", {} },
374 .{ "tanf", {} },
375 .{ "tanf128", {} },
376 .{ "tanl", {} },
377 .{ "trunc", {} },
378 .{ "truncf", {} },
379 .{ "truncf128", {} },
380 .{ "truncl", {} },
381
305382 // windows.h
383 .{"DUMMYSTRUCTNAME"},
384 .{"DUMMYSTRUCTNAME2"},
385 .{"DUMMYSTRUCTNAME3"},
386 .{"DUMMYSTRUCTNAME4"},
387 .{"DUMMYSTRUCTNAME5"},
388 .{"DUMMYSTRUCTNAME6"},
389 .{"DUMMYUNIONNAME"},
390 .{"DUMMYUNIONNAME2"},
391 .{"DUMMYUNIONNAME3"},
392 .{"DUMMYUNIONNAME4"},
393 .{"DUMMYUNIONNAME5"},
394 .{"DUMMYUNIONNAME6"},
395 .{"DUMMYUNIONNAME7"},
396 .{"DUMMYUNIONNAME8"},
397 .{"DUMMYUNIONNAME9"},
306398 .{ "max", {} },
307399 .{ "min", {} },
308400});
......@@ -316,13 +408,6 @@ fn isReservedIdent(ident: []const u8) bool {
316408 }
317409 }
318410
319 // windows.h
320 if (mem.startsWith(u8, ident, "DUMMYSTRUCTNAME") or
321 mem.startsWith(u8, ident, "DUMMYUNIONNAME"))
322 {
323 return true;
324 }
325
326411 // CType
327412 if (mem.startsWith(u8, ident, "enum__") or
328413 mem.startsWith(u8, ident, "bitpack__") or
......@@ -453,8 +538,8 @@ pub const Function = struct {
453538
454539 fn wantSafety(f: *Function) bool {
455540 return switch (f.dg.mod.optimize_mode) {
456 .Debug, .ReleaseSafe => true,
457 .ReleaseFast, .ReleaseSmall => false,
541 .debug, .safe => true,
542 .fast, .small => false,
458543 };
459544 }
460545
......@@ -469,10 +554,7 @@ pub const Function = struct {
469554 }
470555
471556 fn allocLocal(f: *Function, inst: ?Air.Inst.Index, ty: Type) !CValue {
472 return f.allocAlignedLocal(inst, .{
473 .type = ty,
474 .alignment = .none,
475 });
557 return f.allocAlignedLocal(inst, .{ .type = ty });
476558 }
477559
478560 /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should
......@@ -564,10 +646,6 @@ pub const Function = struct {
564646 return f.dg.renderType(w, ty);
565647 }
566648
567 fn renderIntCast(f: *Function, w: *Writer, dest_ty: Type, src: CValue, v: Vectorize, src_ty: Type, location: ValueRenderLocation) !void {
568 return f.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location);
569 }
570
571649 fn fmtIntLiteralDec(f: *Function, val: Value) !std.fmt.Alt(FormatIntLiteralContext, formatIntLiteral) {
572650 return f.dg.fmtIntLiteralDec(val, .other);
573651 }
......@@ -672,7 +750,9 @@ pub const DeclGen = struct {
672750 // Render an undefined pointer if we have a pointer to a zero-bit or comptime type.
673751 const ptr_ty: Type = .fromInterned(uav.orig_ty);
674752 if (ptr_ty.isPtrAtRuntime(zcu) and !uav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {
675 return dg.renderUndefValue(w, ptr_ty, location);
753 try w.writeByte('(');
754 try dg.renderOpvPointer(w, ptr_ty, location);
755 return w.writeByte(')');
676756 }
677757
678758 switch (ip.indexToKey(uav.val)) {
......@@ -737,8 +817,10 @@ pub const DeclGen = struct {
737817 // Render an undefined pointer if we have a pointer to a zero-bit or comptime type.
738818 const nav_ty: Type = .fromInterned(ip.getNav(owner_nav).resolved.?.type);
739819 const ptr_ty = try pt.navPtrType(owner_nav);
740 if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {
741 return dg.renderUndefValue(w, ptr_ty, location);
820 if (nav_ty.zigTypeTag(zcu) != .@"opaque" and !nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {
821 try w.writeByte('(');
822 try dg.renderOpvPointer(w, ptr_ty, location);
823 return w.writeByte(')');
742824 }
743825
744826 // We shouldn't cast C function pointers as this is UB (when you call
......@@ -758,6 +840,26 @@ pub const DeclGen = struct {
758840 if (need_cast) try w.writeByte(')');
759841 }
760842
843 fn renderOpvPointer(
844 dg: *DeclGen,
845 w: *Writer,
846 ptr_ty: Type,
847 location: ValueRenderLocation,
848 ) Error!void {
849 const zcu = dg.pt.zcu;
850 const target = zcu.getTarget();
851 try w.writeByte('(');
852 try dg.renderType(w, ptr_ty);
853 return w.print("){f}", .{fmtUnsignedIntLiteralSmall(
854 target,
855 .uintptr_t,
856 ptr_ty.ptrAlignment(zcu).forward(undefPattern(u64) >> @intCast(64 - target.ptrBitWidth())),
857 location == .static_initializer,
858 16,
859 .lower,
860 )});
861 }
862
761863 fn renderPointer(
762864 dg: *DeclGen,
763865 w: *Writer,
......@@ -959,9 +1061,6 @@ pub const DeclGen = struct {
9591061 const bits = ty.floatBits(target);
9601062 const f128_val = val.toFloat(f128, zcu);
9611063
962 // All unsigned ints matching float types are pre-allocated.
963 const repr_ty = pt.intType(.unsigned, bits) catch unreachable;
964
9651064 assert(bits <= 128);
9661065 var repr_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined;
9671066 var repr_val_big = BigInt.Mutable{
......@@ -971,29 +1070,27 @@ pub const DeclGen = struct {
9711070 };
9721071
9731072 switch (bits) {
1073 else => unreachable,
9741074 16 => repr_val_big.set(@as(u16, @bitCast(val.toFloat(f16, zcu)))),
9751075 32 => repr_val_big.set(@as(u32, @bitCast(val.toFloat(f32, zcu)))),
9761076 64 => repr_val_big.set(@as(u64, @bitCast(val.toFloat(f64, zcu)))),
9771077 80 => repr_val_big.set(@as(u80, @bitCast(val.toFloat(f80, zcu)))),
9781078 128 => repr_val_big.set(@as(u128, @bitCast(f128_val))),
979 else => unreachable,
9801079 }
9811080
982 var empty = true;
9831081 if (std.math.isFinite(f128_val)) {
9841082 try w.writeAll("zig_make_");
9851083 try dg.renderTypeForBuiltinFnName(w, ty);
9861084 try w.writeByte('(');
9871085 switch (bits) {
1086 else => unreachable,
9881087 16 => try w.print("{x}", .{val.toFloat(f16, zcu)}),
9891088 32 => try w.print("{x}", .{val.toFloat(f32, zcu)}),
9901089 64 => try w.print("{x}", .{val.toFloat(f64, zcu)}),
9911090 80 => try w.print("{x}", .{val.toFloat(f80, zcu)}),
9921091 128 => try w.print("{x}", .{f128_val}),
993 else => unreachable,
9941092 }
9951093 try w.writeAll(", ");
996 empty = false;
9971094 } else {
9981095 // isSignalNan is equivalent to isNan currently, and MSVC doesn't have nans, so prefer nan
9991096 const operation = if (std.math.isNan(f128_val))
......@@ -1028,6 +1125,7 @@ pub const DeclGen = struct {
10281125 try w.writeAll(operation);
10291126 try w.writeAll(", ");
10301127 if (std.math.isNan(f128_val)) switch (bits) {
1128 else => unreachable,
10311129 // We only actually need to pass the significand, but it will get
10321130 // properly masked anyway, so just pass the whole value.
10331131 16 => try w.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, zcu)))}),
......@@ -1035,16 +1133,23 @@ pub const DeclGen = struct {
10351133 64 => try w.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, zcu)))}),
10361134 80 => try w.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, zcu)))}),
10371135 128 => try w.print("\"0x{x}\"", .{@as(u128, @bitCast(f128_val))}),
1038 else => unreachable,
10391136 };
10401137 try w.writeAll(", ");
1041 empty = false;
10421138 }
1043 try w.print("{f}", .{try dg.fmtIntLiteralHex(
1044 try pt.intValue_big(repr_ty, repr_val_big.toConst()),
1045 location,
1046 )});
1047 if (!empty) try w.writeByte(')');
1139 switch (bits) {
1140 else => unreachable,
1141 16, 32, 64 => {
1142 // All unsigned ints matching float types are pre-allocated.
1143 const repr_ty = pt.intType(.unsigned, bits) catch unreachable;
1144 try w.print("{f}", .{try dg.fmtIntLiteralHex(
1145 try pt.intValue_big(repr_ty, repr_val_big.toConst()),
1146 location,
1147 )});
1148 },
1149 80 => try F80Repr.write(@bitCast(val.toFloat(f80, zcu)), w, target, location == .static_initializer),
1150 128 => try F128Repr.write(@bitCast(f128_val), w, target, location == .static_initializer),
1151 }
1152 try w.writeByte(')');
10481153 },
10491154 .slice => |slice| {
10501155 if (!location.isInitializer()) {
......@@ -1306,8 +1411,8 @@ pub const DeclGen = struct {
13061411 };
13071412
13081413 const safety_on = switch (dg.mod.optimize_mode) {
1309 .Debug, .ReleaseSafe => true,
1310 .ReleaseFast, .ReleaseSmall => false,
1414 .debug, .safe => true,
1415 .fast, .small => false,
13111416 };
13121417
13131418 switch (ty.toIntern()) {
......@@ -1319,22 +1424,29 @@ pub const DeclGen = struct {
13191424 .f128_type,
13201425 => {
13211426 const bits = ty.floatBits(target);
1322 // All unsigned ints matching float types are pre-allocated.
1323 const repr_ty = dg.pt.intType(.unsigned, bits) catch unreachable;
13241427
13251428 try w.writeAll("zig_make_");
13261429 try dg.renderTypeForBuiltinFnName(w, ty);
13271430 try w.writeByte('(');
13281431 switch (bits) {
1329 16 => try w.print("{x}", .{@as(f16, @bitCast(undefPattern(i16)))}),
1330 32 => try w.print("{x}", .{@as(f32, @bitCast(undefPattern(i32)))}),
1331 64 => try w.print("{x}", .{@as(f64, @bitCast(undefPattern(i64)))}),
1332 80 => try w.print("{x}", .{@as(f80, @bitCast(undefPattern(i80)))}),
1333 128 => try w.print("{x}", .{@as(f128, @bitCast(undefPattern(i128)))}),
13341432 else => unreachable,
1433 16 => try w.print("{x}", .{undefPattern(f16)}),
1434 32 => try w.print("{x}", .{undefPattern(f32)}),
1435 64 => try w.print("{x}", .{undefPattern(f64)}),
1436 80 => try w.print("{x}", .{undefPattern(f80)}),
1437 128 => try w.print("{x}", .{undefPattern(f128)}),
13351438 }
13361439 try w.writeAll(", ");
1337 try dg.renderUndefValue(w, repr_ty, .other);
1440 switch (bits) {
1441 else => unreachable,
1442 16, 32, 64 => {
1443 // All unsigned ints matching float types are pre-allocated.
1444 const repr_ty = dg.pt.intType(.unsigned, bits) catch unreachable;
1445 try dg.renderUndefValue(w, repr_ty, .other);
1446 },
1447 80 => try undefPattern(F80Repr).write(w, target, location == .static_initializer),
1448 128 => try undefPattern(F128Repr).write(w, target, location == .static_initializer),
1449 }
13381450 return w.writeByte(')');
13391451 },
13401452 .bool_type => try w.writeAll(if (safety_on) "0xaa" else "false"),
......@@ -1638,8 +1750,6 @@ pub const DeclGen = struct {
16381750 try w.writeAll("zig_no_builtin ");
16391751 }
16401752
1641 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
1642
16431753 // While incomplete types are usually an acceptable substitute for "void", this is not true
16441754 // in function return types, where "void" is the only incomplete type permitted.
16451755 const actual_return_type: Type = .fromInterned(fn_info.return_type);
......@@ -1651,8 +1761,9 @@ pub const DeclGen = struct {
16511761
16521762 const ret_cty: CType = try .lower(effective_return_type, &dg.ctype_deps, dg.arena, zcu);
16531763 try w.print("{f}", .{ret_cty.fmtDeclaratorPrefix(zcu)});
1654 if (toCallingConvention(fn_info.cc, zcu)) |call_conv| {
1655 try w.print("zig_callconv({s}) ", .{call_conv});
1764 switch (CType.CallingConvention.fromLang(fn_info.cc, zcu.getTarget())) {
1765 .c => {},
1766 else => |cc| try w.print("zig_callconv({t}) ", .{cc}),
16561767 }
16571768 switch (name) {
16581769 .nav => |nav| try renderNavName(w, nav, ip),
......@@ -1726,136 +1837,6 @@ pub const DeclGen = struct {
17261837 try w.print("{f}", .{cty.fmtTypeName(zcu)});
17271838 }
17281839
1729 const IntCastContext = union(enum) {
1730 c_value: struct {
1731 f: *Function,
1732 value: CValue,
1733 v: Vectorize,
1734 },
1735 value: struct {
1736 value: Value,
1737 },
1738
1739 pub fn writeValue(self: *const IntCastContext, dg: *DeclGen, w: *Writer, location: ValueRenderLocation) !void {
1740 switch (self.*) {
1741 .c_value => |v| {
1742 try v.f.writeCValue(w, v.value, location);
1743 try v.v.elem(v.f, w);
1744 },
1745 .value => |v| try dg.renderValue(w, v.value, location),
1746 }
1747 }
1748 };
1749 fn intCastIsNoop(dg: *DeclGen, dest_ty: Type, src_ty: Type) bool {
1750 const pt = dg.pt;
1751 const zcu = pt.zcu;
1752 const dest_bits = dest_ty.bitSize(zcu);
1753 const dest_int_info = dest_ty.intInfo(pt.zcu);
1754
1755 const src_is_ptr = src_ty.isPtrAtRuntime(pt.zcu);
1756 const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) {
1757 .unsigned => .usize,
1758 .signed => .isize,
1759 } else src_ty;
1760
1761 const src_bits = src_eff_ty.bitSize(zcu);
1762 const src_int_info = if (src_eff_ty.isAbiInt(pt.zcu)) src_eff_ty.intInfo(pt.zcu) else null;
1763 if (dest_bits <= 64 and src_bits <= 64) {
1764 const needs_cast = src_int_info == null or
1765 (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or
1766 dest_int_info.signedness != src_int_info.?.signedness);
1767 return !needs_cast and !src_is_ptr;
1768 } else return false;
1769 }
1770 /// Renders a cast to an int type, from either an int or a pointer.
1771 ///
1772 /// Some platforms don't have 128 bit integers, so we need to use
1773 /// the zig_make_ and zig_lo_ macros in those cases.
1774 ///
1775 /// | Dest type bits | Src type | Result
1776 /// |------------------|------------------|---------------------------|
1777 /// | < 64 bit integer | pointer | (zig_<dest_ty>)(zig_<u|i>size)src
1778 /// | < 64 bit integer | < 64 bit integer | (zig_<dest_ty>)src
1779 /// | < 64 bit integer | > 64 bit integer | zig_lo(src)
1780 /// | > 64 bit integer | pointer | zig_make_<dest_ty>(0, (zig_<u|i>size)src)
1781 /// | > 64 bit integer | < 64 bit integer | zig_make_<dest_ty>(0, src)
1782 /// | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src))
1783 fn renderIntCast(
1784 dg: *DeclGen,
1785 w: *Writer,
1786 dest_ty: Type,
1787 context: IntCastContext,
1788 src_ty: Type,
1789 location: ValueRenderLocation,
1790 ) !void {
1791 const pt = dg.pt;
1792 const zcu = pt.zcu;
1793 const dest_bits = dest_ty.bitSize(zcu);
1794 const dest_int_info = dest_ty.intInfo(zcu);
1795
1796 const src_is_ptr = src_ty.isPtrAtRuntime(zcu);
1797 const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) {
1798 .unsigned => .usize,
1799 .signed => .isize,
1800 } else src_ty;
1801
1802 const src_bits = src_eff_ty.bitSize(zcu);
1803 const src_int_info = if (src_eff_ty.isAbiInt(zcu)) src_eff_ty.intInfo(zcu) else null;
1804 if (dest_bits <= 64 and src_bits <= 64) {
1805 const needs_cast = src_int_info == null or
1806 (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or
1807 dest_int_info.signedness != src_int_info.?.signedness);
1808
1809 if (needs_cast) {
1810 try w.writeByte('(');
1811 try dg.renderType(w, dest_ty);
1812 try w.writeByte(')');
1813 }
1814 if (src_is_ptr) {
1815 try w.writeByte('(');
1816 try dg.renderType(w, src_eff_ty);
1817 try w.writeByte(')');
1818 }
1819 try context.writeValue(dg, w, location);
1820 } else if (dest_bits <= 64 and src_bits > 64) {
1821 assert(!src_is_ptr);
1822 if (dest_bits < 64) {
1823 try w.writeByte('(');
1824 try dg.renderType(w, dest_ty);
1825 try w.writeByte(')');
1826 }
1827 try w.writeAll("zig_lo_");
1828 try dg.renderTypeForBuiltinFnName(w, src_eff_ty);
1829 try w.writeByte('(');
1830 try context.writeValue(dg, w, .other);
1831 try w.writeByte(')');
1832 } else if (dest_bits > 64 and src_bits <= 64) {
1833 try w.writeAll("zig_make_");
1834 try dg.renderTypeForBuiltinFnName(w, dest_ty);
1835 try w.writeAll("(0, ");
1836 if (src_is_ptr) {
1837 try w.writeByte('(');
1838 try dg.renderType(w, src_eff_ty);
1839 try w.writeByte(')');
1840 }
1841 try context.writeValue(dg, w, .other);
1842 try w.writeByte(')');
1843 } else {
1844 assert(!src_is_ptr);
1845 try w.writeAll("zig_make_");
1846 try dg.renderTypeForBuiltinFnName(w, dest_ty);
1847 try w.writeAll("(zig_hi_");
1848 try dg.renderTypeForBuiltinFnName(w, src_eff_ty);
1849 try w.writeByte('(');
1850 try context.writeValue(dg, w, .other);
1851 try w.writeAll("), zig_lo_");
1852 try dg.renderTypeForBuiltinFnName(w, src_eff_ty);
1853 try w.writeByte('(');
1854 try context.writeValue(dg, w, .other);
1855 try w.writeAll("))");
1856 }
1857 }
1858
18591840 /// Renders to `w` a C declarator whose type is the C lowering of the given Zig type.
18601841 fn renderTypeAndName(
18611842 dg: *DeclGen,
......@@ -2000,6 +1981,7 @@ pub const DeclGen = struct {
20001981 switch (info) {
20011982 .none => if (!is_big) return,
20021983 .bits => {},
1984 .bits_none, .big_temp_bits => unreachable,
20031985 }
20041986
20051987 const int_info: std.lang.Type.Int = if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else .{
......@@ -2056,6 +2038,72 @@ const CQualifiers = packed struct {
20562038 restrict: bool = false,
20572039};
20582040
2041pub fn genHeader(zcu: *Zcu, w: *Writer) !void {
2042 const gpa = zcu.comp.gpa;
2043
2044 var arena: std.heap.ArenaAllocator = .init(gpa);
2045 defer arena.deinit();
2046 var ctype_deps: CType.Dependencies = .empty;
2047 defer ctype_deps.deinit(gpa);
2048
2049 const target = zcu.getTarget();
2050 switch (target.abi) {
2051 .msvc, .itanium => try w.writeAll("#define ZIG_TARGET_ABI_MSVC\n"),
2052 else => {},
2053 }
2054 for ([_]u16{ 16, 32, 64, 80, 128 }) |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) {
2055 .hard => {},
2056 .soft => try w.print("#define ZIG_TARGET_SOFT_COMPILER_RT_F{d}_ABI\n", .{bits}),
2057 };
2058 try w.print(
2059 \\#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}
2060 \\#include "zig.h"
2061 \\
2062 \\
2063 ,
2064 .{target.cMaxIntAlignment()},
2065 );
2066
2067 var basic_ty: Type = .fromInterned(.first_type);
2068 while (true) : ({
2069 basic_ty = .fromInterned(@fromBackingInt(@intCast(@backingInt(basic_ty.toIntern()) + 1)));
2070 if (basic_ty.toIntern() == InternPool.Index.last_type) break;
2071 }) {
2072 switch (basic_ty.toIntern()) {
2073 else => {},
2074 .anyframe_type,
2075 .adhoc_inferred_error_set_type,
2076 .generic_poison_type,
2077 => continue, // skip unsupported types
2078 }
2079 const basic_cty: CType = try .lower(basic_ty, &ctype_deps, arena.allocator(), zcu);
2080 switch (basic_cty) {
2081 .void => {}, // no layout to check
2082 .bool,
2083 .int,
2084 .float,
2085 => try CType.render_defs.writeStaticAssertTypeLayout(basic_ty, basic_cty, w, zcu),
2086 .@"fn",
2087 .@"enum",
2088 .bitpack,
2089 .@"struct",
2090 .union_auto,
2091 .union_extern,
2092 .slice,
2093 .opt,
2094 .arr,
2095 .vec,
2096 .errunion,
2097 .aligned,
2098 .bigint,
2099 .pointer,
2100 .array,
2101 .function,
2102 => {},
2103 }
2104 }
2105}
2106
20592107pub fn genGlobalAsm(zcu: *Zcu, w: *Writer) !void {
20602108 for (zcu.global_assembly.values()) |asm_source| {
20612109 try w.print("__asm({f});\n", .{fmtStringLiteral(asm_source, null)});
......@@ -2070,16 +2118,16 @@ pub fn genErrDecls(
20702118 const ip = &zcu.intern_pool;
20712119
20722120 const names = ip.global_error_set.getNamesFromMainThread();
2073 // Don't generate an invalid empty enum if the global error set is empty!
2074 if (names.len > 0) {
2075 try w.writeAll("enum {\n");
2076 for (names, 1..) |name_nts, value| {
2077 try w.writeByte(' ');
2078 try renderErrorName(w, name_nts.toSlice(ip));
2079 try w.print(" = {d}u,\n", .{value});
2080 }
2081 try w.writeAll("};\n");
2121 // Don't generate an invalid empty enum/array if the global error set is empty!
2122 if (names.len == 0) return;
2123
2124 try w.writeAll("enum {\n");
2125 for (names, 1..) |name_nts, value| {
2126 try w.writeByte(' ');
2127 try renderErrorName(w, name_nts.toSlice(ip));
2128 try w.print(" = {d}u,\n", .{value});
20822129 }
2130 try w.writeAll("};\n");
20832131
20842132 for (names) |name_nts| {
20852133 const name = name_nts.toSlice(ip);
......@@ -2093,7 +2141,7 @@ pub fn genErrDecls(
20932141 "static {s} const zig_errorName[{d}] = {{",
20942142 .{ slice_const_u8_sentinel_0_type_name, names.len },
20952143 );
2096 if (names.len > 0) try w.writeByte('\n');
2144 try w.writeByte('\n');
20972145 for (names) |name_nts| {
20982146 const name = name_nts.toSlice(ip);
20992147 try w.print(
......@@ -2114,10 +2162,18 @@ pub fn genTagNameFn(
21142162 const ip = &zcu.intern_pool;
21152163 const loaded_enum = ip.loadEnumType(enum_ty.toIntern());
21162164 assert(loaded_enum.field_names.len > 0);
2117 if (Type.fromInterned(loaded_enum.int_tag_type).bitSize(zcu) > 64) {
2118 @panic("TODO CBE: tagName for enum over 64 bits");
2165 switch (CType.classifyInt(enum_ty, zcu)) {
2166 .void => unreachable,
2167 .small => |int| switch (int) {
2168 else => {},
2169 .zig_u128, .zig_i128 => @panic("TODO CBE: tagName for 128-bit enums"),
2170 },
2171 .big => @panic("TODO CBE: tagName for bigint enums"),
21192172 }
21202173
2174 if (!zcu.comp.config.root_strip) try w.print("/* @tagName({f}) */\n", .{
2175 loaded_enum.name.fmt(ip),
2176 });
21212177 try w.print("static {s} zig_tagName_{f}__{d}({s} tag) {{\n", .{
21222178 slice_const_u8_sentinel_0_type_name,
21232179 fmtIdentUnsolo(loaded_enum.name.toSlice(ip)),
......@@ -2164,6 +2220,7 @@ pub fn genLazyCallModifierFn(
21642220
21652221 const fn_val = zcu.navValue(fn_nav);
21662222
2223 if (fn_val.typeOf(zcu).fnReturnType(zcu).isNoReturn(zcu)) try w.writeAll("zig_noreturn ");
21672224 try w.print("static zig_{t} ", .{kind});
21682225 try dg.renderFunctionSignature(w, fn_val, .none, .definition, switch (kind) {
21692226 .never_tail => .{ .nav_never_tail = fn_nav },
......@@ -2269,8 +2326,10 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E
22692326 const gpa = f.dg.gpa;
22702327 const nav_index = f.dg.owner_nav.unwrap().?;
22712328 const nav_val = zcu.navValue(nav_index);
2329 const fn_info = zcu.typeToFunc(nav_val.typeOf(zcu)).?;
22722330 const nav = ip.getNav(nav_index);
22732331
2332 if (Type.fromInterned(fn_info.return_type).isNoReturn(zcu)) try fwd_decl_writer.writeAll("zig_noreturn ");
22742333 try fwd_decl_writer.writeAll("static ");
22752334 try f.dg.renderFunctionSignature(
22762335 fwd_decl_writer,
......@@ -2291,11 +2350,41 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E
22912350 .{ .nav = nav_index },
22922351 );
22932352 try header_writer.writeAll(" {\n ");
2353 if (!f.dg.mod.strip) try header_writer.print("/* {f} */\n ", .{nav.fqn.fmt(ip)});
22942354
22952355 f.free_locals_map.clearRetainingCapacity();
22962356
22972357 const main_body = f.air.getMainBody();
22982358 f.indent();
2359 if (switch (fn_info.cc) {
2360 inline else => |pl| switch (@TypeOf(pl)) {
2361 void,
2362 std.lang.CallingConvention.SpirvKernelOptions,
2363 std.lang.CallingConvention.SpirvFragmentOptions,
2364 std.lang.CallingConvention.SpirvMeshOptions,
2365 => null,
2366 std.lang.CallingConvention.ArcInterruptOptions,
2367 std.lang.CallingConvention.ArmInterruptOptions,
2368 std.lang.CallingConvention.RiscvInterruptOptions,
2369 std.lang.CallingConvention.ShInterruptOptions,
2370 std.lang.CallingConvention.MicroblazeInterruptOptions,
2371 std.lang.CallingConvention.MipsInterruptOptions,
2372 std.lang.CallingConvention.CommonOptions,
2373 std.lang.CallingConvention.X86RegparmOptions,
2374 => pl.incoming_stack_alignment,
2375 else => @compileError(@tagName(pl)),
2376 },
2377 }) |incoming_stack_alignment| realign_stack: {
2378 const normal_stack_align = zcu.getTarget().stackAlignment();
2379 if (incoming_stack_alignment >= normal_stack_align) break :realign_stack;
2380 try header_writer.print("char zig_align({d}) zig_realign_stack;\n ", .{
2381 normal_stack_align << 1,
2382 });
2383 try f.code.writer.writeAll(
2384 \\__asm volatile("" :: [zig_realign_stack] "m" (zig_realign_stack));
2385 );
2386 try f.newline();
2387 }
22992388 try genBodyResolveState(f, undefined, &.{}, main_body, true);
23002389 try f.outdent();
23012390 try f.code.writer.writeByte('}');
......@@ -2346,6 +2435,7 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E
23462435 for (list.keys()) |local_index| {
23472436 const local = f.locals.items[local_index];
23482437 try f.dg.renderTypeAndName(header_writer, local.type, .{ .local = local_index }, .{}, local.alignment);
2438 if (local.array_len != 1) try header_writer.print("[{d}]", .{local.array_len});
23492439 try header_writer.writeAll(";\n ");
23502440 }
23512441 }
......@@ -2397,10 +2487,12 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void {
23972487
23982488 .@"extern" => |@"extern"| switch (nav_ty.zigTypeTag(zcu)) {
23992489 .@"fn" => {
2490 const fn_val: Value = .fromInterned(nav.resolved.?.value);
2491 if (fn_val.typeOf(zcu).fnReturnType(zcu).isNoReturn(zcu)) try w.writeAll("zig_noreturn ");
24002492 try w.writeAll("zig_extern ");
24012493 try dg.renderFunctionSignature(
24022494 w,
2403 .fromInterned(nav.resolved.?.value),
2495 fn_val,
24042496 nav.resolved.?.@"align",
24052497 .forward_decl,
24062498 .{ .@"export" = .{
......@@ -2461,7 +2553,12 @@ pub fn genDeclValue(dg: *DeclGen, w: *Writer, options: struct {
24612553 try dg.renderTypeAndName(w, ty, options.name, .{ .@"const" = options.@"const" }, .none);
24622554 try w.writeAll(" = ");
24632555 try dg.renderValue(w, options.init_val, .static_initializer);
2464 try w.writeAll(";\n");
2556 try w.writeByte(';');
2557 if (dg.owner_nav.unwrap()) |nav_index| {
2558 const ip = &zcu.intern_pool;
2559 if (!dg.mod.strip) try w.print(" /* {f} */", .{ip.getNav(nav_index).fqn.fmt(ip)});
2560 }
2561 try w.writeByte('\n');
24652562}
24662563pub fn genDeclValueFwd(dg: *DeclGen, w: *Writer, options: struct {
24672564 name: CValue,
......@@ -2496,11 +2593,13 @@ pub fn genExports(dg: *DeclGen, w: *Writer, exported: Zcu.Exported, export_indic
24962593 const exported_val = exported.getValue(zcu);
24972594 if (ip.isFunctionType(exported_val.typeOf(zcu).toIntern())) return for (export_indices) |export_index| {
24982595 const @"export" = export_index.ptr(zcu);
2596 const fn_val = exported.getValue(zcu);
2597 if (fn_val.typeOf(zcu).fnReturnType(zcu).isNoReturn(zcu)) try w.writeAll("zig_noreturn ");
24992598 try w.writeAll("zig_extern ");
25002599 if (@"export".opts.linkage == .weak) try w.writeAll("zig_weak_linkage_fn ");
25012600 try dg.renderFunctionSignature(
25022601 w,
2503 exported.getValue(zcu),
2602 fn_val,
25042603 exported.getAlign(zcu),
25052604 .forward_decl,
25062605 .{ .@"export" = .{
......@@ -2662,22 +2761,22 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {
26622761 .mul => try airBinOp(f, inst, "*", "mul", .none),
26632762
26642763 .neg => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "neg", .none),
2665 .div_float => try airBinBuiltinCall(f, inst, "div", .none),
2764 .div_float => try airBinBuiltinCall(f, inst, "div", .big_temp_bits),
26662765
2667 .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .none),
2766 .div_trunc, .div_exact => try airBinOp(f, inst, "/", "divTrunc", .big_temp_bits),
26682767 .rem => blk: {
26692768 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
26702769 const lhs_scalar_ty = f.typeOf(bin_op.lhs).scalarType(zcu);
26712770 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
26722771 // so we only check one.
26732772 break :blk if (lhs_scalar_ty.isInt(zcu))
2674 try airBinOp(f, inst, "%", "rem", .none)
2773 try airBinOp(f, inst, "%", "rem", .big_temp_bits)
26752774 else
26762775 try airBinBuiltinCall(f, inst, "fmod", .none);
26772776 },
2678 .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .none),
2679 .div_ceil => try airBinBuiltinCall(f, inst, "div_ceil", .none),
2680 .mod => try airBinBuiltinCall(f, inst, "mod", .none),
2777 .div_floor => try airBinBuiltinCall(f, inst, "divFloor", .big_temp_bits),
2778 .div_ceil => try airBinBuiltinCall(f, inst, "divCeil", .big_temp_bits),
2779 .mod => try airBinBuiltinCall(f, inst, "mod", .big_temp_bits),
26812780 .abs => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "abs", .none),
26822781
26832782 .add_wrap => try airBinBuiltinCall(f, inst, "addw", .bits),
......@@ -2687,7 +2786,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {
26872786 .add_sat => try airBinBuiltinCall(f, inst, "adds", .bits),
26882787 .sub_sat => try airBinBuiltinCall(f, inst, "subs", .bits),
26892788 .mul_sat => try airBinBuiltinCall(f, inst, "muls", .bits),
2690 .shl_sat => try airBinBuiltinCall(f, inst, "shls", .bits),
2789 .shl_sat => try airBinBuiltinCall(f, inst, "shls", .bits_none),
26912790
26922791 .sqrt => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "sqrt", .none),
26932792 .sin => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "sin", .none),
......@@ -2764,8 +2863,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {
27642863 .int_from_error => try airNopCast(f, inst),
27652864 .union_from_enum => try airUnionFromEnum(f, inst),
27662865 .bit_cast => try airBitCast(f, inst),
2767 .int_cast => try airIntCast(f, inst),
2768 .trunc => try airTrunc(f, inst),
2866 .int_cast => try airIntCast(f, inst, "intCast", .none),
2867 .trunc => try airIntCast(f, inst, "truncate", .bits),
27692868 .load => try airLoad(f, inst),
27702869 .store => try airStore(f, inst, false),
27712870 .store_safe => try airStore(f, inst, true),
......@@ -2783,9 +2882,9 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {
27832882 .get_union_tag => try airGetUnionTag(f, inst),
27842883 .clz => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "clz", .bits),
27852884 .ctz => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "ctz", .bits),
2786 .popcount => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "popcount", .bits),
2787 .byte_swap => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "byte_swap", .bits),
2788 .bit_reverse => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "bit_reverse", .bits),
2885 .popcount => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "popCount", .bits),
2886 .byte_swap => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "byteSwap", .bits),
2887 .bit_reverse => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "bitReverse", .bits),
27892888 .tag_name => try airTagName(f, inst),
27902889 .error_name => try airErrorName(f, inst),
27912890 .splat => try airSplat(f, inst),
......@@ -3124,7 +3223,16 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {
31243223 const zcu = pt.zcu;
31253224 const inst_ty = f.typeOfIndex(inst);
31263225 const elem_ty = inst_ty.childType(zcu);
3127 if (!elem_ty.hasRuntimeBits(zcu)) return .{ .undef = inst_ty };
3226 if (!elem_ty.hasRuntimeBits(zcu)) {
3227 const w = &f.code.writer;
3228 const local = try f.allocLocal(inst, inst_ty);
3229 try f.writeCValue(w, local, .other);
3230 try w.writeAll(" = ");
3231 try f.dg.renderOpvPointer(w, inst_ty, .other);
3232 try w.writeByte(';');
3233 try f.newline();
3234 return local;
3235 }
31283236
31293237 const local = try f.allocLocalValue(.{
31303238 .type = elem_ty,
......@@ -3298,120 +3406,57 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void {
32983406 }
32993407}
33003408
3301fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {
3409fn airIntCast(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !CValue {
33023410 const pt = f.dg.pt;
33033411 const zcu = pt.zcu;
33043412 const ty_op = f.air.instructions.items(.data)[@backingInt(inst)].ty_op;
33053413
3306 const operand = try f.resolveInst(ty_op.operand);
3307 try reap(f, inst, &.{ty_op.operand});
3308
3309 const inst_ty = f.typeOfIndex(inst);
3414 const inst_ty = ty_op.ty.toType();
33103415 const inst_scalar_ty = inst_ty.scalarType(zcu);
33113416 const operand_ty = f.typeOf(ty_op.operand);
3312 const scalar_ty = operand_ty.scalarType(zcu);
3313
3314 // `intCastIsNoop` doesn't apply to vectors because every vector lowers to a different C struct.
3315 if (inst_ty.zigTypeTag(zcu) != .vector and f.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) {
3316 return f.moveCValue(inst, inst_ty, operand);
3317 }
3318
3319 const w = &f.code.writer;
3320 const local = try f.allocLocal(inst, inst_ty);
3321 const v = try Vectorize.start(f, inst, w, operand_ty);
3322 try f.writeCValue(w, local, .other);
3323 try v.elem(f, w);
3324 try w.writeAll(" = ");
3325 try f.renderIntCast(w, inst_scalar_ty, operand, v, scalar_ty, .other);
3326 try w.writeByte(';');
3327 try f.newline();
3328 try v.end(f, inst, w);
3329 return local;
3330}
3331
3332fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
3333 const pt = f.dg.pt;
3334 const zcu = pt.zcu;
3335 const ty_op = f.air.instructions.items(.data)[@backingInt(inst)].ty_op;
3417 const operand_scalar_ty = operand_ty.scalarType(zcu);
3418 const is_big = lowersToBigInt(operand_ty, zcu);
33363419
33373420 const operand = try f.resolveInst(ty_op.operand);
3338 try reap(f, inst, &.{ty_op.operand});
3421 if (!is_big) try reap(f, inst, &.{ty_op.operand});
33393422
3340 const inst_ty = f.typeOfIndex(inst);
3341 const inst_scalar_ty = inst_ty.scalarType(zcu);
3342 const dest_int_info = inst_scalar_ty.intInfo(zcu);
3343 const dest_bits = dest_int_info.bits;
3344 const dest_c_bits = toCIntBits(dest_bits) orelse
3345 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
3346 const operand_ty = f.typeOf(ty_op.operand);
3347 const scalar_ty = operand_ty.scalarType(zcu);
3348 const scalar_int_info = scalar_ty.intInfo(zcu);
3349
3350 const need_cast = dest_c_bits < 64;
3351 const need_lo = scalar_int_info.bits > 64 and dest_bits <= 64;
3352 const need_mask = dest_bits < 8 or !std.math.isPowerOfTwo(dest_bits);
3353 if (!need_cast and !need_lo and !need_mask) return f.moveCValue(inst, inst_ty, operand);
3423 const ref_ret = lowersToBigInt(inst_scalar_ty, zcu);
3424 const ref_arg = lowersToBigInt(operand_scalar_ty, zcu);
33543425
33553426 const w = &f.code.writer;
33563427 const local = try f.allocLocal(inst, inst_ty);
3428 if (is_big) try reap(f, inst, &.{ty_op.operand});
33573429 const v = try Vectorize.start(f, inst, w, operand_ty);
3358 try f.writeCValue(w, local, .other);
3359 try v.elem(f, w);
3360 try w.writeAll(" = ");
3361 if (need_cast) {
3362 try w.writeByte('(');
3363 try f.renderType(w, inst_scalar_ty);
3364 try w.writeByte(')');
3365 }
3366 if (need_lo) {
3367 try w.writeAll("zig_lo_");
3368 try f.dg.renderTypeForBuiltinFnName(w, scalar_ty);
3369 try w.writeByte('(');
3430 if (!ref_ret) {
3431 try f.writeCValue(w, local, .other);
3432 try v.elem(f, w);
3433 try w.writeAll(" = ");
33703434 }
3371 if (!need_mask) {
3372 try f.writeCValue(w, operand, .other);
3435 try w.writeAll("zig_");
3436 try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty);
3437 try w.print("_{s}_", .{operation});
3438 try f.dg.renderTypeForBuiltinFnName(w, operand_scalar_ty);
3439 try w.writeByte('(');
3440 if (ref_ret) {
3441 try w.writeByte('&');
3442 try f.writeCValue(w, local, .other);
33733443 try v.elem(f, w);
3374 } else switch (dest_int_info.signedness) {
3375 .unsigned => {
3376 try w.writeAll("zig_and_");
3377 try f.dg.renderTypeForBuiltinFnName(w, scalar_ty);
3378 try w.writeByte('(');
3379 try f.writeCValue(w, operand, .other);
3380 try v.elem(f, w);
3381 try w.print(", {f})", .{
3382 try f.fmtIntLiteralHex(try inst_scalar_ty.maxIntScalar(pt, scalar_ty)),
3383 });
3384 },
3385 .signed => {
3386 const c_bits = toCIntBits(scalar_int_info.bits) orelse
3387 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
3388 const shift_val = try pt.intValue(.u8, c_bits - dest_bits);
3389
3390 try w.writeAll("zig_shr_");
3391 try f.dg.renderTypeForBuiltinFnName(w, scalar_ty);
3392 if (c_bits == 128) {
3393 try w.print("(zig_bitCast_i{d}(", .{c_bits});
3394 } else {
3395 try w.print("((int{d}_t)", .{c_bits});
3396 }
3397 try w.print("zig_shl_u{d}(", .{c_bits});
3398 if (c_bits == 128) {
3399 try w.print("zig_bitCast_u{d}(", .{c_bits});
3400 } else {
3401 try w.print("(uint{d}_t)", .{c_bits});
3402 }
3403 try f.writeCValue(w, operand, .other);
3404 try v.elem(f, w);
3405 if (c_bits == 128) try w.writeByte(')');
3406 try w.print(", {f})", .{try f.fmtIntLiteralDec(shift_val)});
3407 if (c_bits == 128) try w.writeByte(')');
3408 try w.print(", {f})", .{try f.fmtIntLiteralDec(shift_val)});
3409 },
3444 try w.writeAll(", ");
34103445 }
3411 if (need_lo) try w.writeByte(')');
3412 try w.writeByte(';');
3446 if (ref_arg) {
3447 try w.writeByte('&');
3448 switch (operand) {
3449 .constant => |val| try f.dg.renderValueAsLvalue(w, val),
3450 else => try f.writeCValue(w, operand, .other),
3451 }
3452 } else try f.writeCValue(w, operand, .other);
3453 try v.elem(f, w);
3454 try f.dg.renderBuiltinInfo(w, inst_scalar_ty, info);
3455 try f.dg.renderBuiltinInfo(w, operand_scalar_ty, .none);
3456 try w.writeAll(");");
34133457 try f.newline();
34143458 try v.end(f, inst, w);
3459
34153460 return local;
34163461}
34173462
......@@ -3525,39 +3570,46 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
35253570 const ty_pl = f.air.instructions.items(.data)[@backingInt(inst)].ty_pl;
35263571 const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;
35273572
3573 const lhs_ty = f.typeOf(bin_op.lhs);
3574 const rhs_ty = f.typeOf(bin_op.rhs);
3575 const is_big = lowersToBigInt(lhs_ty, zcu);
3576
35283577 const lhs = try f.resolveInst(bin_op.lhs);
35293578 const rhs = try f.resolveInst(bin_op.rhs);
3530 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
3579 if (!is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
35313580
3532 const inst_ty = f.typeOfIndex(inst);
3533 const operand_ty = f.typeOf(bin_op.lhs);
3534 const scalar_ty = operand_ty.scalarType(zcu);
3581 const lhs_scalar_ty = lhs_ty.scalarType(zcu);
3582 const rhs_scalar_ty = rhs_ty.scalarType(zcu);
35353583
3536 const ref_arg = lowersToBigInt(scalar_ty, zcu);
3584 const ref_lhs = lowersToBigInt(lhs_scalar_ty, zcu);
3585 const ref_rhs = lowersToBigInt(rhs_scalar_ty, zcu);
35373586
35383587 const w = &f.code.writer;
3539 const local = try f.allocLocal(inst, inst_ty);
3540 const v = try Vectorize.start(f, inst, w, operand_ty);
3588 const local = try f.allocLocal(inst, f.typeOfIndex(inst));
3589 if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
3590 const v = try Vectorize.start(f, inst, w, lhs_ty);
35413591 try f.writeCValueMember(w, local, .{ .field = 1 });
35423592 try v.elem(f, w);
3543 try w.writeAll(" = zig_");
3593 try w.writeAll(" = ");
3594 try w.writeAll("zig_");
35443595 try w.writeAll(operation);
35453596 try w.writeAll("o_");
3546 try f.dg.renderTypeForBuiltinFnName(w, scalar_ty);
3597 try f.dg.renderTypeForBuiltinFnName(w, lhs_scalar_ty);
35473598 try w.writeByte('(');
35483599
35493600 // '&dest', possibly preceded by a cast
3550 switch (zcu.intern_pool.indexToKey(scalar_ty.toIntern())) {
3601 switch (zcu.intern_pool.indexToKey(lhs_scalar_ty.toIntern())) {
35513602 .int_type => {}, // we already have a '[u]intX_t *'
35523603 .simple_type => {
35533604 // '&dest' will be something like a 'uintptr_t *', which might be a different C type to
35543605 // the equivalent sized integer (e.g. 'uint64_t *'), so we need a cast. We don't need a
35553606 // cast on the *operands* because they are passed by value (except for big integers,
35563607 // where this issue doesn't exist because no "simple" int type needs bigint repr).
3557 try w.print("({s}int{d}_t *)", .{
3558 if (scalar_ty.isUnsignedInt(zcu)) "u" else "",
3559 scalar_ty.abiSize(zcu) * 8,
3560 });
3608 const inst_int_info = lhs_scalar_ty.intInfo(zcu);
3609 try w.print("({s}int{d}_t *)", .{ switch (inst_int_info.signedness) {
3610 .signed => "",
3611 .unsigned => "u",
3612 }, inst_int_info.bits });
35613613 },
35623614 else => unreachable,
35633615 }
......@@ -3566,14 +3618,24 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
35663618 try v.elem(f, w);
35673619
35683620 try w.writeAll(", ");
3569 if (ref_arg) try w.writeByte('&');
3570 try f.writeCValue(w, lhs, .other);
3621 if (ref_lhs) {
3622 try w.writeByte('&');
3623 switch (lhs) {
3624 .constant => |lhs_val| try f.dg.renderValueAsLvalue(w, lhs_val),
3625 else => try f.writeCValue(w, lhs, .other),
3626 }
3627 } else try f.writeCValue(w, lhs, .other);
35713628 try v.elem(f, w);
35723629 try w.writeAll(", ");
3573 if (ref_arg) try w.writeByte('&');
3574 try f.writeCValue(w, rhs, .other);
3575 if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w);
3576 try f.dg.renderBuiltinInfo(w, scalar_ty, info);
3630 if (ref_rhs) {
3631 try w.writeByte('&');
3632 switch (rhs) {
3633 .constant => |rhs_val| try f.dg.renderValueAsLvalue(w, rhs_val),
3634 else => try f.writeCValue(w, rhs, .other),
3635 }
3636 } else try f.writeCValue(w, rhs, .other);
3637 try v.elem(f, w);
3638 try f.dg.renderBuiltinInfo(w, lhs_scalar_ty, info);
35773639 try w.writeAll(");");
35783640 try f.newline();
35793641 try v.end(f, inst, w);
......@@ -3622,8 +3684,18 @@ fn airBinOp(
36223684 const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op;
36233685 const operand_ty = f.typeOf(bin_op.lhs);
36243686 const scalar_ty = operand_ty.scalarType(zcu);
3625 if ((scalar_ty.isInt(zcu) and scalar_ty.bitSize(zcu) > 64) or scalar_ty.isRuntimeFloat())
3626 return try airBinBuiltinCall(f, inst, operation, info);
3687
3688 builtin: {
3689 if (scalar_ty.isInt(zcu)) switch (CType.classifyInt(scalar_ty, zcu)) {
3690 .void => unreachable,
3691 .small => |int| switch (int) {
3692 else => break :builtin,
3693 .zig_u128, .zig_i128 => {},
3694 },
3695 .big => {},
3696 } else if (!scalar_ty.isRuntimeFloat()) break :builtin;
3697 return airBinBuiltinCall(f, inst, operation, info);
3698 }
36273699
36283700 const lhs = try f.resolveInst(bin_op.lhs);
36293701 const rhs = try f.resolveInst(bin_op.rhs);
......@@ -3662,19 +3734,21 @@ fn airCmpOp(
36623734 const lhs_ty = f.typeOf(data.lhs);
36633735 const scalar_ty = lhs_ty.scalarType(zcu);
36643736
3665 if (scalar_ty.isInt(zcu)) {
3666 const scalar_bits = scalar_ty.bitSize(zcu);
3667 if (scalar_bits > 64) return airCmpBuiltinCall(
3668 f,
3669 inst,
3670 data,
3671 operator,
3672 .cmp,
3673 if (scalar_bits > 128) .bits else .none,
3674 );
3737 builtin: {
3738 if (scalar_ty.isInt(zcu)) {
3739 switch (CType.classifyInt(scalar_ty, zcu)) {
3740 .void => unreachable,
3741 .small => |int| switch (int) {
3742 else => break :builtin,
3743 .zig_u128, .zig_i128 => {},
3744 },
3745 .big => {},
3746 }
3747 return airCmpBuiltinCall(f, inst, data, operator, .cmp, .none);
3748 }
3749 if (scalar_ty.isRuntimeFloat())
3750 return airCmpBuiltinCall(f, inst, data, operator, .operator, .none);
36753751 }
3676 if (scalar_ty.isRuntimeFloat())
3677 return airCmpBuiltinCall(f, inst, data, operator, .operator, .none);
36783752
36793753 const inst_ty = f.typeOfIndex(inst);
36803754 const lhs = try f.resolveInst(data.lhs);
......@@ -3716,21 +3790,23 @@ fn airEquality(
37163790 const pt = f.dg.pt;
37173791 const zcu = pt.zcu;
37183792 const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op;
3719
37203793 const operand_ty = f.typeOf(bin_op.lhs);
3721 if (operand_ty.isAbiInt(zcu)) {
3722 const operand_bits = operand_ty.bitSize(zcu);
3723 if (operand_bits > 64) return airCmpBuiltinCall(
3724 f,
3725 inst,
3726 bin_op,
3727 operator,
3728 .cmp,
3729 if (operand_bits > 128) .bits else .none,
3730 );
3794
3795 builtin: {
3796 if (operand_ty.isAbiInt(zcu)) {
3797 switch (CType.classifyInt(operand_ty, zcu)) {
3798 .void => unreachable,
3799 .small => |int| switch (int) {
3800 else => break :builtin,
3801 .zig_u128, .zig_i128 => {},
3802 },
3803 .big => {},
3804 }
3805 return airCmpBuiltinCall(f, inst, bin_op, operator, .cmp, .none);
3806 }
3807 if (operand_ty.isRuntimeFloat())
3808 return airCmpBuiltinCall(f, inst, bin_op, operator, .operator, .none);
37313809 }
3732 if (operand_ty.isRuntimeFloat())
3733 return airCmpBuiltinCall(f, inst, bin_op, operator, .operator, .none);
37343810
37353811 const lhs = try f.resolveInst(bin_op.lhs);
37363812 const rhs = try f.resolveInst(bin_op.rhs);
......@@ -3809,7 +3885,7 @@ fn airCmpLteErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {
38093885 try f.writeCValue(w, local, .other);
38103886 try w.writeAll(" = ");
38113887 try f.writeCValue(w, operand, .other);
3812 try w.writeAll(" < sizeof(zig_errorName) / sizeof(*zig_errorName);");
3888 try w.writeAll(" <= sizeof(zig_errorName) / sizeof(*zig_errorName);");
38133889 try f.newline();
38143890 return local;
38153891}
......@@ -3862,8 +3938,17 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons
38623938 const inst_ty = f.typeOfIndex(inst);
38633939 const inst_scalar_ty = inst_ty.scalarType(zcu);
38643940
3865 if ((inst_scalar_ty.isInt(zcu) and inst_scalar_ty.bitSize(zcu) > 64) or inst_scalar_ty.isRuntimeFloat())
3866 return try airBinBuiltinCall(f, inst, operation, .none);
3941 builtin: {
3942 if (inst_scalar_ty.isInt(zcu)) switch (CType.classifyInt(inst_scalar_ty, zcu)) {
3943 .void => unreachable,
3944 .small => |int| switch (int) {
3945 else => break :builtin,
3946 .zig_u128, .zig_i128 => {},
3947 },
3948 .big => {},
3949 } else if (!inst_scalar_ty.isRuntimeFloat()) break :builtin;
3950 return airBinBuiltinCall(f, inst, operation, .none);
3951 }
38673952
38683953 const lhs = try f.resolveInst(bin_op.lhs);
38693954 const rhs = try f.resolveInst(bin_op.rhs);
......@@ -3979,10 +4064,7 @@ fn airCall(
39794064 try w.writeAll("(void)");
39804065 break :result .none;
39814066 } else {
3982 const local = try f.allocAlignedLocal(inst, .{
3983 .type = ret_ty,
3984 .alignment = .none,
3985 });
4067 const local = try f.allocAlignedLocal(inst, .{ .type = ret_ty });
39864068 try f.writeCValue(w, local, .other);
39874069 try w.writeAll(" = ");
39884070 break :result local;
......@@ -4058,16 +4140,7 @@ fn airCall(
40584140fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
40594141 const dbg_stmt = f.air.instructions.items(.data)[@backingInt(inst)].dbg_stmt;
40604142 const w = &f.code.writer;
4061 // TODO re-evaluate whether to emit these or not. If we naively emit
4062 // these directives, the output file will report bogus line numbers because
4063 // every newline after the #line directive adds one to the line.
4064 // We also don't print the filename yet, so the output is strictly unhelpful.
4065 // If we wanted to go this route, we would need to go all the way and not output
4066 // newlines until the next dbg_stmt occurs.
4067 // Perhaps an additional compilation option is in order?
4068 //try w.print("#line {d}", .{dbg_stmt.line + 1});
4069 //try f.newline();
4070 try w.print("/* file:{d}:{d} */", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 });
4143 try w.print("/* {d}:{d} */", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 });
40714144 try f.newline();
40724145 return .none;
40734146}
......@@ -4433,12 +4506,12 @@ fn airBitCast(f: *Function, inst: Air.Inst.Index) Error!CValue {
44334506 const operand_scalar_ty = operand_ty.scalarType(zcu);
44344507 const dest_scalar_ty = dest_ty.scalarType(zcu);
44354508
4436 // Some cases are handled with a simple cast:
4437 // * float -> float
4438 // * bool -> int
44394509 if ((operand_scalar_ty.isRuntimeFloat() and dest_scalar_ty.isRuntimeFloat()) or
44404510 (operand_scalar_ty.toIntern() == .bool_type and dest_scalar_ty.isAbiInt(zcu)))
44414511 {
4512 // Some cases are handled with a simple cast:
4513 // * float -> float
4514 // * bool -> int
44424515 try f.writeCValue(w, dest_local, .other);
44434516 try v.elem(f, w);
44444517 try w.writeAll(" = (");
......@@ -4458,85 +4531,44 @@ fn airBitCast(f: *Function, inst: Air.Inst.Index) Error!CValue {
44584531 try v.elem(f, w);
44594532 try w.writeAll(" != 0;");
44604533 try f.newline();
4461 } else if (dest_scalar_ty.isRuntimeFloat()) {
4462 // For int->float, just do a memcpy.
4463 assert(operand_scalar_ty.isAbiInt(zcu));
4464 try w.writeAll("memcpy(&");
4465 try f.writeCValue(w, dest_local, .other);
4466 try v.elem(f, w);
4467 try w.writeAll(", &");
4468 switch (operand) {
4469 .constant => |val| try f.dg.renderValueAsLvalue(w, val),
4470 else => try f.writeCValue(w, operand, .other),
4471 }
4472 try v.elem(f, w);
4473 try w.print(", {d});", .{@min(operand_scalar_ty.abiSize(zcu), dest_scalar_ty.abiSize(zcu))});
4474 try f.newline();
44754534 } else {
4476 // The only remaining possibility is that the result is an integer. We will need to use
4477 // `zig_wrap_*` to correct the "padding" bits after we populate the value bits.
4478 assert(dest_scalar_ty.isAbiInt(zcu));
44794535 assert(operand_scalar_ty.isRuntimeFloat() or operand_scalar_ty.isAbiInt(zcu));
4536 assert(dest_scalar_ty.isRuntimeFloat() or dest_scalar_ty.isAbiInt(zcu));
44804537
4481 // memcpy the value...
4482 try w.writeAll("memcpy(&");
4483 try f.writeCValue(w, dest_local, .other);
4484 try v.elem(f, w);
4485 try w.writeAll(", &");
4486 switch (operand) {
4487 .constant => |val| try f.dg.renderValueAsLvalue(w, val),
4488 else => try f.writeCValue(w, operand, .other),
4538 const ref_ret = lowersToBigInt(dest_scalar_ty, zcu);
4539 const ref_arg = lowersToBigInt(operand_scalar_ty, zcu);
4540
4541 if (!ref_ret) {
4542 try f.writeCValue(w, dest_local, .other);
4543 try v.elem(f, w);
4544 try w.writeAll(" = ");
44894545 }
4546 try w.writeAll("zig_");
4547 try f.dg.renderTypeForBuiltinFnName(w, dest_scalar_ty);
4548 try w.writeAll("_bitCast_");
4549 try f.dg.renderTypeForBuiltinFnName(w, operand_scalar_ty);
4550 try w.writeByte('(');
4551 if (ref_ret) {
4552 try w.writeByte('&');
4553 try f.writeCValue(w, dest_local, .other);
4554 try v.elem(f, w);
4555 try w.writeAll(", ");
4556 }
4557 if (ref_arg) {
4558 try w.writeByte('&');
4559 switch (operand) {
4560 .constant => |val| try f.dg.renderValueAsLvalue(w, val),
4561 else => try f.writeCValue(w, operand, .other),
4562 }
4563 } else try f.writeCValue(w, operand, .other);
44904564 try v.elem(f, w);
4491 try w.print(", {d});", .{@min(operand_scalar_ty.abiSize(zcu), dest_scalar_ty.abiSize(zcu))});
4565 try f.dg.renderBuiltinInfo(
4566 w,
4567 dest_scalar_ty,
4568 if (operand_scalar_ty.isRuntimeFloat() or dest_scalar_ty.isRuntimeFloat()) .none else .bits,
4569 );
4570 try w.writeAll(");");
44924571 try f.newline();
4493
4494 // ...and ensure padding bits have the correct value.
4495 switch (CType.classifyInt(dest_scalar_ty, zcu)) {
4496 .void => unreachable, // opv
4497 .small => {
4498 try f.writeCValue(w, dest_local, .other);
4499 try v.elem(f, w);
4500 try w.writeAll(" = zig_wrap_");
4501 try f.dg.renderTypeForBuiltinFnName(w, dest_scalar_ty);
4502 try w.writeByte('(');
4503 try f.writeCValue(w, dest_local, .other);
4504 try v.elem(f, w);
4505 try f.dg.renderBuiltinInfo(w, dest_scalar_ty, .bits);
4506 try w.writeAll(");");
4507 try f.newline();
4508 },
4509 .big => |big| {
4510 const dest_info = dest_scalar_ty.intInfo(zcu);
4511 const padding_index: u16 = switch (f.dg.mod.resolved_target.result.cpu.arch.endian()) {
4512 .little => big.limbs_len - 1,
4513 .big => 0,
4514 };
4515 const wrap_bits = ((dest_info.bits - 1) % big.limb_size.bits()) + 1;
4516 if (big.limb_size != .@"128" or dest_info.signedness == .unsigned) {
4517 try f.writeCValue(w, dest_local, .other);
4518 try v.elem(f, w);
4519 try w.print(".limbs[{d}] = zig_wrap_{c}{d}(", .{
4520 padding_index,
4521 signAbbrev(dest_info.signedness),
4522 big.limb_size.bits(),
4523 });
4524 try f.writeCValue(w, dest_local, .other);
4525 try v.elem(f, w);
4526 try w.print(".limbs[{d}], {d});", .{ padding_index, wrap_bits });
4527 } else {
4528 try f.writeCValue(w, dest_local, .other);
4529 try v.elem(f, w);
4530 try w.print(".limbs[{d}] = zig_bitCast_u128(zig_wrap_i128(zig_bitCast_i128(", .{
4531 padding_index,
4532 });
4533 try f.writeCValue(w, dest_local, .other);
4534 try v.elem(f, w);
4535 try w.print(".limbs[{d}]), {d}));", .{ padding_index, wrap_bits });
4536 try f.newline();
4537 }
4538 },
4539 }
45404572 }
45414573
45424574 try v.end(f, inst, w);
......@@ -4906,11 +4938,9 @@ fn lowerSwitchCmp(
49064938
49074939fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool {
49084940 const dg = f.dg;
4909 const target = &dg.mod.resolved_target.result;
49104941 return switch (constraint[0]) {
49114942 '{' => true,
4912 'i', 'r' => false,
4913 'I' => !target.cpu.arch.isArm(),
4943 'r', 'i', 'n', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P' => false,
49144944 else => switch (value) {
49154945 .constant => |val| switch (dg.pt.zcu.intern_pool.indexToKey(val.toIntern())) {
49164946 .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) {
......@@ -4937,10 +4967,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
49374967 const w = &f.code.writer;
49384968 const inst_ty = f.typeOfIndex(inst);
49394969 const inst_local = if (inst_ty.hasRuntimeBits(zcu)) local: {
4940 const inst_local = try f.allocLocalValue(.{
4941 .type = inst_ty,
4942 .alignment = .none,
4943 });
4970 const inst_local = try f.allocLocalValue(.{ .type = inst_ty });
49444971 if (f.wantSafety()) {
49454972 try f.writeCValue(w, inst_local, .other);
49464973 try w.writeAll(" = ");
......@@ -4967,10 +4994,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
49674994 if (is_reg) {
49684995 const output_ty = if (output.operand == .none) inst_ty else f.typeOf(output.operand).childType(zcu);
49694996 try w.writeAll("register ");
4970 const output_local = try f.allocLocalValue(.{
4971 .type = output_ty,
4972 .alignment = .none,
4973 });
4997 const output_local = try f.allocLocalValue(.{ .type = output_ty });
49744998 try f.allocs.put(gpa, output_local.new_local, false);
49754999 try f.dg.renderTypeAndName(w, output_ty, output_local, .{}, .none);
49765000 try w.writeAll(" __asm(\"");
......@@ -4989,7 +5013,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
49895013 while (it.next()) |input| {
49905014 const constraint = input.constraint;
49915015
4992 if (constraint.len < 1 or mem.indexOfScalar(u8, "=+&%", constraint[0]) != null or
5016 if (constraint.len < 1 or mem.findScalar(u8, "=+&%", constraint[0]) != null or
49935017 (constraint[0] == '{' and constraint[constraint.len - 1] != '}'))
49945018 {
49955019 return f.fail("CBE: constraint not supported: '{s}'", .{constraint});
......@@ -5000,10 +5024,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
50005024 if (asmInputNeedsLocal(f, constraint, input_val)) {
50015025 const input_ty = f.typeOf(input.operand);
50025026 if (is_reg) try w.writeAll("register ");
5003 const input_local = try f.allocLocalValue(.{
5004 .type = input_ty,
5005 .alignment = .none,
5006 });
5027 const input_local = try f.allocLocalValue(.{ .type = input_ty });
50075028 try f.allocs.put(gpa, input_local.new_local, false);
50085029 // Do not render the declaration as `const` qualified if we're generating an
50095030 // explicit `register` local, as GCC will ignore the constraint completely.
......@@ -5056,7 +5077,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
50565077 }
50575078
50585079 const desc = mem.sliceTo(asm_source[src_i..], ']');
5059 if (mem.indexOfScalar(u8, desc, ':')) |colon| {
5080 if (mem.findScalar(u8, desc, ':')) |colon| {
50605081 const name = desc[0..colon];
50615082 const modifier = desc[colon + 1 ..];
50625083
......@@ -5853,28 +5874,124 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
58535874 else
58545875 unreachable;
58555876
5877 const ref_ret = lowersToBigInt(inst_scalar_ty, zcu);
5878 const ref_operand = lowersToBigInt(scalar_ty, zcu);
5879
58565880 const w = &f.code.writer;
58575881 const local = try f.allocLocal(inst, inst_ty);
58585882 const v = try Vectorize.start(f, inst, w, operand_ty);
5859 try f.writeCValue(w, local, .other);
5860 try v.elem(f, w);
5861 try w.writeAll(" = ");
5883 if (ref_ret) {
5884 const inst_int_info = inst_scalar_ty.intInfo(zcu);
5885 if (inst_int_info.bits <= 128) {
5886 try w.writeAll("zig_");
5887 try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty);
5888 try w.print("_intCast_{c}{d}", .{
5889 @as(u8, switch (inst_int_info.signedness) {
5890 .signed => 'i',
5891 .unsigned => 'u',
5892 }),
5893 std.math.ceilPowerOfTwoAssert(u16, @max(inst_int_info.bits, 32)),
5894 });
5895 try w.writeAll("(&");
5896 try f.writeCValue(w, local, .other);
5897 try v.elem(f, w);
5898 try w.writeAll(", ");
5899 }
5900 } else {
5901 try f.writeCValue(w, local, .other);
5902 try v.elem(f, w);
5903 try w.writeAll(" = ");
5904 }
58625905 if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) {
5863 try w.writeAll("zig_wrap_");
5864 try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty);
5865 try w.writeByte('(');
5906 const inst_int_info = inst_scalar_ty.intInfo(zcu);
5907 if (inst_int_info.bits <= 128) try w.print("zig_{c}{d}_truncate_{[0]c}{[1]d}(", .{
5908 @as(u8, switch (inst_int_info.signedness) {
5909 .signed => 'i',
5910 .unsigned => 'u',
5911 }),
5912 std.math.ceilPowerOfTwoAssert(u16, @max(inst_int_info.bits, 32)),
5913 });
58665914 }
58675915 try w.writeAll("zig_");
58685916 try w.writeAll(operation);
58695917 try w.writeAll(compilerRtAbbrev(scalar_ty, zcu, target));
58705918 try w.writeAll(compilerRtAbbrev(inst_scalar_ty, zcu, target));
58715919 try w.writeByte('(');
5872 try f.writeCValue(w, operand, .other);
5873 try v.elem(f, w);
5920 if (ref_ret) {
5921 const inst_int_info = inst_scalar_ty.intInfo(zcu);
5922 if (inst_int_info.bits > 128) {
5923 try w.writeByte('&');
5924 try f.writeCValue(w, local, .other);
5925 try v.elem(f, w);
5926 try w.writeAll(", ");
5927 }
5928 }
5929 if (ref_operand) {
5930 const operand_int_info = scalar_ty.intInfo(zcu);
5931 if (operand_int_info.bits <= 128) {
5932 try w.print("zig_{c}{d}_intCast_", .{
5933 @as(u8, switch (operand_int_info.signedness) {
5934 .signed => 'i',
5935 .unsigned => 'u',
5936 }),
5937 std.math.ceilPowerOfTwoAssert(u16, @max(operand_int_info.bits, 32)),
5938 });
5939 try f.dg.renderTypeForBuiltinFnName(w, scalar_ty);
5940 try w.writeAll("(&");
5941 switch (operand) {
5942 .constant => |val| try f.dg.renderValueAsLvalue(w, val),
5943 else => try f.writeCValue(w, operand, .other),
5944 }
5945 try v.elem(f, w);
5946 try f.dg.renderBuiltinInfo(w, scalar_ty, .none);
5947 try w.writeByte(')');
5948 } else {
5949 try w.writeByte('&');
5950 switch (operand) {
5951 .constant => |val| try f.dg.renderValueAsLvalue(w, val),
5952 else => try f.writeCValue(w, operand, .other),
5953 }
5954 try v.elem(f, w);
5955 try w.print(", {f}", .{fmtUnsignedIntLiteralSmall(
5956 target,
5957 .uint16_t,
5958 operand_int_info.bits,
5959 false,
5960 10,
5961 .lower,
5962 )});
5963 }
5964 } else {
5965 try f.writeCValue(w, operand, .other);
5966 try v.elem(f, w);
5967 }
5968 if (ref_ret) {
5969 const inst_int_info = inst_scalar_ty.intInfo(zcu);
5970 if (inst_int_info.bits > 128) try w.print(", {f}", .{fmtUnsignedIntLiteralSmall(
5971 target,
5972 .uint16_t,
5973 inst_int_info.bits,
5974 false,
5975 10,
5976 .lower,
5977 )});
5978 }
58745979 try w.writeByte(')');
58755980 if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) {
5876 try f.dg.renderBuiltinInfo(w, inst_scalar_ty, .bits);
5877 try w.writeByte(')');
5981 const inst_int_info = inst_scalar_ty.intInfo(zcu);
5982 if (inst_int_info.bits <= 128) {
5983 try w.print(", {f}", .{
5984 try f.dg.fmtIntLiteralDec(try pt.intValue(.u8, inst_int_info.bits), .other),
5985 });
5986 try w.writeByte(')');
5987 }
5988 }
5989 if (ref_ret) {
5990 const inst_int_info = inst_scalar_ty.intInfo(zcu);
5991 if (inst_int_info.bits <= 128) {
5992 try f.dg.renderBuiltinInfo(w, inst_scalar_ty, .none);
5993 try w.writeByte(')');
5994 }
58785995 }
58795996 try w.writeByte(';');
58805997 try f.newline();
......@@ -5893,18 +6010,21 @@ fn airUnBuiltinCall(
58936010 const pt = f.dg.pt;
58946011 const zcu = pt.zcu;
58956012
5896 const operand = try f.resolveInst(operand_ref);
5897 try reap(f, inst, &.{operand_ref});
58986013 const inst_ty = f.typeOfIndex(inst);
58996014 const inst_scalar_ty = inst_ty.scalarType(zcu);
59006015 const operand_ty = f.typeOf(operand_ref);
59016016 const scalar_ty = operand_ty.scalarType(zcu);
6017 const is_big = lowersToBigInt(operand_ty, zcu);
6018
6019 const operand = try f.resolveInst(operand_ref);
6020 if (!is_big) try reap(f, inst, &.{operand_ref});
59026021
59036022 const ref_ret = lowersToBigInt(inst_scalar_ty, zcu);
59046023 const ref_arg = lowersToBigInt(scalar_ty, zcu);
59056024
59066025 const w = &f.code.writer;
59076026 const local = try f.allocLocal(inst, inst_ty);
6027 if (is_big) try reap(f, inst, &.{operand_ref});
59086028 const v = try Vectorize.start(f, inst, w, operand_ty);
59096029 if (!ref_ret) {
59106030 try f.writeCValue(w, local, .other);
......@@ -5920,8 +6040,13 @@ fn airUnBuiltinCall(
59206040 try v.elem(f, w);
59216041 try w.writeAll(", ");
59226042 }
5923 if (ref_arg) try w.writeByte('&');
5924 try f.writeCValue(w, operand, .other);
6043 if (ref_arg) {
6044 try w.writeByte('&');
6045 switch (operand) {
6046 .constant => |val| try f.dg.renderValueAsLvalue(w, val),
6047 else => try f.writeCValue(w, operand, .other),
6048 }
6049 } else try f.writeCValue(w, operand, .other);
59256050 try v.elem(f, w);
59266051 try f.dg.renderBuiltinInfo(w, scalar_ty, info);
59276052 try w.writeAll(");");
......@@ -5941,8 +6066,9 @@ fn airBinBuiltinCall(
59416066 const zcu = pt.zcu;
59426067 const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op;
59436068
5944 const operand_ty = f.typeOf(bin_op.lhs);
5945 const is_big = lowersToBigInt(operand_ty, zcu);
6069 const lhs_ty = f.typeOf(bin_op.lhs);
6070 const rhs_ty = f.typeOf(bin_op.rhs);
6071 const is_big = lowersToBigInt(lhs_ty, zcu);
59466072
59476073 const lhs = try f.resolveInst(bin_op.lhs);
59486074 const rhs = try f.resolveInst(bin_op.rhs);
......@@ -5950,22 +6076,31 @@ fn airBinBuiltinCall(
59506076
59516077 const inst_ty = f.typeOfIndex(inst);
59526078 const inst_scalar_ty = inst_ty.scalarType(zcu);
5953 const scalar_ty = operand_ty.scalarType(zcu);
6079 const lhs_scalar_ty = lhs_ty.scalarType(zcu);
6080 const rhs_scalar_ty = rhs_ty.scalarType(zcu);
59546081
59556082 const ref_ret = lowersToBigInt(inst_scalar_ty, zcu);
5956 const ref_arg = lowersToBigInt(scalar_ty, zcu);
6083 const ref_lhs = lowersToBigInt(lhs_scalar_ty, zcu);
6084 const ref_rhs = lowersToBigInt(rhs_scalar_ty, zcu);
59576085
59586086 const w = &f.code.writer;
59596087 const local = try f.allocLocal(inst, inst_ty);
59606088 if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
5961 const v = try Vectorize.start(f, inst, w, operand_ty);
6089 const v = try Vectorize.start(f, inst, w, lhs_ty);
59626090 if (!ref_ret) {
59636091 try f.writeCValue(w, local, .other);
59646092 try v.elem(f, w);
59656093 try w.writeAll(" = ");
59666094 }
59676095 try w.print("zig_{s}_", .{operation});
5968 try f.dg.renderTypeForBuiltinFnName(w, scalar_ty);
6096 try f.dg.renderTypeForBuiltinFnName(w, lhs_scalar_ty);
6097 switch (info) {
6098 .bits, .none, .big_temp_bits => {},
6099 .bits_none => {
6100 try w.writeByte('_');
6101 try f.dg.renderTypeForBuiltinFnName(w, rhs_scalar_ty);
6102 },
6103 }
59696104 try w.writeByte('(');
59706105 if (ref_ret) {
59716106 try w.writeByte('&');
......@@ -5973,15 +6108,45 @@ fn airBinBuiltinCall(
59736108 try v.elem(f, w);
59746109 try w.writeAll(", ");
59756110 }
5976 if (ref_arg) try w.writeByte('&');
5977 try f.writeCValue(w, lhs, .other);
6111 if (ref_lhs) {
6112 try w.writeByte('&');
6113 switch (lhs) {
6114 .constant => |lhs_val| try f.dg.renderValueAsLvalue(w, lhs_val),
6115 else => try f.writeCValue(w, lhs, .other),
6116 }
6117 } else try f.writeCValue(w, lhs, .other);
59786118 try v.elem(f, w);
59796119 try w.writeAll(", ");
5980 if (ref_arg) try w.writeByte('&');
5981 try f.writeCValue(w, rhs, .other);
5982 if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w);
5983 try f.dg.renderBuiltinInfo(w, scalar_ty, info);
5984 try w.writeAll(");\n");
6120 if (ref_rhs) {
6121 try w.writeByte('&');
6122 switch (rhs) {
6123 .constant => |rhs_val| try f.dg.renderValueAsLvalue(w, rhs_val),
6124 else => try f.writeCValue(w, rhs, .other),
6125 }
6126 } else try f.writeCValue(w, rhs, .other);
6127 try v.elem(f, w);
6128 try f.dg.renderBuiltinInfo(w, lhs_scalar_ty, info: switch (info) {
6129 .none => .none,
6130 .bits, .bits_none => .bits,
6131 .big_temp_bits => {
6132 if (lowersToBigInt(lhs_scalar_ty, zcu)) {
6133 const temp_local = try f.allocAlignedLocal(inst, .{
6134 .type = lhs_scalar_ty,
6135 .array_len = 2,
6136 });
6137 try w.writeAll(", &");
6138 try f.writeCValue(w, temp_local, .other);
6139 try freeLocal(f, inst, temp_local.new_local, null);
6140 }
6141 break :info .none;
6142 },
6143 });
6144 switch (info) {
6145 .none, .bits, .big_temp_bits => {},
6146 .bits_none => try f.dg.renderBuiltinInfo(w, rhs_scalar_ty, .none),
6147 }
6148 try w.writeAll(");");
6149 try f.newline();
59856150 try v.end(f, inst, w);
59866151
59876152 return local;
......@@ -6029,12 +6194,22 @@ fn airCmpBuiltinCall(
60296194 try v.elem(f, w);
60306195 try w.writeAll(", ");
60316196 }
6032 if (ref_arg) try w.writeByte('&');
6033 try f.writeCValue(w, lhs, .other);
6197 if (ref_arg) {
6198 try w.writeByte('&');
6199 switch (lhs) {
6200 .constant => |lhs_val| try f.dg.renderValueAsLvalue(w, lhs_val),
6201 else => try f.writeCValue(w, lhs, .other),
6202 }
6203 } else try f.writeCValue(w, lhs, .other);
60346204 try v.elem(f, w);
60356205 try w.writeAll(", ");
6036 if (ref_arg) try w.writeByte('&');
6037 try f.writeCValue(w, rhs, .other);
6206 if (ref_arg) {
6207 try w.writeByte('&');
6208 switch (rhs) {
6209 .constant => |rhs_val| try f.dg.renderValueAsLvalue(w, rhs_val),
6210 else => try f.writeCValue(w, rhs, .other),
6211 }
6212 } else try f.writeCValue(w, rhs, .other);
60386213 try v.elem(f, w);
60396214 try f.dg.renderBuiltinInfo(w, scalar_ty, info);
60406215 try w.writeByte(')');
......@@ -6595,7 +6770,8 @@ fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue {
65956770 },
65966771 .value => |val| try f.dg.renderValue(w, .fromInterned(val), .other),
65976772 }
6598 try w.writeAll(";\n");
6773 try w.writeByte(';');
6774 try f.newline();
65996775 }
66006776
66016777 return local;
......@@ -6653,7 +6829,14 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
66536829 const operand_ty = f.typeOf(reduce.operand);
66546830 const w = &f.code.writer;
66556831
6656 const use_operator = scalar_ty.bitSize(zcu) <= 64;
6832 const use_operator, const is_big = if (scalar_ty.isInt(zcu)) switch (CType.classifyInt(scalar_ty, zcu)) {
6833 .void => unreachable,
6834 .small => |int| switch (int) {
6835 else => .{ true, false },
6836 .zig_u128, .zig_i128 => .{ false, false },
6837 },
6838 .big => .{ false, true },
6839 } else .{ false, false };
66576840 const op: union(enum) {
66586841 const Func = struct { operation: []const u8, info: BuiltinInfo = .none };
66596842 builtin: Func,
......@@ -6742,25 +6925,57 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
67426925 try f.newline();
67436926
67446927 const v = try Vectorize.start(f, inst, w, operand_ty);
6745 try f.writeCValue(w, accum, .other);
67466928 switch (op) {
67476929 .builtin => |func| {
6748 try w.print(" = zig_{s}_", .{func.operation});
6930 const prev_accum = if (is_big) prev_accum: {
6931 const prev_accum = try f.allocLocal(inst, scalar_ty);
6932 try f.writeCValue(w, prev_accum, .other);
6933 try w.writeAll(" = ");
6934 try f.writeCValue(w, accum, .other);
6935 try w.writeByte(';');
6936 try f.newline();
6937 break :prev_accum prev_accum;
6938 } else prev_accum: {
6939 try f.writeCValue(w, accum, .other);
6940 try w.writeAll(" = ");
6941 break :prev_accum accum;
6942 };
6943 try w.print("zig_{s}_", .{func.operation});
67496944 try f.dg.renderTypeForBuiltinFnName(w, scalar_ty);
67506945 try w.writeByte('(');
6751 try f.writeCValue(w, accum, .other);
6946 if (is_big) {
6947 try w.writeByte('&');
6948 switch (accum) {
6949 .constant => |val| try f.dg.renderValueAsLvalue(w, val),
6950 else => try f.writeCValue(w, accum, .other),
6951 }
6952 try w.writeAll(", &");
6953 switch (prev_accum) {
6954 .constant => |val| try f.dg.renderValueAsLvalue(w, val),
6955 else => try f.writeCValue(w, prev_accum, .other),
6956 }
6957 } else try f.writeCValue(w, prev_accum, .other);
67526958 try w.writeAll(", ");
6753 try f.writeCValue(w, operand, .other);
6959 if (is_big) {
6960 try w.writeByte('&');
6961 switch (operand) {
6962 .constant => |val| try f.dg.renderValueAsLvalue(w, val),
6963 else => try f.writeCValue(w, operand, .other),
6964 }
6965 } else try f.writeCValue(w, operand, .other);
67546966 try v.elem(f, w);
67556967 try f.dg.renderBuiltinInfo(w, scalar_ty, func.info);
67566968 try w.writeByte(')');
6969 if (is_big) try freeLocal(f, inst, prev_accum.new_local, null);
67576970 },
67586971 .infix => |ass| {
6972 try f.writeCValue(w, accum, .other);
67596973 try w.writeAll(ass);
67606974 try f.writeCValue(w, operand, .other);
67616975 try v.elem(f, w);
67626976 },
67636977 .ternary => |cmp| {
6978 try f.writeCValue(w, accum, .other);
67646979 try w.writeAll(" = ");
67656980 try f.writeCValue(w, accum, .other);
67666981 try w.writeAll(cmp);
......@@ -7097,101 +7312,6 @@ fn writeMemoryOrder(w: *Writer, order: std.lang.AtomicOrder) !void {
70977312 return w.writeAll(toMemoryOrder(order));
70987313}
70997314
7100fn toCallingConvention(cc: std.lang.CallingConvention, zcu: *Zcu) ?[]const u8 {
7101 if (zcu.getTarget().cCallingConvention()) |ccc| {
7102 if (cc.eql(ccc)) {
7103 return null;
7104 }
7105 }
7106 return switch (cc) {
7107 .auto, .naked => null,
7108
7109 .x86_16_cdecl => "cdecl",
7110 .x86_16_regparmcall => "regparmcall",
7111 .x86_64_sysv, .x86_sysv => "sysv_abi",
7112 .x86_64_win, .x86_win => "ms_abi",
7113 .x86_16_stdcall, .x86_stdcall => "stdcall",
7114 .x86_fastcall => "fastcall",
7115 .x86_thiscall => "thiscall",
7116
7117 .x86_vectorcall,
7118 .x86_64_vectorcall,
7119 => "vectorcall",
7120
7121 .x86_64_regcall_v3_sysv,
7122 .x86_64_regcall_v4_win,
7123 .x86_regcall_v3,
7124 .x86_regcall_v4_win,
7125 => "regcall",
7126
7127 .aarch64_vfabi => "aarch64_vector_pcs",
7128 .aarch64_vfabi_sve => "aarch64_sve_pcs",
7129
7130 .arm_aapcs => "pcs(\"aapcs\")",
7131 .arm_aapcs_vfp => "pcs(\"aapcs-vfp\")",
7132
7133 .arc_interrupt => |opts| switch (opts.type) {
7134 inline else => |t| "interrupt(\"" ++ @tagName(t) ++ "\")",
7135 },
7136
7137 .arm_interrupt => |opts| switch (opts.type) {
7138 .generic => "interrupt",
7139 .irq => "interrupt(\"IRQ\")",
7140 .fiq => "interrupt(\"FIQ\")",
7141 .swi => "interrupt(\"SWI\")",
7142 .abort => "interrupt(\"ABORT\")",
7143 .undef => "interrupt(\"UNDEF\")",
7144 },
7145
7146 .avr_signal => "signal",
7147
7148 .microblaze_interrupt => |opts| switch (opts.type) {
7149 .user => "save_volatiles",
7150 .regular => "interrupt_handler",
7151 .fast => "fast_interrupt",
7152 .breakpoint => "break_handler",
7153 },
7154
7155 .mips_interrupt,
7156 .mips64_interrupt,
7157 => |opts| switch (opts.mode) {
7158 inline else => |m| "interrupt(\"" ++ @tagName(m) ++ "\")",
7159 },
7160
7161 .riscv64_lp64_v, .riscv32_ilp32_v => "riscv_vector_cc",
7162
7163 .riscv32_interrupt,
7164 .riscv64_interrupt,
7165 => |opts| switch (opts.mode) {
7166 inline else => |m| "interrupt(\"" ++ @tagName(m) ++ "\")",
7167 },
7168
7169 .sh_renesas => "renesas",
7170 .sh_interrupt => |opts| switch (opts.save) {
7171 .fpscr => "trapa_handler", // Implies `interrupt_handler`.
7172 .high => "interrupt_handler, nosave_low_regs",
7173 .full => "interrupt_handler",
7174 .bank => "interrupt_handler, resbank",
7175 },
7176
7177 .m68k_rtd => "m68k_rtd",
7178
7179 .avr_interrupt,
7180 .csky_interrupt,
7181 .m68k_interrupt,
7182 .msp430_interrupt,
7183 .x86_16_interrupt,
7184 .x86_interrupt,
7185 .x86_64_interrupt,
7186 => "interrupt",
7187
7188 .ez80_tiflags,
7189 => "__tiflags__",
7190
7191 else => unreachable, // `Zcu.callconvSupported`
7192 };
7193}
7194
71957315fn toAtomicRmwSuffix(order: std.lang.AtomicRmwOp) []const u8 {
71967316 return switch (order) {
71977317 .Xchg => "xchg",
......@@ -7224,17 +7344,18 @@ fn signAbbrev(signedness: std.lang.Signedness) u8 {
72247344
72257345fn compilerRtAbbrev(ty: Type, zcu: *Zcu, target: *const std.Target) []const u8 {
72267346 return if (ty.isInt(zcu)) switch (ty.intInfo(zcu).bits) {
7347 0 => unreachable,
72277348 1...32 => "si",
72287349 33...64 => "di",
72297350 65...128 => "ti",
7230 else => unreachable,
7351 else => "ei",
72317352 } else if (ty.isRuntimeFloat()) switch (ty.floatBits(target)) {
7353 else => unreachable,
72327354 16 => "hf",
72337355 32 => "sf",
72347356 64 => "df",
72357357 80 => "xf",
7236 128 => "tf",
7237 else => unreachable,
7358 128 => if (target.cpu.arch.isPowerPC()) "kf" else "tf",
72387359 } else unreachable;
72397360}
72407361
......@@ -7390,10 +7511,8 @@ fn fmtStringLiteral(str: []const u8, sentinel: ?u8) std.fmt.Alt(FormatStringCont
73907511 return .{ .data = .{ .str = str, .sentinel = sentinel } };
73917512}
73927513
7393fn undefPattern(comptime IntType: type) IntType {
7394 const int_info = @typeInfo(IntType).int;
7395 const UnsignedType = @Int(.unsigned, int_info.bits);
7396 return @bitCast(@as(UnsignedType, (1 << (int_info.bits | 1)) / 3));
7514fn undefPattern(comptime Result: type) Result {
7515 return @bitCast(@as(@Int(.unsigned, @bitSizeOf(Result)), (1 << (@bitSizeOf(Result) | 1)) / 3));
73977516}
73987517
73997518const FormatIntLiteralContext = struct {
......@@ -7580,11 +7699,9 @@ const FormatSignedIntLiteralSmall = struct {
75807699 case: std.fmt.Case,
75817700 pub fn format(data: FormatSignedIntLiteralSmall, w: *Writer) Writer.Error!void {
75827701 const bits = data.int_cty.bits(data.target);
7583 const max_int: i64 = @bitCast((@as(u64, 1) << @intCast(bits - 1)) - 1);
7584 const min_int: i64 = @bitCast(@as(u64, 1) << @intCast(bits - 1));
7585 if (data.val == max_int) {
7702 if (data.val == @as(i64, std.math.maxInt(i64)) >> @intCast(64 - bits)) {
75867703 return w.print("{s}_MAX", .{minMaxMacroPrefix(data.int_cty)});
7587 } else if (data.val == min_int) {
7704 } else if (data.val == @as(i64, std.math.minInt(i64)) >> @intCast(64 - bits)) {
75887705 return w.print("{s}_MIN", .{minMaxMacroPrefix(data.int_cty)});
75897706 }
75907707 if (data.val < 0) try w.writeByte('-');
......@@ -7596,7 +7713,7 @@ const FormatSignedIntLiteralSmall = struct {
75967713 16 => try w.writeAll("0x"),
75977714 else => unreachable,
75987715 }
7599 // This `@abs` is safe thanks to the `min_int` case above.
7716 // This `@abs` is safe thanks to the min int check above.
76007717 try w.printInt(@abs(data.val), data.base, data.case, .{});
76017718 try w.writeAll(intLiteralSuffix(data.int_cty));
76027719 }
......@@ -7610,8 +7727,7 @@ const FormatUnsignedIntLiteralSmall = struct {
76107727 case: std.fmt.Case,
76117728 pub fn format(data: FormatUnsignedIntLiteralSmall, w: *Writer) Writer.Error!void {
76127729 const bits = data.int_cty.bits(data.target);
7613 const max_int: u64 = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - bits);
7614 if (data.val == max_int) {
7730 if (data.val == @as(u64, std.math.maxInt(u64)) >> @intCast(64 - bits)) {
76157731 return w.print("{s}_MAX", .{minMaxMacroPrefix(data.int_cty)});
76167732 }
76177733 try w.writeAll(intLiteralPrefix(data.int_cty, data.is_global));
......@@ -7735,6 +7851,31 @@ fn intLiteralSuffix(cty: CType.Int) []const u8 {
77357851 };
77367852}
77377853
7854const F80Repr = packed struct {
7855 mantissa: u64,
7856 exponent: u16,
7857
7858 fn write(repr: F80Repr, w: *Writer, target: *const std.Target, is_global: bool) Writer.Error!void {
7859 try w.print("zig_{s}_repr_f80({f}, {f})", .{
7860 if (is_global) "init" else "make",
7861 fmtUnsignedIntLiteralSmall(target, .uint64_t, repr.mantissa, is_global, 16, .lower),
7862 fmtUnsignedIntLiteralSmall(target, .uint16_t, repr.exponent, is_global, 16, .lower),
7863 });
7864 }
7865};
7866const F128Repr = packed struct {
7867 lo: u64,
7868 hi: u64,
7869
7870 fn write(repr: F128Repr, w: *Writer, target: *const std.Target, is_global: bool) Writer.Error!void {
7871 try w.print("zig_{s}_repr_f128({f}, {f})", .{
7872 if (is_global) "init" else "make",
7873 fmtUnsignedIntLiteralSmall(target, .uint64_t, repr.hi, is_global, 16, .lower),
7874 fmtUnsignedIntLiteralSmall(target, .uint64_t, repr.lo, is_global, 16, .lower),
7875 });
7876 }
7877};
7878
77387879const Materialize = struct {
77397880 local: CValue,
77407881
src/codegen/c/type.zig+204-23
......@@ -44,8 +44,181 @@ pub const CType = union(enum) {
4444 param_tys: []const CType,
4545 ret_ty: *const CType,
4646 varargs: bool,
47 cc: CallingConvention,
4748 },
4849
50 pub const CallingConvention = enum {
51 c,
52
53 cdecl,
54 regparmcall,
55 sysv_abi,
56 ms_abi,
57 stdcall,
58 fastcall,
59 thiscall,
60
61 vectorcall,
62
63 regcall,
64
65 preserve_none,
66
67 aarch64_vector_pcs,
68 aarch64_sve_pcs,
69
70 @"pcs(\"aapcs\")",
71 @"pcs(\"aapcs-vfp\")",
72
73 @"interrupt(\"ilink1\")",
74 @"interrupt(\"ilink2\")",
75 @"interrupt(\"ilink\")",
76 @"interrupt(\"firq\")",
77
78 interrupt,
79 @"interrupt(\"IRQ\")",
80 @"interrupt(\"FIQ\")",
81 @"interrupt(\"SWI\")",
82 @"interrupt(\"ABORT\")",
83 @"interrupt(\"UNDEF\")",
84
85 signal,
86
87 save_volatiles,
88 interrupt_handler,
89 fast_interrupt,
90 break_handler,
91
92 @"interrupt(\"eic\")",
93 @"interrupt(\"sw0\")",
94 @"interrupt(\"sw1\")",
95 @"interrupt(\"hw0\")",
96 @"interrupt(\"hw1\")",
97 @"interrupt(\"hw2\")",
98 @"interrupt(\"hw3\")",
99 @"interrupt(\"hw4\")",
100 @"interrupt(\"hw5\")",
101
102 riscv_vector_cc,
103 @"interrupt(\"supervisor\")",
104 @"interrupt(\"machine\")",
105
106 renesas,
107 /// Implies `interrupt_handler`.
108 trapa_handler,
109 @"interrupt_handler, nosave_low_regs",
110 @"interrupt_handler, resbank",
111
112 m68k_rtd,
113
114 tiflags,
115
116 pub fn fromLang(cc: std.lang.CallingConvention, target: *const std.Target) CallingConvention {
117 if (target.cCallingConvention()) |ccc| {
118 if (cc.eql(ccc)) {
119 return .c;
120 }
121 }
122 return switch (cc) {
123 .auto, .naked => .c,
124
125 .x86_16_cdecl => .cdecl,
126 .x86_16_regparmcall => .regparmcall,
127 .x86_64_sysv, .x86_sysv => .sysv_abi,
128 .x86_64_win, .x86_win, .x86_mingw => .ms_abi,
129 .x86_16_stdcall, .x86_stdcall => .stdcall,
130 .x86_fastcall => .fastcall,
131 .x86_thiscall => .thiscall,
132
133 .x86_vectorcall,
134 .x86_64_vectorcall,
135 => .vectorcall,
136
137 .x86_64_regcall_v3_sysv,
138 .x86_64_regcall_v4_win,
139 .x86_regcall_v3,
140 .x86_regcall_v4_win,
141 => .regcall,
142
143 .x86_64_preserve_none,
144 .aarch64_preserve_none,
145 => .preserve_none,
146
147 .aarch64_vfabi => .aarch64_vector_pcs,
148 .aarch64_vfabi_sve => .aarch64_sve_pcs,
149
150 .arm_aapcs => .@"pcs(\"aapcs\")",
151 .arm_aapcs_vfp => .@"pcs(\"aapcs-vfp\")",
152
153 .arc_interrupt => |opts| switch (opts.type) {
154 .ilink1 => .@"interrupt(\"ilink1\")",
155 .ilink2 => .@"interrupt(\"ilink2\")",
156 .ilink => .@"interrupt(\"ilink\")",
157 .firq => .@"interrupt(\"firq\")",
158 },
159
160 .arm_interrupt => |opts| switch (opts.type) {
161 .generic => .interrupt,
162 .irq => .@"interrupt(\"IRQ\")",
163 .fiq => .@"interrupt(\"FIQ\")",
164 .swi => .@"interrupt(\"SWI\")",
165 .abort => .@"interrupt(\"ABORT\")",
166 .undef => .@"interrupt(\"UNDEF\")",
167 },
168
169 .avr_signal => .signal,
170
171 .microblaze_interrupt => |opts| switch (opts.type) {
172 .user => .save_volatiles,
173 .regular => .interrupt_handler,
174 .fast => .fast_interrupt,
175 .breakpoint => .break_handler,
176 },
177
178 .mips_interrupt, .mips64_interrupt => |opts| switch (opts.mode) {
179 .eic => .@"interrupt(\"eic\")",
180 .sw0 => .@"interrupt(\"sw0\")",
181 .sw1 => .@"interrupt(\"sw1\")",
182 .hw0 => .@"interrupt(\"hw0\")",
183 .hw1 => .@"interrupt(\"hw1\")",
184 .hw2 => .@"interrupt(\"hw2\")",
185 .hw3 => .@"interrupt(\"hw3\")",
186 .hw4 => .@"interrupt(\"hw4\")",
187 .hw5 => .@"interrupt(\"hw5\")",
188 },
189
190 .riscv64_lp64_v, .riscv32_ilp32_v => .riscv_vector_cc,
191 .riscv32_interrupt, .riscv64_interrupt => |opts| switch (opts.mode) {
192 .supervisor => .@"interrupt(\"supervisor\")",
193 .machine => .@"interrupt(\"machine\")",
194 },
195
196 .sh_renesas => .renesas,
197 .sh_interrupt => |opts| switch (opts.save) {
198 .fpscr => .trapa_handler,
199 .high => .@"interrupt_handler, nosave_low_regs",
200 .full => .interrupt_handler,
201 .bank => .@"interrupt_handler, resbank",
202 },
203
204 .m68k_rtd => .m68k_rtd,
205
206 .avr_interrupt,
207 .csky_interrupt,
208 .m68k_interrupt,
209 .msp430_interrupt,
210 .x86_16_interrupt,
211 .x86_interrupt,
212 .x86_64_interrupt,
213 => .interrupt,
214
215 .ez80_tiflags => .tiflags,
216
217 else => unreachable, // `Zcu.callconvSupported`
218 };
219 }
220 };
221
49222 /// Returns `true` if this node has a postfix operator, meaning an `[...]` or `(...)` appears
50223 /// after the identifier in a declarator with this type. In this case, if this node is wrapped
51224 /// in a pointer type, we will need to add parentheses due to operator precedence.
......@@ -130,28 +303,28 @@ pub const CType = union(enum) {
130303 pub fn bits(int: Int, target: *const std.Target) u16 {
131304 return switch (int) {
132305 // zig fmt: off
133 .char => target.cTypeBitSize(.char),
134
135 .@"unsigned short" => target.cTypeBitSize(.ushort),
136 .@"unsigned int" => target.cTypeBitSize(.uint),
137 .@"unsigned long" => target.cTypeBitSize(.ulong),
138 .@"unsigned long long" => target.cTypeBitSize(.ulonglong),
139
140 .@"signed short" => target.cTypeBitSize(.short),
141 .@"signed int" => target.cTypeBitSize(.int),
142 .@"signed long" => target.cTypeBitSize(.long),
143 .@"signed long long" => target.cTypeBitSize(.longlong),
144
145 .uintptr_t, .intptr_t => target.ptrBitWidth(),
146
147 .uint8_t, .int8_t => 8,
148 .uint16_t, .int16_t => 16,
149 .uint24_t, .int24_t => 24,
150 .uint32_t, .int32_t => 32,
151 .uint48_t, .int48_t => 48,
152 .uint64_t, .int64_t => 64,
153 .zig_u128, .zig_i128 => 128,
154 // zig fmt: on
306 .char => target.cTypeBitSize(.char).?,
307
308 .@"unsigned short" => target.cTypeBitSize(.ushort).?,
309 .@"unsigned int" => target.cTypeBitSize(.uint).?,
310 .@"unsigned long" => target.cTypeBitSize(.ulong).?,
311 .@"unsigned long long" => target.cTypeBitSize(.ulonglong).?,
312
313 .@"signed short" => target.cTypeBitSize(.short).?,
314 .@"signed int" => target.cTypeBitSize(.int).?,
315 .@"signed long" => target.cTypeBitSize(.long).?,
316 .@"signed long long" => target.cTypeBitSize(.longlong).?,
317
318 .uintptr_t, .intptr_t => target.ptrBitWidth(),
319
320 .uint8_t, .int8_t => 8,
321 .uint16_t, .int16_t => 16,
322 .uint24_t, .int24_t => 24,
323 .uint32_t, .int32_t => 32,
324 .uint48_t, .int48_t => 48,
325 .uint64_t, .int64_t => 64,
326 .zig_u128, .zig_i128 => 128,
327 // zig fmt: on
155328 };
156329 }
157330 };
......@@ -376,6 +549,7 @@ pub const CType = union(enum) {
376549 .ret_ty = ret_cty_buf,
377550 .param_tys = param_cty_buf,
378551 .varargs = func_type.is_var_args,
552 .cc = .fromLang(func_type.cc, zcu.getTarget()),
379553 } };
380554 }
381555 try deps.addType(gpa, cur_ty, allow_incomplete);
......@@ -763,6 +937,13 @@ pub const CType = union(enum) {
763937 try w.writeByte('(');
764938 },
765939 }
940 switch (ptr.elem_ty.*) {
941 else => {},
942 .function => |function| switch (function.cc) {
943 .c => {},
944 else => |cc| try w.print("zig_callconv({t}) ", .{cc}),
945 },
946 }
766947 try w.writeByte('*');
767948 },
768949
......@@ -812,7 +993,7 @@ pub const CType = union(enum) {
812993 => {},
813994
814995 .pointer => |ptr| {
815 // Match opening paren "(" write `writeTypePrefix`.
996 // Match opening paren "(" in `writeTypePrefix`.
816997 switch (ptr.elem_ty.kind()) {
817998 .specifier, .pointer => {},
818999 .postfix_op => try w.writeByte(')'),
src/codegen/c/type/render_defs.zig+143-155
......@@ -21,16 +21,21 @@ pub fn defineAligned(
2121 if (complete and alignment.compareStrict(.lt, ty.abiAlignment(zcu))) {
2222 try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?});
2323 }
24 try w.print("{f}{f}{f}; /* align({d}) {f} */\n", .{
24 try w.print("{f}{f}{f};", .{
2525 cty.fmtDeclaratorPrefix(zcu),
2626 name_cty.fmtTypeName(zcu),
2727 cty.fmtDeclaratorSuffix(zcu),
28 });
29 if (!zcu.comp.config.root_strip) try w.print(" /* align({d}) {f} */", .{
2830 alignment.toByteUnits().?,
2931 ty.fmt(pt),
3032 });
33 try w.writeByte('\n');
3134}
3235/// Renders the definition of a big-int `struct`.
3336pub fn defineBigInt(big: CType.BigInt, w: *Writer, zcu: *const Zcu) Writer.Error!void {
37 const target = zcu.getTarget();
38 const bits = big.limb_size.bits() *| big.limbs_len;
3439 const name_cty: CType = .{ .bigint = .{
3540 .limb_size = big.limb_size,
3641 .limbs_len = big.limbs_len,
......@@ -41,12 +46,20 @@ pub fn defineBigInt(big: CType.BigInt, w: *Writer, zcu: *const Zcu) Writer.Error
4146 .elem_ty = &limb_cty,
4247 .nonstring = limb_cty.isStringElem(),
4348 } };
44 try w.print("{f} {{ {f}limbs{f}; }}; /* {d} bits */\n", .{
49 try w.print("{f} {{ {f}limbs{f}; }};", .{
4550 name_cty.fmtTypeName(zcu),
4651 array_cty.fmtDeclaratorPrefix(zcu),
4752 array_cty.fmtDeclaratorSuffix(zcu),
48 big.limb_size.bits() * @as(u17, big.limbs_len),
4953 });
54 if (!zcu.comp.config.root_strip) try w.print(" /* u{d}, i{d} */", .{ bits, bits });
55 try w.writeByte('\n');
56 try writeStaticAssertCTypeLayout(
57 name_cty,
58 std.zig.target.intByteSize(target, bits),
59 .fromByteUnits(std.zig.target.intAlignment(target, bits)),
60 w,
61 zcu,
62 );
5063}
5164
5265/// Renders a forward declaration of the `struct` which represents an error union whose payload type
......@@ -81,27 +94,28 @@ pub fn errunionDefineComplete(
8194 if (payload_ty.hasRuntimeBits(zcu)) {
8295 const payload_cty: CType = try .lower(payload_ty, deps, arena, zcu);
8396 try w.print(
84 \\{f} {{ /* anyerror!{f} */
97 \\{f} {{
8598 \\ {f}payload{f};
8699 \\ {f}error{f};
87100 \\}};
88 \\
89101 , .{
90102 name_cty.fmtTypeName(zcu),
91 payload_ty.fmt(pt),
92103 payload_cty.fmtDeclaratorPrefix(zcu),
93104 payload_cty.fmtDeclaratorSuffix(zcu),
94105 error_cty.fmtDeclaratorPrefix(zcu),
95106 error_cty.fmtDeclaratorSuffix(zcu),
96107 });
97108 } else {
98 try w.print("{f} {{ {f}error{f}; }}; /* anyerror!{f} */\n", .{
109 try w.print("{f} {{ {f}error{f}; }};", .{
99110 name_cty.fmtTypeName(zcu),
100111 error_cty.fmtDeclaratorPrefix(zcu),
101112 error_cty.fmtDeclaratorSuffix(zcu),
102 payload_ty.fmt(pt),
103113 });
104114 }
115 if (!zcu.comp.config.root_strip) try w.print(" /* anyerror!{f} */", .{
116 payload_ty.fmt(pt),
117 });
118 try w.writeByte('\n');
105119}
106120
107121/// 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
141155 },
142156 else => return,
143157 };
144 try w.print("typedef void {f}; /* {f} */\n", .{
158 try w.print("typedef void {f};", .{
145159 name_cty.fmtTypeName(zcu),
160 });
161 if (!zcu.comp.config.root_strip) try w.print(" /* {f} */", .{
146162 ty.fmt(pt),
147163 });
164 try w.writeByte('\n');
148165}
149166
150167/// 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(
163180
164181 ty.assertHasLayout(zcu);
165182
166 switch (ty.zigTypeTag(zcu)) {
183 const check_cty = check_cty: switch (ty.zigTypeTag(zcu)) {
167184 .@"fn" => if (!ty.fnHasRuntimeBits(zcu)) {
168185 const name_cty: CType = .{ .@"fn" = ty };
169 try w.print("typedef void {f}; /* {f} */\n", .{
186 try w.print("typedef void {f};", .{
170187 name_cty.fmtTypeName(zcu),
171 ty.fmt(pt),
172188 });
189 break :check_cty null;
173190 } else {
174191 const ip = &zcu.intern_pool;
175192 const func_type = ip.indexToKey(ty.toIntern()).func_type;
......@@ -186,10 +203,12 @@ pub fn defineComplete(
186203 const name_cty: CType = .{ .@"fn" = ty };
187204 const ret_cty: CType = try .lower(effective_ret_ty, deps, arena, zcu);
188205
189 try w.print("typedef {f}{f}(", .{
190 ret_cty.fmtDeclaratorPrefix(zcu),
191 name_cty.fmtTypeName(zcu),
192 });
206 try w.print("typedef {f}", .{ret_cty.fmtDeclaratorPrefix(zcu)});
207 switch (CType.CallingConvention.fromLang(func_type.cc, zcu.getTarget())) {
208 .c => {},
209 else => |cc| try w.print("zig_callconv({t}) ", .{cc}),
210 }
211 try w.print("{f}(", .{name_cty.fmtTypeName(zcu)});
193212 var any_params = false;
194213 for (func_type.param_types.get(ip)) |param_ty_ip| {
195214 const param_ty: Type = .fromInterned(param_ty_ip);
......@@ -205,88 +224,85 @@ pub fn defineComplete(
205224 } else if (!any_params) {
206225 try w.writeAll("void");
207226 }
208 try w.print("){f}; /* {f} */\n", .{
209 ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu),
210 ty.fmt(pt),
211 });
227 try w.print("){f};", .{ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu)});
228 break :check_cty null;
212229 },
213230 .@"enum" => {
214231 const name_cty: CType = .{ .@"enum" = ty };
215232 const cty: CType = try .lower(ty.backingIntType(zcu), deps, arena, zcu);
216 try w.print("typedef {f}{f}{f}; /* {f} */\n", .{
233 try w.print("typedef {f}{f}{f};", .{
217234 cty.fmtDeclaratorPrefix(zcu),
218235 name_cty.fmtTypeName(zcu),
219236 cty.fmtDeclaratorSuffix(zcu),
220 ty.fmt(pt),
221237 });
238 break :check_cty null;
222239 },
223 .@"struct" => if (ty.isTuple(zcu)) {
224 try defineTuple(ty, deps, arena, w, pt);
225 } else switch (ty.containerLayout(zcu)) {
226 .auto, .@"extern" => try defineStruct(ty, deps, arena, w, pt),
240 .@"struct" => if (ty.isTuple(zcu))
241 if (ty.hasRuntimeBits(zcu)) try defineTuple(ty, deps, arena, w, pt) else return
242 else switch (ty.containerLayout(zcu)) {
243 .auto, .@"extern" => if (ty.hasRuntimeBits(zcu)) try defineStruct(ty, deps, arena, w, pt) else return,
227244 .@"packed" => try defineBitpack(ty, deps, arena, w, pt),
228245 },
229246 .@"union" => switch (ty.containerLayout(zcu)) {
230 .auto => try defineUnionAuto(ty, deps, arena, w, pt),
231 .@"extern" => try defineUnionExtern(ty, deps, arena, w, pt),
247 .auto => if (ty.hasRuntimeBits(zcu)) try defineUnionAuto(ty, deps, arena, w, pt) else return,
248 .@"extern" => if (ty.hasRuntimeBits(zcu)) try defineUnionExtern(ty, deps, arena, w, pt) else return,
232249 .@"packed" => try defineBitpack(ty, deps, arena, w, pt),
233250 },
234251 .pointer => if (ty.isSlice(zcu)) {
235252 const name_cty: CType = .{ .slice = ty };
236253 const ptr_cty: CType = try .lower(ty.slicePtrFieldType(zcu), deps, arena, zcu);
237254 try w.print(
238 \\{f} {{ /* {f} */
255 \\{f} {{
239256 \\ {f}ptr{f};
240 \\ size_t len;
257 \\ uintptr_t len;
241258 \\}};
242 \\
243259 , .{
244260 name_cty.fmtTypeName(zcu),
245 ty.fmt(pt),
246261 ptr_cty.fmtDeclaratorPrefix(zcu),
247262 ptr_cty.fmtDeclaratorSuffix(zcu),
248263 });
249 // Don't bother with `writeStaticAssertLayout`---there's not really any way we could mess
250 // slices up, and they're all obviously the same layout.
251 },
264 break :check_cty switch (ty.toIntern()) {
265 .slice_const_u8_sentinel_0_type => name_cty,
266 else => null,
267 };
268 } else return,
252269 .optional => switch (CType.classifyOptional(ty, zcu)) {
253270 .error_set,
254271 .ptr_like,
255272 .slice_like,
256273 .npv_payload,
257 => {},
274 => return,
258275
259276 .opv_payload => {
260277 const name_cty: CType = .{ .opt = ty };
261 try w.print("{f} {{ bool is_null; }}; /* {f} */\n", .{
278 try w.print("{f} {{ bool is_null; }};", .{
262279 name_cty.fmtTypeName(zcu),
263 ty.fmt(pt),
264280 });
265 try writeStaticAssertLayout(ty, name_cty, w, zcu);
281 break :check_cty switch (ty.toIntern()) {
282 .optional_noreturn_type => name_cty,
283 else => null,
284 };
266285 },
267286
268287 .@"struct" => {
269288 const name_cty: CType = .{ .opt = ty };
270289 const payload_cty: CType = try .lower(ty.optionalChild(zcu), deps, arena, zcu);
271290 try w.print(
272 \\{f} {{ /* {f} */
291 \\{f} {{
273292 \\ {f}payload{f};
274293 \\ bool is_null;
275294 \\}};
276 \\
277295 , .{
278296 name_cty.fmtTypeName(zcu),
279 ty.fmt(pt),
280297 payload_cty.fmtDeclaratorPrefix(zcu),
281298 payload_cty.fmtDeclaratorSuffix(zcu),
282299 });
283 try writeStaticAssertLayout(ty, name_cty, w, zcu);
300 break :check_cty name_cty;
284301 },
285302 },
286303 .array => if (ty.hasRuntimeBits(zcu)) {
287 const elem_ty = ty.childType(zcu);
288304 const name_cty: CType = .{ .arr = ty };
289 const elem_cty: CType = try .lower(elem_ty, deps, arena, zcu);
305 const elem_cty: CType = try .lower(ty.childType(zcu), deps, arena, zcu);
290306 const array_cty: CType = .{ .array = .{
291307 .len = ty.arrayLenIncludingSentinel(zcu),
292308 .elem_ty = &elem_cty,
......@@ -296,43 +312,35 @@ pub fn defineComplete(
296312 break :nonstring Value.compareHetero(s, .neq, .zero_comptime_int, zcu);
297313 },
298314 } };
299 if (elem_ty.defaultStructFieldAlignment(.auto, zcu) == elem_ty.abiAlignment(zcu)) {
300 try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{
301 name_cty.fmtTypeName(zcu),
302 array_cty.fmtDeclaratorPrefix(zcu),
303 array_cty.fmtDeclaratorSuffix(zcu),
304 ty.fmt(pt),
305 });
306 } else {
307 try w.print("zig_packed({f} {{ zig_under_align({d}) {f}array{f}; }}); /* {f} */\n", .{
308 name_cty.fmtTypeName(zcu),
309 elem_ty.abiAlignment(zcu).toByteUnits().?,
310 array_cty.fmtDeclaratorPrefix(zcu),
311 array_cty.fmtDeclaratorSuffix(zcu),
312 ty.fmt(pt),
313 });
314 }
315 try writeStaticAssertLayout(ty, name_cty, w, zcu);
316 },
315 try w.print("{f} {{ {f}array{f}; }};", .{
316 name_cty.fmtTypeName(zcu),
317 array_cty.fmtDeclaratorPrefix(zcu),
318 array_cty.fmtDeclaratorSuffix(zcu),
319 });
320 break :check_cty name_cty;
321 } else return,
317322 .vector => if (ty.hasRuntimeBits(zcu)) {
318 const elem_ty = ty.childType(zcu);
319323 const name_cty: CType = .{ .vec = ty };
320 const elem_cty: CType = try .lower(elem_ty, deps, arena, zcu);
324 const elem_cty: CType = try .lower(ty.childType(zcu), deps, arena, zcu);
321325 const array_cty: CType = .{ .array = .{
322326 .len = ty.arrayLenIncludingSentinel(zcu),
323327 .elem_ty = &elem_cty,
324328 .nonstring = elem_cty.isStringElem(),
325329 } };
326 try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{
330 try w.print("{f} {{ {f}array{f}; }};", .{
327331 name_cty.fmtTypeName(zcu),
328332 array_cty.fmtDeclaratorPrefix(zcu),
329333 array_cty.fmtDeclaratorSuffix(zcu),
330 ty.fmt(pt),
331334 });
332 try writeStaticAssertLayout(ty, name_cty, w, zcu);
333 },
334 else => {},
335 }
335 break :check_cty name_cty;
336 } else return,
337 else => return,
338 };
339 if (!zcu.comp.config.root_strip) try w.print(" /* {f} */", .{
340 ty.fmt(pt),
341 });
342 try w.writeByte('\n');
343 if (check_cty) |cty| try writeStaticAssertTypeLayout(ty, cty, w, zcu);
336344}
337345fn defineBitpack(
338346 ty: Type,
......@@ -340,16 +348,16 @@ fn defineBitpack(
340348 arena: Allocator,
341349 w: *Writer,
342350 pt: Zcu.PerThread,
343) (Allocator.Error || Writer.Error)!void {
351) (Allocator.Error || Writer.Error)!?CType {
344352 const zcu = pt.zcu;
345353 const name_cty: CType = .{ .bitpack = ty };
346354 const cty: CType = try .lower(ty.backingIntType(zcu), deps, arena, zcu);
347 try w.print("typedef {f}{f}{f}; /* {f} */\n", .{
355 try w.print("typedef {f}{f}{f};", .{
348356 cty.fmtDeclaratorPrefix(zcu),
349357 name_cty.fmtTypeName(zcu),
350358 cty.fmtDeclaratorSuffix(zcu),
351 ty.fmt(pt),
352359 });
360 return null;
353361}
354362fn defineTuple(
355363 ty: Type,
......@@ -357,72 +365,54 @@ fn defineTuple(
357365 arena: Allocator,
358366 w: *Writer,
359367 pt: Zcu.PerThread,
360) (Allocator.Error || Writer.Error)!void {
368) (Allocator.Error || Writer.Error)!CType {
361369 const zcu = pt.zcu;
362 if (!ty.hasRuntimeBits(zcu)) return;
363370 const ip = &zcu.intern_pool;
364371 const tuple = ip.indexToKey(ty.toIntern()).tuple_type;
365372
366 const tuple_align = ty.abiAlignment(zcu);
373 // Fields cannot be underaligned, because tuple fields cannot have specified alignments.
374 // However, overaligned fields are possible thanks to intermediate zero-bit fields.
367375
368 // If there are any underaligned fields, we need to byte-pack the tuple.
369 const pack: bool = pack: {
370 var offset: u64 = 0;
371 for (tuple.types.get(ip)) |field_ty_ip| {
372 const field_ty: Type = .fromInterned(field_ty_ip);
373 if (!field_ty.hasRuntimeBits(zcu)) continue;
374 const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu);
375 const natural_offset = natural_align.forward(offset);
376 offset = field_ty.abiAlignment(zcu).forward(offset);
377 if (offset < natural_offset) break :pack true;
378 // Also pack if any field is more aligned than the tuple should be.
379 if (natural_align.compareStrict(.gt, tuple_align)) break :pack true;
380 offset += field_ty.abiSize(zcu);
381 }
382 break :pack false;
383 };
376 const tuple_align = ty.abiAlignment(zcu);
384377
385378 // If the alignment of other fields would not give the tuple sufficient alignment, we
386379 // need to align the first field (which does not affect its offset, because 0 is always
387380 // well-aligned) to indirectly specify the tuple alignment.
388 const overalign: bool = switch (pack) {
389 true => tuple_align.compareStrict(.gt, .@"1"),
390 false => for (tuple.types.get(ip)) |field_ty_ip| {
391 const field_ty: Type = .fromInterned(field_ty_ip);
392 if (!field_ty.hasRuntimeBits(zcu)) continue;
393 const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu);
394 if (natural_align.compareStrict(.gte, tuple_align)) break false;
395 } else true,
396 };
381 const overalign: bool = for (tuple.types.get(ip)) |field_ty_ip| {
382 const field_ty: Type = .fromInterned(field_ty_ip);
383 if (!field_ty.hasRuntimeBits(zcu)) continue;
384 const natural_align = field_ty.abiAlignment(zcu);
385 if (natural_align.compareStrict(.gte, tuple_align)) break false;
386 } else true;
397387
398 if (pack) try w.writeAll("zig_packed(");
399388 const name_cty: CType = .{ .@"struct" = ty };
400 try w.print("{f} {{ /* {f} */\n", .{
389 try w.print("{f} {{\n", .{
401390 name_cty.fmtTypeName(zcu),
402 ty.fmt(pt),
403391 });
404392 var zig_offset: u64 = 0;
405393 var c_offset: u64 = 0;
406394 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty_ip, field_val_ip, field_index| {
407395 if (field_val_ip != .none) continue; // `comptime` field
408396 const field_ty: Type = .fromInterned(field_ty_ip);
409 zig_offset = field_ty.abiAlignment(zcu).forward(zig_offset);
397 const field_align = field_ty.abiAlignment(zcu);
398 zig_offset = field_align.forward(zig_offset);
410399 if (!field_ty.hasRuntimeBits(zcu)) continue;
411 if (!pack) c_offset = field_ty.defaultStructFieldAlignment(.auto, zcu).forward(c_offset);
400 c_offset = field_align.forward(c_offset);
412401 try w.writeByte(' ');
413402 if (zig_offset == 0 and overalign) {
414403 // This is the first field; specify its alignment to align the tuple.
415404 try writeFieldAlign(field_ty, tuple_align, w, zcu);
416 } else if (zig_offset > c_offset) {
417 // This field needs to be underaligned or overaligned compared to what its
418 // offset would otherwise be.
419 const need_align: Alignment = .minStrict(
420 tuple_align, // don't make the tuple more aligned than it should be
421 .fromLog2Units(@ctz(zig_offset)),
422 );
423 try writeFieldAlign(field_ty, need_align, w, zcu);
424 c_offset = need_align.forward(c_offset);
405 } else switch (zig_offset - c_offset) {
406 0 => {},
407 else => |need_bytes| {
408 // This field needs to be overaligned compared to what its offset would otherwise be.
409 const need_align: Alignment = .fromLog2Units(std.math.log2_int(u64, need_bytes) + 1);
410 assert(need_align.compareStrict(.lte, tuple_align));
411 try writeFieldAlign(field_ty, need_align, w, zcu);
412 c_offset = need_align.forward(c_offset);
413 },
425414 }
415 assert(c_offset == zig_offset);
426416 const field_cty: CType = try .lower(field_ty, deps, arena, zcu);
427417 try w.print("{f}f{d}{f};\n", .{
428418 field_cty.fmtDeclaratorPrefix(zcu),
......@@ -433,11 +423,8 @@ fn defineTuple(
433423 zig_offset += field_size;
434424 c_offset += field_size;
435425 }
436 try w.writeByte('}');
437 if (pack) try w.writeByte(')');
438 try w.writeAll(";\n");
439
440 try writeStaticAssertLayout(ty, name_cty, w, zcu);
426 try w.writeAll("};");
427 return name_cty;
441428}
442429fn defineStruct(
443430 ty: Type,
......@@ -445,9 +432,8 @@ fn defineStruct(
445432 arena: Allocator,
446433 w: *Writer,
447434 pt: Zcu.PerThread,
448) (Allocator.Error || Writer.Error)!void {
435) (Allocator.Error || Writer.Error)!CType {
449436 const zcu = pt.zcu;
450 if (!ty.hasRuntimeBits(zcu)) return;
451437 const ip = &zcu.intern_pool;
452438
453439 const struct_type = ip.loadStructType(ty.toIntern());
......@@ -459,7 +445,7 @@ fn defineStruct(
459445 while (it.next()) |field_index| {
460446 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]);
461447 if (!field_ty.hasRuntimeBits(zcu)) continue;
462 const natural_align = field_ty.defaultStructFieldAlignment(struct_type.layout, zcu);
448 const natural_align = field_ty.abiAlignment(zcu);
463449 const natural_offset = natural_align.forward(offset);
464450 const actual_offset = struct_type.field_offsets.get(ip)[field_index];
465451 if (actual_offset < natural_offset) break :pack true;
......@@ -480,7 +466,7 @@ fn defineStruct(
480466 while (it.next()) |field_index| {
481467 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]);
482468 if (!field_ty.hasRuntimeBits(zcu)) continue;
483 const natural_align = field_ty.defaultStructFieldAlignment(struct_type.layout, zcu);
469 const natural_align = field_ty.abiAlignment(zcu);
484470 if (natural_align.compareStrict(.gte, struct_type.alignment)) break :overalign false;
485471 }
486472 break :overalign true;
......@@ -489,16 +475,15 @@ fn defineStruct(
489475
490476 if (pack) try w.writeAll("zig_packed(");
491477 const name_cty: CType = .{ .@"struct" = ty };
492 try w.print("{f} {{ /* {f} */\n", .{
478 try w.print("{f} {{\n", .{
493479 name_cty.fmtTypeName(zcu),
494 ty.fmt(pt),
495480 });
496481 var it = struct_type.iterateRuntimeOrder(ip);
497482 var offset: u64 = 0;
498483 while (it.next()) |field_index| {
499484 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]);
500485 if (!field_ty.hasRuntimeBits(zcu)) continue;
501 const natural_align = field_ty.defaultStructFieldAlignment(struct_type.layout, zcu);
486 const natural_align = field_ty.abiAlignment(zcu);
502487 const natural_offset = switch (pack) {
503488 true => offset,
504489 false => natural_align.forward(offset),
......@@ -529,9 +514,8 @@ fn defineStruct(
529514 assert(struct_type.alignment.forward(offset) == struct_type.size);
530515 try w.writeByte('}');
531516 if (pack) try w.writeByte(')');
532 try w.writeAll(";\n");
533
534 try writeStaticAssertLayout(ty, name_cty, w, zcu);
517 try w.writeByte(';');
518 return name_cty;
535519}
536520fn defineUnionAuto(
537521 ty: Type,
......@@ -539,9 +523,8 @@ fn defineUnionAuto(
539523 arena: Allocator,
540524 w: *Writer,
541525 pt: Zcu.PerThread,
542) (Allocator.Error || Writer.Error)!void {
526) (Allocator.Error || Writer.Error)!CType {
543527 const zcu = pt.zcu;
544 if (!ty.hasRuntimeBits(zcu)) return;
545528 const ip = &zcu.intern_pool;
546529
547530 const union_type = ip.loadUnionType(ty.toIntern());
......@@ -553,7 +536,7 @@ fn defineUnionAuto(
553536 const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| {
554537 const field_ty: Type = .fromInterned(field_ty_ip);
555538 if (!field_ty.hasRuntimeBits(zcu)) continue;
556 const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu);
539 const natural_align = field_ty.abiAlignment(zcu);
557540 if (natural_align.compareStrict(.gt, union_type.alignment)) break true;
558541 // The tag will immediately follow the payload. This layout may put the tag in what would
559542 // otherwise be padding on the payload union, because if the most-aligned union field is not
......@@ -571,7 +554,7 @@ fn defineUnionAuto(
571554 false => for (union_type.field_types.get(ip)) |field_ty_ip| {
572555 const field_ty: Type = .fromInterned(field_ty_ip);
573556 if (!field_ty.hasRuntimeBits(zcu)) continue;
574 const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu);
557 const natural_align = field_ty.abiAlignment(zcu);
575558 if (natural_align.compareStrict(.gte, union_type.alignment)) break false;
576559 } else overalign: {
577560 if (union_type.has_runtime_tag) {
......@@ -585,9 +568,8 @@ fn defineUnionAuto(
585568 const payload_has_bits = !union_type.has_runtime_tag or union_type.size > enum_tag_ty.abiSize(zcu);
586569
587570 const name_cty: CType = .{ .union_auto = ty };
588 try w.print("{f} {{ /* {f} */\n", .{
571 try w.print("{f} {{\n", .{
589572 name_cty.fmtTypeName(zcu),
590 ty.fmt(pt),
591573 });
592574 if (payload_has_bits) {
593575 try w.writeByte(' ');
......@@ -619,9 +601,8 @@ fn defineUnionAuto(
619601 tag_cty.fmtDeclaratorSuffix(zcu),
620602 });
621603 }
622 try w.writeAll("};\n");
623
624 try writeStaticAssertLayout(ty, name_cty, w, zcu);
604 try w.writeAll("};");
605 return name_cty;
625606}
626607fn defineUnionExtern(
627608 ty: Type,
......@@ -629,9 +610,8 @@ fn defineUnionExtern(
629610 arena: Allocator,
630611 w: *Writer,
631612 pt: Zcu.PerThread,
632) (Allocator.Error || Writer.Error)!void {
613) (Allocator.Error || Writer.Error)!CType {
633614 const zcu = pt.zcu;
634 if (!ty.hasRuntimeBits(zcu)) return;
635615 const ip = &zcu.intern_pool;
636616
637617 const union_type = ip.loadUnionType(ty.toIntern());
......@@ -642,7 +622,7 @@ fn defineUnionExtern(
642622 const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| {
643623 const field_ty: Type = .fromInterned(field_ty_ip);
644624 if (!field_ty.hasRuntimeBits(zcu)) continue;
645 const natural_align = field_ty.defaultStructFieldAlignment(.@"extern", zcu);
625 const natural_align = field_ty.abiAlignment(zcu);
646626 if (natural_align.compareStrict(.gt, union_type.alignment)) break true;
647627 } else false;
648628
......@@ -654,7 +634,7 @@ fn defineUnionExtern(
654634 false => for (union_type.field_types.get(ip)) |field_ty_ip| {
655635 const field_ty: Type = .fromInterned(field_ty_ip);
656636 if (!field_ty.hasRuntimeBits(zcu)) continue;
657 const natural_align = field_ty.defaultStructFieldAlignment(.@"extern", zcu);
637 const natural_align = field_ty.abiAlignment(zcu);
658638 if (natural_align.compareStrict(.gte, union_type.alignment)) break false;
659639 } else overalign: {
660640 if (union_type.has_runtime_tag) {
......@@ -668,9 +648,8 @@ fn defineUnionExtern(
668648 if (pack) try w.writeAll("zig_packed(");
669649
670650 const name_cty: CType = .{ .union_extern = ty };
671 try w.print("{f} {{ /* {f} */\n", .{
651 try w.print("{f} {{\n", .{
672652 name_cty.fmtTypeName(zcu),
673 ty.fmt(pt),
674653 });
675654
676655 for (0..enum_tag_ty.enumFieldCount(zcu)) |field_index| {
......@@ -691,9 +670,8 @@ fn defineUnionExtern(
691670 }
692671 try w.writeByte('}');
693672 if (pack) try w.writeByte(')');
694 try w.writeAll(";\n");
695
696 try writeStaticAssertLayout(ty, name_cty, w, zcu);
673 try w.writeByte(';');
674 return name_cty;
697675}
698676
699677/// Writes an annotation which, placed before a struct/union field declaration with field type `ty`,
......@@ -704,7 +682,7 @@ fn writeFieldAlign(
704682 w: *Writer,
705683 zcu: *const Zcu,
706684) Writer.Error!void {
707 if (alignment.compareStrict(.lt, ty.defaultStructFieldAlignment(.auto, zcu))) {
685 if (alignment.compareStrict(.lt, ty.abiAlignment(zcu))) {
708686 try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?});
709687 } else {
710688 try w.print("zig_align({d}) ", .{alignment.toByteUnits().?});
......@@ -712,19 +690,29 @@ fn writeFieldAlign(
712690}
713691
714692/// Emits static assertions that the size and alignment of `cty` match those of the Zig type `ty`.
715fn writeStaticAssertLayout(
693pub fn writeStaticAssertTypeLayout(
716694 ty: Type,
717695 cty: CType,
718696 w: *Writer,
719697 zcu: *const Zcu,
698) Writer.Error!void {
699 try writeStaticAssertCTypeLayout(cty, ty.abiSize(zcu), ty.abiAlignment(zcu), w, zcu);
700}
701
702/// Emits static assertions that the size and alignment of `cty` match the provided values.
703pub fn writeStaticAssertCTypeLayout(
704 cty: CType,
705 expected_size: u64,
706 expected_alignment: Alignment,
707 w: *Writer,
708 zcu: *const Zcu,
720709) Writer.Error!void {
721710 try w.print(
722 \\zig_static_assert(sizeof ({f}) == {d}, "incorrect size");
723 \\zig_static_assert(_Alignof ({f}) == {d}, "incorrect alignment");
711 \\zig_static_assert(sizeof({f}) == {d} && zig_alignOf({f}) == {d}, "abi mismatch");
724712 \\
725713 , .{
726 cty.fmtTypeName(zcu), ty.abiSize(zcu),
727 cty.fmtTypeName(zcu), ty.abiAlignment(zcu).toByteUnits().?,
714 cty.fmtTypeName(zcu), expected_size,
715 cty.fmtTypeName(zcu), expected_alignment.toByteUnits().?,
728716 });
729717}
730718
src/codegen/llvm.zig+722-544
......@@ -263,7 +263,7 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8
263263 => {},
264264 .semver => |ver| if (target.os.tag == .wasi and ver.min.major == 0) {
265265 try llvm_triple.print("p{d}", .{ver.min.minor});
266 } else {
266 } else if (target.os.tag != .amdhsa) {
267267 try llvm_triple.print("{d}.{d}.{d}", .{
268268 ver.min.major,
269269 ver.min.minor,
......@@ -345,160 +345,6 @@ pub fn supportsTailCall(target: *const std.Target) bool {
345345 };
346346}
347347
348pub fn dataLayout(target: *const std.Target) []const u8 {
349 // These data layouts should match Clang.
350 return switch (target.cpu.arch) {
351 .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",
352 .xcore => "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:32-f64:32-a:0:32-n32",
353 .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",
354 .lanai => "E-m:e-p:32:32-i64:64-a:0:32-n32-S64",
355 .aarch64 => if (target.ofmt == .macho)
356 if (target.os.tag == .windows or target.os.tag == .uefi)
357 "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
358 else if (target.abi == .ilp32)
359 "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
360 else
361 "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
362 else if (target.os.tag == .windows or target.os.tag == .uefi)
363 "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"
364 else
365 "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",
366 .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",
367 .arm => if (target.ofmt == .macho)
368 "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
369 else
370 "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
371 .armeb, .thumbeb => if (target.ofmt == .macho)
372 "E-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
373 else
374 "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
375 .thumb => if (target.ofmt == .macho)
376 "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
377 else if (target.os.tag == .windows or target.os.tag == .uefi)
378 "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
379 else
380 "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
381 .avr => "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8:16-a:8",
382 .bpfeb => "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
383 .bpfel => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
384 .msp430 => "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16",
385 .mips => "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64",
386 .mipsel => "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64",
387 .mips64 => switch (target.abi) {
388 .gnuabin32, .muslabin32, .abin32 => "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
389 else => "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
390 },
391 .mips64el => switch (target.abi) {
392 .gnuabin32, .muslabin32, .abin32 => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
393 else => "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
394 },
395 .m68k => "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16",
396 .powerpc => "E-m:e-p:32:32-Fn32-i64:64-n32",
397 .powerpcle => "e-m:e-p:32:32-Fn32-i64:64-n32",
398 .powerpc64 => switch (target.os.tag) {
399 .linux => "E-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512",
400 .ps3 => "E-m:e-p:32:32-Fi64-i64:64-i128:128-n32:64",
401 else => "E-m:e-Fn32-i64:64-i128:128-n32:64",
402 },
403 .powerpc64le => if (target.os.tag == .linux)
404 "e-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512"
405 else
406 "e-m:e-Fn32-i64:64-i128:128-n32:64",
407 .nvptx => "e-p:32:32-p6:32:32-p7:32:32-i64:64-i128:128-i256:256-v16:16-v32:32-n16:32:64",
408 .nvptx64 => "e-p6:32:32-i64:64-i128:128-i256:256-v16:16-v32:32-n16:32:64",
409 .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",
410 .riscv32 => if (target.cpu.has(.riscv, .e))
411 "e-m:e-p:32:32-i64:64-n32-S32"
412 else
413 "e-m:e-p:32:32-i64:64-n32-S128",
414 .riscv32be => if (target.cpu.has(.riscv, .e))
415 "E-m:e-p:32:32-i64:64-n32-S32"
416 else
417 "E-m:e-p:32:32-i64:64-n32-S128",
418 .riscv64 => if (target.cpu.has(.riscv, .e))
419 "e-m:e-p:64:64-i64:64-i128:128-n32:64-S64"
420 else
421 "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
422 .riscv64be => if (target.cpu.has(.riscv, .e))
423 "E-m:e-p:64:64-i64:64-i128:128-n32:64-S64"
424 else
425 "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
426 .sparc => "E-m:e-p:32:32-i64:64-i128:128-f128:64-n32-S64",
427 .sparc64 => "E-m:e-i64:64-i128:128-n32:64-S128",
428 .s390x => "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64",
429 .x86 => if (target.os.tag == .windows or target.os.tag == .uefi) switch (target.abi) {
430 .gnu => if (target.ofmt == .coff)
431 "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"
432 else
433 "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",
434 else => blk: {
435 const msvc = switch (target.abi) {
436 .none, .msvc => true,
437 else => false,
438 };
439
440 break :blk if (target.ofmt == .coff)
441 if (msvc)
442 "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"
443 else
444 "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"
445 else if (msvc)
446 "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"
447 else
448 "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";
449 },
450 } else if (target.ofmt == .macho)
451 "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"
452 else
453 "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",
454 .x86_64 => if (target.os.tag.isDarwin() or target.ofmt == .macho)
455 "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
456 else switch (target.abi) {
457 .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",
458 else => if ((target.os.tag == .windows or target.os.tag == .uefi) and target.ofmt == .coff)
459 "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
460 else
461 "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
462 },
463 .spirv32 => switch (target.os.tag) {
464 .vulkan, .opengl => "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1",
465 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",
466 },
467 .spirv64 => "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1",
468 .wasm32 => if (target.os.tag == .emscripten)
469 "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"
470 else
471 "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20",
472 .wasm64 => if (target.os.tag == .emscripten)
473 "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"
474 else
475 "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20",
476 .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",
477 .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",
478 .loongarch32 => "e-m:e-p:32:32-i64:64-n32-S128",
479 .loongarch64 => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
480 .xtensa => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32",
481
482 .alpha,
483 .arceb,
484 .ez80,
485 .hppa,
486 .hppa64,
487 .kalimba,
488 .kvx,
489 .m88k,
490 .microblaze,
491 .microblazeel,
492 .or1k,
493 .propeller,
494 .sh,
495 .sheb,
496 .x86_16,
497 .xtensaeb,
498 => unreachable, // Gated by hasLlvmSupport().
499 };
500}
501
502348// Avoid depending on `bindings.CodeModel` in the bitcode-only case.
503349const CodeModel = enum {
504350 default,
......@@ -573,6 +419,8 @@ pub const Object = struct {
573419 val: InternPool.Index,
574420 @"addrspace": std.lang.AddressSpace,
575421 }, Builder.Variable.Index),
422 /// Same as `uav_map` but for llvm values not originating from the frontend.
423 const_map: std.AutoHashMapUnmanaged(Builder.Constant, Builder.Variable.Index),
576424 /// Maps enum types to their corresponding LLVM functions for implementing the `tag_name` instruction.
577425 enum_tag_name_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Function.Index),
578426 /// Serves the same purpose as `enum_tag_name_map` but for the `is_named_enum_value` instruction.
......@@ -616,8 +464,6 @@ pub const Object = struct {
616464 });
617465 errdefer builder.deinit();
618466
619 builder.data_layout = try builder.string(dataLayout(target));
620
621467 const debug_compile_unit, const debug_enums_fwd_ref, const debug_globals_fwd_ref =
622468 if (!builder.strip) debug_info: {
623469 // We fully resolve all paths at this point to avoid lack of
......@@ -653,7 +499,7 @@ pub const Object = struct {
653499 }),
654500 debug_enums_fwd_ref,
655501 debug_globals_fwd_ref,
656 .{ .optimized = comp.root_mod.optimize_mode != .Debug },
502 .{ .optimized = comp.root_mod.optimize_mode != .debug },
657503 );
658504
659505 try builder.addNamedMetadata(try builder.string("llvm.dbg.cu"), &.{debug_compile_unit});
......@@ -693,6 +539,7 @@ pub const Object = struct {
693539 .zcu = zcu,
694540 .nav_map = .empty,
695541 .uav_map = .empty,
542 .const_map = .empty,
696543 .enum_tag_name_map = .empty,
697544 .named_enum_map = .empty,
698545 .type_map = .empty,
......@@ -703,21 +550,22 @@ pub const Object = struct {
703550 return obj;
704551 }
705552
706 pub fn deinit(self: *Object) void {
707 const gpa = self.gpa;
708 self.type_pool.deinit(gpa);
709 self.lazy_abi_aligns.deinit(gpa);
710 self.debug_enums.deinit(gpa);
711 self.debug_globals.deinit(gpa);
712 self.debug_file_map.deinit(gpa);
713 self.debug_types.deinit(gpa);
714 self.nav_map.deinit(gpa);
715 self.uav_map.deinit(gpa);
716 self.enum_tag_name_map.deinit(gpa);
717 self.named_enum_map.deinit(gpa);
718 self.type_map.deinit(gpa);
719 self.builder.deinit();
720 self.* = undefined;
553 pub fn deinit(o: *Object) void {
554 const gpa = o.gpa;
555 o.type_pool.deinit(gpa);
556 o.lazy_abi_aligns.deinit(gpa);
557 o.debug_enums.deinit(gpa);
558 o.debug_globals.deinit(gpa);
559 o.debug_file_map.deinit(gpa);
560 o.debug_types.deinit(gpa);
561 o.nav_map.deinit(gpa);
562 o.uav_map.deinit(gpa);
563 o.const_map.deinit(gpa);
564 o.enum_tag_name_map.deinit(gpa);
565 o.named_enum_map.deinit(gpa);
566 o.type_map.deinit(gpa);
567 o.builder.deinit();
568 o.* = undefined;
721569 }
722570
723571 fn genErrorNameTable(o: *Object) Allocator.Error!void {
......@@ -741,16 +589,16 @@ pub const Object = struct {
741589 for (llvm_errors[1..], error_name_list) |*llvm_error, name| {
742590 const name_string = try o.builder.stringNull(name.toSlice(ip));
743591 const name_init = try o.builder.stringConst(name_string);
744 const name_variable_index = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
745 try name_variable_index.setInitializer(name_init, &o.builder);
746 name_variable_index.setMutability(.constant, &o.builder);
747 name_variable_index.setAlignment(comptime .fromByteUnits(1), &o.builder);
748 const global_index = name_variable_index.ptrConst(&o.builder).global;
749 global_index.setLinkage(.private, &o.builder);
750 global_index.setUnnamedAddr(.unnamed_addr, &o.builder);
592 const name_llvm_variable = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
593 try name_llvm_variable.setInitializer(name_init, &o.builder);
594 name_llvm_variable.setMutability(.constant, &o.builder);
595 name_llvm_variable.setAlignment(comptime .fromByteUnits(1), &o.builder);
596 const llvm_global = name_llvm_variable.ptrConst(&o.builder).global;
597 llvm_global.setLinkage(.private, &o.builder);
598 llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder);
751599
752600 llvm_error.* = try o.builder.structConst(llvm_slice_ty, &.{
753 name_variable_index.toConst(&o.builder),
601 name_llvm_variable.toConst(&o.builder),
754602 try o.builder.intConst(llvm_usize_ty, name_string.slice(&o.builder).?.len - 1),
755603 });
756604 }
......@@ -770,7 +618,7 @@ pub const Object = struct {
770618 b.module_asm.appendSliceAssumeCapacity(assembly);
771619 b.module_asm.appendAssumeCapacity('\n');
772620 }
773 if (b.module_asm.getLast()) |last| {
621 if (b.module_asm.last()) |last| {
774622 if (last != '\n') try b.module_asm.append(gpa, '\n');
775623 }
776624 }
......@@ -1028,7 +876,7 @@ pub const Object = struct {
1028876
1029877 const optimize_mode = comp.root_mod.optimize_mode;
1030878
1031 const opt_level: bindings.CodeGenOptLevel = if (optimize_mode == .Debug)
879 const opt_level: bindings.CodeGenOptLevel = if (optimize_mode == .debug)
1032880 .None
1033881 else
1034882 .Aggressive;
......@@ -1199,19 +1047,33 @@ pub const Object = struct {
11991047 global.dll_storage_class = .default;
12001048 global.unnamed_addr = .unnamed_addr;
12011049 }
1202 llvm_function.setAlignment(switch (nav.resolved.?.@"align") {
1203 .none => fn_ty.abiAlignment(zcu).toLlvm(),
1204 else => |a| a.toLlvm(),
1205 }, &o.builder);
1050 llvm_function.setAlignment(nav.resolved.?.@"align".toLlvm(), &o.builder);
12061051 llvm_function.setSection(s: {
12071052 const section = nav.resolved.?.@"linksection".toSlice(ip) orelse break :s .none;
12081053 break :s try o.builder.string(section);
12091054 }, &o.builder);
1210 try o.addLlvmFunctionAttributes(pt, func.owner_nav, llvm_function);
12111055
1212 var attributes = try llvm_function.ptrConst(&o.builder).attributes.toWip(&o.builder);
1056 var attributes: Builder.FunctionAttributes.Wip = .{};
12131057 defer attributes.deinit(&o.builder);
12141058
1059 // Function attributes that are independent of analysis results of the function body.
1060 try o.addCommonFnAttributes(
1061 &attributes,
1062 owner_mod,
1063 // Some backends don't respect the `naked` attribute in `TargetFrameLowering::hasFP()`,
1064 // so for these backends, LLVM will happily emit code that accesses the stack through
1065 // the frame pointer. This is nonsensical since what the `naked` attribute does is
1066 // suppress generation of the prologue and epilogue, and the prologue is where the
1067 // frame pointer normally gets set up. At time of writing, this is the case for at
1068 // least x86 and RISC-V.
1069 owner_mod.omit_frame_pointer or fn_info.cc == .naked,
1070 );
1071
1072 try o.addCallingConventionFnAttributes(pt, llvm_function, &attributes, if (nav.getExtern(ip)) |@"extern"| .{
1073 .name = nav.name.toSlice(ip),
1074 .lib_name = @"extern".lib_name.toSlice(ip),
1075 } else null, .fromIntern(fn_info, ip));
1076
12151077 const func_analysis = func.analysisUnordered(ip);
12161078 if (func_analysis.is_noinline) {
12171079 try attributes.addFnAttr(.@"noinline", &o.builder);
......@@ -1299,7 +1161,7 @@ pub const Object = struct {
12991161 .NoReturn = fn_info.return_type == .noreturn_type,
13001162 },
13011163 .sp_flags = .{
1302 .Optimized = owner_mod.optimize_mode != .Debug,
1164 .Optimized = owner_mod.optimize_mode != .debug,
13031165 .Definition = true,
13041166 .LocalToUnit = is_internal_linkage,
13051167 },
......@@ -1324,7 +1186,7 @@ pub const Object = struct {
13241186 const counters_variable = try o.builder.addVariable(anon_name, .void, .default);
13251187 try o.used.append(gpa, counters_variable.toConst(&o.builder));
13261188 counters_variable.ptrConst(&o.builder).global.setLinkage(.private, &o.builder);
1327 counters_variable.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder);
1189 counters_variable.setAlignment(comptime .fromByteUnits(1), &o.builder);
13281190
13291191 if (target.ofmt == .macho) {
13301192 counters_variable.setSection(try o.builder.string("__DATA,__sancov_cntrs"), &o.builder);
......@@ -1507,10 +1369,6 @@ pub const Object = struct {
15071369 llvm_global.ptr(&o.builder).unnamed_addr = .unnamed_addr;
15081370 }
15091371
1510 const llvm_align = switch (resolved.@"align") {
1511 .none => nav_ty.abiAlignment(zcu).toLlvm(),
1512 else => |a| a.toLlvm(),
1513 };
15141372 const llvm_section: Builder.String = if (resolved.@"linksection".toSlice(ip)) |section| s: {
15151373 break :s try o.builder.string(section);
15161374 } else .none;
......@@ -1519,13 +1377,20 @@ pub const Object = struct {
15191377 // can see are extern functions or other comptime function body values (e.g. undefined). Of
15201378 // these, only extern functions need to be lowered to LLVM functions.
15211379 if (opt_extern != null and nav_ty.zigTypeTag(zcu) == .@"fn" and nav_ty.fnHasRuntimeBits(zcu)) {
1380 const fn_info = zcu.typeToFunc(nav_ty).?;
15221381 const llvm_function: Builder.Function.Index = switch (llvm_global.ptrConst(&o.builder).kind) {
15231382 .function => |function| function, // re-use existing `Builder.Function`
15241383 .replaced, .alias, .variable => try llvm_global.toNewFunction(&o.builder),
15251384 };
1526 llvm_function.setAlignment(llvm_align, &o.builder);
1385 llvm_function.setAlignment(resolved.@"align".toLlvm(), &o.builder);
15271386 llvm_function.setSection(llvm_section, &o.builder);
1528 try o.addLlvmFunctionAttributes(pt, nav_id, llvm_function);
1387 var attributes: Builder.FunctionAttributes.Wip = .{};
1388 defer attributes.deinit(&o.builder);
1389 try o.addCallingConventionFnAttributes(pt, llvm_function, &attributes, .{
1390 .name = nav.name.toSlice(ip),
1391 .lib_name = opt_extern.?.lib_name.toSlice(ip),
1392 }, .fromIntern(fn_info, ip));
1393 llvm_function.setAttributes(try attributes.finish(&o.builder), &o.builder);
15291394 } else {
15301395 const file_scope = nav.srcInst(ip).resolveFile(ip);
15311396 const mod = zcu.fileByIndex(file_scope).mod.?;
......@@ -1534,7 +1399,10 @@ pub const Object = struct {
15341399 .variable => |variable| variable, // re-use existing `Builder.Variable`
15351400 .replaced, .alias, .function => try llvm_global.toNewVariable(&o.builder),
15361401 };
1537 llvm_variable.setAlignment(llvm_align, &o.builder);
1402 llvm_variable.setAlignment(switch (resolved.@"align") {
1403 .none => nav_ty.abiAlignment(zcu).toLlvm(),
1404 else => |a| a.toLlvm(),
1405 }, &o.builder);
15381406 llvm_variable.setSection(llvm_section, &o.builder);
15391407 llvm_variable.setMutability(if (resolved.@"const") .constant else .global, &o.builder);
15401408 try llvm_variable.setInitializer(if (opt_extern != null) .no_init else try o.lowerValue(resolved.value, .in_memory), &o.builder);
......@@ -1585,7 +1453,7 @@ pub const Object = struct {
15851453 const uav_ty = Value.fromInterned(uav).typeOf(zcu);
15861454 const uav_ref = try o.lowerUavRef(
15871455 uav,
1588 uav_ty.abiAlignment(zcu),
1456 uav_ty.abiAlignment(zcu).toLlvm(),
15891457 target_util.defaultAddressSpace(zcu.getTarget(), .global_constant),
15901458 );
15911459 break :exp .{ uav_ty, uav_ref };
......@@ -1599,7 +1467,7 @@ pub const Object = struct {
15991467
16001468 fn updateExportedGlobal(
16011469 o: *Object,
1602 global_index: Builder.Global.Index,
1470 llvm_global: Builder.Global.Index,
16031471 ty: Type,
16041472 export_indices: []const Zcu.Export.Index,
16051473 ) link.Error!void {
......@@ -1634,18 +1502,21 @@ pub const Object = struct {
16341502 // make much sense: the linksection should be associated with the declaration itself rather
16351503 // than some particular symbol it is exported as!
16361504 if (export_indices[0].ptr(zcu).opts.section.toSlice(ip)) |section_slice| {
1637 const variable = &global_index.ptrConst(&o.builder).kind.variable;
1505 const variable = &llvm_global.ptrConst(&o.builder).kind.variable;
16381506 variable.setSection(try o.builder.string(section_slice), &o.builder);
16391507 }
16401508
1641 const llvm_global_ty = global_index.typeOf(&o.builder);
1509 const arch = comp.root_mod.resolved_target.result.cpu.arch;
1510 const workaround_alias_bugs = arch == .amdgcn or arch == .nvptx or arch == .nvptx64;
1511
1512 const llvm_global_ty = llvm_global.typeOf(&o.builder);
16421513
16431514 // All exports are represented as aliases to the original global.
16441515
16451516 // TODO: we currently do not delete old exports. To do that we'll need to track which
16461517 // globals actually *are* exports.
16471518
1648 for (export_indices) |export_idx| {
1519 for (export_indices, 0..) |export_idx, export_i| {
16491520 const exp = export_idx.ptr(zcu);
16501521 const exp_name = try o.builder.strtabString(exp.opts.name.toSlice(ip));
16511522
......@@ -1656,13 +1527,23 @@ pub const Object = struct {
16561527 // The name, aliasee, and type will be set within this block. Other properties of the
16571528 // alias will be set below.
16581529 const alias_global: Builder.Global.Index = global: {
1530
1531 // WORKAROUND (see https://github.com/llvm/llvm-project/issues/213504, https://github.com/llvm/llvm-project/issues/214835)
1532 // For NVPTX, LLVM throws "NVPTX aliasee must be a non-kernel function definition" if we try to alias a kernel
1533 // On AMDGCN, LLVM does not generate an alias for the kernel descriptor symbol on associated functions
1534 // To solve these, we rename the global
1535 if (workaround_alias_bugs and export_i == 0) {
1536 try llvm_global.rename(exp_name, &o.builder);
1537 break :global llvm_global;
1538 }
1539
16591540 const existing_global = o.builder.getGlobal(exp_name) orelse {
16601541 // There is no existing global with this name, so make a new alias.
16611542 const alias = try o.builder.addAlias(
16621543 exp_name,
16631544 llvm_global_ty,
1664 .default,
1665 global_index.toConst(),
1545 llvm_global.ptrConst(&o.builder).addr_space,
1546 llvm_global.toConst(),
16661547 );
16671548 break :global alias.ptrConst(&o.builder).global;
16681549 };
......@@ -1671,8 +1552,9 @@ pub const Object = struct {
16711552 switch (existing_global.ptrConst(&o.builder).kind) {
16721553 .alias => |alias| {
16731554 // We can just repurpose the existing alias.
1674 alias.setAliasee(global_index.toConst(), &o.builder);
1675 alias.ptrConst(&o.builder).global.ptr(&o.builder).type = global_index.typeOf(&o.builder);
1555 alias.setAliasee(llvm_global.toConst(), &o.builder);
1556 alias.ptrConst(&o.builder).global.ptr(&o.builder).type = llvm_global.typeOf(&o.builder);
1557 alias.ptrConst(&o.builder).global.ptr(&o.builder).addr_space = llvm_global.ptrConst(&o.builder).addr_space;
16761558 break :global existing_global;
16771559 },
16781560 .variable, .function => {
......@@ -1682,13 +1564,13 @@ pub const Object = struct {
16821564 // We need to make a new global which is an alias. Replace this existing one
16831565 // with the target global, making the name available and fixing references
16841566 // to this global to point to the target.
1685 try existing_global.replace(global_index, &o.builder);
1567 try existing_global.replace(llvm_global, &o.builder);
16861568 // The name is now free, so create an alias.
16871569 const alias = try o.builder.addAlias(
16881570 exp_name,
16891571 llvm_global_ty,
1690 .default,
1691 global_index.toConst(),
1572 llvm_global.ptrConst(&o.builder).addr_space,
1573 llvm_global.toConst(),
16921574 );
16931575 break :global alias.ptrConst(&o.builder).global;
16941576 },
......@@ -1721,11 +1603,11 @@ pub const Object = struct {
17211603 pub fn updateContainerType(o: *Object, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Allocator.Error!void {
17221604 _ = o.type_map.remove(ty);
17231605 try o.type_pool.updateContainerType(pt, .{ .llvm = o }, ty, success);
1724 if (o.named_enum_map.get(ty)) |function_index| {
1725 try o.updateIsNamedEnumValueFunction(.fromInterned(ty), function_index);
1606 if (o.named_enum_map.get(ty)) |llvm_function| {
1607 try o.updateIsNamedEnumValueFunction(.fromInterned(ty), llvm_function);
17261608 }
1727 if (o.enum_tag_name_map.get(ty)) |function_index| {
1728 try o.updateEnumTagNameFunction(.fromInterned(ty), function_index);
1609 if (o.enum_tag_name_map.get(ty)) |llvm_function| {
1610 try o.updateEnumTagNameFunction(.fromInterned(ty), llvm_function);
17291611 }
17301612 }
17311613
......@@ -2098,7 +1980,7 @@ pub const Object = struct {
20981980 payload_offset * 8,
20991981 );
21001982
2101 return try o.builder.debugStructType(
1983 return o.builder.debugStructType(
21021984 name,
21031985 null, // File
21041986 o.debug_compile_unit.unwrap().?, // Scope
......@@ -2136,7 +2018,7 @@ pub const Object = struct {
21362018 defer debug_param_types.deinit(gpa);
21372019
21382020 // Return type goes first.
2139 if (try fnReturnStrat(o, fn_info) == .sret) {
2021 if (try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type)) == .sret) {
21402022 // Actual return type is void, then first arg is the sret pointer.
21412023 const ptr_ty = try pt.singleMutPtrType(.fromInterned(fn_info.return_type));
21422024 debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, .void));
......@@ -2571,53 +2453,117 @@ pub const Object = struct {
25712453 fn namespaceToDebugScope(o: *Object, pt: Zcu.PerThread, namespace_index: InternPool.NamespaceIndex) !Builder.Metadata {
25722454 const zcu = o.zcu;
25732455 const namespace = zcu.namespacePtr(namespace_index);
2574 if (namespace.parent == .none) return try o.getDebugFile(namespace.file_scope);
2456 if (namespace.parent == .none) return o.getDebugFile(namespace.file_scope);
25752457 return o.getDebugType(pt, .fromInterned(namespace.owner_type));
25762458 }
25772459
2578 /// Sets the attributes and callconv of the given `Builder.Function`, which corresponds to the
2579 /// given `Nav` (which is a function).
2580 fn addLlvmFunctionAttributes(
2460 fn addCommonFnAttributes(
2461 o: *Object,
2462 attributes: *Builder.FunctionAttributes.Wip,
2463 owner_mod: *Module,
2464 omit_frame_pointer: bool,
2465 ) Allocator.Error!void {
2466 if (!owner_mod.red_zone) {
2467 try attributes.addFnAttr(.noredzone, &o.builder);
2468 }
2469 if (omit_frame_pointer) {
2470 try attributes.addFnAttr(.{ .string = .{
2471 .kind = try o.builder.string("frame-pointer"),
2472 .value = try o.builder.string("none"),
2473 } }, &o.builder);
2474 } else {
2475 try attributes.addFnAttr(.{ .string = .{
2476 .kind = try o.builder.string("frame-pointer"),
2477 .value = try o.builder.string("all"),
2478 } }, &o.builder);
2479 }
2480 try attributes.addFnAttr(.nounwind, &o.builder);
2481 if (owner_mod.unwind_tables != .none) {
2482 try attributes.addFnAttr(
2483 .{ .uwtable = if (owner_mod.unwind_tables == .async) .async else .sync },
2484 &o.builder,
2485 );
2486 }
2487 if (owner_mod.optimize_mode == .small) {
2488 try attributes.addFnAttr(.minsize, &o.builder);
2489 try attributes.addFnAttr(.optsize, &o.builder);
2490 }
2491 const target = &owner_mod.resolved_target.result;
2492 if (target.cpu.model.llvm_name) |s| {
2493 try attributes.addFnAttr(.{ .string = .{
2494 .kind = try o.builder.string("target-cpu"),
2495 .value = try o.builder.string(s),
2496 } }, &o.builder);
2497 }
2498 if (owner_mod.resolved_target.llvm_cpu_features) |s| {
2499 try attributes.addFnAttr(.{ .string = .{
2500 .kind = try o.builder.string("target-features"),
2501 .value = try o.builder.string(std.mem.span(s)),
2502 } }, &o.builder);
2503 }
2504 if (target.abi.float() == .soft) {
2505 // `use-soft-float` means "use software routines for floating point computations". In
2506 // other words, it configures how LLVM lowers basic float instructions like `fcmp`,
2507 // `fadd`, etc. The float calling convention is configured on `TargetMachine` and is
2508 // mostly an orthogonal concept, although obviously we do need hardware float operations
2509 // to actually be able to pass float values in float registers.
2510 //
2511 // Ideally, we would support something akin to the `-mfloat-abi=softfp` option that GCC
2512 // and Clang support for Arm32 and CSKY. We don't currently expose such an option in
2513 // Zig, and using CPU features as the source of truth for this makes for a miserable
2514 // user experience since people expect e.g. `arm-linux-gnueabi` to mean full soft float
2515 // unless the compiler has explicitly been told otherwise. (And note that our baseline
2516 // CPU models almost all include FPU features!)
2517 //
2518 // Revisit this at some point.
2519 try attributes.addFnAttr(.{ .string = .{
2520 .kind = try o.builder.string("use-soft-float"),
2521 .value = try o.builder.string("true"),
2522 } }, &o.builder);
2523
2524 // This prevents LLVM from using FPU/SIMD code for things like `memcpy`. As for the
2525 // above, this should be revisited if `softfp` support is added.
2526 try attributes.addFnAttr(.noimplicitfloat, &o.builder);
2527 }
2528 }
2529
2530 pub fn addCallingConventionFnAttributes(
25812531 o: *Object,
25822532 pt: Zcu.PerThread,
2583 nav_id: InternPool.Nav.Index,
2584 function_index: Builder.Function.Index,
2533 llvm_function: Builder.Function.Index,
2534 attributes: *Builder.FunctionAttributes.Wip,
2535 opt_extern: ?struct {
2536 name: []const u8,
2537 lib_name: ?[]const u8 = null,
2538 },
2539 fn_info: FuncInfo,
25852540 ) Allocator.Error!void {
25862541 const zcu = o.zcu;
2587 const ip = &zcu.intern_pool;
2588 const nav = ip.getNav(nav_id);
2589 const owner_mod = zcu.navFileScope(nav_id).mod.?;
2590 const ty: Type = .fromInterned(nav.resolved.?.type);
2591
2592 const fn_info = zcu.typeToFunc(ty).?;
2593 const target = &owner_mod.resolved_target.result;
2542 const target = zcu.getTarget();
25942543
2595 var attributes: Builder.FunctionAttributes.Wip = .{};
2596 defer attributes.deinit(&o.builder);
2544 if (fn_info.cc == .async) {
2545 @panic("TODO: LLVM backend lower async function");
2546 }
25972547
2598 if (target.cpu.arch.isWasm()) if (nav.getExtern(ip)) |@"extern"| {
2548 if (target.cpu.arch.isWasm()) if (opt_extern) |@"extern"| {
25992549 try attributes.addFnAttr(.{ .string = .{
26002550 .kind = try o.builder.string("wasm-import-name"),
2601 .value = try o.builder.string(nav.name.toSlice(ip)),
2551 .value = try o.builder.string(@"extern".name),
26022552 } }, &o.builder);
2603 if (@"extern".lib_name.toSlice(ip)) |lib_name_slice| {
2604 if (!std.mem.eql(u8, lib_name_slice, "c")) try attributes.addFnAttr(.{ .string = .{
2553 if (@"extern".lib_name) |lib_name| {
2554 if (!std.mem.eql(u8, lib_name, "c")) try attributes.addFnAttr(.{ .string = .{
26052555 .kind = try o.builder.string("wasm-import-module"),
2606 .value = try o.builder.string(lib_name_slice),
2556 .value = try o.builder.string(lib_name),
26072557 } }, &o.builder);
26082558 }
26092559 };
26102560
2611 if (fn_info.cc == .async) {
2612 @panic("TODO: LLVM backend lower async function");
2613 }
2614
26152561 const cc_info = toLlvmCallConv(fn_info.cc, target).?;
26162562
2617 function_index.setCallConv(cc_info.llvm_cc, &o.builder);
2563 llvm_function.setCallConv(cc_info.llvm_cc, &o.builder);
26182564
26192565 if (cc_info.align_stack) {
2620 try attributes.addFnAttr(.{ .alignstack = .wrap(.fromByteUnits(target.stackAlignment())) }, &o.builder);
2566 try attributes.addFnAttr(.{ .string = .{ .kind = try o.builder.string("stackrealign"), .value = .empty } }, &o.builder);
26212567 }
26222568
26232569 if (cc_info.naked) {
......@@ -2668,29 +2614,16 @@ pub const Object = struct {
26682614 else => {},
26692615 }
26702616
2671 // Function attributes that are independent of analysis results of the function body.
2672 try o.addCommonFnAttributes(
2673 &attributes,
2674 owner_mod,
2675 // Some backends don't respect the `naked` attribute in `TargetFrameLowering::hasFP()`,
2676 // so for these backends, LLVM will happily emit code that accesses the stack through
2677 // the frame pointer. This is nonsensical since what the `naked` attribute does is
2678 // suppress generation of the prologue and epilogue, and the prologue is where the
2679 // frame pointer normally gets set up. At time of writing, this is the case for at
2680 // least x86 and RISC-V.
2681 owner_mod.omit_frame_pointer or fn_info.cc == .naked,
2682 );
2683
26842617 if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder);
26852618
2686 var it = iterateParamTypes(o, fn_info);
2687 if (try fnReturnStrat(o, fn_info) == .sret) {
2688 // Sret pointers must not be address 0
2689 try attributes.addParamAttr(it.llvm_index, .nonnull, &o.builder);
2690 try attributes.addParamAttr(it.llvm_index, .@"noalias", &o.builder);
2691
2692 const raw_llvm_ret_ty = try o.lowerType(.fromInterned(fn_info.return_type), .in_memory);
2693 try attributes.addParamAttr(it.llvm_index, .{ .sret = raw_llvm_ret_ty }, &o.builder);
2619 var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types);
2620 if (try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type)) == .sret) {
2621 try o.addSRetFnAttributes(
2622 attributes,
2623 try o.lowerType(.fromInterned(fn_info.return_type), .in_memory),
2624 Type.fromInterned(fn_info.return_type).abiAlignment(zcu).toLlvm(),
2625 .declaration,
2626 );
26942627 it.llvm_index += 1;
26952628 } else if (ccAbiPromoteInt(fn_info.cc, zcu, Type.fromInterned(fn_info.return_type))) |s| switch (s) {
26962629 .signed => try attributes.addRetAttr(.signext, &o.builder),
......@@ -2709,9 +2642,9 @@ pub const Object = struct {
27092642 while (try it.next()) |lowering| switch (lowering) {
27102643 .byval => {
27112644 const param_index = it.zig_index - 1;
2712 const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[param_index]);
2645 const param_ty: Type = .fromInterned(fn_info.param_types[param_index]);
27132646 if (!isByRef(param_ty, zcu)) {
2714 try o.addByValParamAttrs(pt, &attributes, param_ty, param_index, fn_info, it.llvm_index - 1);
2647 try o.addByValParamAttrs(pt, attributes, param_ty, param_index, fn_info, it.llvm_index - 1);
27152648 }
27162649
27172650 if (remaining_inreg_int > 0 and
......@@ -2730,12 +2663,12 @@ pub const Object = struct {
27302663 }
27312664 },
27322665 .byref => {
2733 const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
2734 try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, it.byval_attr, param_ty);
2666 const param_ty: Type = .fromInterned(fn_info.param_types[it.zig_index - 1]);
2667 try o.addByRefParamAttrs(attributes, it.llvm_index - 1, it.byval_attr, param_ty);
27352668 },
27362669 .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder),
27372670 .slice => {
2738 const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
2671 const param_ty: Type = .fromInterned(fn_info.param_types[it.zig_index - 1]);
27392672 const ptr_info = param_ty.ptrInfo(zcu);
27402673 const llvm_ptr_index = it.llvm_index - 2;
27412674 if (std.math.cast(u5, it.zig_index - 1)) |i| {
......@@ -2767,94 +2700,205 @@ pub const Object = struct {
27672700 .i64_array,
27682701 => continue,
27692702 };
2770
2771 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
27722703 }
27732704
2774 fn addCommonFnAttributes(
2705 pub fn addSRetFnAttributes(
27752706 o: *Object,
27762707 attributes: *Builder.FunctionAttributes.Wip,
2777 owner_mod: *Module,
2778 omit_frame_pointer: bool,
2708 ret_ty: Builder.Type,
2709 ret_align: Builder.Alignment,
2710 location: enum { declaration, callsite },
27792711 ) Allocator.Error!void {
2780 if (!owner_mod.red_zone) {
2781 try attributes.addFnAttr(.noredzone, &o.builder);
2782 }
2783 if (omit_frame_pointer) {
2784 try attributes.addFnAttr(.{ .string = .{
2785 .kind = try o.builder.string("frame-pointer"),
2786 .value = try o.builder.string("none"),
2787 } }, &o.builder);
2788 } else {
2789 try attributes.addFnAttr(.{ .string = .{
2790 .kind = try o.builder.string("frame-pointer"),
2791 .value = try o.builder.string("all"),
2792 } }, &o.builder);
2793 }
2794 try attributes.addFnAttr(.nounwind, &o.builder);
2795 if (owner_mod.unwind_tables != .none) {
2796 try attributes.addFnAttr(
2797 .{ .uwtable = if (owner_mod.unwind_tables == .async) .async else .sync },
2798 &o.builder,
2799 );
2800 }
2801 if (owner_mod.optimize_mode == .ReleaseSmall) {
2802 try attributes.addFnAttr(.minsize, &o.builder);
2803 try attributes.addFnAttr(.optsize, &o.builder);
2804 }
2805 const target = &owner_mod.resolved_target.result;
2806 if (target.cpu.model.llvm_name) |s| {
2807 try attributes.addFnAttr(.{ .string = .{
2808 .kind = try o.builder.string("target-cpu"),
2809 .value = try o.builder.string(s),
2810 } }, &o.builder);
2811 }
2812 if (owner_mod.resolved_target.llvm_cpu_features) |s| {
2813 try attributes.addFnAttr(.{ .string = .{
2814 .kind = try o.builder.string("target-features"),
2815 .value = try o.builder.string(std.mem.span(s)),
2816 } }, &o.builder);
2817 }
2818 if (target.abi.float() == .soft) {
2819 // `use-soft-float` means "use software routines for floating point computations". In
2820 // other words, it configures how LLVM lowers basic float instructions like `fcmp`,
2821 // `fadd`, etc. The float calling convention is configured on `TargetMachine` and is
2822 // mostly an orthogonal concept, although obviously we do need hardware float operations
2823 // to actually be able to pass float values in float registers.
2824 //
2825 // Ideally, we would support something akin to the `-mfloat-abi=softfp` option that GCC
2826 // and Clang support for Arm32 and CSKY. We don't currently expose such an option in
2827 // Zig, and using CPU features as the source of truth for this makes for a miserable
2828 // user experience since people expect e.g. `arm-linux-gnueabi` to mean full soft float
2829 // unless the compiler has explicitly been told otherwise. (And note that our baseline
2830 // CPU models almost all include FPU features!)
2831 //
2832 // Revisit this at some point.
2833 try attributes.addFnAttr(.{ .string = .{
2834 .kind = try o.builder.string("use-soft-float"),
2835 .value = try o.builder.string("true"),
2836 } }, &o.builder);
2837
2838 // This prevents LLVM from using FPU/SIMD code for things like `memcpy`. As for the
2839 // above, this should be revisited if `softfp` support is added.
2840 try attributes.addFnAttr(.noimplicitfloat, &o.builder);
2712 try attributes.addParamAttr(0, .dead_on_unwind, &o.builder);
2713 switch (location) {
2714 .declaration => try attributes.addParamAttr(0, .@"noalias", &o.builder),
2715 .callsite => {},
28412716 }
2717 try attributes.addParamAttr(0, .writeonly, &o.builder);
2718 try attributes.addParamAttr(0, .{ .captures = .none }, &o.builder);
2719 try attributes.addParamAttr(0, .{ .sret = ret_ty }, &o.builder);
2720 try attributes.addParamAttr(0, .{ .@"align" = .wrap(ret_align) }, &o.builder);
28422721 }
28432722
28442723 pub const TypeRepr = enum {
28452724 /// The representation of the type when it is being manipulated as a value in a function.
2846 /// e.g. Zig `u5` -> LLVM `i5`
2847 by_value,
2848 /// The representation of the type when it is stored in memory.
2849 /// e.g. Zig `u5` -> LLVM `i8`
2725 /// e.g. Zig `u90` -> LLVM `i90`
2726 as_value,
2727 /// The representation of the type when it is loaded from or stored to memory.
2728 /// e.g. Zig `u90` -> LLVM `i96`
2729 memory_access,
2730 /// The representation of the type when it is in memory.
2731 /// e.g. Zig `u90` -> LLVM `[12 x i8]`
28502732 in_memory,
28512733 };
28522734
2735 pub fn intType(o: *Object, bits: u16, repr: TypeRepr) Allocator.Error!Builder.Type {
2736 switch (repr) {
2737 .as_value => return o.builder.intType(bits),
2738 .memory_access, .in_memory => {},
2739 }
2740 const target = o.zcu.getTarget();
2741 const abi_size = std.zig.target.intByteSize(target, bits);
2742 const llvm_bit_width = @as(u20, 8) * abi_size;
2743 switch (repr) {
2744 .as_value => unreachable,
2745 .memory_access => {},
2746 .in_memory => {
2747 const zig_align = std.zig.target.intAlignment(target, bits);
2748 const llvm_align = o.builder.data_layout.getIntegerSpec(llvm_bit_width).abi_align;
2749 if (zig_align < llvm_align.toByteUnits().?) return o.builder.arrayType(abi_size, .i8);
2750 },
2751 }
2752 return o.builder.intType(llvm_bit_width);
2753 }
2754
28532755 pub fn errorIntType(o: *Object, repr: TypeRepr) Allocator.Error!Builder.Type {
2854 return o.builder.intType(switch (repr) {
2855 .by_value => o.zcu.errorSetBits(),
2856 .in_memory => @intCast(Type.anyerror.abiSize(o.zcu) * 8),
2857 });
2756 return o.intType(o.zcu.errorSetBits(), repr);
2757 }
2758
2759 pub const SoftF80Layout = struct {
2760 alignment: InternPool.Alignment,
2761 /// byte offset of u64 field
2762 mantissa_offset: u64,
2763 /// byte offset of u16 field
2764 exponent_offset: u64,
2765 llvm_fields_len: u32,
2766
2767 pub const LlvmFieldTag = enum { mantissa, exponent, padding };
2768 };
2769 pub fn softF80Layout(o: *Object, opts: struct {
2770 llvm_field_tags_buf: []SoftF80Layout.LlvmFieldTag = &.{},
2771 llvm_field_types_buf: []Builder.Type = &.{},
2772 }) Allocator.Error!SoftF80Layout {
2773 const zcu = o.zcu;
2774 const target = zcu.getTarget();
2775 assert(std.zig.target.compilerRtFloatAbi(target, 80) == .soft);
2776 // Current compiler rt soft abi, which is not yet affected by endianness for simplicity:
2777 //
2778 // typedef struct { uint64_t mantissa; uint16_t exponent; } f80;
2779 //
2780 var layout: SoftF80Layout = .{
2781 .alignment = Type.f80.abiAlignment(zcu),
2782 .mantissa_offset = undefined,
2783 .exponent_offset = undefined,
2784 .llvm_fields_len = 0,
2785 };
2786 var offset: u64 = 0;
2787 for ([2]SoftF80Layout.LlvmFieldTag{ .mantissa, .exponent }, [2]Type{ .u64, .u16 }) |field_tag, field_type| {
2788 const field_align = field_type.abiAlignment(zcu);
2789 assert(field_align.compareStrict(.lte, layout.alignment));
2790 const field_offset = field_align.forward(offset);
2791 switch (field_offset - offset) {
2792 0 => {},
2793 else => |padding| {
2794 if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len)
2795 opts.llvm_field_tags_buf[layout.llvm_fields_len] = .padding;
2796 if (layout.llvm_fields_len < opts.llvm_field_types_buf.len)
2797 opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.builder.arrayType(padding, .i8);
2798 layout.llvm_fields_len += 1;
2799 },
2800 }
2801 switch (field_tag) {
2802 .mantissa => layout.mantissa_offset = field_offset,
2803 .exponent => layout.exponent_offset = field_offset,
2804 .padding => unreachable,
2805 }
2806 if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len)
2807 opts.llvm_field_tags_buf[layout.llvm_fields_len] = field_tag;
2808 if (layout.llvm_fields_len < opts.llvm_field_types_buf.len)
2809 opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.lowerType(field_type, .in_memory);
2810 layout.llvm_fields_len += 1;
2811 offset = field_offset + field_type.abiSize(zcu);
2812 }
2813 const end = layout.alignment.forward(offset);
2814 assert(end == Type.f80.abiSize(zcu));
2815 switch (end - offset) {
2816 0 => {},
2817 else => |padding| {
2818 if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len)
2819 opts.llvm_field_tags_buf[layout.llvm_fields_len] = .padding;
2820 if (layout.llvm_fields_len < opts.llvm_field_types_buf.len)
2821 opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.builder.arrayType(padding, .i8);
2822 layout.llvm_fields_len += 1;
2823 },
2824 }
2825 return layout;
2826 }
2827
2828 pub const SoftF128Layout = struct {
2829 alignment: InternPool.Alignment,
2830 /// byte offset of u64 field
2831 lo_offset: u64,
2832 /// byte offset of u64 field
2833 hi_offset: u64,
2834 llvm_fields_len: u32,
2835
2836 pub const LlvmFieldTag = enum { lo, hi, padding };
2837 };
2838 pub fn softF128Layout(o: *Object, opts: struct {
2839 llvm_field_tags_buf: []SoftF128Layout.LlvmFieldTag = &.{},
2840 llvm_field_types_buf: []Builder.Type = &.{},
2841 }) Allocator.Error!SoftF128Layout {
2842 const zcu = o.zcu;
2843 const target = zcu.getTarget();
2844 assert(std.zig.target.compilerRtFloatAbi(target, 128) == .soft);
2845 // Current compiler rt soft abi:
2846 //
2847 // #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
2848 // typedef struct { uint64_t hi, lo; } f128;
2849 // #else
2850 // typedef struct { uint64_t lo, hi; } f128;
2851 // #endif
2852 //
2853 var layout: SoftF128Layout = .{
2854 .alignment = Type.f128.abiAlignment(zcu),
2855 .lo_offset = undefined,
2856 .hi_offset = undefined,
2857 .llvm_fields_len = 0,
2858 };
2859 var offset: u64 = 0;
2860 for (@as([2]SoftF128Layout.LlvmFieldTag, switch (target.cpu.arch.endian()) {
2861 .big => .{ .hi, .lo },
2862 .little => .{ .lo, .hi },
2863 }), [2]Type{ .u64, .u64 }) |field_tag, field_type| {
2864 const field_align = field_type.abiAlignment(zcu);
2865 assert(field_align.compareStrict(.lte, layout.alignment));
2866 const field_offset = field_align.forward(offset);
2867 switch (field_offset - offset) {
2868 0 => {},
2869 else => |padding| {
2870 if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len)
2871 opts.llvm_field_tags_buf[layout.llvm_fields_len] = .padding;
2872 if (layout.llvm_fields_len < opts.llvm_field_types_buf.len)
2873 opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.builder.arrayType(padding, .i8);
2874 layout.llvm_fields_len += 1;
2875 },
2876 }
2877 switch (field_tag) {
2878 .lo => layout.lo_offset = field_offset,
2879 .hi => layout.hi_offset = field_offset,
2880 .padding => unreachable,
2881 }
2882 if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len)
2883 opts.llvm_field_tags_buf[layout.llvm_fields_len] = field_tag;
2884 if (layout.llvm_fields_len < opts.llvm_field_types_buf.len)
2885 opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.lowerType(field_type, .in_memory);
2886 layout.llvm_fields_len += 1;
2887 offset = field_offset + field_type.abiSize(zcu);
2888 }
2889 const end = layout.alignment.forward(offset);
2890 assert(end == Type.f128.abiSize(zcu));
2891 switch (end - offset) {
2892 0 => {},
2893 else => |padding| {
2894 if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len)
2895 opts.llvm_field_tags_buf[layout.llvm_fields_len] = .padding;
2896 if (layout.llvm_fields_len < opts.llvm_field_types_buf.len)
2897 opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.builder.arrayType(padding, .i8);
2898 layout.llvm_fields_len += 1;
2899 },
2900 }
2901 return layout;
28582902 }
28592903
28602904 pub fn lowerType(o: *Object, t: Type, repr: TypeRepr) Allocator.Error!Builder.Type {
......@@ -2862,42 +2906,31 @@ pub const Object = struct {
28622906 const target = zcu.getTarget();
28632907 const ip = &zcu.intern_pool;
28642908
2865 if (repr == .by_value) {
2866 assert(!isByRef(t, zcu)); // by-ref types must only be manipulated in memory
2909 switch (repr) {
2910 .as_value => assert(!isByRef(t, zcu)), // by-ref types must only be manipulated in memory
2911 .memory_access, .in_memory => {},
28672912 }
28682913
28692914 return switch (t.toIntern()) {
28702915 .u0_type => unreachable, // no runtime bits
2871 inline .u1_type,
2872 .u8_type,
2873 .i8_type,
2874 .u16_type,
2875 .i16_type,
2876 .u29_type,
2877 .u32_type,
2878 .i32_type,
2879 .u64_type,
2880 .i64_type,
2881 .u80_type,
2882 .u128_type,
2883 .i128_type,
2884 => |tag| switch (repr) {
2885 .by_value => @field(Builder.Type, "i" ++ @tagName(tag)[1 .. @tagName(tag).len - "_type".len]),
2886 .in_memory => try o.builder.intType(@intCast(t.abiSize(zcu) * 8)),
2887 },
2888 .usize_type, .isize_type => try o.builder.intType(target.ptrBitWidth()),
2889 inline .c_char_type,
2890 .c_short_type,
2891 .c_ushort_type,
2892 .c_int_type,
2893 .c_uint_type,
2894 .c_long_type,
2895 .c_ulong_type,
2896 .c_longlong_type,
2897 .c_ulonglong_type,
2898 => |tag| try o.builder.intType(target.cTypeBitSize(
2899 @field(std.Target.CType, @tagName(tag)["c_".len .. @tagName(tag).len - "_type".len]),
2900 )),
2916 .u1_type, .bool_type => try o.intType(1, repr),
2917 .u8_type, .i8_type => try o.intType(8, repr),
2918 .u16_type, .i16_type => try o.intType(16, repr),
2919 .u29_type => try o.intType(29, repr),
2920 .u32_type, .i32_type => try o.intType(32, repr),
2921 .u64_type, .i64_type => try o.intType(64, repr),
2922 .u80_type => try o.intType(80, repr),
2923 .u128_type, .i128_type => try o.intType(128, repr),
2924 .usize_type, .isize_type => try o.intType(target.ptrBitWidth(), repr),
2925 .c_char_type => try o.intType(target.cTypeBitSize(.char).?, repr),
2926 .c_short_type => try o.intType(target.cTypeBitSize(.short).?, repr),
2927 .c_ushort_type => try o.intType(target.cTypeBitSize(.ushort).?, repr),
2928 .c_int_type => try o.intType(target.cTypeBitSize(.int).?, repr),
2929 .c_uint_type => try o.intType(target.cTypeBitSize(.uint).?, repr),
2930 .c_long_type => try o.intType(target.cTypeBitSize(.long).?, repr),
2931 .c_ulong_type => try o.intType(target.cTypeBitSize(.ulong).?, repr),
2932 .c_longlong_type => try o.intType(target.cTypeBitSize(.longlong).?, repr),
2933 .c_ulonglong_type => try o.intType(target.cTypeBitSize(.ulonglong).?, repr),
29012934 .c_longdouble_type,
29022935 .f16_type,
29032936 .f32_type,
......@@ -2905,11 +2938,44 @@ pub const Object = struct {
29052938 .f80_type,
29062939 .f128_type,
29072940 => switch (t.floatBits(target)) {
2908 16 => if (backendSupportsF16(target)) .half else .i16,
2909 32 => .float,
2910 64 => .double,
2911 80 => if (backendSupportsF80(target)) .x86_fp80 else .i80,
2912 128 => .fp128,
2941 16 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) {
2942 .hard => .half,
2943 .soft => .i16,
2944 },
2945 32 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) {
2946 .hard => .float,
2947 .soft => .i32,
2948 },
2949 64 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) {
2950 .hard => .double,
2951 .soft => .i64,
2952 },
2953 80 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) {
2954 .hard => .x86_fp80,
2955 .soft => {
2956 var llvm_field_types_buf: [5]Builder.Type = undefined;
2957 const f80_layout = try o.softF80Layout(.{
2958 .llvm_field_types_buf = &llvm_field_types_buf,
2959 });
2960 return o.builder.structType(
2961 .normal,
2962 llvm_field_types_buf[0..f80_layout.llvm_fields_len],
2963 );
2964 },
2965 },
2966 128 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) {
2967 .hard => .fp128,
2968 .soft => {
2969 var llvm_field_types_buf: [5]Builder.Type = undefined;
2970 const f128_layout = try o.softF128Layout(.{
2971 .llvm_field_types_buf = &llvm_field_types_buf,
2972 });
2973 return o.builder.structType(
2974 .normal,
2975 llvm_field_types_buf[0..f128_layout.llvm_fields_len],
2976 );
2977 },
2978 },
29132979 else => unreachable,
29142980 },
29152981 .anyopaque_type => {
......@@ -2918,7 +2984,6 @@ pub const Object = struct {
29182984 // @foo = external global i8
29192985 return .i8;
29202986 },
2921 .bool_type => .i1,
29222987 .anyerror_type => try o.errorIntType(repr),
29232988 .void_type => unreachable, // no runtime bits
29242989 .type_type => unreachable, // no runtime bits
......@@ -2968,10 +3033,7 @@ pub const Object = struct {
29683033 .none,
29693034 => unreachable,
29703035 else => switch (ip.indexToKey(t.toIntern())) {
2971 .int_type => |int_type| switch (repr) {
2972 .by_value => try o.builder.intType(int_type.bits),
2973 .in_memory => try o.builder.intType(@intCast(t.abiSize(zcu) * 8)),
2974 },
3036 .int_type => |int_type| o.intType(int_type.bits, repr),
29753037 .ptr_type => |ptr_type| type: {
29763038 const ptr_ty = try o.builder.ptrType(
29773039 toLlvmAddressSpace(ptr_type.flags.address_space, target),
......@@ -2988,11 +3050,13 @@ pub const Object = struct {
29883050 array_type.lenIncludingSentinel(),
29893051 try o.lowerType(.fromInterned(array_type.child), repr),
29903052 ),
2991 .vector_type => |vector_type| o.builder.vectorType(
2992 .normal,
2993 vector_type.len,
2994 try o.lowerType(.fromInterned(vector_type.child), .by_value),
2995 ),
3053 .vector_type => |vector_type| if (isByRef(t, zcu)) {
3054 const child_llvm_ty = try o.lowerType(.fromInterned(vector_type.child), repr);
3055 return o.builder.arrayType(vector_type.len, child_llvm_ty);
3056 } else {
3057 const child_llvm_ty = try o.lowerType(.fromInterned(vector_type.child), .as_value);
3058 return o.builder.vectorType(.normal, vector_type.len, child_llvm_ty);
3059 },
29963060 .opt_type => |child_ty| {
29973061 // Must stay in sync with `opt_payload` logic in `lowerPtr`.
29983062 switch (Type.fromInterned(child_ty).classify(zcu)) {
......@@ -3252,8 +3316,11 @@ pub const Object = struct {
32523316 return ty;
32533317 },
32543318 .opaque_type, .spirv_type => unreachable, // no runtime bits
3255 .enum_type => try o.lowerType(t.backingIntType(zcu), repr),
3256 .func_type => |func_type| try o.lowerFnType(t, func_type),
3319 .enum_type => try o.intType(t.backingIntType(zcu).intInfo(zcu).bits, repr),
3320 .func_type => |func_type| {
3321 assert(t.fnHasRuntimeBits(zcu));
3322 return o.lowerFnType(.fromIntern(func_type, ip));
3323 },
32573324 .error_set_type, .inferred_error_set_type => try o.errorIntType(repr),
32583325 // values, not types
32593326 .undef,
......@@ -3279,14 +3346,28 @@ pub const Object = struct {
32793346 };
32803347 }
32813348
3282 fn lowerFnType(o: *Object, fn_ty: Type, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type {
3349 pub const FuncInfo = struct {
3350 cc: std.lang.CallingConvention,
3351 noalias_bits: u32 = 0,
3352 param_types: []const InternPool.Index,
3353 return_type: InternPool.Index = .void_type,
3354 is_var_args: bool = false,
3355
3356 pub fn fromIntern(fn_info: InternPool.Key.FuncType, ip: *InternPool) FuncInfo {
3357 return .{
3358 .cc = fn_info.cc,
3359 .noalias_bits = fn_info.noalias_bits,
3360 .param_types = fn_info.param_types.get(ip),
3361 .return_type = fn_info.return_type,
3362 .is_var_args = fn_info.is_var_args,
3363 };
3364 }
3365 };
3366 pub fn lowerFnType(o: *Object, fn_info: FuncInfo) Allocator.Error!Builder.Type {
32833367 const zcu = o.zcu;
3284 const ip = &zcu.intern_pool;
32853368 const target = zcu.getTarget();
32863369
3287 assert(fn_ty.fnHasRuntimeBits(zcu));
3288
3289 const ret_strat = try fnReturnStrat(o, fn_info);
3370 const ret_strat = try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type));
32903371
32913372 var llvm_params: std.ArrayList(Builder.Type) = .empty;
32923373 defer llvm_params.deinit(o.gpa);
......@@ -3301,35 +3382,35 @@ pub const Object = struct {
33013382 try llvm_params.append(o.gpa, llvm_ptr_ty);
33023383 }
33033384
3304 var it = iterateParamTypes(o, fn_info);
3385 var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types);
33053386 while (try it.next()) |lowering| switch (lowering) {
33063387 .no_bits => continue,
33073388 .byval => {
3308 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
3309 try llvm_params.append(o.gpa, try o.lowerType(param_ty, if (isByRef(param_ty, zcu)) .in_memory else .by_value));
3389 const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]);
3390 try llvm_params.append(o.gpa, try o.lowerType(param_ty, if (isByRef(param_ty, zcu)) .memory_access else .as_value));
33103391 },
33113392 .byref, .byref_mut => {
33123393 try llvm_params.append(o.gpa, .ptr);
33133394 },
33143395 .abi_sized_int => {
3315 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
3396 const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]);
33163397 try llvm_params.append(o.gpa, try o.builder.intType(
33173398 @intCast(param_ty.abiSize(zcu) * 8),
33183399 ));
33193400 },
33203401 .slice => {
3321 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
3402 const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]);
33223403 try llvm_params.appendSlice(o.gpa, &.{
33233404 try o.builder.ptrType(toLlvmAddressSpace(param_ty.ptrAddressSpace(zcu), target)),
3324 try o.lowerType(.usize, .by_value),
3405 try o.lowerType(.usize, .as_value),
33253406 });
33263407 },
33273408 .multiple_llvm_types => {
33283409 try llvm_params.appendSlice(o.gpa, it.types_buffer[0..it.types_len]);
33293410 },
33303411 .float_array => |count| {
3331 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
3332 const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, zcu).?, .in_memory);
3412 const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]);
3413 const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, zcu).?, .memory_access);
33333414 try llvm_params.append(o.gpa, try o.builder.arrayType(count, float_ty));
33343415 },
33353416 .i32_array, .i64_array => |arr_len| {
......@@ -3343,7 +3424,7 @@ pub const Object = struct {
33433424
33443425 const llvm_ret_ty: Builder.Type = switch (ret_strat) {
33453426 .void, .sret => .void,
3346 .by_val => try o.lowerType(.fromInterned(fn_info.return_type), .by_value),
3427 .by_val => try o.lowerType(.fromInterned(fn_info.return_type), .as_value),
33473428 .mem_cast => |llvm_ret_ty| llvm_ret_ty,
33483429 };
33493430 const llvm_fn_kind: Builder.Type.Function.Kind = switch (fn_info.is_var_args) {
......@@ -3391,8 +3472,14 @@ pub const Object = struct {
33913472 .null => unreachable, // non-runtime value
33923473 .@"unreachable" => unreachable, // non-runtime value
33933474
3394 .false => .false,
3395 .true => .true,
3475 .false => switch (repr) {
3476 .as_value => .false,
3477 .in_memory, .memory_access => try o.builder.intConst(.i8, 0),
3478 },
3479 .true => switch (repr) {
3480 .as_value => .true,
3481 .in_memory, .memory_access => try o.builder.intConst(.i8, 1),
3482 },
33963483 },
33973484 .enum_literal => unreachable, // non-runtime value
33983485 .@"extern" => unreachable, // non-runtime value
......@@ -3401,7 +3488,12 @@ pub const Object = struct {
34013488 var bigint_space: Value.BigIntSpace = undefined;
34023489 const bigint = val.toBigInt(&bigint_space, zcu);
34033490 const llvm_int_ty = try o.lowerType(ty, repr);
3404 return o.builder.bigIntConst(llvm_int_ty, bigint);
3491 if (llvm_int_ty.isInteger(&o.builder))
3492 return o.builder.bigIntConst(llvm_int_ty, bigint);
3493 const buffer = try o.gpa.alloc(u8, llvm_int_ty.aggregateLen(&o.builder));
3494 defer o.gpa.free(buffer);
3495 bigint.writeTwosComplement(buffer, target.cpu.arch.endian());
3496 return o.builder.stringConst(try o.builder.string(buffer));
34053497 },
34063498 .err => |err| {
34073499 const int = zcu.intern_pool.getErrorValueIfExists(err.name).?;
......@@ -3456,18 +3548,12 @@ pub const Object = struct {
34563548 },
34573549 .enum_tag => |enum_tag| o.lowerValue(enum_tag.int, repr),
34583550 .float => switch (ty.floatBits(target)) {
3459 16 => if (backendSupportsF16(target))
3460 try o.builder.halfConst(val.toFloat(f16, zcu))
3461 else
3462 try o.builder.intConst(.i16, @as(i16, @bitCast(val.toFloat(f16, zcu)))),
3463 32 => try o.builder.floatConst(val.toFloat(f32, zcu)),
3464 64 => try o.builder.doubleConst(val.toFloat(f64, zcu)),
3465 80 => if (backendSupportsF80(target))
3466 try o.builder.x86_fp80Const(val.toFloat(f80, zcu))
3467 else
3468 try o.builder.intConst(.i80, @as(i80, @bitCast(val.toFloat(f80, zcu)))),
3469 128 => try o.builder.fp128Const(val.toFloat(f128, zcu)),
34703551 else => unreachable,
3552 16 => try o.f16Const(val.toFloat(f16, zcu)),
3553 32 => try o.f32Const(val.toFloat(f32, zcu)),
3554 64 => try o.f64Const(val.toFloat(f64, zcu)),
3555 80 => try o.f80Const(val.toFloat(f80, zcu)),
3556 128 => try o.f128Const(val.toFloat(f128, zcu)),
34713557 },
34723558 .ptr => try o.lowerPtr(arg_val, 0),
34733559 .slice => |slice| return o.builder.structConst(try o.lowerType(ty, repr), &.{
......@@ -3586,12 +3672,13 @@ pub const Object = struct {
35863672 },
35873673 .vector_type => |vector_type| {
35883674 const vector_ty = try o.lowerType(ty, repr);
3675 const ExpectedContents = [Builder.expected_fields_len]Builder.Constant;
3676 var bfa_buf: ExpectedContents = undefined;
3677 var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), o.gpa);
3678 const allocator = bfa.allocator();
3679 const is_by_ref = isByRef(ty, zcu);
35893680 switch (aggregate.storage) {
35903681 .bytes, .elems => {
3591 const ExpectedContents = [Builder.expected_fields_len]Builder.Constant;
3592 var bfa_buf: ExpectedContents = undefined;
3593 var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), o.gpa);
3594 const allocator = bfa.allocator();
35953682 const vals = try allocator.alloc(Builder.Constant, vector_type.len);
35963683 defer allocator.free(vals);
35973684
......@@ -3600,16 +3687,21 @@ pub const Object = struct {
36003687 result_val.* = try o.builder.intConst(.i8, byte);
36013688 },
36023689 .elems => |elems| for (vals, elems) |*result_val, elem| {
3603 result_val.* = try o.lowerValue(elem, .by_value);
3690 result_val.* = try o.lowerValue(elem, if (is_by_ref) repr else .as_value);
36043691 },
36053692 .repeated_elem => unreachable,
36063693 }
3607 return o.builder.vectorConst(vector_ty, vals);
3694 return if (is_by_ref)
3695 o.builder.arrayConst(vector_ty, vals)
3696 else
3697 o.builder.vectorConst(vector_ty, vals);
36083698 },
3609 .repeated_elem => |elem| return o.builder.splatConst(
3610 vector_ty,
3611 try o.lowerValue(elem, .by_value),
3612 ),
3699 .repeated_elem => |elem| if (is_by_ref) {
3700 const vals = try allocator.alloc(Builder.Constant, vector_type.len);
3701 defer allocator.free(vals);
3702 @memset(vals, try o.lowerValue(elem, repr));
3703 return o.builder.arrayConst(vector_ty, vals);
3704 } else return o.builder.splatConst(vector_ty, try o.lowerValue(elem, .as_value)),
36133705 }
36143706 },
36153707 .tuple_type => |tuple| {
......@@ -3837,6 +3929,117 @@ pub const Object = struct {
38373929 };
38383930 }
38393931
3932 pub fn f16Const(o: *Object, val: f16) Allocator.Error!Builder.Constant {
3933 return switch (std.zig.target.compilerRtFloatAbi(o.zcu.getTarget(), 16)) {
3934 .hard => o.builder.halfConst(val),
3935 .soft => o.builder.intConst(.i16, @as(u16, @bitCast(val))),
3936 };
3937 }
3938
3939 pub fn f32Const(o: *Object, val: f32) Allocator.Error!Builder.Constant {
3940 return switch (std.zig.target.compilerRtFloatAbi(o.zcu.getTarget(), 32)) {
3941 .hard => o.builder.floatConst(val),
3942 .soft => o.builder.intConst(.i32, @as(u32, @bitCast(val))),
3943 };
3944 }
3945
3946 pub fn f64Const(o: *Object, val: f64) Allocator.Error!Builder.Constant {
3947 return switch (std.zig.target.compilerRtFloatAbi(o.zcu.getTarget(), 64)) {
3948 .hard => o.builder.doubleConst(val),
3949 .soft => o.builder.intConst(.i64, @as(u64, @bitCast(val))),
3950 };
3951 }
3952
3953 pub fn f80Const(o: *Object, val: f80) Allocator.Error!Builder.Constant {
3954 switch (std.zig.target.compilerRtFloatAbi(o.zcu.getTarget(), 80)) {
3955 .hard => return o.builder.x86_fp80Const(val),
3956 .soft => {},
3957 }
3958 var llvm_field_tags_buf: [5]SoftF80Layout.LlvmFieldTag = undefined;
3959 var llvm_field_types_buf: [5]Builder.Type = undefined;
3960 const f80_layout = try o.softF80Layout(.{
3961 .llvm_field_tags_buf = &llvm_field_tags_buf,
3962 .llvm_field_types_buf = &llvm_field_types_buf,
3963 });
3964 const llvm_field_types = llvm_field_types_buf[0..f80_layout.llvm_fields_len];
3965 const f80_llvm_ty = try o.builder.structType(.normal, llvm_field_types);
3966 const f80_repr: packed struct { mantissa: u64, exponent: u16 } = @bitCast(val);
3967 var llvm_field_vals_buf: [5]Builder.Constant = undefined;
3968 const llvm_field_vals = llvm_field_vals_buf[0..f80_layout.llvm_fields_len];
3969 for (
3970 llvm_field_vals,
3971 llvm_field_tags_buf[0..f80_layout.llvm_fields_len],
3972 llvm_field_types,
3973 ) |*llvm_field_val, llvm_field_tag, llvm_field_type|
3974 llvm_field_val.* = switch (llvm_field_tag) {
3975 .mantissa => try o.builder.intConst(llvm_field_type, f80_repr.mantissa),
3976 .exponent => try o.builder.intConst(llvm_field_type, f80_repr.exponent),
3977 .padding => try o.builder.undefConst(llvm_field_type),
3978 };
3979 return o.builder.structConst(f80_llvm_ty, llvm_field_vals);
3980 }
3981
3982 pub fn f128Const(o: *Object, val: f128) Allocator.Error!Builder.Constant {
3983 switch (std.zig.target.compilerRtFloatAbi(o.zcu.getTarget(), 128)) {
3984 .hard => return o.builder.fp128Const(val),
3985 .soft => {},
3986 }
3987 var llvm_field_tags_buf: [5]SoftF128Layout.LlvmFieldTag = undefined;
3988 var llvm_field_types_buf: [5]Builder.Type = undefined;
3989 const f128_layout = try o.softF128Layout(.{
3990 .llvm_field_tags_buf = &llvm_field_tags_buf,
3991 .llvm_field_types_buf = &llvm_field_types_buf,
3992 });
3993 const llvm_field_types = llvm_field_types_buf[0..f128_layout.llvm_fields_len];
3994 const f128_llvm_ty = try o.builder.structType(.normal, llvm_field_types);
3995 const f128_repr: packed struct { lo: u64, hi: u64 } = @bitCast(val);
3996 var llvm_field_vals_buf: [5]Builder.Constant = undefined;
3997 const llvm_field_vals = llvm_field_vals_buf[0..f128_layout.llvm_fields_len];
3998 for (
3999 llvm_field_vals,
4000 llvm_field_tags_buf[0..f128_layout.llvm_fields_len],
4001 llvm_field_types,
4002 ) |*llvm_field_val, llvm_field_tag, llvm_field_type|
4003 llvm_field_val.* = switch (llvm_field_tag) {
4004 .lo => try o.builder.intConst(llvm_field_type, f128_repr.lo),
4005 .hi => try o.builder.intConst(llvm_field_type, f128_repr.hi),
4006 .padding => try o.builder.undefConst(llvm_field_type),
4007 };
4008 return o.builder.structConst(f128_llvm_ty, llvm_field_vals);
4009 }
4010
4011 pub fn lowerConstRef(
4012 o: *Object,
4013 constant: Builder.Constant,
4014 @"align": Builder.Alignment,
4015 ) Allocator.Error!Builder.Constant {
4016 assert(@"align" != .default);
4017 const zcu = o.zcu;
4018 const gpa = zcu.comp.gpa;
4019 const gop = try o.const_map.getOrPut(gpa, constant);
4020 if (gop.found_existing) {
4021 // Keep the greater of the two alignments.
4022 const llvm_variable = gop.value_ptr.*;
4023 const llvm_old_align = llvm_variable.getAlignment(&o.builder);
4024 const llvm_new_align = llvm_old_align.max(@"align");
4025 llvm_variable.setAlignment(llvm_new_align, &o.builder);
4026 return llvm_variable.ptrConst(&o.builder).global.toConst();
4027 }
4028 errdefer assert(o.const_map.remove(constant));
4029
4030 const llvm_ty = constant.typeOf(&o.builder);
4031 const llvm_addrspace = toLlvmAddressSpace(.generic, zcu.getTarget());
4032 const llvm_variable = try o.builder.addVariable(.empty, llvm_ty, llvm_addrspace);
4033 gop.value_ptr.* = llvm_variable;
4034 try llvm_variable.setInitializer(constant, &o.builder);
4035 llvm_variable.setMutability(.constant, &o.builder);
4036 llvm_variable.setAlignment(@"align", &o.builder);
4037 const llvm_global = llvm_variable.ptrConst(&o.builder).global;
4038 llvm_global.setLinkage(.private, &o.builder);
4039 llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder);
4040 return llvm_global.toConst();
4041 }
4042
38404043 fn lowerPtr(
38414044 o: *Object,
38424045 ptr_val: InternPool.Index,
......@@ -3856,7 +4059,7 @@ pub const Object = struct {
38564059 const orig_ptr_ty: Type = .fromInterned(uav.orig_ty);
38574060 const base_ptr = try o.lowerUavRef(
38584061 uav.val,
3859 orig_ptr_ty.ptrAlignment(zcu),
4062 orig_ptr_ty.ptrAlignment(zcu).toLlvm(),
38604063 orig_ptr_ty.ptrAddressSpace(zcu),
38614064 );
38624065 return o.builder.gepConst(.inbounds, .i8, base_ptr, null, &.{
......@@ -3865,8 +4068,8 @@ pub const Object = struct {
38654068 },
38664069 .int => try o.builder.castConst(
38674070 .inttoptr,
3868 try o.builder.intConst(try o.lowerType(.usize, .by_value), offset),
3869 try o.lowerType(.fromInterned(ptr.ty), .by_value),
4071 try o.builder.intConst(try o.lowerType(.usize, .as_value), offset),
4072 try o.lowerType(.fromInterned(ptr.ty), .as_value),
38704073 ),
38714074 .eu_payload => |eu_ptr| try o.lowerPtr(
38724075 eu_ptr,
......@@ -3908,12 +4111,12 @@ pub const Object = struct {
39084111
39094112 pub fn lowerPtrToVoid(
39104113 o: *Object,
3911 /// Must not be `.none`.
3912 @"align": InternPool.Alignment,
4114 /// Must not be `.default`.
4115 @"align": Builder.Alignment,
39134116 @"addrspace": std.lang.AddressSpace,
39144117 ) Allocator.Error!Builder.Constant {
39154118 const addr: u64 = @"align".toByteUnits().?;
3916 const llvm_usize = try o.lowerType(.usize, .by_value);
4119 const llvm_usize = try o.lowerType(.usize, .as_value);
39174120 const llvm_addr = try o.builder.intConst(llvm_usize, addr);
39184121 const llvm_ptr_ty = try o.builder.ptrType(toLlvmAddressSpace(@"addrspace", o.zcu.getTarget()));
39194122 return o.builder.castConst(.inttoptr, llvm_addr, llvm_ptr_ty);
......@@ -3922,11 +4125,11 @@ pub const Object = struct {
39224125 pub fn lowerUavRef(
39234126 o: *Object,
39244127 uav_val: InternPool.Index,
3925 /// Must not be `.none`.
3926 @"align": InternPool.Alignment,
4128 /// Must not be `.default`.
4129 @"align": Builder.Alignment,
39274130 @"addrspace": std.lang.AddressSpace,
39284131 ) Allocator.Error!Builder.Constant {
3929 assert(@"align" != .none);
4132 assert(@"align" != .default);
39304133
39314134 const zcu = o.zcu;
39324135 const ip = &zcu.intern_pool;
......@@ -3951,19 +4154,18 @@ pub const Object = struct {
39514154 // Keep the greater of the two alignments.
39524155 const llvm_variable = gop.value_ptr.*;
39534156 const llvm_old_align = llvm_variable.getAlignment(&o.builder);
3954 const llvm_new_align = llvm_old_align.max(@"align".toLlvm());
4157 const llvm_new_align = llvm_old_align.max(@"align");
39554158 llvm_variable.setAlignment(llvm_new_align, &o.builder);
39564159 return llvm_variable.ptrConst(&o.builder).global.toConst();
39574160 }
39584161 errdefer assert(o.uav_map.remove(.{ .val = uav_val, .@"addrspace" = @"addrspace" }));
39594162
3960 const llvm_ty = try o.lowerType(uav_ty, .in_memory);
39614163 const llvm_name = try o.builder.strtabStringFmt("__anon_{d}", .{@backingInt(uav_val)});
3962 const llvm_variable = try o.builder.addVariable(llvm_name, llvm_ty, llvm_addrspace);
4164 const llvm_variable = try o.builder.addVariable(llvm_name, .void, llvm_addrspace);
39634165 gop.value_ptr.* = llvm_variable;
39644166 try llvm_variable.setInitializer(try o.lowerValue(uav_val, .in_memory), &o.builder);
39654167 llvm_variable.setMutability(.constant, &o.builder);
3966 llvm_variable.setAlignment(@"align".toLlvm(), &o.builder);
4168 llvm_variable.setAlignment(@"align", &o.builder);
39674169 const llvm_global = llvm_variable.ptrConst(&o.builder).global;
39684170 llvm_global.setLinkage(if (o.builder.strip) .private else .internal, &o.builder);
39694171 llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder);
......@@ -3982,7 +4184,7 @@ pub const Object = struct {
39824184 .none => nav_ty.abiAlignment(zcu),
39834185 else => |a| a,
39844186 };
3985 return o.lowerPtrToVoid(nav_align, nav.resolved.?.@"addrspace");
4187 return o.lowerPtrToVoid(nav_align.toLlvm(), nav.resolved.?.@"addrspace");
39864188 }
39874189
39884190 const gop = try o.nav_map.getOrPut(gpa, nav_id);
......@@ -4011,7 +4213,7 @@ pub const Object = struct {
40114213 attributes: *Builder.FunctionAttributes.Wip,
40124214 param_ty: Type,
40134215 param_index: u32,
4014 fn_info: InternPool.Key.FuncType,
4216 fn_info: FuncInfo,
40154217 llvm_arg_i: u32,
40164218 ) Allocator.Error!void {
40174219 const zcu = o.zcu;
......@@ -4051,19 +4253,26 @@ pub const Object = struct {
40514253 };
40524254 }
40534255
4256 pub const Byval = struct { alignment: InternPool.Alignment = .none };
40544257 pub fn addByRefParamAttrs(
40554258 o: *Object,
40564259 attributes: *Builder.FunctionAttributes.Wip,
40574260 llvm_arg_i: u32,
4058 byval: bool,
4261 maybe_byval: ?Byval,
40594262 param_ty: Type,
40604263 ) Allocator.Error!void {
40614264 const llvm_param_ty = try o.lowerType(param_ty, .in_memory);
4062 const alignment = param_ty.abiAlignment(o.zcu).toLlvm();
4063 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
40644265 try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);
4065 try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = .wrap(alignment) }, &o.builder);
4066 if (byval) try attributes.addParamAttr(llvm_arg_i, .{ .byval = llvm_param_ty }, &o.builder);
4266 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
4267 try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder);
4268 const alignment = if (maybe_byval) |byval| alignment: {
4269 try attributes.addParamAttr(llvm_arg_i, .{ .byval = llvm_param_ty }, &o.builder);
4270 break :alignment byval.alignment;
4271 } else .none;
4272 try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = .wrap(switch (alignment) {
4273 .none => param_ty.abiAlignment(o.zcu),
4274 else => alignment,
4275 }.toLlvm()) }, &o.builder);
40674276 }
40684277
40694278 pub fn getErrorNameTable(o: *Object) Allocator.Error!Builder.Variable.Index {
......@@ -4071,18 +4280,18 @@ pub const Object = struct {
40714280
40724281 const name = try o.builder.strtabString("__zig_error_name_table");
40734282 // TODO: Address space
4074 const variable_index = try o.builder.addVariable(name, .ptr, .default);
4075 variable_index.setMutability(.constant, &o.builder);
4076 variable_index.setAlignment(
4283 const llvm_variable = try o.builder.addVariable(name, .ptr, .default);
4284 llvm_variable.setMutability(.constant, &o.builder);
4285 llvm_variable.setAlignment(
40774286 Type.slice_const_u8_sentinel_0.abiAlignment(o.zcu).toLlvm(),
40784287 &o.builder,
40794288 );
4080 const global_index = variable_index.ptrConst(&o.builder).global;
4081 global_index.setLinkage(.private, &o.builder);
4082 global_index.setUnnamedAddr(.unnamed_addr, &o.builder);
4289 const llvm_global = llvm_variable.ptrConst(&o.builder).global;
4290 llvm_global.setLinkage(.private, &o.builder);
4291 llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder);
40834292
4084 o.error_name_table = variable_index;
4085 return variable_index;
4293 o.error_name_table = llvm_variable;
4294 return llvm_variable;
40864295 }
40874296
40884297 pub fn getErrorsLen(o: *Object) Allocator.Error!Builder.Variable.Index {
......@@ -4090,13 +4299,13 @@ pub const Object = struct {
40904299 if (o.errors_len_variable == .none) {
40914300 const llvm_err_int_ty = try o.errorIntType(.in_memory);
40924301 const name = try builder.strtabString("__zig_errors_len");
4093 const variable_index = try builder.addVariable(name, llvm_err_int_ty, .default);
4094 variable_index.setMutability(.constant, builder);
4095 variable_index.setAlignment(Type.errorAbiAlignment(o.zcu).toLlvm(), builder);
4096 const global_index = variable_index.ptrConst(&o.builder).global;
4097 global_index.setLinkage(.private, builder);
4098 global_index.setUnnamedAddr(.unnamed_addr, builder);
4099 o.errors_len_variable = variable_index;
4302 const llvm_variable = try builder.addVariable(name, llvm_err_int_ty, .default);
4303 llvm_variable.setMutability(.constant, builder);
4304 llvm_variable.setAlignment(Type.errorAbiAlignment(o.zcu).toLlvm(), builder);
4305 const llvm_global = llvm_variable.ptrConst(&o.builder).global;
4306 llvm_global.setLinkage(.private, builder);
4307 llvm_global.setUnnamedAddr(.unnamed_addr, builder);
4308 o.errors_len_variable = llvm_variable;
41004309 }
41014310 return o.errors_len_variable;
41024311 }
......@@ -4108,43 +4317,43 @@ pub const Object = struct {
41084317 const gop = try o.enum_tag_name_map.getOrPut(o.gpa, enum_ty.toIntern());
41094318 if (gop.found_existing) return gop.value_ptr.*;
41104319 errdefer assert(o.enum_tag_name_map.remove(enum_ty.toIntern()));
4111 const function_index = try o.builder.addFunction(
4320 const llvm_function = try o.builder.addFunction(
41124321 // Dummy function type; `updateEnumTagNameFunction` will replace it with the correct type.
41134322 // TODO: change the builder API so we don't need to do this.
41144323 try o.builder.fnType(.void, &.{}, .normal),
41154324 try o.builder.strtabStringFmt("__zig_tag_name_{f}", .{enum_ty.containerTypeName(ip).fmt(ip)}),
41164325 toLlvmAddressSpace(.generic, zcu.getTarget()),
41174326 );
4118 gop.value_ptr.* = function_index;
4119 try o.updateEnumTagNameFunction(enum_ty, function_index);
4120 return function_index;
4327 gop.value_ptr.* = llvm_function;
4328 try o.updateEnumTagNameFunction(enum_ty, llvm_function);
4329 return llvm_function;
41214330 }
41224331 fn updateEnumTagNameFunction(
41234332 o: *Object,
41244333 enum_ty: Type,
4125 function_index: Builder.Function.Index,
4334 llvm_function: Builder.Function.Index,
41264335 ) Allocator.Error!void {
41274336 const zcu = o.zcu;
41284337 const ip = &zcu.intern_pool;
41294338 const loaded_enum = ip.loadEnumType(enum_ty.toIntern());
41304339
4131 const llvm_usize_ty = try o.lowerType(.usize, .by_value);
4132 const llvm_ret_ty = try o.lowerType(.slice_const_u8_sentinel_0, .by_value);
4133 const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .by_value);
4340 const llvm_usize_ty = try o.lowerType(.usize, .as_value);
4341 const llvm_ret_ty = try o.lowerType(.slice_const_u8_sentinel_0, .as_value);
4342 const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .as_value);
41344343
4135 function_index.ptrConst(&o.builder).global.ptr(&o.builder).type =
4344 llvm_function.ptrConst(&o.builder).global.ptr(&o.builder).type =
41364345 try o.builder.fnType(llvm_ret_ty, &.{llvm_int_ty}, .normal);
41374346
41384347 var attributes: Builder.FunctionAttributes.Wip = .{};
41394348 defer attributes.deinit(&o.builder);
41404349 try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer);
41414350
4142 function_index.setLinkage(if (o.builder.strip) .private else .internal, &o.builder);
4143 function_index.setCallConv(.fastcc, &o.builder);
4144 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
4351 llvm_function.setLinkage(if (o.builder.strip) .private else .internal, &o.builder);
4352 llvm_function.setCallConv(.fastcc, &o.builder);
4353 llvm_function.setAttributes(try attributes.finish(&o.builder), &o.builder);
41454354
41464355 var wip = try Builder.WipFunction.init(&o.builder, .{
4147 .function = function_index,
4356 .function = llvm_function,
41484357 .strip = true,
41494358 });
41504359 defer wip.deinit();
......@@ -4163,23 +4372,23 @@ pub const Object = struct {
41634372 for (0..loaded_enum.field_names.len) |field_index| {
41644373 const name = try o.builder.stringNull(loaded_enum.field_names.get(ip)[field_index].toSlice(ip));
41654374 const name_init = try o.builder.stringConst(name);
4166 const name_variable_index = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
4167 try name_variable_index.setInitializer(name_init, &o.builder);
4168 name_variable_index.setMutability(.constant, &o.builder);
4169 name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder);
4170 const name_global_index = name_variable_index.ptrConst(&o.builder).global;
4171 name_global_index.setLinkage(.private, &o.builder);
4172 name_global_index.setUnnamedAddr(.unnamed_addr, &o.builder);
4375 const name_llvm_variable = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
4376 try name_llvm_variable.setInitializer(name_init, &o.builder);
4377 name_llvm_variable.setMutability(.constant, &o.builder);
4378 name_llvm_variable.setAlignment(comptime .fromByteUnits(1), &o.builder);
4379 const name_llvm_global = name_llvm_variable.ptrConst(&o.builder).global;
4380 name_llvm_global.setLinkage(.private, &o.builder);
4381 name_llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder);
41734382
41744383 const name_val = try o.builder.structValue(llvm_ret_ty, &.{
4175 name_global_index.toConst(),
4384 name_llvm_global.toConst(),
41764385 try o.builder.intConst(llvm_usize_ty, name.slice(&o.builder).?.len - 1),
41774386 });
41784387
41794388 const return_block = try wip.block(1, "Name");
41804389 const llvm_tag_val = switch (loaded_enum.field_values.getOrNone(ip, field_index)) {
41814390 .none => try o.builder.intConst(llvm_int_ty, field_index), // auto-numbered
4182 else => |tag_val_ip| try o.lowerValue(tag_val_ip, .by_value),
4391 else => |tag_val_ip| try o.lowerValue(tag_val_ip, .as_value),
41834392 };
41844393 try wip_switch.addCase(llvm_tag_val, return_block, &wip);
41854394
......@@ -4205,40 +4414,40 @@ pub const Object = struct {
42054414 const gop = try o.named_enum_map.getOrPut(o.gpa, enum_ty.toIntern());
42064415 if (gop.found_existing) return gop.value_ptr.*;
42074416 errdefer assert(o.named_enum_map.remove(enum_ty.toIntern()));
4208 const function_index = try o.builder.addFunction(
4417 const llvm_function = try o.builder.addFunction(
42094418 // Dummy function type; `updateIsNamedEnumValue` will replace it with the correct type.
42104419 // TODO: change the builder API so we don't need to do this.
42114420 try o.builder.fnType(.void, &.{}, .normal),
42124421 try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_ty.containerTypeName(ip).fmt(ip)}),
42134422 toLlvmAddressSpace(.generic, zcu.getTarget()),
42144423 );
4215 gop.value_ptr.* = function_index;
4216 try o.updateIsNamedEnumValueFunction(enum_ty, function_index);
4217 return function_index;
4424 gop.value_ptr.* = llvm_function;
4425 try o.updateIsNamedEnumValueFunction(enum_ty, llvm_function);
4426 return llvm_function;
42184427 }
42194428 fn updateIsNamedEnumValueFunction(
42204429 o: *Object,
42214430 enum_ty: Type,
4222 function_index: Builder.Function.Index,
4431 llvm_function: Builder.Function.Index,
42234432 ) Allocator.Error!void {
42244433 const zcu = o.zcu;
42254434 const ip = &zcu.intern_pool;
42264435 const loaded_enum = ip.loadEnumType(enum_ty.toIntern());
42274436
4228 const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .by_value);
4229 function_index.ptrConst(&o.builder).global.ptr(&o.builder).type =
4437 const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .as_value);
4438 llvm_function.ptrConst(&o.builder).global.ptr(&o.builder).type =
42304439 try o.builder.fnType(.i1, &.{llvm_int_ty}, .normal);
42314440
42324441 var attributes: Builder.FunctionAttributes.Wip = .{};
42334442 defer attributes.deinit(&o.builder);
42344443 try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer);
42354444
4236 function_index.setLinkage(if (o.builder.strip) .private else .internal, &o.builder);
4237 function_index.setCallConv(.fastcc, &o.builder);
4238 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
4445 llvm_function.setLinkage(if (o.builder.strip) .private else .internal, &o.builder);
4446 llvm_function.setCallConv(.fastcc, &o.builder);
4447 llvm_function.setAttributes(try attributes.finish(&o.builder), &o.builder);
42394448
42404449 var wip: Builder.WipFunction = try .init(&o.builder, .{
4241 .function = function_index,
4450 .function = llvm_function,
42424451 .strip = true,
42434452 });
42444453 defer wip.deinit();
......@@ -4252,7 +4461,7 @@ pub const Object = struct {
42524461
42534462 if (loaded_enum.field_values.len > 0) {
42544463 for (loaded_enum.field_values.get(ip)) |tag_val_ip| {
4255 const llvm_tag_val = try o.lowerValue(tag_val_ip, .by_value);
4464 const llvm_tag_val = try o.lowerValue(tag_val_ip, .as_value);
42564465 try wip_switch.addCase(llvm_tag_val, named_block, &wip);
42574466 }
42584467 } else {
......@@ -4274,20 +4483,27 @@ pub const Object = struct {
42744483
42754484 pub fn getLibcFunction(
42764485 o: *Object,
4486 pt: Zcu.PerThread,
42774487 fn_name: Builder.StrtabString,
4278 param_types: []const Builder.Type,
4279 return_type: Builder.Type,
4488 fn_info: FuncInfo,
42804489 ) Allocator.Error!Builder.Function.Index {
42814490 if (o.builder.getGlobal(fn_name)) |global| return switch (global.ptrConst(&o.builder).kind) {
42824491 .alias => |alias| alias.getAliasee(&o.builder).ptrConst(&o.builder).kind.function,
42834492 .function => |function| function,
42844493 .variable, .replaced => unreachable,
42854494 };
4286 return o.builder.addFunction(
4287 try o.builder.fnType(return_type, param_types, .normal),
4495 const llvm_function = try o.builder.addFunction(
4496 try o.lowerFnType(fn_info),
42884497 fn_name,
42894498 toLlvmAddressSpace(.generic, o.zcu.getTarget()),
42904499 );
4500 var attributes: Builder.FunctionAttributes.Wip = .{};
4501 defer attributes.deinit(&o.builder);
4502 try o.addCallingConventionFnAttributes(pt, llvm_function, &attributes, .{
4503 .name = fn_name.slice(&o.builder).?,
4504 }, fn_info);
4505 llvm_function.setAttributes(try attributes.finish(&o.builder), &o.builder);
4506 return llvm_function;
42914507 }
42924508};
42934509
......@@ -4324,7 +4540,7 @@ pub fn toLlvmCallConv(cc: std.lang.CallingConvention, target: *const std.Target)
43244540 std.lang.CallingConvention.SpirvFragmentOptions,
43254541 std.lang.CallingConvention.SpirvMeshOptions,
43264542 => .{ null, 0, 0 },
4327 else => @compileError("TODO: toLlvmCallConv" ++ @tagName(pl)),
4543 else => @compileError("TODO: toLlvmCallConv(." ++ @tagName(pl) ++ ")"),
43284544 },
43294545 };
43304546 return .{
......@@ -4360,6 +4576,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const
43604576 null,
43614577 .x86_64_vectorcall => .x86_vectorcallcc,
43624578 .x86_64_interrupt => .x86_intrcc,
4579 .x86_64_preserve_none => .preserve_nonecc,
43634580 .x86_stdcall => .x86_stdcallcc,
43644581 .x86_fastcall => .x86_fastcallcc,
43654582 .x86_thiscall => .x86_thiscallcc,
......@@ -4375,6 +4592,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const
43754592 .x86_interrupt => .x86_intrcc,
43764593 .aarch64_vfabi => .aarch64_vector_pcs,
43774594 .aarch64_vfabi_sve => .aarch64_sve_vector_pcs,
4595 .aarch64_preserve_none => .preserve_nonecc,
43784596 .arm_aapcs => .arm_aapcscc,
43794597 .arm_aapcs_vfp => .arm_aapcs_vfpcc,
43804598 .riscv64_lp64_v => .riscv_vectorcallcc,
......@@ -4407,6 +4625,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const
44074625 .x86_16_interrupt,
44084626 .x86_sysv,
44094627 .x86_win,
4628 .x86_mingw,
44104629 .x86_thiscall_mingw,
44114630 .x86_64_x32,
44124631 .aarch64_aapcs,
......@@ -4581,47 +4800,6 @@ fn toLlvmGlobalAddressSpace(wanted_address_space: std.lang.AddressSpace, target:
45814800 };
45824801}
45834802
4584/// This function returns true if we expect LLVM to lower f16 correctly
4585/// and false if we expect LLVM to crash if it encounters an f16 type,
4586/// or if it produces miscompilations.
4587pub fn backendSupportsF16(target: *const std.Target) bool {
4588 return switch (target.cpu.arch) {
4589 .arm,
4590 .armeb,
4591 .thumb,
4592 .thumbeb,
4593 => target.abi.float() == .soft or target.cpu.has(.arm, .fullfp16),
4594 else => true,
4595 };
4596}
4597
4598/// This function returns true if we expect LLVM to lower x86_fp80 correctly
4599/// and false if we expect LLVM to crash if it encounters an x86_fp80 type,
4600/// or if it produces miscompilations.
4601pub fn backendSupportsF80(target: *const std.Target) bool {
4602 return switch (target.cpu.arch) {
4603 .x86, .x86_64 => !target.cpu.has(.x86, .soft_float),
4604 else => false,
4605 };
4606}
4607
4608/// This function returns true if we expect LLVM to lower f128 correctly,
4609/// and false if we expect LLVM to crash if it encounters an f128 type,
4610/// or if it produces miscompilations.
4611pub fn backendSupportsF128(target: *const std.Target) bool {
4612 return switch (target.cpu.arch) {
4613 // https://github.com/llvm/llvm-project/issues/121122
4614 .amdgcn,
4615 => false,
4616 .arm,
4617 .armeb,
4618 .thumb,
4619 .thumbeb,
4620 => target.abi.float() == .soft or target.cpu.has(.arm, .fp_armv8),
4621 else => true,
4622 };
4623}
4624
46254803/// We need to insert extra padding if LLVM's isn't enough.
46264804/// However we don't want to ever call LLVMABIAlignmentOfType or
46274805/// LLVMABISizeOfType because these functions will trip assertions
src/codegen/llvm/FuncGen.zig+1526-1040
......@@ -164,12 +164,12 @@ fn resolveValue(self: *FuncGen, val: Value) Allocator.Error!Builder.Constant {
164164 const zcu = o.zcu;
165165 const ty = val.typeOf(zcu);
166166 if (!isByRef(ty, zcu)) {
167 return o.lowerValue(val.toIntern(), .by_value);
167 return o.lowerValue(val.toIntern(), .as_value);
168168 } else {
169169 // We need a pointer to a global constant, i.e. a UAV.
170170 return o.lowerUavRef(
171171 val.toIntern(),
172 ty.abiAlignment(zcu),
172 ty.abiAlignment(zcu).toLlvm(),
173173 target_util.defaultAddressSpace(zcu.getTarget(), .global_constant),
174174 );
175175 }
......@@ -190,10 +190,10 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {
190190 const fn_info = zcu.typeToFunc(fn_ty).?;
191191 const param_types = fn_info.param_types.get(ip);
192192
193 var it = iterateParamTypes(o, fn_info);
193 var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types.get(ip));
194194
195195 // Populate `fg.ret_ptr`...
196 fg.ret_ptr = switch (try fnReturnStrat(o, fn_info)) {
196 fg.ret_ptr = switch (try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type))) {
197197 .sret => rp: {
198198 defer it.llvm_index += 1;
199199 break :rp fg.wip.arg(it.llvm_index);
......@@ -218,7 +218,7 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {
218218 switch (lowering) {
219219 .no_bits => continue,
220220 .byval => {
221 assert(!it.byval_attr);
221 assert(it.byval_attr == null);
222222 const param_index = it.zig_index - 1;
223223 const param_ty: Type = .fromInterned(param_types[param_index]);
224224 const param = fg.wip.arg(it.llvm_index - 1);
......@@ -237,15 +237,16 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {
237237 .byref, .byref_mut => {
238238 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
239239 const param = fg.wip.arg(it.llvm_index - 1);
240 const alignment = if (it.byval_attr) |byval_attr| byval_attr.alignment else .none;
240241
241 if (isByRef(param_ty, zcu)) {
242 if (alignment == .none and isByRef(param_ty, zcu)) {
242243 args.appendAssumeCapacity(param);
243244 } else {
244 args.appendAssumeCapacity(try fg.load(param, .none, param_ty, .normal));
245 args.appendAssumeCapacity(try fg.load(param, alignment, param_ty, .normal));
245246 }
246247 },
247248 .abi_sized_int => {
248 assert(!it.byval_attr);
249 assert(it.byval_attr == null);
249250 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
250251 const param = fg.wip.arg(it.llvm_index - 1);
251252
......@@ -260,18 +261,18 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {
260261 }
261262 },
262263 .slice => {
263 assert(!it.byval_attr);
264 assert(it.byval_attr == null);
264265 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
265266 assert(!isByRef(param_ty, zcu));
266267 const slice_val = try fg.wip.buildAggregate(
267 try o.lowerType(param_ty, .by_value),
268 try o.lowerType(param_ty, .as_value),
268269 &.{ fg.wip.arg(it.llvm_index - 2), fg.wip.arg(it.llvm_index - 1) },
269270 "",
270271 );
271272 args.appendAssumeCapacity(slice_val);
272273 },
273274 .multiple_llvm_types => {
274 assert(!it.byval_attr);
275 assert(it.byval_attr == null);
275276 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
276277 const param_alignment = param_ty.abiAlignment(zcu);
277278 const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8);
......@@ -696,7 +697,7 @@ fn genBodyDebugScope(
696697 .{
697698 .di_flags = .{ .StaticMember = true },
698699 .sp_flags = .{
699 .Optimized = mod.optimize_mode != .Debug,
700 .Optimized = mod.optimize_mode != .debug,
700701 .Definition = true,
701702 .LocalToUnit = true, // inline functions cannot be exported
702703 },
......@@ -721,29 +722,19 @@ fn genBodyDebugScope(
721722 try self.genBody(body, coverage_point);
722723}
723724
724const CallAttr = enum {
725 Auto,
726 NeverTail,
727 NeverInline,
728 AlwaysTail,
729 AlwaysInline,
730};
731
732fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier) Allocator.Error!Builder.Value {
733 const air_call = self.air.unwrapCall(inst);
734 const args = air_call.args;
735 const o = self.object;
736 const pt = self.pt;
725fn airCall(fg: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier) Allocator.Error!Builder.Value {
726 const o = fg.object;
737727 const zcu = o.zcu;
728 const air_call = fg.air.unwrapCall(inst);
729 const args = air_call.args;
738730 const ip = &zcu.intern_pool;
739 const callee_ty = self.typeOf(air_call.callee);
731 const callee_ty = fg.typeOf(air_call.callee);
740732 const zig_fn_ty = switch (callee_ty.zigTypeTag(zcu)) {
741733 .@"fn" => callee_ty,
742734 .pointer => callee_ty.childType(zcu),
743735 else => unreachable,
744736 };
745737 const fn_info = zcu.typeToFunc(zig_fn_ty).?;
746 const return_type: Type = .fromInterned(fn_info.return_type);
747738 const llvm_fn = llvm_fn: {
748739 // If the callee is a function *body*, we need to use a pointer to the global.
749740 if (air_call.callee.toInterned()) |ip_index| switch (ip.indexToKey(ip_index)) {
......@@ -752,22 +743,54 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
752743 else => {},
753744 };
754745 // Otherwise, the operand is already a function pointer (possibly runtime-known).
755 break :llvm_fn try self.resolveInst(air_call.callee);
746 break :llvm_fn try fg.resolveInst(air_call.callee);
756747 };
748
749 const arg_types = try fg.gpa.alloc(InternPool.Index, args.len);
750 defer fg.gpa.free(arg_types);
751 const arg_values = try fg.gpa.alloc(Builder.Value, args.len);
752 defer fg.gpa.free(arg_values);
753 for (arg_types, arg_values, args) |*arg_type, *arg_value, arg| {
754 const arg_ty = fg.typeOf(arg);
755 arg_type.* = arg_ty.toIntern();
756 arg_value.* = if (arg_ty.hasRuntimeBits(zcu)) try fg.resolveInst(arg) else .none;
757 }
758 return fg.buildCall(.{
759 .is_unused = fg.liveness.isUnused(inst),
760 .modifier = modifier,
761 }, try o.lowerType(zig_fn_ty, .as_value), llvm_fn, .fromIntern(fn_info, ip), arg_types, arg_values);
762}
763
764fn buildCall(
765 fg: *FuncGen,
766 opts: struct {
767 is_unused: bool = false,
768 modifier: std.lang.CallModifier = .auto,
769 },
770 llvm_fn_ty: Builder.Type,
771 llvm_fn: Builder.Value,
772 fn_info: Object.FuncInfo,
773 arg_types: []const InternPool.Index,
774 arg_values: []const Builder.Value,
775) Allocator.Error!Builder.Value {
776 const o = fg.object;
777 const pt = fg.pt;
778 const zcu = o.zcu;
779 const return_type: Type = .fromInterned(fn_info.return_type);
757780 const target = zcu.getTarget();
758 const ret_strat = try fnReturnStrat(o, fn_info);
781 const ret_strat = try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type));
759782
760 var llvm_args = std.array_list.Managed(Builder.Value).init(self.gpa);
761 defer llvm_args.deinit();
783 var llvm_args: std.ArrayList(Builder.Value) = .empty;
784 defer llvm_args.deinit(fg.gpa);
762785
763786 var attributes: Builder.FunctionAttributes.Wip = .{};
764787 defer attributes.deinit(&o.builder);
765788
766 if (self.disable_intrinsics) {
789 if (fg.disable_intrinsics) {
767790 try attributes.addFnAttr(.nobuiltin, &o.builder);
768791 }
769792
770 switch (modifier) {
793 switch (opts.modifier) {
771794 .auto, .always_tail => {},
772795 .never_tail, .never_inline => try attributes.addFnAttr(.@"noinline", &o.builder),
773796 .no_suspend, .always_inline, .compile_time => unreachable,
......@@ -775,10 +798,11 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
775798
776799 const sret_alloc: ?Builder.Value = switch (ret_strat) {
777800 .sret => sret_alloc: {
778 try attributes.addParamAttr(0, .{ .sret = try o.lowerType(return_type, .in_memory) }, &o.builder);
801 const alignment = return_type.abiAlignment(zcu).toLlvm();
802 try o.addSRetFnAttributes(&attributes, try o.lowerType(return_type, .in_memory), alignment, .callsite);
779803
780 const ptr = try self.buildZigAlloca(return_type, .none);
781 try llvm_args.append(ptr);
804 const ptr = try fg.buildZigAlloca(return_type, .none);
805 try llvm_args.append(fg.gpa, ptr);
782806 break :sret_alloc ptr;
783807 },
784808 else => sret_alloc: {
......@@ -792,132 +816,111 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
792816
793817 const err_return_tracing = fn_info.cc == .auto and zcu.comp.config.any_error_tracing;
794818 if (err_return_tracing) {
795 assert(self.err_ret_trace != .none);
796 try llvm_args.append(self.err_ret_trace);
797 }
798
799 var it = iterateParamTypes(o, fn_info);
800 while (try it.nextCall(self, args)) |lowering| switch (lowering) {
801 .no_bits => continue,
802 .byval => {
803 const arg = args[it.zig_index - 1];
804 const param_ty = self.typeOf(arg);
805 const llvm_arg = try self.resolveInst(arg);
806 if (isByRef(param_ty, zcu)) {
807 const alignment = param_ty.abiAlignment(zcu).toLlvm();
808 // We don't need to handle non-ABI-sized integer types in memory here since they are
809 // never by-ref.
810 const llvm_param_ty = try o.lowerType(param_ty, .in_memory);
811 const loaded = try self.wip.load(.normal, llvm_param_ty, llvm_arg, alignment, "");
812 try llvm_args.append(loaded);
813 } else {
814 try llvm_args.append(llvm_arg);
815 }
816 },
817 .byref => {
818 const arg = args[it.zig_index - 1];
819 const param_ty = self.typeOf(arg);
820 const llvm_arg = try self.resolveInst(arg);
821 if (isByRef(param_ty, zcu)) {
822 try llvm_args.append(llvm_arg);
823 } else {
824 const arg_ptr = try self.buildZigAlloca(param_ty, .none);
825 try self.store(arg_ptr, .none, llvm_arg, param_ty, .normal);
826 try llvm_args.append(arg_ptr);
827 }
828 },
829 .byref_mut => {
830 const arg = args[it.zig_index - 1];
831 const param_ty = self.typeOf(arg);
832 const llvm_arg = try self.resolveInst(arg);
833
834 const arg_ptr = try self.buildZigAlloca(param_ty, .none);
835 try self.store(arg_ptr, .none, llvm_arg, param_ty, .normal);
836 try llvm_args.append(arg_ptr);
837 },
838 .abi_sized_int => {
839 const arg = args[it.zig_index - 1];
840 const param_ty = self.typeOf(arg);
841 const llvm_arg = try self.resolveInst(arg);
842 const int_llvm_ty = try o.builder.intType(@intCast(param_ty.abiSize(zcu) * 8));
843
844 if (isByRef(param_ty, zcu)) {
845 const alignment = param_ty.abiAlignment(zcu).toLlvm();
846 const loaded = try self.wip.load(.normal, int_llvm_ty, llvm_arg, alignment, "");
847 try llvm_args.append(loaded);
848 } else {
849 // LLVM does not allow bitcasting structs so we must allocate
850 // a local, store as one type, and then load as another type.
851 const alignment = param_ty.abiAlignment(zcu).toLlvm();
852 const ptr = try self.buildAlloca(int_llvm_ty, alignment);
853 try self.store(ptr, .none, llvm_arg, param_ty, .normal);
854 const loaded = try self.wip.load(.normal, int_llvm_ty, ptr, alignment, "");
855 try llvm_args.append(loaded);
856 }
857 },
858 .slice => {
859 const arg = args[it.zig_index - 1];
860 const llvm_arg = try self.resolveInst(arg);
861 const ptr = try self.wip.extractValue(llvm_arg, &.{0}, "");
862 const len = try self.wip.extractValue(llvm_arg, &.{1}, "");
863 try llvm_args.appendSlice(&.{ ptr, len });
864 },
865 .multiple_llvm_types => {
866 const arg = args[it.zig_index - 1];
867 const param_ty = self.typeOf(arg);
868 const llvm_arg = try self.resolveInst(arg);
869 const param_alignment = param_ty.abiAlignment(zcu);
870 const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8);
871 const arg_ptr = try self.buildAlloca(llvm_ty, param_alignment.toLlvm());
872 try self.store(arg_ptr, .none, llvm_arg, param_ty, .normal);
873
874 try llvm_args.ensureUnusedCapacity(it.types_len);
875 for (it.types_buffer[0..it.types_len], it.offsets_buffer[0..it.types_len]) |field_ty, offset| {
876 const field_ptr = try self.ptraddConst(arg_ptr, offset);
877 const loaded = try self.wip.load(.normal, field_ty, field_ptr, param_alignment.offset(offset).toLlvm(), "");
878 llvm_args.appendAssumeCapacity(loaded);
879 }
880 },
881 .float_array => |count| {
882 const arg = args[it.zig_index - 1];
883 const arg_ty = self.typeOf(arg);
884 const arg_val = try self.resolveInst(arg);
885
886 const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: {
887 const ptr = try self.buildZigAlloca(arg_ty, .none);
888 try self.store(ptr, .none, arg_val, arg_ty, .normal);
889 break :ptr ptr;
890 } else arg_val;
891
892 const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, zcu).?, .in_memory);
893 const array_ty = try o.builder.arrayType(count, float_ty);
819 assert(fg.err_ret_trace != .none);
820 try llvm_args.append(fg.gpa, fg.err_ret_trace);
821 }
894822
895 const loaded = try self.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), "");
896 try llvm_args.append(loaded);
897 },
898 .i32_array, .i64_array => |arr_len| {
899 const elem_size: u8 = if (lowering == .i32_array) 32 else 64;
900 const arg = args[it.zig_index - 1];
901 const arg_ty = self.typeOf(arg);
902 const arg_val = try self.resolveInst(arg);
903
904 const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: {
905 const ptr = try self.buildZigAlloca(arg_ty, .none);
906 try self.store(ptr, .none, arg_val, arg_ty, .normal);
907 break :ptr ptr;
908 } else arg_val;
823 var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types);
824 while (try it.nextCall(arg_types)) |lowering| {
825 const arg_ty: Type = .fromInterned(arg_types[it.zig_index - 1]);
826 const arg_val = arg_values[it.zig_index - 1];
827 switch (lowering) {
828 .no_bits => continue,
829 .byval => {
830 if (isByRef(arg_ty, zcu)) {
831 const alignment = arg_ty.abiAlignment(zcu).toLlvm();
832 // We don't need to handle non-ABI-sized integer types in memory here since they are
833 // never by-ref.
834 const llvm_arg_ty = try o.lowerType(arg_ty, .memory_access);
835 const loaded = try fg.wip.load(.normal, llvm_arg_ty, arg_val, alignment, "");
836 try llvm_args.append(fg.gpa, loaded);
837 } else {
838 try llvm_args.append(fg.gpa, arg_val);
839 }
840 },
841 .byref => {
842 if (isByRef(arg_ty, zcu)) {
843 try llvm_args.append(fg.gpa, arg_val);
844 } else {
845 const arg_ptr = try fg.buildZigAlloca(arg_ty, .none);
846 try fg.store(arg_ptr, .none, arg_val, arg_ty, .normal);
847 try llvm_args.append(fg.gpa, arg_ptr);
848 }
849 },
850 .byref_mut => {
851 const arg_ptr = try fg.buildZigAlloca(arg_ty, .none);
852 try fg.store(arg_ptr, .none, arg_val, arg_ty, .normal);
853 try llvm_args.append(fg.gpa, arg_ptr);
854 },
855 .abi_sized_int => {
856 const int_llvm_ty = try o.builder.intType(@intCast(arg_ty.abiSize(zcu) * 8));
909857
910 const array_ty = try o.builder.arrayType(arr_len, try o.builder.intType(@intCast(elem_size)));
911 const loaded = try self.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), "");
912 try llvm_args.append(loaded);
913 },
914 };
858 if (isByRef(arg_ty, zcu)) {
859 const alignment = arg_ty.abiAlignment(zcu).toLlvm();
860 const loaded = try fg.wip.load(.normal, int_llvm_ty, arg_val, alignment, "");
861 try llvm_args.append(fg.gpa, loaded);
862 } else {
863 // LLVM does not allow bitcasting structs so we must allocate
864 // a local, store as one type, and then load as another type.
865 const alignment = arg_ty.abiAlignment(zcu).toLlvm();
866 const ptr = try fg.buildAlloca(int_llvm_ty, alignment);
867 try fg.store(ptr, .none, arg_val, arg_ty, .normal);
868 const loaded = try fg.wip.load(.normal, int_llvm_ty, ptr, alignment, "");
869 try llvm_args.append(fg.gpa, loaded);
870 }
871 },
872 .slice => {
873 const ptr = try fg.wip.extractValue(arg_val, &.{0}, "");
874 const len = try fg.wip.extractValue(arg_val, &.{1}, "");
875 try llvm_args.appendSlice(fg.gpa, &.{ ptr, len });
876 },
877 .multiple_llvm_types => {
878 const arg_alignment = arg_ty.abiAlignment(zcu);
879 const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8);
880 const arg_ptr = try fg.buildAlloca(llvm_ty, arg_alignment.toLlvm());
881 try fg.store(arg_ptr, .none, arg_val, arg_ty, .normal);
882
883 try llvm_args.ensureUnusedCapacity(fg.gpa, it.types_len);
884 for (it.types_buffer[0..it.types_len], it.offsets_buffer[0..it.types_len]) |field_ty, offset| {
885 const field_ptr = try fg.ptraddConst(arg_ptr, offset);
886 const loaded = try fg.wip.load(.normal, field_ty, field_ptr, arg_alignment.offset(offset).toLlvm(), "");
887 llvm_args.appendAssumeCapacity(loaded);
888 }
889 },
890 .float_array => |count| {
891 const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: {
892 const ptr = try fg.buildZigAlloca(arg_ty, .none);
893 try fg.store(ptr, .none, arg_val, arg_ty, .normal);
894 break :ptr ptr;
895 } else arg_val;
896
897 const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, zcu).?, .memory_access);
898 const array_ty = try o.builder.arrayType(count, float_ty);
899
900 const loaded = try fg.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), "");
901 try llvm_args.append(fg.gpa, loaded);
902 },
903 .i32_array, .i64_array => |arr_len| {
904 const elem_size: u8 = if (lowering == .i32_array) 32 else 64;
905
906 const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: {
907 const ptr = try fg.buildZigAlloca(arg_ty, .none);
908 try fg.store(ptr, .none, arg_val, arg_ty, .normal);
909 break :ptr ptr;
910 } else arg_val;
911
912 const array_ty = try o.builder.arrayType(arr_len, try o.builder.intType(@intCast(elem_size)));
913 const loaded = try fg.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), "");
914 try llvm_args.append(fg.gpa, loaded);
915 },
916 }
917 }
915918
916919 const cc_info = llvm.toLlvmCallConv(fn_info.cc, target).?;
917920
918921 {
919922 // Add argument attributes.
920 it = iterateParamTypes(o, fn_info);
923 it = iterateParamTypes(o, fn_info.cc, fn_info.param_types);
921924 it.llvm_index += @intFromBool(ret_strat == .sret);
922925 it.llvm_index += @intFromBool(err_return_tracing);
923926 var remaining_inreg_int = cc_info.inreg_int_params;
......@@ -925,7 +928,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
925928 while (try it.next()) |lowering| switch (lowering) {
926929 .byval => {
927930 const param_index = it.zig_index - 1;
928 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]);
931 const param_ty = Type.fromInterned(fn_info.param_types[param_index]);
929932 if (!isByRef(param_ty, zcu)) {
930933 try o.addByValParamAttrs(pt, &attributes, param_ty, param_index, fn_info, it.llvm_index - 1);
931934 }
......@@ -947,7 +950,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
947950 },
948951 .byref => {
949952 const param_index = it.zig_index - 1;
950 const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[param_index]);
953 const param_ty: Type = .fromInterned(fn_info.param_types[param_index]);
951954 try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, it.byval_attr, param_ty);
952955 },
953956 .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder),
......@@ -961,8 +964,8 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
961964 => continue,
962965
963966 .slice => {
964 assert(!it.byval_attr);
965 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
967 assert(it.byval_attr == null);
968 const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]);
966969 const ptr_info = param_ty.ptrInfo(zcu);
967970 const llvm_arg_i = it.llvm_index - 2;
968971
......@@ -989,8 +992,8 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
989992 };
990993 }
991994
992 const call = try self.wip.call(
993 switch (modifier) {
995 const call = try fg.wip.call(
996 switch (opts.modifier) {
994997 .auto, .never_inline => .normal,
995998 .never_tail => .notail,
996999 .always_tail => .musttail,
......@@ -998,19 +1001,14 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
9981001 },
9991002 cc_info.llvm_cc,
10001003 try attributes.finish(&o.builder),
1001 try o.lowerType(zig_fn_ty, .by_value),
1004 llvm_fn_ty,
10021005 llvm_fn,
10031006 llvm_args.items,
10041007 "",
10051008 );
10061009
1007 if (fn_info.return_type == .noreturn_type and modifier != .always_tail) {
1008 return .none;
1009 }
1010
1011 if (self.liveness.isUnused(inst)) {
1012 return .none;
1013 }
1010 if (opts.is_unused) return .none;
1011 if (fn_info.return_type == .noreturn_type and opts.modifier != .always_tail) return .none;
10141012
10151013 // We exit this `switch` if we have a pointer to the return value.
10161014 const ret_val_ptr: Builder.Value = switch (ret_strat) {
......@@ -1020,15 +1018,15 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
10201018 .sret => sret_alloc.?,
10211019 .mem_cast => |llvm_ret_ty| ret_val_ptr: {
10221020 const alignment = return_type.abiAlignment(zcu).toLlvm();
1023 const ptr = try self.buildAlloca(llvm_ret_ty, alignment);
1024 _ = try self.wip.store(.normal, call, ptr, alignment);
1021 const ptr = try fg.buildAlloca(llvm_ret_ty, alignment);
1022 _ = try fg.wip.store(.normal, call, ptr, alignment);
10251023 break :ret_val_ptr ptr;
10261024 },
10271025 };
10281026 if (isByRef(return_type, zcu)) {
10291027 return ret_val_ptr;
10301028 } else {
1031 return self.load(ret_val_ptr, .none, return_type, .normal);
1029 return fg.load(ret_val_ptr, .none, return_type, .normal);
10321030 }
10331031}
10341032
......@@ -1038,7 +1036,7 @@ fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.SimplePanicId) Allocator.Error!v
10381036 const target = zcu.getTarget();
10391037 const panic_func = zcu.funcInfo(zcu.std_lang_decl_values.get(panic_id.toStdLangDecl()));
10401038 const fn_info = zcu.typeToFunc(.fromInterned(panic_func.ty)).?;
1041 const llvm_panic_fn_ty = try o.lowerType(.fromInterned(panic_func.ty), .by_value);
1039 const llvm_panic_fn_ty = try o.lowerType(.fromInterned(panic_func.ty), .as_value);
10421040
10431041 const llvm_panic_fn_ref = try o.lowerNavRef(panic_func.owner_nav);
10441042
......@@ -1067,7 +1065,7 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!vo
10671065
10681066 const fn_info = zcu.typeToFunc(Type.fromInterned(ip.getNav(self.nav_index).resolved.?.type)).?;
10691067
1070 const ret_strat = try fnReturnStrat(o, fn_info);
1068 const ret_strat = try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type));
10711069 const val_is_undef = if (un_op.toInterned()) |i| Value.fromInterned(i).isUndef(zcu) else false;
10721070 const ret_ty_align = ret_ty.abiAlignment(zcu);
10731071
......@@ -1076,7 +1074,7 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!vo
10761074 .none => try self.buildZigAlloca(ret_ty, .none),
10771075 else => |rp| rp,
10781076 };
1079 const len = try o.builder.intValue(try o.lowerType(.usize, .by_value), ret_ty.abiSize(zcu));
1077 const len = try o.builder.intValue(try o.lowerType(.usize, .as_value), ret_ty.abiSize(zcu));
10801078 _ = try self.wip.callMemSet(
10811079 rp,
10821080 ret_ty_align.toLlvm(),
......@@ -1141,7 +1139,7 @@ fn airRetLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!void {
11411139 const ret_ty = ptr_ty.childType(zcu);
11421140 const fn_info = zcu.typeToFunc(.fromInterned(ip.getNav(self.nav_index).resolved.?.type)).?;
11431141 const ptr = try self.resolveInst(un_op);
1144 switch (try fnReturnStrat(o, fn_info)) {
1142 switch (try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type))) {
11451143 .void => _ = try self.wip.retVoid(),
11461144 .sret => {
11471145 assert(self.ret_ptr != .none);
......@@ -1165,7 +1163,7 @@ fn airCVaArg(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
11651163 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
11661164 const list = try self.resolveInst(ty_op.operand);
11671165 const arg_ty = ty_op.ty.toType();
1168 const llvm_arg_ty = try self.object.lowerType(arg_ty, .by_value);
1166 const llvm_arg_ty = try self.object.lowerType(arg_ty, .as_value);
11691167
11701168 return self.wip.vaArg(list, llvm_arg_ty, "");
11711169}
......@@ -1378,7 +1376,7 @@ fn lowerBlock(
13781376 if (have_block_result) {
13791377 const llvm_ty: Builder.Type = switch (isByRef(inst_ty, zcu)) {
13801378 true => .ptr,
1381 false => try o.lowerType(inst_ty, .by_value),
1379 false => try o.lowerType(inst_ty, .as_value),
13821380 };
13831381 parent_bb.ptr(&self.wip).incoming = @intCast(breaks.list.len);
13841382 const phi = try self.wip.phi(llvm_ty, "");
......@@ -1485,7 +1483,7 @@ fn lowerSwitchDispatch(
14851483 const table_index = try self.wip.conv(
14861484 .unsigned,
14871485 try self.wip.bin(.@"sub nuw", cond, jmp_table.min.toValue(), ""),
1488 try o.lowerType(.usize, .by_value),
1486 try o.lowerType(.usize, .as_value),
14891487 "",
14901488 );
14911489 const target_ptr_ptr = try self.ptraddScaled(
......@@ -1510,7 +1508,7 @@ fn lowerSwitchDispatch(
15101508 // The switch prongs will correspond to our scalar cases. Ranges will
15111509 // be handled by conditional branches in the `else` prong.
15121510
1513 const llvm_usize = try o.lowerType(.usize, .by_value);
1511 const llvm_usize = try o.lowerType(.usize, .as_value);
15141512 const cond_int = if (cond_ty.zigTypeTag(zcu) == .pointer)
15151513 try self.wip.cast(.ptrtoint, cond, llvm_usize, "")
15161514 else
......@@ -1725,7 +1723,7 @@ fn lowerTry(
17251723 if (err_union_ty.isVolatilePtr(zcu)) .@"volatile" else .normal,
17261724 );
17271725 };
1728 const zero = try o.builder.intValue(try o.errorIntType(.by_value), 0);
1726 const zero = try o.builder.intValue(try o.errorIntType(.as_value), 0);
17291727 const is_err = try fg.wip.icmp(.ne, loaded, zero, "");
17301728
17311729 const return_block = try fg.wip.block(1, "TryRet");
......@@ -1862,8 +1860,8 @@ fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Tod
18621860 const table_includes_else = item_count != table_len;
18631861
18641862 break :jmp_table .{
1865 .min = try o.lowerValue(min.toIntern(), .by_value),
1866 .max = try o.lowerValue(max.toIntern(), .by_value),
1863 .min = try o.lowerValue(min.toIntern(), .as_value),
1864 .max = try o.lowerValue(max.toIntern(), .as_value),
18671865 .in_bounds_hint = if (table_includes_else) .none else switch (switch_br.getElseHint()) {
18681866 .none, .cold => .none,
18691867 .unpredictable => .unpredictable,
......@@ -2021,142 +2019,102 @@ fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder
20212019 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
20222020 const operand_ty = self.typeOf(ty_op.operand);
20232021 const array_ty = operand_ty.childType(zcu);
2024 const llvm_usize = try o.lowerType(.usize, .by_value);
2022 const llvm_usize = try o.lowerType(.usize, .as_value);
20252023 const len = try o.builder.intValue(llvm_usize, array_ty.arrayLen(zcu));
2026 const slice_llvm_ty = try o.lowerType(self.typeOfIndex(inst), .by_value);
2024 const slice_llvm_ty = try o.lowerType(self.typeOfIndex(inst), .as_value);
20272025 const operand = try self.resolveInst(ty_op.operand);
20282026 return self.wip.buildAggregate(slice_llvm_ty, &.{ operand, len }, "");
20292027}
20302028
2031fn airFloatFromInt(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
2032 const o = self.object;
2029fn airFloatFromInt(fg: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
2030 const o = fg.object;
20332031 const zcu = o.zcu;
2034 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
2032 const ty_op = fg.air.instructions.items(.data)[@backingInt(inst)].ty_op;
20352033
2036 const operand = try self.resolveInst(ty_op.operand);
2037 const operand_ty = self.typeOf(ty_op.operand);
2034 const operand = try fg.resolveInst(ty_op.operand);
2035 const operand_ty = fg.typeOf(ty_op.operand);
20382036 const operand_scalar_ty = operand_ty.scalarType(zcu);
2039 const is_signed_int = operand_scalar_ty.isSignedInt(zcu);
2037 const operand_scalar_info = operand_scalar_ty.intInfo(zcu);
20402038
2041 const dest_ty = self.typeOfIndex(inst);
2039 const dest_ty = fg.typeOfIndex(inst);
20422040 const dest_scalar_ty = dest_ty.scalarType(zcu);
2043 const dest_llvm_ty = try o.lowerType(dest_ty, .by_value);
20442041 const target = zcu.getTarget();
20452042
2046 if (intrinsicsAllowed(dest_scalar_ty, target)) return self.wip.conv(
2047 if (is_signed_int) .signed else .unsigned,
2048 operand,
2049 dest_llvm_ty,
2050 "",
2051 );
2043 if (intrinsicsAllowed(.compiler_rt, dest_scalar_ty, target))
2044 return fg.wip.conv(.fromStdLang(operand_scalar_info.signedness), operand, try o.lowerType(dest_ty, .as_value), "");
20522045
2053 const rt_int_bits = compilerRtIntBits(@intCast(operand_scalar_ty.bitSize(zcu))) orelse {
2054 return self.todo("float_from_int on {d} bit integer", .{operand_scalar_ty.bitSize(zcu)});
2046 const rt_int_ty = compilerRtPromoteInt(operand_scalar_info) orelse {
2047 return fg.todo("float_from_int on {d} bit integer", .{operand_scalar_info.bits});
20552048 };
2056 const rt_int_ty = try o.builder.intType(rt_int_bits);
2057 var extended = try self.wip.conv(
2058 if (is_signed_int) .signed else .unsigned,
2049 const vector_len = if (operand_ty.isVector(zcu)) operand_ty.vectorLen(zcu) else null;
2050 const rt_llvm_int_ty = try o.lowerType(rt_int_ty, .as_value);
2051 const extended = try fg.wip.conv(
2052 .fromStdLang(operand_scalar_info.signedness),
20592053 operand,
2060 rt_int_ty,
2054 if (vector_len) |len|
2055 try o.builder.vectorType(.normal, len, rt_llvm_int_ty)
2056 else
2057 rt_llvm_int_ty,
20612058 "",
20622059 );
2063 const dest_bits = dest_scalar_ty.floatBits(target);
2064 const compiler_rt_operand_abbrev = compilerRtIntAbbrev(rt_int_bits);
2065 const compiler_rt_dest_abbrev = compilerRtFloatAbbrev(dest_bits);
2066 const sign_prefix = if (is_signed_int) "" else "un";
20672060 const fn_name = try o.builder.strtabStringFmt("__float{s}{s}i{s}f", .{
2068 sign_prefix,
2069 compiler_rt_operand_abbrev,
2070 compiler_rt_dest_abbrev,
2061 switch (operand_scalar_info.signedness) {
2062 .signed => "",
2063 .unsigned => "un",
2064 },
2065 compilerRtIntAbbrev(rt_int_ty.intInfo(zcu).bits),
2066 compilerRtFloatAbbrev(target, dest_scalar_ty.floatBits(target)),
20712067 });
2072
2073 var param_type = rt_int_ty;
2074 if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) {
2075 // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard
2076 // i128 calling convention to adhere to the ABI that LLVM expects compiler-rt to have.
2077 param_type = try o.builder.vectorType(.normal, 2, .i64);
2078 extended = try self.wip.cast(.bitcast, extended, param_type, "");
2079 }
2080
2081 const libc_fn = try o.getLibcFunction(fn_name, &.{param_type}, dest_llvm_ty);
2082 return self.wip.call(
2083 .normal,
2084 .ccc,
2085 .none,
2086 libc_fn.typeOf(&o.builder),
2087 libc_fn.toValue(&o.builder),
2088 &.{extended},
2089 "",
2090 );
2068 return fg.buildElementwiseCall(fn_name, .{
2069 .cc = target.cCallingConvention().?,
2070 .param_types = &.{rt_int_ty.toIntern()},
2071 .return_type = dest_scalar_ty.toIntern(),
2072 }, &.{extended}, vector_len);
20912073}
20922074
20932075fn airIntFromFloat(
2094 self: *FuncGen,
2076 fg: *FuncGen,
20952077 inst: Air.Inst.Index,
20962078 fast: Builder.FastMathKind,
20972079) TodoError!Builder.Value {
20982080 _ = fast;
20992081
2100 const o = self.object;
2082 const o = fg.object;
21012083 const zcu = o.zcu;
21022084 const target = zcu.getTarget();
2103 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
2085 const ty_op = fg.air.instructions.items(.data)[@backingInt(inst)].ty_op;
21042086
2105 const operand = try self.resolveInst(ty_op.operand);
2106 const operand_ty = self.typeOf(ty_op.operand);
2087 const operand = try fg.resolveInst(ty_op.operand);
2088 const operand_ty = fg.typeOf(ty_op.operand);
21072089 const operand_scalar_ty = operand_ty.scalarType(zcu);
21082090
2109 const dest_ty = self.typeOfIndex(inst);
2091 const dest_ty = fg.typeOfIndex(inst);
21102092 const dest_scalar_ty = dest_ty.scalarType(zcu);
2111 const dest_llvm_ty = try o.lowerType(dest_ty, .by_value);
2093 const dest_llvm_ty = try o.lowerType(dest_ty, .as_value);
2094 const dest_scalar_info = dest_scalar_ty.intInfo(zcu);
21122095
2113 if (intrinsicsAllowed(operand_scalar_ty, target)) {
2096 if (intrinsicsAllowed(.compiler_rt, operand_scalar_ty, target)) {
21142097 // TODO set fast math flag
2115 return self.wip.conv(
2116 if (dest_scalar_ty.isSignedInt(zcu)) .signed else .unsigned,
2117 operand,
2118 dest_llvm_ty,
2119 "",
2120 );
2098 return fg.wip.conv(.fromStdLang(dest_scalar_info.signedness), operand, dest_llvm_ty, "");
21212099 }
21222100
2123 const rt_int_bits = compilerRtIntBits(@intCast(dest_scalar_ty.bitSize(zcu))) orelse {
2124 return self.todo("int_from_float to {d} bit integer", .{dest_scalar_ty.bitSize(zcu)});
2101 const rt_int_ty = compilerRtPromoteInt(dest_scalar_info) orelse {
2102 return fg.todo("int_from_float to {d} bit integer", .{dest_scalar_info.bits});
21252103 };
2126 const ret_ty = try o.builder.intType(rt_int_bits);
2127 const libc_ret_ty = if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) b: {
2128 // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard
2129 // i128 calling convention to adhere to the ABI that LLVM expects compiler-rt to have.
2130 break :b try o.builder.vectorType(.normal, 2, .i64);
2131 } else ret_ty;
2132
2133 const operand_bits = operand_scalar_ty.floatBits(target);
2134 const compiler_rt_operand_abbrev = compilerRtFloatAbbrev(operand_bits);
2135
2136 const compiler_rt_dest_abbrev = compilerRtIntAbbrev(rt_int_bits);
2137 const sign_prefix = if (dest_scalar_ty.isSignedInt(zcu)) "" else "uns";
2138
21392104 const fn_name = try o.builder.strtabStringFmt("__fix{s}{s}f{s}i", .{
2140 sign_prefix,
2141 compiler_rt_operand_abbrev,
2142 compiler_rt_dest_abbrev,
2105 switch (dest_scalar_info.signedness) {
2106 .signed => "",
2107 .unsigned => "uns",
2108 },
2109 compilerRtFloatAbbrev(target, operand_scalar_ty.floatBits(target)),
2110 compilerRtIntAbbrev(rt_int_ty.intInfo(zcu).bits),
21432111 });
2144
2145 const operand_llvm_ty = try o.lowerType(operand_ty, .by_value);
2146 const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, libc_ret_ty);
2147 var result = try self.wip.call(
2148 .normal,
2149 .ccc,
2150 .none,
2151 libc_fn.typeOf(&o.builder),
2152 libc_fn.toValue(&o.builder),
2153 &.{operand},
2154 "",
2155 );
2156
2157 if (libc_ret_ty != ret_ty) result = try self.wip.cast(.bitcast, result, ret_ty, "");
2158 if (ret_ty != dest_llvm_ty) result = try self.wip.cast(.trunc, result, dest_llvm_ty, "");
2159 return result;
2112 const result = try fg.buildElementwiseCall(fn_name, .{
2113 .cc = target.cCallingConvention().?,
2114 .param_types = &.{operand_scalar_ty.toIntern()},
2115 .return_type = rt_int_ty.toIntern(),
2116 }, &.{operand}, if (operand_ty.isVector(zcu)) operand_ty.vectorLen(zcu) else null);
2117 return fg.wip.cast(.trunc, result, try o.lowerType(dest_ty, .as_value), "");
21602118}
21612119
21622120fn sliceOrArrayPtr(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!Builder.Value {
......@@ -2167,7 +2125,7 @@ fn sliceOrArrayPtr(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!B
21672125fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!Builder.Value {
21682126 const o = fg.object;
21692127 const zcu = o.zcu;
2170 const llvm_usize = try o.lowerType(.usize, .by_value);
2128 const llvm_usize = try o.lowerType(.usize, .as_value);
21712129 switch (ty.ptrSize(zcu)) {
21722130 .slice => {
21732131 const len = try fg.wip.extractValue(ptr, &.{1}, "");
......@@ -2365,7 +2323,7 @@ fn airAggFieldVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.
23652323 },
23662324 .float => {
23672325 // bitcast int->float
2368 return self.wip.cast(.bitcast, field_int_val, try o.lowerType(field_ty, .by_value), "");
2326 return self.wip.cast(.bitcast, field_int_val, try o.lowerType(field_ty, .as_value), "");
23692327 },
23702328 }
23712329 }
......@@ -2395,8 +2353,8 @@ fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build
23952353 const field_offset = parent_ty.structFieldOffset(extra.field_index, zcu);
23962354 if (field_offset == 0) return field_ptr;
23972355
2398 const res_ty = try o.lowerType(ty_pl.ty.toType(), .by_value);
2399 const llvm_usize = try o.lowerType(.usize, .by_value);
2356 const res_ty = try o.lowerType(ty_pl.ty.toType(), .as_value);
2357 const llvm_usize = try o.lowerType(.usize, .as_value);
24002358
24012359 const field_ptr_int = try self.wip.cast(.ptrtoint, field_ptr, llvm_usize, "");
24022360 const base_ptr_int = try self.wip.bin(
......@@ -2516,7 +2474,7 @@ fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index, is_arg: bool) Allocator.Er
25162474 },
25172475 "",
25182476 );
2519 } else if (owner_mod.optimize_mode == .Debug and !self.is_naked) {
2477 } else if (owner_mod.optimize_mode == .debug and !self.is_naked) {
25202478 // We avoid taking this path for naked functions because there's no guarantee that such
25212479 // functions even have a valid stack pointer, making the `alloca` + `store` unsafe.
25222480
......@@ -2612,7 +2570,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
26122570 const output_inst = try self.resolveInst(output.operand);
26132571 const output_ty = self.typeOf(output.operand);
26142572 assert(output_ty.zigTypeTag(zcu) == .pointer);
2615 const elem_llvm_ty = try o.lowerType(output_ty.childType(zcu), .by_value);
2573 const elem_llvm_ty = try o.lowerType(output_ty.childType(zcu), .as_value);
26162574
26172575 switch (constraint[0]) {
26182576 '=' => {},
......@@ -2650,7 +2608,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
26502608 llvm_ret_indirect[output.index] = false;
26512609
26522610 const ret_ty = self.typeOfIndex(inst);
2653 llvm_ret_types[llvm_ret_i] = try o.lowerType(ret_ty, .by_value);
2611 llvm_ret_types[llvm_ret_i] = try o.lowerType(ret_ty, .as_value);
26542612 llvm_ret_i += 1;
26552613 }
26562614
......@@ -2689,7 +2647,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
26892647 llvm_param_types[llvm_param_i] = arg_llvm_value.typeOfWip(&self.wip);
26902648 } else {
26912649 const alignment = arg_ty.abiAlignment(zcu).toLlvm();
2692 const arg_llvm_ty = try o.lowerType(arg_ty, .by_value);
2650 const arg_llvm_ty = try o.lowerType(arg_ty, .as_value);
26932651 const load_inst = try self.wip.load(.normal, arg_llvm_ty, arg_llvm_value, alignment, "");
26942652 llvm_param_values[llvm_param_i] = load_inst;
26952653 llvm_param_types[llvm_param_i] = arg_llvm_ty;
......@@ -2729,7 +2687,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
27292687 llvm_param_attrs[llvm_param_i] = if (constraint[0] == '*') blk: {
27302688 if (!is_by_ref) self.maybeMarkAllowZeroAccess(arg_ty.ptrInfo(zcu));
27312689
2732 break :blk try o.lowerType(if (is_by_ref) arg_ty else arg_ty.childType(zcu), .by_value);
2690 break :blk try o.lowerType(if (is_by_ref) arg_ty else arg_ty.childType(zcu), .as_value);
27332691 } else .none;
27342692
27352693 llvm_param_i += 1;
......@@ -2743,7 +2701,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
27432701 if (constraint[0] != '+') continue;
27442702
27452703 const rw_ty = self.typeOf(output.operand);
2746 const llvm_elem_ty = try o.lowerType(rw_ty.childType(zcu), .by_value);
2704 const llvm_elem_ty = try o.lowerType(rw_ty.childType(zcu), .as_value);
27472705 if (llvm_ret_indirect[output.index]) {
27482706 llvm_param_values[llvm_param_i] = llvm_rw_vals[output.index];
27492707 llvm_param_types[llvm_param_i] = llvm_rw_vals[output.index].typeOfWip(&self.wip);
......@@ -2957,7 +2915,7 @@ fn airIsNonNull(
29572915 ));
29582916 return self.wip.icmp(cond, slice_ptr, try o.builder.nullValue(ptr_ty), "");
29592917 }
2960 return self.wip.icmp(cond, loaded, try o.builder.zeroInitValue(try o.lowerType(optional_ty, .by_value)), "");
2918 return self.wip.icmp(cond, loaded, try o.builder.zeroInitValue(try o.lowerType(optional_ty, .as_value)), "");
29612919 }
29622920
29632921 comptime assert(optional_layout_version == 3);
......@@ -2986,18 +2944,17 @@ fn airIsErr(
29862944 const operand_ty = self.typeOf(un_op);
29872945 const err_union_ty = if (operand_is_ptr) operand_ty.childType(zcu) else operand_ty;
29882946 const payload_ty = err_union_ty.errorUnionPayload(zcu);
2989 const zero_err = try o.builder.intValue(try o.errorIntType(.by_value), 0);
2947 const zero_err = try o.builder.intValue(try o.errorIntType(.as_value), 0);
29902948
29912949 const access_kind: Builder.MemoryAccessKind =
29922950 if (operand_is_ptr and operand_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
29932951
29942952 if (err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) {
2995 const val: Builder.Constant = switch (cond) {
2953 return switch (cond) {
29962954 .eq => .true, // 0 == 0
29972955 .ne => .false, // 0 != 0
29982956 else => unreachable,
29992957 };
3000 return val.toValue();
30012958 }
30022959
30032960 if (operand_is_ptr) self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu));
......@@ -3156,7 +3113,7 @@ fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) Allocator.Erro
31563113 const err_union_ptr_align = err_union_ptr_ty.ptrAlignment(zcu);
31573114
31583115 const payload_ty = err_union_ty.errorUnionPayload(zcu);
3159 const non_error_val = try o.builder.intValue(try o.errorIntType(.by_value), 0);
3116 const non_error_val = try o.builder.intValue(try o.errorIntType(.as_value), 0);
31603117
31613118 const access_kind: Builder.MemoryAccessKind =
31623119 if (err_union_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
......@@ -3234,7 +3191,7 @@ fn airWrapErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!
32343191 const payload_ty = self.typeOf(ty_op.operand);
32353192 assert(payload_ty.hasRuntimeBits(zcu));
32363193 assert(isByRef(err_un_ty, zcu)); // error unions with runtime bits are always by-ref
3237 const ok_err_code = try o.builder.intValue(try o.errorIntType(.by_value), 0);
3194 const ok_err_code = try o.builder.intValue(try o.errorIntType(.as_value), 0);
32383195
32393196 const result_ptr = try self.buildZigAlloca(err_un_ty, .none);
32403197
......@@ -3273,7 +3230,7 @@ fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build
32733230 const o = self.object;
32743231 const pl_op = self.air.instructions.items(.data)[@backingInt(inst)].pl_op;
32753232 const index = pl_op.payload;
3276 const llvm_usize = try o.lowerType(.usize, .by_value);
3233 const llvm_usize = try o.lowerType(.usize, .as_value);
32773234 return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.size", &.{llvm_usize}, &.{
32783235 try o.builder.intValue(.i32, index),
32793236 }, "");
......@@ -3283,7 +3240,7 @@ fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build
32833240 const o = self.object;
32843241 const pl_op = self.air.instructions.items(.data)[@backingInt(inst)].pl_op;
32853242 const index = pl_op.payload;
3286 const llvm_isize = try o.lowerType(.isize, .by_value);
3243 const llvm_isize = try o.lowerType(.isize, .as_value);
32873244 return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.grow", &.{llvm_isize}, &.{
32883245 try o.builder.intValue(.i32, index), try self.resolveInst(pl_op.operand),
32893246 }, "");
......@@ -3310,7 +3267,7 @@ fn airMin(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
33103267 .normal,
33113268 .none,
33123269 if (scalar_ty.isSignedInt(zcu)) .smin else .umin,
3313 &.{try o.lowerType(inst_ty, .by_value)},
3270 &.{try o.lowerType(inst_ty, .as_value)},
33143271 &.{ lhs, rhs },
33153272 "",
33163273 );
......@@ -3330,7 +3287,7 @@ fn airMax(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
33303287 .normal,
33313288 .none,
33323289 if (scalar_ty.isSignedInt(zcu)) .smax else .umax,
3333 &.{try o.lowerType(inst_ty, .by_value)},
3290 &.{try o.lowerType(inst_ty, .as_value)},
33343291 &.{ lhs, rhs },
33353292 "",
33363293 );
......@@ -3342,7 +3299,7 @@ fn airSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
33423299 const ptr = try self.resolveInst(bin_op.lhs);
33433300 const len = try self.resolveInst(bin_op.rhs);
33443301 const inst_ty = self.typeOfIndex(inst);
3345 return self.wip.buildAggregate(try self.object.lowerType(inst_ty, .by_value), &.{ ptr, len }, "");
3302 return self.wip.buildAggregate(try self.object.lowerType(inst_ty, .as_value), &.{ ptr, len }, "");
33463303}
33473304
33483305fn airAdd(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value {
......@@ -3373,7 +3330,7 @@ fn airSafeArithmetic(
33733330 const scalar_ty = inst_ty.scalarType(zcu);
33743331
33753332 const intrinsic = if (scalar_ty.isSignedInt(zcu)) signed_intrinsic else unsigned_intrinsic;
3376 const llvm_inst_ty = try o.lowerType(inst_ty, .by_value);
3333 const llvm_inst_ty = try o.lowerType(inst_ty, .as_value);
33773334 const results =
33783335 try fg.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_inst_ty}, &.{ lhs, rhs }, "");
33793336
......@@ -3423,7 +3380,7 @@ fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
34233380 .normal,
34243381 .none,
34253382 if (scalar_ty.isSignedInt(zcu)) .@"sadd.sat" else .@"uadd.sat",
3426 &.{try o.lowerType(inst_ty, .by_value)},
3383 &.{try o.lowerType(inst_ty, .as_value)},
34273384 &.{ lhs, rhs },
34283385 "",
34293386 );
......@@ -3462,7 +3419,7 @@ fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
34623419 .normal,
34633420 .none,
34643421 if (scalar_ty.isSignedInt(zcu)) .@"ssub.sat" else .@"usub.sat",
3465 &.{try o.lowerType(inst_ty, .by_value)},
3422 &.{try o.lowerType(inst_ty, .as_value)},
34663423 &.{ lhs, rhs },
34673424 "",
34683425 );
......@@ -3501,7 +3458,7 @@ fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
35013458 .normal,
35023459 .none,
35033460 if (scalar_ty.isSignedInt(zcu)) .@"smul.fix.sat" else .@"umul.fix.sat",
3504 &.{try o.lowerType(inst_ty, .by_value)},
3461 &.{try o.lowerType(inst_ty, .as_value)},
35053462 &.{ lhs, rhs, .@"0" },
35063463 "",
35073464 );
......@@ -3545,8 +3502,8 @@ fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind)
35453502 return self.buildFloatOp(.floor, fast, inst_ty, 1, .{result});
35463503 }
35473504 if (scalar_ty.isSignedInt(zcu)) {
3548 const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value);
3549 const inst_llvm_ty = try o.lowerType(inst_ty, .by_value);
3505 const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value);
3506 const inst_llvm_ty = try o.lowerType(inst_ty, .as_value);
35503507
35513508 const ExpectedContents = [std.math.big.int.calcTwosCompLimbCount(256)]std.math.big.Limb;
35523509 var bfa_buf: ExpectedContents = undefined;
......@@ -3594,8 +3551,8 @@ fn airDivCeil(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind)
35943551 return self.buildFloatOp(.ceil, fast, inst_ty, 1, .{result});
35953552 }
35963553 if (scalar_ty.isSignedInt(zcu)) {
3597 const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value);
3598 const inst_llvm_ty = try o.lowerType(inst_ty, .by_value);
3554 const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value);
3555 const inst_llvm_ty = try o.lowerType(inst_ty, .as_value);
35993556
36003557 const ExpectedContents = [std.math.big.int.calcTwosCompLimbCount(256)]std.math.big.Limb;
36013558 var bfa_buf: ExpectedContents = undefined;
......@@ -3634,8 +3591,8 @@ fn airDivCeil(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind)
36343591 const correction = try self.wip.cast(.zext, need_correction, inst_llvm_ty, "divCeil.correction");
36353592 return self.wip.bin(.@"add nsw", div, correction, "divCeil");
36363593 } else {
3637 const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value);
3638 const inst_llvm_ty = try o.lowerType(inst_ty, .by_value);
3594 const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value);
3595 const inst_llvm_ty = try o.lowerType(inst_ty, .as_value);
36393596
36403597 const zero = try o.builder.splatValue(
36413598 inst_llvm_ty,
......@@ -3692,15 +3649,17 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo
36923649 const lhs = try self.resolveInst(bin_op.lhs);
36933650 const rhs = try self.resolveInst(bin_op.rhs);
36943651 const inst_ty = self.typeOfIndex(inst);
3695 const inst_llvm_ty = try o.lowerType(inst_ty, .by_value);
36963652 const scalar_ty = inst_ty.scalarType(zcu);
36973653
36983654 if (scalar_ty.isRuntimeFloat()) {
36993655 const a = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ lhs, rhs });
37003656 const b = try self.buildFloatOp(.add, fast, inst_ty, 2, .{ a, rhs });
37013657 const c = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ b, rhs });
3702 const zero = try o.builder.zeroInitValue(inst_llvm_ty);
3703 const ltz = try self.buildFloatCmp(fast, .lt, inst_ty, .{ lhs, zero });
3658 const zero = if (isByRef(inst_ty, zcu)) zero: {
3659 const zero = try o.builder.zeroInitConst(try o.lowerType(inst_ty, .in_memory));
3660 break :zero try o.lowerConstRef(zero, inst_ty.abiAlignment(zcu).toLlvm());
3661 } else try o.builder.zeroInitConst(try o.lowerType(inst_ty, .as_value));
3662 const ltz = try self.buildFloatCmp(fast, .lt, inst_ty, .{ lhs, zero.toValue() });
37043663 return self.wip.select(fast, ltz, c, a, "");
37053664 }
37063665 if (scalar_ty.isSignedInt(zcu)) {
......@@ -3709,6 +3668,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo
37093668 var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), self.gpa);
37103669 const allocator = bfa.allocator();
37113670
3671 const inst_llvm_ty = try o.lowerType(inst_ty, .as_value);
37123672 const scalar_bits = scalar_ty.intInfo(zcu).bits;
37133673 var smin_big_int: std.math.big.int.Mutable = .{
37143674 .limbs = try allocator.alloc(
......@@ -3721,7 +3681,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo
37213681 defer allocator.free(smin_big_int.limbs);
37223682 smin_big_int.setTwosCompIntLimit(.min, .signed, scalar_bits);
37233683 const smin = try o.builder.splatValue(inst_llvm_ty, try o.builder.bigIntConst(
3724 try o.lowerType(scalar_ty, .by_value),
3684 try o.lowerType(scalar_ty, .as_value),
37253685 smin_big_int.toConst(),
37263686 ));
37273687
......@@ -3757,7 +3717,7 @@ fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
37573717 const ty_pl = self.air.instructions.items(.data)[@backingInt(inst)].ty_pl;
37583718 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
37593719 const ptr_or_slice = try self.resolveInst(bin_op.lhs);
3760 const llvm_usize_ty = try o.lowerType(.usize, .by_value);
3720 const llvm_usize_ty = try o.lowerType(.usize, .as_value);
37613721 const ptr_ty = self.typeOf(bin_op.lhs);
37623722 const elem_ty = ptr_ty.indexableElem(zcu);
37633723 const ptr = switch (ptr_ty.ptrSize(zcu)) {
......@@ -3790,7 +3750,7 @@ fn airOverflow(
37903750 assert(isByRef(inst_ty, zcu)); // auto structs are by-ref
37913751
37923752 const intrinsic = if (scalar_ty.isSignedInt(zcu)) signed_intrinsic else unsigned_intrinsic;
3793 const llvm_lhs_ty = try o.lowerType(lhs_ty, .by_value);
3753 const llvm_lhs_ty = try o.lowerType(lhs_ty, .as_value);
37943754 const results =
37953755 try self.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_lhs_ty}, &.{ lhs, rhs }, "");
37963756
......@@ -3818,34 +3778,97 @@ fn airOverflow(
38183778}
38193779
38203780fn buildElementwiseCall(
3821 self: *FuncGen,
3822 llvm_fn: Builder.Function.Index,
3823 args_vectors: []const Builder.Value,
3824 result_vector: Builder.Value,
3825 vector_len: usize,
3781 fg: *FuncGen,
3782 fn_name: Builder.StrtabString,
3783 fn_info: Object.FuncInfo,
3784 arg_values: []const Builder.Value,
3785 vector_len: ?u32,
38263786) Allocator.Error!Builder.Value {
3827 const o = self.object;
3828 assert(args_vectors.len <= 3);
3787 const o = fg.object;
3788 const zcu = o.zcu;
3789 const llvm_fn = try fg.object.getLibcFunction(fg.pt, fn_name, fn_info);
3790
3791 const iterations = vector_len orelse 1;
3792 const ret_ty: Type = .fromInterned(fn_info.return_type);
3793 const ret_is_by_ref = isByRef(ret_ty, zcu);
3794 if (iterations > 1 and (fn_info.return_type == .void_type or ret_is_by_ref) and
3795 for (fn_info.param_types) |param_type| {
3796 if (!isByRef(.fromInterned(param_type), zcu)) break false;
3797 } else true)
3798 {
3799 const entry_block = fg.wip.cursor.block;
3800 const loop_block = try fg.wip.block(2, "elementwise.loop");
3801 const done_block = try fg.wip.block(1, "elementwise.done");
3802
3803 const result_ptr = if (fn_info.return_type == .void_type) .none else result_ptr: {
3804 const ret_llvm_ty = try o.lowerType(ret_ty, .in_memory);
3805 break :result_ptr try fg.buildAlloca(
3806 if (vector_len) |len| try o.builder.arrayType(len, ret_llvm_ty) else ret_llvm_ty,
3807 ret_ty.abiAlignment(zcu).toLlvm(),
3808 );
3809 };
3810 _ = try fg.wip.br(loop_block);
38293811
3830 var i: usize = 0;
3831 var result = result_vector;
3832 while (i < vector_len) : (i += 1) {
3833 const index_i32 = try o.builder.intValue(.i32, i);
3812 fg.wip.cursor = .{ .block = loop_block };
3813 const index = try fg.wip.phi(.i32, "elementwise.index");
38343814
3835 var args: [3]Builder.Value = undefined;
3836 for (args[0..args_vectors.len], args_vectors) |*arg_elem, arg_vector| {
3837 arg_elem.* = try self.wip.extractElement(arg_vector, index_i32, "");
3815 var arg_elems_buf: [3]Builder.Value = undefined;
3816 const arg_elems = arg_elems_buf[0..arg_values.len];
3817 for (arg_elems, fn_info.param_types, arg_values) |*arg_elem, param_type, arg_value| {
3818 const arg_elem_ptr = try fg.ptraddScaled(arg_value, index.toValue(), Type.fromInterned(param_type).abiSize(zcu));
3819 arg_elem.* = try fg.load(arg_elem_ptr, .none, .fromInterned(param_type), .normal);
38383820 }
3839 const result_elem = try self.wip.call(
3840 .normal,
3841 .ccc,
3842 .none,
3843 llvm_fn.typeOf(&o.builder),
3844 llvm_fn.toValue(&o.builder),
3845 args[0..args_vectors.len],
3846 "",
3821 const result_elem = try fg.buildCall(.{}, llvm_fn.typeOf(&o.builder), llvm_fn.toValue(&o.builder), fn_info, fn_info.param_types, arg_elems);
3822 if (fn_info.return_type == .void_type) {
3823 assert(result_elem == .none);
3824 } else if (result_elem != .none) {
3825 const result_elem_ptr = try fg.ptraddScaled(result_ptr, index.toValue(), ret_ty.abiSize(zcu));
3826 try fg.store(result_elem_ptr, .none, result_elem, ret_ty, .normal);
3827 }
3828
3829 const next_index = try fg.wip.bin(.@"add nuw", index.toValue(), try o.builder.intValue(.i32, 1), "elementwise.next_index");
3830 index.finish(&.{ try o.builder.intValue(.i32, 0), next_index }, &.{ entry_block, loop_block }, &fg.wip);
3831 const is_done = try fg.wip.icmp(.eq, next_index, try o.builder.intValue(.i32, iterations), "elementwise.is_done");
3832 _ = try fg.wip.brCond(is_done, done_block, loop_block, .none);
3833
3834 fg.wip.cursor = .{ .block = done_block };
3835 return result_ptr;
3836 }
3837
3838 var result = if (fn_info.return_type == .void_type) .none else if (ret_is_by_ref) result: {
3839 const ret_llvm_ty = try o.lowerType(ret_ty, .in_memory);
3840 break :result try fg.buildAlloca(
3841 if (vector_len) |len| try o.builder.arrayType(len, ret_llvm_ty) else ret_llvm_ty,
3842 ret_ty.abiAlignment(zcu).toLlvm(),
38473843 );
3848 result = try self.wip.insertElement(result, result_elem, index_i32, "");
3844 } else if (vector_len) |len| try o.builder.poisonValue(
3845 try o.builder.vectorType(.normal, len, try o.lowerType(ret_ty, .as_value)),
3846 ) else .none;
3847 for (0..iterations) |index| {
3848 const index_value = try o.builder.intValue(.i32, index);
3849 var arg_elems_buf: [3]Builder.Value = undefined;
3850 const arg_elems = arg_elems_buf[0..arg_values.len];
3851 for (arg_elems, fn_info.param_types, arg_values) |*arg_elem_value, param_type, arg_value| {
3852 const arg_ty: Type = .fromInterned(param_type);
3853 if (isByRef(arg_ty, zcu)) {
3854 const arg_elem_ptr = try fg.ptraddConst(arg_value, index * arg_ty.abiSize(zcu));
3855 arg_elem_value.* = try fg.load(arg_elem_ptr, .none, .fromInterned(param_type), .normal);
3856 } else if (vector_len) |_| {
3857 arg_elem_value.* = try fg.wip.extractElement(arg_value, index_value, "elementwise.arg_elem");
3858 } else arg_elem_value.* = arg_value;
3859 }
3860 const result_elem = try fg.buildCall(.{}, llvm_fn.typeOf(&o.builder), llvm_fn.toValue(&o.builder), fn_info, fn_info.param_types, arg_elems);
3861 if (fn_info.return_type == .void_type) {
3862 assert(result_elem == .none);
3863 } else if (ret_is_by_ref) {
3864 const result_elem_ptr = try fg.ptraddConst(result, index * ret_ty.abiSize(zcu));
3865 try fg.store(result_elem_ptr, .none, result_elem, ret_ty, .normal);
3866 } else if (vector_len) |_| {
3867 result = try fg.wip.insertElement(result, result_elem, index_value, "elementwise.result");
3868 } else {
3869 assert(result == .none);
3870 result = result_elem;
3871 }
38493872 }
38503873 return result;
38513874}
......@@ -3853,19 +3876,18 @@ fn buildElementwiseCall(
38533876/// Creates a floating point comparison by lowering to the appropriate
38543877/// hardware instruction or softfloat routine for the target
38553878fn buildFloatCmp(
3856 self: *FuncGen,
3879 fg: *FuncGen,
38573880 fast: Builder.FastMathKind,
38583881 pred: math.CompareOperator,
38593882 ty: Type,
38603883 params: [2]Builder.Value,
38613884) Allocator.Error!Builder.Value {
3862 const o = self.object;
3885 const o = fg.object;
38633886 const zcu = o.zcu;
38643887 const target = zcu.getTarget();
38653888 const scalar_ty = ty.scalarType(zcu);
3866 const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value);
38673889
3868 if (intrinsicsAllowed(scalar_ty, target)) {
3890 if (intrinsicsAllowed(.compiler_rt, scalar_ty, target)) {
38693891 const cond: Builder.FloatCondition = switch (pred) {
38703892 .eq => .oeq,
38713893 .neq => .une,
......@@ -3874,53 +3896,33 @@ fn buildFloatCmp(
38743896 .gt => .ogt,
38753897 .gte => .oge,
38763898 };
3877 return self.wip.fcmp(fast, cond, params[0], params[1], "");
3899 return fg.wip.fcmp(fast, cond, params[0], params[1], "");
38783900 }
38793901
3880 const float_bits = scalar_ty.floatBits(target);
3881 const compiler_rt_float_abbrev = compilerRtFloatAbbrev(float_bits);
3882 const fn_base_name = switch (pred) {
3883 .neq => "ne",
3884 .eq => "eq",
3885 .lt => "lt",
3886 .lte => "le",
3887 .gt => "gt",
3888 .gte => "ge",
3889 };
3890 const fn_name = try o.builder.strtabStringFmt("__{s}{s}f2", .{ fn_base_name, compiler_rt_float_abbrev });
3891
3892 const libc_fn = try o.getLibcFunction(fn_name, &.{ scalar_llvm_ty, scalar_llvm_ty }, .i32);
3893
3894 const int_cond: Builder.IntegerCondition = switch (pred) {
3902 const fn_name = try o.builder.strtabStringFmt("__{s}{s}f2", .{
3903 switch (pred) {
3904 .neq => "ne",
3905 .eq => "eq",
3906 .lt => "lt",
3907 .lte => "le",
3908 .gt => "gt",
3909 .gte => "ge",
3910 },
3911 compilerRtFloatAbbrev(target, scalar_ty.floatBits(target)),
3912 });
3913 const result = try fg.buildElementwiseCall(fn_name, .{
3914 .cc = target.cCallingConvention().?,
3915 .param_types = &.{ scalar_ty.toIntern(), scalar_ty.toIntern() },
3916 .return_type = .i32_type,
3917 }, &params, if (ty.isVector(zcu)) ty.vectorLen(zcu) else null);
3918 return fg.wip.icmp(switch (pred) {
38953919 .eq => .eq,
38963920 .neq => .ne,
38973921 .lt => .slt,
38983922 .lte => .sle,
38993923 .gt => .sgt,
39003924 .gte => .sge,
3901 };
3902
3903 if (ty.zigTypeTag(zcu) == .vector) {
3904 const vec_len = ty.vectorLen(zcu);
3905 const vector_result_ty = try o.builder.vectorType(.normal, vec_len, .i32);
3906
3907 const init = try o.builder.poisonValue(vector_result_ty);
3908 const result = try self.buildElementwiseCall(libc_fn, &params, init, vec_len);
3909
3910 const zero_vector = try o.builder.splatValue(vector_result_ty, .@"0");
3911 return self.wip.icmp(int_cond, result, zero_vector, "");
3912 }
3913
3914 const result = try self.wip.call(
3915 .normal,
3916 .ccc,
3917 .none,
3918 libc_fn.typeOf(&o.builder),
3919 libc_fn.toValue(&o.builder),
3920 &params,
3921 "",
3922 );
3923 return self.wip.icmp(int_cond, result, .@"0", "");
3925 }, result, try o.builder.splatValue(result.typeOfWip(&fg.wip), .@"0"), "");
39243926}
39253927
39263928const FloatOp = enum {
......@@ -3949,32 +3951,30 @@ const FloatOp = enum {
39493951 trunc,
39503952};
39513953
3952const FloatOpStrat = union(enum) {
3953 intrinsic: []const u8,
3954 libc: Builder.String,
3955};
3956
39573954/// Creates a floating point operation (add, sub, fma, sqrt, exp, etc.)
39583955/// by lowering to the appropriate hardware instruction or softfloat
39593956/// routine for the target
39603957fn buildFloatOp(
3961 self: *FuncGen,
3958 fg: *FuncGen,
39623959 comptime op: FloatOp,
39633960 fast: Builder.FastMathKind,
39643961 ty: Type,
39653962 comptime params_len: usize,
39663963 params: [params_len]Builder.Value,
39673964) Allocator.Error!Builder.Value {
3968 const o = self.object;
3965 const o = fg.object;
39693966 const zcu = o.zcu;
39703967 const target = zcu.getTarget();
39713968 const scalar_ty = ty.scalarType(zcu);
3972 const llvm_ty = try o.lowerType(ty, .by_value);
39733969
3974 if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) {
3970 switch (op) {
39753971 // Some operations are dedicated LLVM instructions, not available as intrinsics
3976 .neg => return self.wip.un(.fneg, params[0], ""),
3977 .add, .sub, .mul, .div, .fmod => return self.wip.bin(switch (fast) {
3972 .neg => if (intrinsicsAllowed(.compiler_rt, scalar_ty, target)) return fg.wip.un(.fneg, params[0], ""),
3973 .add, .sub, .mul, .div, .fmod => if (intrinsicsAllowed(switch (op) {
3974 else => unreachable,
3975 .add, .sub, .mul, .div => .compiler_rt,
3976 .fmod => .libc,
3977 }, scalar_ty, target)) return fg.wip.bin(switch (fast) {
39783978 .normal => switch (op) {
39793979 .add => .fadd,
39803980 .sub => .fsub,
......@@ -3992,6 +3992,7 @@ fn buildFloatOp(
39923992 else => unreachable,
39933993 },
39943994 }, params[0], params[1], ""),
3995 .fma,
39953996 .fmax,
39963997 .fmin,
39973998 .ceil,
......@@ -4006,9 +4007,10 @@ fn buildFloatOp(
40064007 .round,
40074008 .sin,
40084009 .sqrt,
4010 .tan,
40094011 .trunc,
4010 .fma,
4011 => return self.wip.callIntrinsic(fast, .none, switch (op) {
4012 => if (intrinsicsAllowed(.libc, scalar_ty, target)) return fg.wip.callIntrinsic(fast, .none, switch (op) {
4013 .fma => .fma,
40124014 .fmax => .maxnum,
40134015 .fmin => .minnum,
40144016 .ceil => .ceil,
......@@ -4023,39 +4025,154 @@ fn buildFloatOp(
40234025 .round => .round,
40244026 .sin => .sin,
40254027 .sqrt => .sqrt,
4028 .tan => .tan,
40264029 .trunc => .trunc,
4027 .fma => .fma,
40284030 else => unreachable,
4029 }, &.{llvm_ty}, &params, ""),
4030 .tan => unreachable,
4031 };
4031 }, &.{try o.lowerType(ty, .as_value)}, &params, ""),
4032 }
40324033
40334034 const float_bits = scalar_ty.floatBits(target);
40344035 const fn_name = switch (op) {
4035 .neg => {
4036 // In this case we can generate a softfloat negation by XORing the
4037 // bits with a constant.
4036 // In these cases we can generate a softfloat operation by modifying the sign bit using a bitwise operation.
4037 .neg, .fabs => if (isByRef(scalar_ty, zcu)) {
4038 const is_vector = ty.toIntern() != scalar_ty.toIntern();
4039 const result_ptr = try fg.buildZigAlloca(ty, .none);
4040 const entry_block = fg.wip.cursor.block;
4041 const loop_block, const done_block, const llvm_usize_ty, const offset, const elem, const result_elem = if (is_vector) loop: {
4042 const loop_block = try fg.wip.block(2, "neg_fabs.loop");
4043 const done_block = try fg.wip.block(1, "neg_fabs.done");
4044 _ = try fg.wip.br(loop_block);
4045
4046 fg.wip.cursor = .{ .block = loop_block };
4047 const llvm_usize_ty = try o.lowerType(.usize, .as_value);
4048 const offset = try fg.wip.phi(llvm_usize_ty, "neg_fabs.offset");
4049 break :loop .{
4050 loop_block,
4051 done_block,
4052 llvm_usize_ty,
4053 offset,
4054 try fg.ptraddScaled(params[0], offset.toValue(), 1),
4055 try fg.ptraddScaled(result_ptr, offset.toValue(), 1),
4056 };
4057 } else .{ undefined, undefined, undefined, undefined, params[0], result_ptr };
4058 switch (scalar_ty.floatBits(target)) {
4059 else => unreachable,
4060 80 => {
4061 const f80_layout = o.softF80Layout(.{}) catch unreachable;
4062 const mantissa = try fg.load(
4063 try fg.ptraddConst(elem, f80_layout.mantissa_offset),
4064 f80_layout.alignment.offset(f80_layout.mantissa_offset),
4065 .u64,
4066 .normal,
4067 );
4068 const exponent = try fg.load(
4069 try fg.ptraddConst(elem, f80_layout.exponent_offset),
4070 f80_layout.alignment.offset(f80_layout.exponent_offset),
4071 .u16,
4072 .normal,
4073 );
4074 const exponent_sign_bit: u16 = 1 << (16 - 1);
4075 const updated_exponent = try fg.wip.bin(switch (op) {
4076 else => unreachable,
4077 .neg => .xor,
4078 .fabs => .@"and",
4079 }, exponent, try o.builder.intValue(.i16, switch (op) {
4080 else => unreachable,
4081 .neg => exponent_sign_bit,
4082 .fabs => exponent_sign_bit - 1,
4083 }), "neg_fabs.updated_exponent");
4084 try fg.store(
4085 try fg.ptraddConst(result_elem, f80_layout.mantissa_offset),
4086 f80_layout.alignment.offset(f80_layout.mantissa_offset),
4087 mantissa,
4088 .u64,
4089 .normal,
4090 );
4091 try fg.store(
4092 try fg.ptraddConst(result_elem, f80_layout.exponent_offset),
4093 f80_layout.alignment.offset(f80_layout.exponent_offset),
4094 updated_exponent,
4095 .u16,
4096 .normal,
4097 );
4098 },
4099 128 => {
4100 const f128_layout = o.softF128Layout(.{}) catch unreachable;
4101 const lo = try fg.load(
4102 try fg.ptraddConst(elem, f128_layout.lo_offset),
4103 f128_layout.alignment.offset(f128_layout.lo_offset),
4104 .u64,
4105 .normal,
4106 );
4107 const hi = try fg.load(
4108 try fg.ptraddConst(elem, f128_layout.hi_offset),
4109 f128_layout.alignment.offset(f128_layout.hi_offset),
4110 .u64,
4111 .normal,
4112 );
4113 const hi_sign_bit: u64 = 1 << (64 - 1);
4114 const updated_hi = try fg.wip.bin(switch (op) {
4115 else => unreachable,
4116 .neg => .xor,
4117 .fabs => .@"and",
4118 }, hi, try o.builder.intValue(.i64, switch (op) {
4119 else => unreachable,
4120 .neg => hi_sign_bit,
4121 .fabs => hi_sign_bit - 1,
4122 }), "neg_fabs.updated_hi");
4123 try fg.store(
4124 try fg.ptraddConst(result_elem, f128_layout.lo_offset),
4125 f128_layout.alignment.offset(f128_layout.lo_offset),
4126 lo,
4127 .u64,
4128 .normal,
4129 );
4130 try fg.store(
4131 try fg.ptraddConst(result_elem, f128_layout.hi_offset),
4132 f128_layout.alignment.offset(f128_layout.hi_offset),
4133 updated_hi,
4134 .u64,
4135 .normal,
4136 );
4137 },
4138 }
4139 if (is_vector) {
4140 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");
4141 offset.finish(&.{ try o.builder.intValue(llvm_usize_ty, 0), next_offset }, &.{ entry_block, loop_block }, &fg.wip);
4142 const is_done = try fg.wip.icmp(.eq, next_offset, try o.builder.intValue(llvm_usize_ty, ty.abiSize(zcu)), "neg_fabs.is_done");
4143 _ = try fg.wip.brCond(is_done, done_block, loop_block, .none);
4144
4145 fg.wip.cursor = .{ .block = done_block };
4146 }
4147 return result_ptr;
4148 } else {
40384149 const int_ty = try o.builder.intType(@intCast(float_bits));
40394150 const cast_ty = switch (ty.zigTypeTag(zcu)) {
40404151 .vector => try o.builder.vectorType(.normal, ty.vectorLen(zcu), int_ty),
40414152 else => int_ty,
40424153 };
4043 const sign_mask = try o.builder.splatValue(
4044 cast_ty,
4045 try o.builder.intConst(int_ty, @as(u128, 1) << @intCast(float_bits - 1)),
4046 );
4047 const bitcasted_operand = try self.wip.cast(.bitcast, params[0], cast_ty, "");
4048 const result = try self.wip.bin(.xor, bitcasted_operand, sign_mask, "");
4049 return self.wip.cast(.bitcast, result, llvm_ty, "");
4154 const sign_bit = @as(u128, 1) << @intCast(float_bits - 1);
4155 const bitwise_rhs = try o.builder.splatValue(cast_ty, try o.builder.intConst(int_ty, switch (op) {
4156 else => unreachable,
4157 .neg => sign_bit,
4158 .fabs => sign_bit - 1,
4159 }));
4160 const bitcasted_operand = try fg.wip.cast(.bitcast, params[0], cast_ty, "");
4161 const result = try fg.wip.bin(switch (op) {
4162 else => unreachable,
4163 .neg => .xor,
4164 .fabs => .@"and",
4165 }, bitcasted_operand, bitwise_rhs, "");
4166 const llvm_ty = try o.lowerType(ty, .as_value);
4167 return fg.wip.cast(.bitcast, result, llvm_ty, "");
40504168 },
40514169 .add, .sub, .div, .mul => try o.builder.strtabStringFmt("__{s}{s}f3", .{
4052 @tagName(op), compilerRtFloatAbbrev(float_bits),
4170 @tagName(op), compilerRtFloatAbbrev(target, float_bits),
40534171 }),
40544172 .ceil,
40554173 .cos,
40564174 .exp,
40574175 .exp2,
4058 .fabs,
40594176 .floor,
40604177 .fma,
40614178 .fmax,
......@@ -4073,27 +4190,27 @@ fn buildFloatOp(
40734190 libcFloatPrefix(float_bits), @tagName(op), libcFloatSuffix(float_bits),
40744191 }),
40754192 };
4193 return fg.buildElementwiseCall(fn_name, .{
4194 .cc = target.cCallingConvention().?,
4195 .param_types = &@as([params_len]InternPool.Index, @splat(scalar_ty.toIntern())),
4196 .return_type = scalar_ty.toIntern(),
4197 }, &params, if (ty.isVector(zcu)) ty.vectorLen(zcu) else null);
4198}
40764199
4077 const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value);
4078 const libc_fn = try o.getLibcFunction(
4079 fn_name,
4080 @as([3]Builder.Type, @splat(scalar_llvm_ty))[0..params.len],
4081 scalar_llvm_ty,
4082 );
4083 if (ty.zigTypeTag(zcu) == .vector) {
4084 const result = try o.builder.poisonValue(llvm_ty);
4085 return self.buildElementwiseCall(libc_fn, &params, result, ty.vectorLen(zcu));
4086 }
4087
4088 return self.wip.call(
4089 fast.toCallKind(),
4090 .ccc,
4091 .none,
4092 libc_fn.typeOf(&o.builder),
4093 libc_fn.toValue(&o.builder),
4094 &params,
4095 "",
4096 );
4200/// Creates a floating point cast operation by lowering to the specified softfloat routine.
4201fn buildFloatCastCall(
4202 fg: *FuncGen,
4203 dest_ty: Type,
4204 fn_name: Builder.StrtabString,
4205 operand_ty: Type,
4206 operand: Builder.Value,
4207) Allocator.Error!Builder.Value {
4208 const zcu = fg.object.zcu;
4209 return fg.buildElementwiseCall(fn_name, .{
4210 .cc = zcu.getTarget().cCallingConvention().?,
4211 .param_types = &.{operand_ty.scalarType(zcu).toIntern()},
4212 .return_type = dest_ty.scalarType(zcu).toIntern(),
4213 }, &.{operand}, if (operand_ty.isVector(zcu)) operand_ty.vectorLen(zcu) else null);
40974214}
40984215
40994216fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
......@@ -4129,7 +4246,7 @@ fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Buil
41294246 const dest_ty = self.typeOfIndex(inst);
41304247 assert(isByRef(dest_ty, zcu)); // auto structs are by-ref
41314248
4132 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .by_value), "");
4249 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .as_value), "");
41334250
41344251 const result = try self.wip.bin(.shl, lhs, casted_rhs, "");
41354252 const reconstructed = try self.wip.bin(if (lhs_scalar_ty.isSignedInt(zcu))
......@@ -4196,7 +4313,7 @@ fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
41964313 }
41974314 const lhs_scalar_ty = lhs_ty.scalarType(zcu);
41984315
4199 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .by_value), "");
4316 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .as_value), "");
42004317 return self.wip.bin(if (lhs_scalar_ty.isSignedInt(zcu))
42014318 .@"shl nsw"
42024319 else
......@@ -4217,7 +4334,7 @@ fn airShl(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
42174334 // features which we do not use. Therefore this branch is currently impossible.
42184335 unreachable;
42194336 }
4220 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .by_value), "");
4337 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .as_value), "");
42214338 return self.wip.bin(.shl, lhs, casted_rhs, "");
42224339}
42234340
......@@ -4231,8 +4348,8 @@ fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
42314348
42324349 const lhs_ty = self.typeOf(bin_op.lhs);
42334350 const lhs_info = lhs_ty.intInfo(zcu);
4234 const llvm_lhs_ty = try o.lowerType(lhs_ty, .by_value);
4235 const llvm_lhs_scalar_ty = try o.lowerType(lhs_ty.scalarType(zcu), .by_value);
4351 const llvm_lhs_ty = try o.lowerType(lhs_ty, .as_value);
4352 const llvm_lhs_scalar_ty = try o.lowerType(lhs_ty.scalarType(zcu), .as_value);
42364353
42374354 const rhs_ty = self.typeOf(bin_op.rhs);
42384355 if (lhs_ty.isVector(zcu) and !rhs_ty.isVector(zcu)) {
......@@ -4242,8 +4359,8 @@ fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
42424359 }
42434360 const rhs_info = rhs_ty.intInfo(zcu);
42444361 assert(rhs_info.signedness == .unsigned);
4245 const llvm_rhs_ty = try o.lowerType(rhs_ty, .by_value);
4246 const llvm_rhs_scalar_ty = try o.lowerType(rhs_ty.scalarType(zcu), .by_value);
4362 const llvm_rhs_ty = try o.lowerType(rhs_ty, .as_value);
4363 const llvm_rhs_scalar_ty = try o.lowerType(rhs_ty.scalarType(zcu), .as_value);
42474364
42484365 const result = try self.wip.callIntrinsic(
42494366 .normal,
......@@ -4319,7 +4436,7 @@ fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) Allocator.Error!
43194436 }
43204437 const lhs_scalar_ty = lhs_ty.scalarType(zcu);
43214438
4322 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .by_value), "");
4439 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .as_value), "");
43234440 const is_signed_int = lhs_scalar_ty.isSignedInt(zcu);
43244441
43254442 return self.wip.bin(if (is_exact)
......@@ -4340,7 +4457,7 @@ fn airAbs(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
43404457 .normal,
43414458 .none,
43424459 .abs,
4343 &.{try o.lowerType(operand_ty, .by_value)},
4460 &.{try o.lowerType(operand_ty, .as_value)},
43444461 &.{ operand, .false },
43454462 "",
43464463 ),
......@@ -4354,7 +4471,7 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!
43544471 const zcu = o.zcu;
43554472 const ty_op = fg.air.instructions.items(.data)[@backingInt(inst)].ty_op;
43564473 const dest_ty = fg.typeOfIndex(inst);
4357 const dest_llvm_ty = try o.lowerType(dest_ty, .by_value);
4474 const dest_llvm_ty = try o.lowerType(dest_ty, .as_value);
43584475 const operand = try fg.resolveInst(ty_op.operand);
43594476 const operand_ty = fg.typeOf(ty_op.operand);
43604477 const operand_info = operand_ty.intInfo(zcu);
......@@ -4382,8 +4499,8 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!
43824499
43834500 if (!have_min_check and !have_max_check) break :bounds_check;
43844501
4385 const operand_llvm_ty = try o.lowerType(operand_ty, .by_value);
4386 const operand_scalar_llvm_ty = try o.lowerType(operand_scalar, .by_value);
4502 const operand_llvm_ty = try o.lowerType(operand_ty, .as_value);
4503 const operand_scalar_llvm_ty = try o.lowerType(operand_scalar, .as_value);
43874504
43884505 const is_vector = operand_ty.zigTypeTag(zcu) == .vector;
43894506 assert(is_vector == (dest_ty.zigTypeTag(zcu) == .vector));
......@@ -4461,7 +4578,7 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!
44614578fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
44624579 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
44634580 const operand = try self.resolveInst(ty_op.operand);
4464 const dest_llvm_ty = try self.object.lowerType(self.typeOfIndex(inst), .by_value);
4581 const dest_llvm_ty = try self.object.lowerType(self.typeOfIndex(inst), .as_value);
44654582 return self.wip.cast(.trunc, operand, dest_llvm_ty, "");
44664583}
44674584
......@@ -4471,32 +4588,20 @@ fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu
44714588 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
44724589 const operand = try self.resolveInst(ty_op.operand);
44734590 const operand_ty = self.typeOf(ty_op.operand);
4591 const operand_scalar_ty = operand_ty.scalarType(zcu);
44744592 const dest_ty = self.typeOfIndex(inst);
4593 const dest_scalar_ty = dest_ty.scalarType(zcu);
44754594 const target = zcu.getTarget();
44764595
4477 if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) {
4478 return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty, .by_value), "");
4479 } else {
4480 const operand_llvm_ty = try o.lowerType(operand_ty, .by_value);
4481 const dest_llvm_ty = try o.lowerType(dest_ty, .by_value);
4482
4483 const dest_bits = dest_ty.floatBits(target);
4484 const src_bits = operand_ty.floatBits(target);
4485 const fn_name = try o.builder.strtabStringFmt("__trunc{s}f{s}f2", .{
4486 compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits),
4487 });
4488
4489 const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty);
4490 return self.wip.call(
4491 .normal,
4492 .ccc,
4493 .none,
4494 libc_fn.typeOf(&o.builder),
4495 libc_fn.toValue(&o.builder),
4496 &.{operand},
4497 "",
4498 );
4499 }
4596 if (intrinsicsAllowed(.compiler_rt, dest_scalar_ty, target) and
4597 intrinsicsAllowed(.compiler_rt, operand_scalar_ty, target))
4598 return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty, .as_value), "");
4599 const dest_bits = dest_scalar_ty.floatBits(target);
4600 const src_bits = operand_scalar_ty.floatBits(target);
4601 const fn_name = try o.builder.strtabStringFmt("__trunc{s}f{s}f2", .{
4602 compilerRtFloatAbbrev(target, src_bits), compilerRtFloatAbbrev(target, dest_bits),
4603 });
4604 return self.buildFloatCastCall(dest_ty, fn_name, operand_ty, operand);
45004605}
45014606
45024607fn airFpext(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
......@@ -4505,38 +4610,20 @@ fn airFpext(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
45054610 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
45064611 const operand = try self.resolveInst(ty_op.operand);
45074612 const operand_ty = self.typeOf(ty_op.operand);
4613 const operand_scalar_ty = operand_ty.scalarType(zcu);
45084614 const dest_ty = self.typeOfIndex(inst);
4615 const dest_scalar_ty = dest_ty.scalarType(zcu);
45094616 const target = zcu.getTarget();
45104617
4511 if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) {
4512 return self.wip.cast(.fpext, operand, try o.lowerType(dest_ty, .by_value), "");
4513 } else {
4514 const operand_llvm_ty = try o.lowerType(operand_ty, .by_value);
4515 const dest_llvm_ty = try o.lowerType(dest_ty, .by_value);
4516
4517 const dest_bits = dest_ty.scalarType(zcu).floatBits(target);
4518 const src_bits = operand_ty.scalarType(zcu).floatBits(target);
4519 const fn_name = try o.builder.strtabStringFmt("__extend{s}f{s}f2", .{
4520 compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits),
4521 });
4522
4523 const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty);
4524 if (dest_ty.isVector(zcu)) return self.buildElementwiseCall(
4525 libc_fn,
4526 &.{operand},
4527 try o.builder.poisonValue(dest_llvm_ty),
4528 dest_ty.vectorLen(zcu),
4529 );
4530 return self.wip.call(
4531 .normal,
4532 .ccc,
4533 .none,
4534 libc_fn.typeOf(&o.builder),
4535 libc_fn.toValue(&o.builder),
4536 &.{operand},
4537 "",
4538 );
4539 }
4618 if (intrinsicsAllowed(.compiler_rt, dest_scalar_ty, target) and
4619 intrinsicsAllowed(.compiler_rt, operand_scalar_ty, target))
4620 return self.wip.cast(.fpext, operand, try o.lowerType(dest_ty, .as_value), "");
4621 const dest_bits = dest_scalar_ty.floatBits(target);
4622 const src_bits = operand_scalar_ty.floatBits(target);
4623 const fn_name = try o.builder.strtabStringFmt("__extend{s}f{s}f2", .{
4624 compilerRtFloatAbbrev(target, src_bits), compilerRtFloatAbbrev(target, dest_bits),
4625 });
4626 return self.buildFloatCastCall(dest_ty, fn_name, operand_ty, operand);
45404627}
45414628
45424629fn airBitCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Builder.Value {
......@@ -4558,28 +4645,161 @@ fn airBitCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!
45584645 // * bool/int/float <-> bool/int/float
45594646 // * `@Vector(n, A)` <-> `@Vector(n, B)`
45604647 //
4561 // All of these cases can be handled by LLVM's `bitcast` instruction.
4648 // Most of these cases can be handled by LLVM's `bitcast` instruction, except when
4649 // a non-native type like `f80` is used.
45624650
4563 assert(!isByRef(operand_ty, zcu));
4564 assert(!isByRef(dest_ty, zcu));
4651 if (isByRef(operand_ty, zcu)) {
4652 const operand_scalar_ty = operand_ty.scalarType(zcu);
4653 const target = zcu.getTarget();
4654 const bits = operand_scalar_ty.floatBits(target);
4655 const dest_scalar_ty = dest_ty.scalarType(zcu);
4656 if (isByRef(dest_ty, zcu)) {
4657 assert(dest_scalar_ty.floatBits(target) == bits);
4658 return operand;
4659 }
4660 assert(dest_scalar_ty.intInfo(zcu).bits == bits);
45654661
4566 const llvm_dest_ty = try o.lowerType(dest_ty, .by_value);
4567 const result = try fg.wip.cast(.bitcast, operand, llvm_dest_ty, "");
4568 if (safety and dest_ty.zigTypeTag(zcu) == .@"enum" and !dest_ty.isNonexhaustiveEnum(zcu)) {
4569 const llvm_fn = try o.getIsNamedEnumValueFunction(dest_ty);
4570 const is_valid_enum_val = try fg.wip.call(
4571 .normal,
4572 .fastcc,
4573 .none,
4574 llvm_fn.typeOf(&o.builder),
4575 llvm_fn.toValue(&o.builder),
4576 &.{result},
4577 "",
4578 );
4579 const fail_block = try fg.wip.block(1, "ValidEnumFail");
4580 const ok_block = try fg.wip.block(1, "ValidEnumOk");
4581 _ = try fg.wip.brCond(is_valid_enum_val, ok_block, fail_block, .none);
4582 fg.wip.cursor = .{ .block = fail_block };
4662 const len = if (operand_ty.toIntern() != operand_scalar_ty.toIntern())
4663 operand_ty.vectorLen(zcu)
4664 else
4665 null;
4666 const operand_scalar_size = operand_scalar_ty.abiSize(zcu);
4667 var result = if (len) |_|
4668 try o.builder.poisonValue(try o.lowerType(dest_ty, .as_value))
4669 else
4670 undefined;
4671 for (0..len orelse 1) |index| {
4672 const result_elem = result_elem: switch (bits) {
4673 else => unreachable,
4674 80 => {
4675 const f80_layout = o.softF80Layout(.{}) catch unreachable;
4676 const mantissa = try fg.load(
4677 try fg.ptraddConst(operand, operand_scalar_size * index + f80_layout.mantissa_offset),
4678 f80_layout.alignment.offset(f80_layout.mantissa_offset),
4679 .u64,
4680 .normal,
4681 );
4682 const exponent = try fg.load(
4683 try fg.ptraddConst(operand, operand_scalar_size * index + f80_layout.exponent_offset),
4684 f80_layout.alignment.offset(f80_layout.exponent_offset),
4685 .u16,
4686 .normal,
4687 );
4688 const casted_mantissa = try fg.wip.cast(.zext, mantissa, .i80, "bitCast.casted_mantissa");
4689 const casted_exponent = try fg.wip.cast(.zext, exponent, .i80, "bitCast.casted_exponent");
4690 const shifted_exponent = try fg.wip.bin(.@"shl nuw", casted_exponent, try o.builder.intValue(.i80, 64), "bitCast.shifted_exponent");
4691 break :result_elem try fg.wip.bin(.@"or", casted_mantissa, shifted_exponent, "bitCast.result_elem");
4692 },
4693 128 => {
4694 const f128_layout = o.softF128Layout(.{}) catch unreachable;
4695 const lo = try fg.load(
4696 try fg.ptraddConst(operand, operand_scalar_size * index + f128_layout.lo_offset),
4697 f128_layout.alignment.offset(f128_layout.lo_offset),
4698 .u64,
4699 .normal,
4700 );
4701 const hi = try fg.load(
4702 try fg.ptraddConst(operand, operand_scalar_size * index + f128_layout.hi_offset),
4703 f128_layout.alignment.offset(f128_layout.hi_offset),
4704 .u64,
4705 .normal,
4706 );
4707 const casted_lo = try fg.wip.cast(.zext, lo, .i128, "bitCast.casted_lo");
4708 const casted_hi = try fg.wip.cast(.zext, hi, .i128, "bitCast.casted_hi");
4709 const shifted_hi = try fg.wip.bin(.@"shl nuw", casted_hi, try o.builder.intValue(.i128, 64), "bitCast.shifted_hi");
4710 break :result_elem try fg.wip.bin(.@"or", casted_lo, shifted_hi, "bitCast.result_elem");
4711 },
4712 };
4713 result = if (len) |_|
4714 try fg.wip.insertElement(result, result_elem, try o.builder.intValue(.i32, index), "elementwise.result")
4715 else
4716 result_elem;
4717 }
4718 return result;
4719 }
4720
4721 if (isByRef(dest_ty, zcu)) {
4722 const dest_scalar_ty = dest_ty.scalarType(zcu);
4723 const bits = dest_scalar_ty.floatBits(zcu.getTarget());
4724 assert(dest_scalar_ty.isRuntimeFloat());
4725 const operand_scalar_ty = operand_ty.scalarType(zcu);
4726 assert(operand_scalar_ty.intInfo(zcu).bits == bits);
4727
4728 const len = if (operand_ty.toIntern() != operand_scalar_ty.toIntern())
4729 operand_ty.vectorLen(zcu)
4730 else
4731 null;
4732 const operand_scalar_size = operand_scalar_ty.abiSize(zcu);
4733 const result_ptr = try fg.buildZigAlloca(dest_ty, .none);
4734 for (0..len orelse 1) |index| {
4735 const operand_elem = if (len) |_|
4736 try fg.wip.extractElement(operand, try o.builder.intValue(.i32, index), "elementwise.operand_elem")
4737 else
4738 operand;
4739 switch (bits) {
4740 else => unreachable,
4741 80 => {
4742 const f80_layout = o.softF80Layout(.{}) catch unreachable;
4743 const mantissa = try fg.wip.cast(.trunc, operand_elem, .i64, "bitCast.mantissa");
4744 const shifted_exponent = try fg.wip.bin(.lshr, operand_elem, try o.builder.intValue(.i80, 64), "bitCast.shifted_exponent");
4745 const exponent = try fg.wip.cast(.@"trunc nuw", shifted_exponent, .i16, "bitCast.exponent");
4746 try fg.store(
4747 try fg.ptraddConst(result_ptr, operand_scalar_size * index + f80_layout.mantissa_offset),
4748 f80_layout.alignment.offset(f80_layout.mantissa_offset),
4749 mantissa,
4750 .u64,
4751 .normal,
4752 );
4753 try fg.store(
4754 try fg.ptraddConst(result_ptr, operand_scalar_size * index + f80_layout.exponent_offset),
4755 f80_layout.alignment.offset(f80_layout.exponent_offset),
4756 exponent,
4757 .u16,
4758 .normal,
4759 );
4760 },
4761 128 => {
4762 const f128_layout = o.softF128Layout(.{}) catch unreachable;
4763 const lo = try fg.wip.cast(.trunc, operand_elem, .i64, "bitCast.lo");
4764 const shifted_hi = try fg.wip.bin(.lshr, operand_elem, try o.builder.intValue(.i128, 64), "bitCast.shifted_hi");
4765 const hi = try fg.wip.cast(.@"trunc nuw", shifted_hi, .i64, "bitCast.hi");
4766 try fg.store(
4767 try fg.ptraddConst(result_ptr, operand_scalar_size * index + f128_layout.lo_offset),
4768 f128_layout.alignment.offset(f128_layout.lo_offset),
4769 lo,
4770 .u64,
4771 .normal,
4772 );
4773 try fg.store(
4774 try fg.ptraddConst(result_ptr, operand_scalar_size * index + f128_layout.hi_offset),
4775 f128_layout.alignment.offset(f128_layout.hi_offset),
4776 hi,
4777 .u64,
4778 .normal,
4779 );
4780 },
4781 }
4782 }
4783 return result_ptr;
4784 }
4785
4786 const llvm_dest_ty = try o.lowerType(dest_ty, .as_value);
4787 const result = try fg.wip.cast(.bitcast, operand, llvm_dest_ty, "");
4788 if (safety and dest_ty.zigTypeTag(zcu) == .@"enum" and !dest_ty.isNonexhaustiveEnum(zcu)) {
4789 const llvm_fn = try o.getIsNamedEnumValueFunction(dest_ty);
4790 const is_valid_enum_val = try fg.wip.call(
4791 .normal,
4792 .fastcc,
4793 .none,
4794 llvm_fn.typeOf(&o.builder),
4795 llvm_fn.toValue(&o.builder),
4796 &.{result},
4797 "",
4798 );
4799 const fail_block = try fg.wip.block(1, "ValidEnumFail");
4800 const ok_block = try fg.wip.block(1, "ValidEnumOk");
4801 _ = try fg.wip.brCond(is_valid_enum_val, ok_block, fail_block, .none);
4802 fg.wip.cursor = .{ .block = fail_block };
45834803 try fg.buildSimplePanic(.invalid_enum_value);
45844804 fg.wip.cursor = .{ .block = ok_block };
45854805 }
......@@ -4606,7 +4826,7 @@ fn airPtrFromInt(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
46064826 assert(dest_ty.scalarType(zcu).isPtrAtRuntime(zcu));
46074827
46084828 const operand = try fg.resolveInst(ty_op.operand);
4609 const llvm_dest_ty = try o.lowerType(dest_ty, .by_value);
4829 const llvm_dest_ty = try o.lowerType(dest_ty, .as_value);
46104830 return fg.wip.cast(.inttoptr, operand, llvm_dest_ty, "");
46114831}
46124832
......@@ -4620,7 +4840,7 @@ fn airIntFromPtr(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
46204840 assert(dest_ty.scalarType(zcu).toIntern() == .usize_type);
46214841
46224842 const operand = try fg.resolveInst(ty_op.operand);
4623 const llvm_dest_ty = try o.lowerType(dest_ty, .by_value);
4843 const llvm_dest_ty = try o.lowerType(dest_ty, .as_value);
46244844 return fg.wip.cast(.ptrtoint, operand, llvm_dest_ty, "");
46254845}
46264846
......@@ -4689,7 +4909,7 @@ fn airArg(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
46894909 },
46904910 "",
46914911 );
4692 } else if (mod.optimize_mode == .Debug) {
4912 } else if (mod.optimize_mode == .debug) {
46934913 const alloca = try self.buildZigAlloca(inst_ty, .none);
46944914 try self.store(alloca, .none, arg_val, inst_ty, .normal);
46954915 _ = try self.wip.callIntrinsic(
......@@ -4730,7 +4950,7 @@ fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
47304950 const ptr_align = ptr_ty.ptrAlignment(zcu);
47314951 const elem_ty = ptr_ty.childType(zcu);
47324952 if (!elem_ty.hasRuntimeBits(zcu)) {
4733 return (try o.lowerPtrToVoid(ptr_align, ptr_ty.ptrAddressSpace(zcu))).toValue();
4953 return (try o.lowerPtrToVoid(ptr_align.toLlvm(), ptr_ty.ptrAddressSpace(zcu))).toValue();
47344954 }
47354955 return self.buildZigAlloca(elem_ty, ptr_align);
47364956}
......@@ -4743,7 +4963,7 @@ fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
47434963 const ptr_align = ptr_ty.ptrAlignment(zcu);
47444964 const elem_ty = ptr_ty.childType(zcu);
47454965 if (!elem_ty.hasRuntimeBits(zcu)) {
4746 return (try o.lowerPtrToVoid(ptr_align, ptr_ty.ptrAddressSpace(zcu))).toValue();
4966 return (try o.lowerPtrToVoid(ptr_align.toLlvm(), ptr_ty.ptrAddressSpace(zcu))).toValue();
47474967 }
47484968 return self.buildZigAlloca(elem_ty, ptr_align);
47494969}
......@@ -4754,10 +4974,7 @@ fn buildZigAlloca(fg: *FuncGen, ty: Type, @"align": InternPool.Alignment) Alloca
47544974 .none => ty.abiAlignment(o.zcu),
47554975 else => |a| a,
47564976 };
4757 return fg.buildAlloca(
4758 try o.lowerType(ty, .in_memory),
4759 resolved_align.toLlvm(),
4760 );
4977 return fg.buildAlloca(try o.lowerType(ty, .in_memory), resolved_align.toLlvm());
47614978}
47624979
47634980/// Unlike `WipFunction.alloca`, this puts the alloca instruction at the top of the function.
......@@ -4820,7 +5037,7 @@ fn airStore(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Bu
48205037 // unexpected call in the user's code. This is problematic if the code in question is
48215038 // not ready to correctly make calls yet, such as in our early PIE startup code, or in
48225039 // the early stages of a dynamic linker, etc.
4823 if (!safety and owner_mod.optimize_mode == .Debug) {
5040 if (!safety and owner_mod.optimize_mode == .debug) {
48245041 return .none;
48255042 }
48265043
......@@ -4832,7 +5049,7 @@ fn airStore(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Bu
48325049 return .none;
48335050 }
48345051
4835 const len = try o.builder.intValue(try o.lowerType(.usize, .by_value), elem_ty.abiSize(zcu));
5052 const len = try o.builder.intValue(try o.lowerType(.usize, .as_value), elem_ty.abiSize(zcu));
48365053 _ = try fg.wip.callMemSet(
48375054 ptr,
48385055 ptr_alignment.toLlvm(),
......@@ -4850,24 +5067,31 @@ fn airStore(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Bu
48505067 const elem = try fg.resolveInst(bin_op.rhs);
48515068
48525069 if (ptr_info.flags.vector_index != .none) {
4853 // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.
4854 const vec_ty = try fg.pt.vectorType(.{
4855 .len = ptr_info.packed_offset.host_size,
4856 .child = elem_ty.toIntern(),
4857 });
5070 if (isByRef(elem_ty, zcu)) {
5071 const offset = @backingInt(ptr_info.flags.vector_index) * elem_ty.abiSize(zcu);
5072 const elem_ptr = try fg.ptraddConst(ptr, offset);
5073 try fg.store(elem_ptr, ptr_alignment.offset(offset), elem, elem_ty, access_kind);
5074 } else {
5075 // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.
5076 const vec_ty = try fg.pt.vectorType(.{
5077 .len = ptr_info.packed_offset.host_size,
5078 .child = elem_ty.toIntern(),
5079 });
5080
5081 const loaded_vector = try fg.load(ptr, ptr_alignment, vec_ty, access_kind);
5082 const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index);
5083 const modified_vector = try fg.wip.insertElement(loaded_vector, elem, index_val, "");
48585084
4859 const loaded_vector = try fg.load(ptr, ptr_alignment, vec_ty, access_kind);
4860 const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index);
4861 const modified_vector = try fg.wip.insertElement(loaded_vector, elem, index_val, "");
5085 try fg.store(ptr, ptr_alignment, modified_vector, vec_ty, access_kind);
5086 }
48625087
4863 try fg.store(ptr, ptr_alignment, modified_vector, vec_ty, access_kind);
48645088 return .none;
48655089 }
48665090
48675091 if (ptr_info.packed_offset.host_size != 0) {
48685092 // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.
48695093 const backing_int_ty = try fg.pt.intType(.unsigned, @intCast(ptr_info.packed_offset.host_size * 8));
4870 const llvm_backing_int_ty = try o.lowerType(backing_int_ty, .by_value);
5094 const llvm_backing_int_ty = try o.lowerType(backing_int_ty, .as_value);
48715095
48725096 const backing_int_val = try fg.load(ptr, ptr_alignment, backing_int_ty, access_kind);
48735097
......@@ -4927,32 +5151,98 @@ fn airLoad(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
49275151 if (ptr_info.flags.is_volatile) .@"volatile" else .normal;
49285152
49295153 if (ptr_info.flags.vector_index != .none) {
4930 // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.
4931 const vec_ty = try fg.pt.vectorType(.{
4932 .len = ptr_info.packed_offset.host_size,
4933 .child = elem_ty.toIntern(),
4934 });
4935 const vector_val = try fg.load(ptr, ptr_align, vec_ty, access_kind);
4936 const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index);
4937 return fg.wip.extractElement(vector_val, index_val, "");
5154 if (isByRef(elem_ty, zcu)) {
5155 const elem_size = elem_ty.abiSize(zcu);
5156 const offset = @backingInt(ptr_info.flags.vector_index) * elem_size;
5157 const elem_ptr = try fg.ptraddConst(ptr, offset);
5158 return fg.load(elem_ptr, ptr_align.offset(offset), elem_ty, access_kind);
5159 } else {
5160 // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.
5161 const vec_ty = try fg.pt.vectorType(.{
5162 .len = ptr_info.packed_offset.host_size,
5163 .child = elem_ty.toIntern(),
5164 });
5165 const vector_val = try fg.load(ptr, ptr_align, vec_ty, access_kind);
5166 const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index);
5167 return fg.wip.extractElement(vector_val, index_val, "");
5168 }
49385169 }
49395170
49405171 if (ptr_info.packed_offset.host_size == 0) {
49415172 return fg.load(ptr, ptr_align, elem_ty, access_kind);
49425173 }
49435174
4944 assert(!isByRef(elem_ty, zcu)); // all packable types are by-val
4945
49465175 // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.
49475176 const backing_int_ty = try fg.pt.intType(.unsigned, @intCast(ptr_info.packed_offset.host_size * 8));
4948 const llvm_backing_int_ty = try o.lowerType(backing_int_ty, .by_value);
5177 const llvm_backing_int_ty = try o.lowerType(backing_int_ty, .as_value);
49495178
49505179 const backing_int_val = try fg.load(ptr, ptr_align, backing_int_ty, .normal);
49515180
49525181 const elem_bits = ptr_ty.childType(zcu).bitSize(zcu);
49535182 const shift_amt = try o.builder.intValue(llvm_backing_int_ty, ptr_info.packed_offset.bit_offset);
49545183 const shifted_value = try fg.wip.bin(.lshr, backing_int_val, shift_amt, "");
4955 const elem_llvm_ty = try o.lowerType(elem_ty, .by_value);
5184
5185 if (isByRef(elem_ty, zcu)) {
5186 const result_ptr = try fg.buildZigAlloca(elem_ty, .none);
5187 switch (elem_ty.floatBits(zcu.getTarget())) {
5188 else => unreachable,
5189 80 => {
5190 const f80_layout = o.softF80Layout(.{}) catch unreachable;
5191 const mantissa = try fg.wip.cast(.trunc, shifted_value, .i64, "load.mantissa");
5192 const shifted_exponent = try fg.wip.bin(
5193 .lshr,
5194 backing_int_val,
5195 try o.builder.intValue(llvm_backing_int_ty, ptr_info.packed_offset.bit_offset + 64),
5196 "load.shifted_exponent",
5197 );
5198 const exponent = try fg.wip.cast(.trunc, shifted_exponent, .i16, "load.exponent");
5199
5200 try fg.store(
5201 try fg.ptraddConst(result_ptr, f80_layout.mantissa_offset),
5202 f80_layout.alignment.offset(f80_layout.mantissa_offset),
5203 mantissa,
5204 .u64,
5205 .normal,
5206 );
5207 try fg.store(
5208 try fg.ptraddConst(result_ptr, f80_layout.exponent_offset),
5209 f80_layout.alignment.offset(f80_layout.exponent_offset),
5210 exponent,
5211 .u16,
5212 .normal,
5213 );
5214 },
5215 128 => {
5216 const f128_layout = o.softF128Layout(.{}) catch unreachable;
5217 const lo = try fg.wip.cast(.trunc, shifted_value, .i64, "load.lo");
5218 const shifted_hi = try fg.wip.bin(
5219 .lshr,
5220 backing_int_val,
5221 try o.builder.intValue(llvm_backing_int_ty, ptr_info.packed_offset.bit_offset + 64),
5222 "load.shifted_hi",
5223 );
5224 const hi = try fg.wip.cast(.trunc, shifted_hi, .i64, "load.hi");
5225
5226 try fg.store(
5227 try fg.ptraddConst(result_ptr, f128_layout.lo_offset),
5228 f128_layout.alignment.offset(f128_layout.lo_offset),
5229 lo,
5230 .u64,
5231 .normal,
5232 );
5233 try fg.store(
5234 try fg.ptraddConst(result_ptr, f128_layout.hi_offset),
5235 f128_layout.alignment.offset(f128_layout.hi_offset),
5236 hi,
5237 .u64,
5238 .normal,
5239 );
5240 },
5241 }
5242 return result_ptr;
5243 }
5244
5245 const elem_llvm_ty = try o.lowerType(elem_ty, .as_value);
49565246
49575247 if (elem_ty.zigTypeTag(zcu) == .float or elem_ty.zigTypeTag(zcu) == .vector) {
49585248 const same_size_int = try o.builder.intType(@intCast(elem_bits));
......@@ -5002,7 +5292,7 @@ fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.V
50025292fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
50035293 _ = inst;
50045294 const o = self.object;
5005 const llvm_usize = try o.lowerType(.usize, .by_value);
5295 const llvm_usize = try o.lowerType(.usize, .as_value);
50065296 if (!target_util.supportsReturnAddress(self.object.zcu.getTarget(), self.ownerModule().optimize_mode)) {
50075297 // https://github.com/ziglang/zig/issues/11946
50085298 return o.builder.intValue(llvm_usize, 0);
......@@ -5014,7 +5304,7 @@ fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu
50145304fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
50155305 _ = inst;
50165306 const result = try self.wip.callIntrinsic(.normal, .none, .frameaddress, &.{.ptr}, &.{.@"0"}, "");
5017 return self.wip.cast(.ptrtoint, result, try self.object.lowerType(.usize, .by_value), "");
5307 return self.wip.cast(.ptrtoint, result, try self.object.lowerType(.usize, .as_value), "");
50185308}
50195309
50205310fn airCmpxchg(
......@@ -5031,7 +5321,7 @@ fn airCmpxchg(
50315321 var expected_value = try self.resolveInst(extra.expected_value);
50325322 var new_value = try self.resolveInst(extra.new_value);
50335323 const operand_ty = ptr_ty.childType(zcu);
5034 const llvm_operand_ty = try o.lowerType(operand_ty, .by_value);
5324 const llvm_operand_ty = try o.lowerType(operand_ty, .as_value);
50355325 const llvm_abi_ty = try self.getAtomicAbiType(operand_ty, false);
50365326 if (llvm_abi_ty != .none) {
50375327 // operand needs widening and truncating
......@@ -5101,7 +5391,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va
51015391 const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float);
51025392 const ordering = toLlvmAtomicOrdering(extra.ordering());
51035393 const llvm_abi_ty = try self.getAtomicAbiType(operand_ty, op == .xchg);
5104 const llvm_operand_ty = try o.lowerType(operand_ty, .by_value);
5394 const llvm_operand_ty = try o.lowerType(operand_ty, .as_value);
51055395
51065396 const access_kind: Builder.MemoryAccessKind =
51075397 if (ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
......@@ -5130,7 +5420,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va
51305420
51315421 // If we are storing a pointer we need to convert to and from a plain old integer.
51325422 const non_ptr_operand = switch (operand_ty.zigTypeTag(zcu)) {
5133 .pointer => try self.wip.cast(.ptrtoint, operand, try o.lowerType(.usize, .by_value), ""),
5423 .pointer => try self.wip.cast(.ptrtoint, operand, try o.lowerType(.usize, .as_value), ""),
51345424 else => operand,
51355425 };
51365426
......@@ -5169,7 +5459,7 @@ fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.V
51695459 Type.fromInterned(info.child).abiAlignment(zcu)).toLlvm();
51705460 const access_kind: Builder.MemoryAccessKind =
51715461 if (info.flags.is_volatile) .@"volatile" else .normal;
5172 const elem_llvm_ty = try o.lowerType(elem_ty, .by_value);
5462 const elem_llvm_ty = try o.lowerType(elem_ty, .as_value);
51735463
51745464 self.maybeMarkAllowZeroAccess(info);
51755465
......@@ -5503,11 +5793,11 @@ fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic)
55035793 .normal,
55045794 .none,
55055795 intrinsic,
5506 &.{try o.lowerType(operand_ty, .by_value)},
5796 &.{try o.lowerType(operand_ty, .as_value)},
55075797 &.{ operand, .false },
55085798 "",
55095799 );
5510 return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .by_value), "");
5800 return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .as_value), "");
55115801}
55125802
55135803fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) Allocator.Error!Builder.Value {
......@@ -5521,11 +5811,11 @@ fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic)
55215811 .normal,
55225812 .none,
55235813 intrinsic,
5524 &.{try o.lowerType(operand_ty, .by_value)},
5814 &.{try o.lowerType(operand_ty, .as_value)},
55255815 &.{operand},
55265816 "",
55275817 );
5528 return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .by_value), "");
5818 return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .as_value), "");
55295819}
55305820
55315821fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
......@@ -5538,7 +5828,7 @@ fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
55385828
55395829 const inst_ty = self.typeOfIndex(inst);
55405830 var operand = try self.resolveInst(ty_op.operand);
5541 var llvm_operand_ty = try o.lowerType(operand_ty, .by_value);
5831 var llvm_operand_ty = try o.lowerType(operand_ty, .as_value);
55425832
55435833 if (bits % 16 == 8) {
55445834 // If not an even byte-multiple, we need zero-extend + shift-left 1 byte
......@@ -5559,7 +5849,7 @@ fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
55595849
55605850 const result =
55615851 try self.wip.callIntrinsic(.normal, .none, .bswap, &.{llvm_operand_ty}, &.{operand}, "");
5562 return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .by_value), "");
5852 return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .as_value), "");
55635853}
55645854
55655855fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
......@@ -5579,7 +5869,7 @@ fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Bui
55795869
55805870 for (0..names.len) |name_index| {
55815871 const err_int = ip.getErrorValueIfExists(names.get(ip)[name_index]).?;
5582 const this_tag_int_value = try o.builder.intConst(try o.errorIntType(.by_value), err_int);
5872 const this_tag_int_value = try o.builder.intConst(try o.errorIntType(.as_value), err_int);
55835873 try wip_switch.addCase(this_tag_int_value, valid_block, &self.wip);
55845874 }
55855875 self.wip.cursor = .{ .block = valid_block };
......@@ -5638,7 +5928,7 @@ fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va
56385928 const slice_ty = self.typeOfIndex(inst);
56395929
56405930 // If operand is small (e.g. `u8`), then signedness becomes a problem -- GEP always treats the index as signed.
5641 const operand_usize = try self.wip.conv(.unsigned, operand, try o.lowerType(.usize, .by_value), "");
5931 const operand_usize = try self.wip.conv(.unsigned, operand, try o.lowerType(.usize, .as_value), "");
56425932
56435933 const error_name_table_ptr = try o.getErrorNameTable();
56445934 const error_name_ptr = try self.ptraddScaled(error_name_table_ptr.toValue(&o.builder), operand_usize, slice_ty.abiSize(zcu));
......@@ -5649,7 +5939,7 @@ fn airSplat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
56495939 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
56505940 const scalar = try self.resolveInst(ty_op.operand);
56515941 const vector_ty = self.typeOfIndex(inst);
5652 return self.wip.splatVector(try self.object.lowerType(vector_ty, .by_value), scalar, "");
5942 return self.wip.splatVector(try self.object.lowerType(vector_ty, .as_value), scalar, "");
56535943}
56545944
56555945fn airSelect(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
......@@ -5672,9 +5962,9 @@ fn airShuffleOne(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
56725962 const operand = try fg.resolveInst(unwrapped.operand);
56735963 const mask = unwrapped.mask;
56745964 const operand_ty = fg.typeOf(unwrapped.operand);
5675 const llvm_operand_ty = try o.lowerType(operand_ty, .by_value);
5676 const llvm_result_ty = try o.lowerType(unwrapped.result_ty, .by_value);
5677 const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .by_value);
5965 const llvm_operand_ty = try o.lowerType(operand_ty, .as_value);
5966 const llvm_result_ty = try o.lowerType(unwrapped.result_ty, .as_value);
5967 const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .as_value);
56785968 const llvm_poison_elem = try o.builder.poisonConst(llvm_elem_ty);
56795969 const llvm_poison_mask_elem = try o.builder.poisonConst(.i32);
56805970 const llvm_mask_ty = try o.builder.vectorType(.normal, @intCast(mask.len), .i32);
......@@ -5704,7 +5994,7 @@ fn airShuffleOne(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
57045994 .elem => llvm_poison_elem,
57055995 .value => |val| if (!Value.fromInterned(val).isUndef(zcu)) elem: {
57065996 any_defined_comptime_value = true;
5707 break :elem try o.lowerValue(val, .by_value);
5997 break :elem try o.lowerValue(val, .as_value);
57085998 } else llvm_poison_elem,
57095999 };
57106000 }
......@@ -5776,7 +6066,7 @@ fn airShuffleTwo(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
57766066 const unwrapped = fg.air.unwrapShuffleTwo(zcu, inst);
57776067
57786068 const mask = unwrapped.mask;
5779 const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .by_value);
6069 const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .as_value);
57806070 const llvm_mask_ty = try o.builder.vectorType(.normal, @intCast(mask.len), .i32);
57816071 const llvm_poison_mask_elem = try o.builder.poisonConst(.i32);
57826072
......@@ -5848,95 +6138,25 @@ fn airShuffleTwo(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
58486138 );
58496139}
58506140
5851/// Reduce a vector by repeatedly applying `llvm_fn` to produce an accumulated result.
5852///
5853/// Equivalent to:
5854/// ```
5855/// var accum: T = init;
5856/// for (0..i) |i| {
5857/// accum = llvm_fn(accum, vec[i]);
5858/// }
5859/// // result is 'accum'
5860/// ```
5861fn buildReducedCall(
5862 self: *FuncGen,
5863 llvm_fn: Builder.Function.Index,
5864 operand_vector: Builder.Value,
5865 vector_len: usize,
5866 accum_init: Builder.Value,
5867) Allocator.Error!Builder.Value {
5868 const o = self.object;
5869 const llvm_usize_ty = try o.lowerType(.usize, .by_value);
5870 const llvm_vector_len = try o.builder.intValue(llvm_usize_ty, vector_len);
5871 const llvm_result_ty = accum_init.typeOfWip(&self.wip);
5872
5873 const entry_block = self.wip.cursor.block;
5874
5875 const cond_block = try self.wip.block(2, "ReduceLoopCond");
5876 const body_block = try self.wip.block(1, "ReduceLoopBody");
5877 const exit_block = try self.wip.block(1, "ReduceLoopExit");
5878
5879 _ = try self.wip.br(cond_block);
5880
5881 // ReduceLoopCond:
5882 // %index = phi iN [0, %Entry], [%new_index, %ReduceLoopBody]
5883 // %accum = phi T [%accum_init, %Entry], [%new_accum, %ReduceLoopBody]
5884 // %cond = icmp ult iN %index, %vector_len
5885 // br i1 %cond, label %ReduceLoopBody, label %ReduceLoopExit
5886 self.wip.cursor = .{ .block = cond_block };
5887 const index = try self.wip.phi(llvm_usize_ty, "");
5888 const accum = try self.wip.phi(llvm_result_ty, "");
5889 const cond = try self.wip.icmp(.ult, index.toValue(), llvm_vector_len, "");
5890 _ = try self.wip.brCond(cond, body_block, exit_block, .none);
5891
5892 // ReduceLoopBody:
5893 // %elem = extractelement <n x T> %operand_vec, iN %index
5894 // %new_accum = call T @llvm_fn(T %accum, T %elem)
5895 // %new_index = add nuw iN %index, 1
5896 // br label %ReduceLoopCond
5897 self.wip.cursor = .{ .block = body_block };
5898 const elem = try self.wip.extractElement(operand_vector, index.toValue(), "");
5899 const new_accum = try self.wip.call(
5900 .normal,
5901 .ccc,
5902 .none,
5903 llvm_fn.typeOf(&o.builder),
5904 llvm_fn.toValue(&o.builder),
5905 &.{ accum.toValue(), elem },
5906 "",
5907 );
5908 const new_index = try self.wip.bin(.@"add nuw", index.toValue(), try o.builder.intValue(llvm_usize_ty, 1), "");
5909 _ = try self.wip.br(cond_block);
5910
5911 const index_init = try o.builder.intValue(llvm_usize_ty, 0);
5912 index.finish(&.{ index_init, new_index }, &.{ entry_block, body_block }, &self.wip);
5913 accum.finish(&.{ accum_init, new_accum }, &.{ entry_block, body_block }, &self.wip);
5914
5915 self.wip.cursor = .{ .block = exit_block };
5916 return accum.toValue();
5917}
5918
5919fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value {
5920 const o = self.object;
6141fn airReduce(fg: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value {
6142 const o = fg.object;
59216143 const zcu = o.zcu;
59226144 const target = zcu.getTarget();
59236145
5924 const reduce = self.air.instructions.items(.data)[@backingInt(inst)].reduce;
5925 const operand = try self.resolveInst(reduce.operand);
5926 const operand_ty = self.typeOf(reduce.operand);
5927 const llvm_operand_ty = try o.lowerType(operand_ty, .by_value);
5928 const scalar_ty = self.typeOfIndex(inst);
5929 const llvm_scalar_ty = try o.lowerType(scalar_ty, .by_value);
6146 const reduce = fg.air.instructions.items(.data)[@backingInt(inst)].reduce;
6147 const operand = try fg.resolveInst(reduce.operand);
6148 const operand_ty = fg.typeOf(reduce.operand);
6149 const scalar_ty = fg.typeOfIndex(inst);
59306150
59316151 switch (reduce.operation) {
5932 .And, .Or, .Xor => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
6152 .And, .Or, .Xor => return fg.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
59336153 .And => .@"vector.reduce.and",
59346154 .Or => .@"vector.reduce.or",
59356155 .Xor => .@"vector.reduce.xor",
59366156 else => unreachable,
5937 }, &.{llvm_operand_ty}, &.{operand}, ""),
6157 }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""),
59386158 .Min, .Max => switch (scalar_ty.zigTypeTag(zcu)) {
5939 .int => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
6159 .int => return fg.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
59406160 .Min => if (scalar_ty.isSignedInt(zcu))
59416161 .@"vector.reduce.smin"
59426162 else
......@@ -5946,29 +6166,29 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) A
59466166 else
59476167 .@"vector.reduce.umax",
59486168 else => unreachable,
5949 }, &.{llvm_operand_ty}, &.{operand}, ""),
5950 .float => if (intrinsicsAllowed(scalar_ty, target))
5951 return self.wip.callIntrinsic(fast, .none, switch (reduce.operation) {
6169 }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""),
6170 .float => if (intrinsicsAllowed(.libc, scalar_ty, target))
6171 return fg.wip.callIntrinsic(fast, .none, switch (reduce.operation) {
59526172 .Min => .@"vector.reduce.fmin",
59536173 .Max => .@"vector.reduce.fmax",
59546174 else => unreachable,
5955 }, &.{llvm_operand_ty}, &.{operand}, ""),
6175 }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""),
59566176 else => unreachable,
59576177 },
59586178 .Add, .Mul => switch (scalar_ty.zigTypeTag(zcu)) {
5959 .int => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
6179 .int => return fg.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
59606180 .Add => .@"vector.reduce.add",
59616181 .Mul => .@"vector.reduce.mul",
59626182 else => unreachable,
5963 }, &.{llvm_operand_ty}, &.{operand}, ""),
5964 .float => if (intrinsicsAllowed(scalar_ty, target))
5965 return self.wip.callIntrinsic(fast, .none, switch (reduce.operation) {
6183 }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""),
6184 .float => if (intrinsicsAllowed(.compiler_rt, scalar_ty, target))
6185 return fg.wip.callIntrinsic(fast, .none, switch (reduce.operation) {
59666186 .Add => .@"vector.reduce.fadd",
59676187 .Mul => .@"vector.reduce.fmul",
59686188 else => unreachable,
5969 }, &.{llvm_operand_ty}, &.{ switch (reduce.operation) {
5970 .Add => try o.builder.fpValue(llvm_scalar_ty, -0.0),
5971 .Mul => try o.builder.fpValue(llvm_scalar_ty, 1.0),
6189 }, &.{try o.lowerType(operand_ty, .as_value)}, &.{ switch (reduce.operation) {
6190 .Add => try o.builder.fpValue(try o.lowerType(scalar_ty, .as_value), -0.0),
6191 .Mul => try o.builder.fpValue(try o.lowerType(scalar_ty, .as_value), 1.0),
59726192 else => unreachable,
59736193 }, operand }, ""),
59746194 else => unreachable,
......@@ -5986,62 +6206,119 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) A
59866206 libcFloatPrefix(float_bits), libcFloatSuffix(float_bits),
59876207 }),
59886208 .Add => try o.builder.strtabStringFmt("__add{s}f3", .{
5989 compilerRtFloatAbbrev(float_bits),
6209 compilerRtFloatAbbrev(target, float_bits),
59906210 }),
59916211 .Mul => try o.builder.strtabStringFmt("__mul{s}f3", .{
5992 compilerRtFloatAbbrev(float_bits),
6212 compilerRtFloatAbbrev(target, float_bits),
59936213 }),
59946214 else => unreachable,
59956215 };
5996
5997 const libc_fn = try o.getLibcFunction(fn_name, &.{ llvm_scalar_ty, llvm_scalar_ty }, llvm_scalar_ty);
5998 const init_val = switch (llvm_scalar_ty) {
5999 .i16 => try o.builder.intValue(.i16, @as(i16, @bitCast(
6000 @as(f16, switch (reduce.operation) {
6001 .Min, .Max => std.math.nan(f16),
6002 .Add => -0.0,
6003 .Mul => 1.0,
6004 else => unreachable,
6005 }),
6006 ))),
6007 .i80 => try o.builder.intValue(.i80, @as(i80, @bitCast(
6008 @as(f80, switch (reduce.operation) {
6009 .Min, .Max => std.math.nan(f80),
6010 .Add => -0.0,
6011 .Mul => 1.0,
6012 else => unreachable,
6013 }),
6014 ))),
6015 .i128 => try o.builder.intValue(.i128, @as(i128, @bitCast(
6016 @as(f128, switch (reduce.operation) {
6017 .Min, .Max => std.math.nan(f128),
6018 .Add => -0.0,
6019 .Mul => 1.0,
6020 else => unreachable,
6021 }),
6022 ))),
6216 const fn_info: Object.FuncInfo = .{
6217 .cc = target.cCallingConvention().?,
6218 .param_types = &.{ scalar_ty.toIntern(), scalar_ty.toIntern() },
6219 .return_type = scalar_ty.toIntern(),
6220 };
6221 const llvm_fn = try fg.object.getLibcFunction(fg.pt, fn_name, fn_info);
6222 const init = switch (float_bits) {
60236223 else => unreachable,
6224 16 => try o.f16Const(switch (reduce.operation) {
6225 else => unreachable,
6226 .Min, .Max => std.math.nan(f16),
6227 .Add => -0.0,
6228 .Mul => 1.0,
6229 }),
6230 32 => try o.f32Const(switch (reduce.operation) {
6231 else => unreachable,
6232 .Min, .Max => std.math.nan(f32),
6233 .Add => -0.0,
6234 .Mul => 1.0,
6235 }),
6236 64 => try o.f64Const(switch (reduce.operation) {
6237 else => unreachable,
6238 .Min, .Max => std.math.nan(f64),
6239 .Add => -0.0,
6240 .Mul => 1.0,
6241 }),
6242 80 => try o.f80Const(switch (reduce.operation) {
6243 else => unreachable,
6244 .Min, .Max => std.math.nan(f80),
6245 .Add => -0.0,
6246 .Mul => 1.0,
6247 }),
6248 128 => try o.f128Const(switch (reduce.operation) {
6249 else => unreachable,
6250 .Min, .Max => std.math.nan(f128),
6251 .Add => -0.0,
6252 .Mul => 1.0,
6253 }),
60246254 };
6025 return self.buildReducedCall(libc_fn, operand, operand_ty.vectorLen(zcu), init_val);
6255 const iterations = operand_ty.vectorLen(zcu);
6256 const is_by_ref = isByRef(operand_ty, zcu);
6257 if (iterations > 1 and is_by_ref) {
6258 const init_ref = try o.lowerConstRef(init, scalar_ty.abiAlignment(zcu).toLlvm());
6259
6260 const entry_block = fg.wip.cursor.block;
6261 const loop_block = try fg.wip.block(2, "reduce.loop");
6262 const done_block = try fg.wip.block(1, "reduce.loop");
6263
6264 _ = try fg.wip.br(loop_block);
6265
6266 fg.wip.cursor = .{ .block = loop_block };
6267 const index = try fg.wip.phi(.i32, "reduce.index");
6268 const result = try fg.wip.phi(.ptr, "reduce.result");
6269
6270 const rhs_elem_ptr = try fg.ptraddScaled(operand, index.toValue(), scalar_ty.abiSize(zcu));
6271 const rhs_elem = try fg.load(rhs_elem_ptr, .none, scalar_ty, .normal);
6272 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 });
6273
6274 const next_index = try fg.wip.bin(.@"add nuw", index.toValue(), try o.builder.intValue(.i32, 1), "reduce.next_index");
6275 index.finish(&.{ try o.builder.intValue(.i32, 0), next_index }, &.{ entry_block, loop_block }, &fg.wip);
6276 result.finish(&.{ init_ref.toValue(), next_result }, &.{ entry_block, loop_block }, &fg.wip);
6277 const is_done = try fg.wip.icmp(.eq, next_index, try o.builder.intValue(.i32, iterations), "reduce.is_done");
6278 _ = try fg.wip.brCond(is_done, done_block, loop_block, .none);
6279
6280 fg.wip.cursor = .{ .block = done_block };
6281 return next_result;
6282 }
6283 var result = init.toValue();
6284 for (0..iterations) |index| {
6285 const index_value = try o.builder.intValue(.i32, index);
6286 const rhs_elem = if (is_by_ref) rhs_elem: {
6287 const rhs_elem_ptr = try fg.ptraddConst(operand, index * scalar_ty.abiSize(zcu));
6288 break :rhs_elem try fg.load(rhs_elem_ptr, .none, scalar_ty, .normal);
6289 } else try fg.wip.extractElement(operand, index_value, "reduce.rhs_elem");
6290 result = try fg.buildCall(.{}, llvm_fn.typeOf(&o.builder), llvm_fn.toValue(&o.builder), fn_info, fn_info.param_types, &.{ result, rhs_elem });
6291 }
6292 return result;
60266293}
60276294
6028fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
6029 const o = self.object;
6295fn airAggregateInit(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
6296 const o = fg.object;
60306297 const zcu = o.zcu;
60316298 const ip = &zcu.intern_pool;
6032 const ty_pl = self.air.instructions.items(.data)[@backingInt(inst)].ty_pl;
6033 const result_ty = self.typeOfIndex(inst);
6299 const ty_pl = fg.air.instructions.items(.data)[@backingInt(inst)].ty_pl;
6300 const result_ty = fg.typeOfIndex(inst);
60346301 const len: usize = @intCast(result_ty.arrayLen(zcu));
6035 const elements: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[ty_pl.payload..][0..len]);
6302 const elements: []const Air.Inst.Ref = @ptrCast(fg.air.extra.items[ty_pl.payload..][0..len]);
60366303
60376304 switch (result_ty.zigTypeTag(zcu)) {
6038 .vector => {
6039 const llvm_result_ty = try o.lowerType(result_ty, .by_value);
6305 .vector => if (isByRef(result_ty, zcu)) {
6306 const elem_ty = result_ty.childType(zcu);
6307 const elem_size = elem_ty.abiSize(zcu);
6308 const result_ptr = try fg.buildZigAlloca(result_ty, .none);
6309 for (elements, 0..) |elem, elem_index| {
6310 const elem_ptr = try fg.ptraddConst(result_ptr, elem_index * elem_size);
6311 const llvm_elem = try fg.resolveInst(elem);
6312 try fg.store(elem_ptr, .none, llvm_elem, elem_ty, .normal);
6313 }
6314 return result_ptr;
6315 } else {
6316 const llvm_result_ty = try o.lowerType(result_ty, .as_value);
60406317 var vector = try o.builder.poisonValue(llvm_result_ty);
6041 for (elements, 0..) |elem, i| {
6042 const index_u32 = try o.builder.intValue(.i32, i);
6043 const llvm_elem = try self.resolveInst(elem);
6044 vector = try self.wip.insertElement(vector, llvm_elem, index_u32, "");
6318 for (elements, 0..) |elem, elem_index| {
6319 const elem_index_val = try o.builder.intValue(.i32, elem_index);
6320 const llvm_elem = try fg.resolveInst(elem);
6321 vector = try fg.wip.insertElement(vector, llvm_elem, elem_index_val, "");
60456322 }
60466323 return vector;
60476324 },
......@@ -6057,18 +6334,18 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde
60576334 for (elements, struct_type.field_types.get(ip)) |elem, field_ty| {
60586335 if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue;
60596336
6060 const non_int_val = try self.resolveInst(elem);
6337 const non_int_val = try fg.resolveInst(elem);
60616338 const ty_bit_size: u16 = @intCast(Type.fromInterned(field_ty).bitSize(zcu));
60626339 const small_int_ty = try o.builder.intType(ty_bit_size);
60636340 const small_int_val = if (Type.fromInterned(field_ty).isPtrAtRuntime(zcu))
6064 try self.wip.cast(.ptrtoint, non_int_val, small_int_ty, "")
6341 try fg.wip.cast(.ptrtoint, non_int_val, small_int_ty, "")
60656342 else
6066 try self.wip.cast(.bitcast, non_int_val, small_int_ty, "");
6343 try fg.wip.cast(.bitcast, non_int_val, small_int_ty, "");
60676344 const shift_rhs = try o.builder.intValue(int_ty, running_bits);
60686345 const extended_int_val =
6069 try self.wip.conv(.unsigned, small_int_val, int_ty, "");
6070 const shifted = try self.wip.bin(.shl, extended_int_val, shift_rhs, "");
6071 running_int = try self.wip.bin(.@"or", running_int, shifted, "");
6346 try fg.wip.conv(.unsigned, small_int_val, int_ty, "");
6347 const shifted = try fg.wip.bin(.shl, extended_int_val, shift_rhs, "");
6348 running_int = try fg.wip.bin(.@"or", running_int, shifted, "");
60726349 running_bits += ty_bit_size;
60736350 }
60746351 return running_int;
......@@ -6078,19 +6355,19 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde
60786355 // TODO in debug builds init to undef so that the padding will be 0xaa
60796356 // even if we fully populate the fields.
60806357 const struct_align = result_ty.abiAlignment(zcu);
6081 const alloca_inst = try self.buildZigAlloca(result_ty, .none);
6358 const alloca_inst = try fg.buildZigAlloca(result_ty, .none);
60826359
60836360 for (elements, 0..) |elem, field_index| {
60846361 if (result_ty.structFieldIsComptime(field_index, zcu)) continue;
60856362 const field_ty = result_ty.fieldType(field_index, zcu);
60866363 if (!field_ty.hasRuntimeBits(zcu)) continue;
60876364 const offset = result_ty.structFieldOffset(field_index, zcu);
6088 const field_ptr = try self.ptraddConst(alloca_inst, offset);
6365 const field_ptr = try fg.ptraddConst(alloca_inst, offset);
60896366 const field_ptr_align = struct_align.offset(offset);
60906367
6091 const llvm_field_val = try self.resolveInst(elem);
6368 const llvm_field_val = try fg.resolveInst(elem);
60926369
6093 try self.store(field_ptr, field_ptr_align, llvm_field_val, field_ty, .normal);
6370 try fg.store(field_ptr, field_ptr_align, llvm_field_val, field_ty, .normal);
60946371 }
60956372
60966373 return alloca_inst;
......@@ -6099,21 +6376,21 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde
60996376 .array => {
61006377 assert(isByRef(result_ty, zcu));
61016378
6102 const alloca_inst = try self.buildZigAlloca(result_ty, .none);
6379 const alloca_inst = try fg.buildZigAlloca(result_ty, .none);
61036380
61046381 const array_info = result_ty.arrayInfo(zcu);
61056382
61066383 const elem_size = array_info.elem_type.abiSize(zcu);
61076384
61086385 for (elements, 0..) |elem, i| {
6109 const elem_ptr = try self.ptraddConst(alloca_inst, elem_size * i);
6110 const llvm_elem = try self.resolveInst(elem);
6111 try self.store(elem_ptr, .none, llvm_elem, array_info.elem_type, .normal);
6386 const elem_ptr = try fg.ptraddConst(alloca_inst, elem_size * i);
6387 const llvm_elem = try fg.resolveInst(elem);
6388 try fg.store(elem_ptr, .none, llvm_elem, array_info.elem_type, .normal);
61126389 }
61136390 if (array_info.sentinel) |sent_val| {
6114 const elem_ptr = try self.ptraddConst(alloca_inst, elem_size * array_info.len);
6115 const llvm_elem = try self.resolveValue(sent_val);
6116 try self.store(elem_ptr, .none, llvm_elem.toValue(), array_info.elem_type, .normal);
6391 const elem_ptr = try fg.ptraddConst(alloca_inst, elem_size * array_info.len);
6392 const llvm_elem = try fg.resolveValue(sent_val);
6393 try fg.store(elem_ptr, .none, llvm_elem.toValue(), array_info.elem_type, .normal);
61176394 }
61186395
61196396 return alloca_inst;
......@@ -6153,10 +6430,10 @@ fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va
61536430 const loaded_enum = ip.loadEnumType(tag_ty.toIntern());
61546431 const llvm_tag_val = switch (loaded_enum.field_values.getOrNone(ip, extra.field_index)) {
61556432 .none => try o.builder.intConst(
6156 try o.lowerType(.fromInterned(union_obj.enum_tag_type), .by_value),
6433 try o.lowerType(.fromInterned(union_obj.enum_tag_type), .as_value),
61576434 extra.field_index, // auto-numbered
61586435 ),
6159 else => |tag_val_ip| try o.lowerValue(tag_val_ip, .by_value),
6436 else => |tag_val_ip| try o.lowerValue(tag_val_ip, .as_value),
61606437 };
61616438 const tag_ptr = try self.ptraddConst(result_ptr, layout.tagOffset());
61626439 try self.store(tag_ptr, layout.tag_align, llvm_tag_val.toValue(), tag_ty, .normal);
......@@ -6218,7 +6495,7 @@ fn airAddrSpaceCast(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde
62186495 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
62196496 const inst_ty = self.typeOfIndex(inst);
62206497 const operand = try self.resolveInst(ty_op.operand);
6221 return self.wip.cast(.addrspacecast, operand, try self.object.lowerType(inst_ty, .by_value), "");
6498 return self.wip.cast(.addrspacecast, operand, try self.object.lowerType(inst_ty, .as_value), "");
62226499}
62236500
62246501fn workIntrinsic(
......@@ -6370,7 +6647,7 @@ fn load(
63706647 };
63716648
63726649 if (isByRef(load_ty, zcu)) {
6373 const llvm_usize_ty = try o.lowerType(.usize, .by_value);
6650 const llvm_usize_ty = try o.lowerType(.usize, .as_value);
63746651 const result_ptr = try fg.buildZigAlloca(load_ty, .none);
63756652 _ = try fg.wip.callMemCpy(
63766653 result_ptr,
......@@ -6384,11 +6661,14 @@ fn load(
63846661 return result_ptr;
63856662 }
63866663
6387 const llvm_memory_ty = try o.lowerType(load_ty, .in_memory);
6388 const llvm_value_ty = try o.lowerType(load_ty, .by_value);
6664 const llvm_access_ty = try o.lowerType(load_ty, .memory_access);
6665 const llvm_value_ty = try o.lowerType(load_ty, .as_value);
63896666
6390 if (llvm_memory_ty != llvm_value_ty) {
6391 assert(load_ty.isAbiInt(zcu));
6667 if (llvm_access_ty != llvm_value_ty) {
6668 const signedness: std.lang.Signedness = switch (load_ty.toIntern()) {
6669 .bool_type => .unsigned,
6670 else => load_ty.intInfo(zcu).signedness,
6671 };
63926672 // `load_ty` is an integer type with padding bits. In theory, we shouldn't need any special
63936673 // handling for these, as LLVM's documented semantics are a valid implementation of Zig's
63946674 // semantics. However:
......@@ -6401,13 +6681,13 @@ fn load(
64016681 //
64026682 // Therefore, we handle these memory accesses specially: in this case we will actually load
64036683 // the next-largest "natural" integer type and then truncate to `load_ty`.
6404 const loaded = try fg.wip.load(access_kind, llvm_memory_ty, ptr, llvm_ptr_align, "");
6684 const loaded = try fg.wip.load(access_kind, llvm_access_ty, ptr, llvm_ptr_align, "");
64056685 // For packed structs, current Zig semantics don't really allow us to make the padding bits
64066686 // well-defined. This should be solved once https://github.com/ziglang/zig/issues/24061 is
64076687 // implemented, but until then, do a normal trunc for packed types.
64086688 return fg.wip.cast(switch (load_ty.zigTypeTag(zcu)) {
64096689 .@"struct", .@"union" => .trunc,
6410 else => switch (load_ty.intInfo(zcu).signedness) {
6690 else => switch (signedness) {
64116691 .unsigned => .@"trunc nuw",
64126692 .signed => .@"trunc nsw",
64136693 },
......@@ -6443,7 +6723,7 @@ fn store(
64436723 };
64446724
64456725 if (isByRef(elem_ty, zcu)) {
6446 const llvm_usize_ty = try o.lowerType(.usize, .by_value);
6726 const llvm_usize_ty = try o.lowerType(.usize, .as_value);
64476727 _ = try fg.wip.callMemCpy(
64486728 ptr,
64496729 llvm_ptr_align,
......@@ -6456,45 +6736,34 @@ fn store(
64566736 return;
64576737 }
64586738
6459 assert(elem.typeOfWip(&fg.wip) == try o.lowerType(elem_ty, .by_value));
6739 assert(elem.typeOfWip(&fg.wip) == try o.lowerType(elem_ty, .as_value));
64606740
6461 const llvm_memory_ty = try o.lowerType(elem_ty, .in_memory);
6462 const llvm_value_ty = try o.lowerType(elem_ty, .by_value);
6741 const llvm_access_ty = try o.lowerType(elem_ty, .memory_access);
6742 const llvm_value_ty = try o.lowerType(elem_ty, .as_value);
64636743
6464 if (llvm_memory_ty != llvm_value_ty) {
6465 assert(elem_ty.isAbiInt(zcu));
6744 if (llvm_access_ty != llvm_value_ty) {
6745 const signedness: std.lang.Signedness = switch (elem_ty.toIntern()) {
6746 .bool_type => .unsigned,
6747 else => elem_ty.intInfo(zcu).signedness,
6748 };
64666749 // `elem_ty` is an integer type with padding bits, so we need to handle it specially---see
64676750 // the corresponding comment in `FuncGen.load` for more details.
6468 const extended = try fg.wip.cast(switch (elem_ty.intInfo(zcu).signedness) {
6751 const extended = try fg.wip.cast(switch (signedness) {
64696752 .unsigned => .zext,
64706753 .signed => .sext,
6471 }, elem, llvm_memory_ty, "");
6472 _ = try fg.wip.storeAtomic(
6473 access_kind,
6474 extended,
6475 ptr,
6476 fg.sync_scope,
6477 .none,
6478 llvm_ptr_align,
6479 );
6754 }, elem, llvm_access_ty, "");
6755 _ = try fg.wip.store(access_kind, extended, ptr, llvm_ptr_align);
64806756 return;
64816757 }
64826758
64836759 // `elem_ty` is a simple by-val type which requires no special handling.
6484 _ = try fg.wip.storeAtomic(
6485 access_kind,
6486 elem,
6487 ptr,
6488 fg.sync_scope,
6489 .none,
6490 llvm_ptr_align,
6491 );
6760 _ = try fg.wip.store(access_kind, elem, ptr, llvm_ptr_align);
64926761}
64936762
64946763fn valgrindMarkUndef(fg: *FuncGen, ptr: Builder.Value, len: Builder.Value) Allocator.Error!void {
64956764 const VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545;
64966765 const o = fg.object;
6497 const usize_ty = try o.lowerType(.usize, .by_value);
6766 const usize_ty = try o.lowerType(.usize, .as_value);
64986767 const zero = try o.builder.intValue(usize_ty, 0);
64996768 const req = try o.builder.intValue(usize_ty, VG_USERREQ__MAKE_MEM_UNDEFINED);
65006769 const ptr_as_usize = try fg.wip.cast(.ptrtoint, ptr, usize_ty, "");
......@@ -6516,7 +6785,7 @@ fn valgrindClientRequest(
65166785 const target = zcu.getTarget();
65176786 if (!target_util.hasValgrindSupport(target, .stage2_llvm)) return default_value;
65186787
6519 const llvm_usize = try o.lowerType(.usize, .by_value);
6788 const llvm_usize = try o.lowerType(.usize, .as_value);
65206789 const usize_align = Type.usize.abiAlignment(zcu).toLlvm();
65216790
65226791 const array_llvm_ty = try o.builder.arrayType(6, llvm_usize);
......@@ -6650,13 +6919,14 @@ fn typeOfIndex(fg: *FuncGen, inst: Air.Inst.Index) Type {
66506919
66516920const ParamTypeIterator = struct {
66526921 object: *Object,
6653 fn_info: InternPool.Key.FuncType,
6922 cc: std.lang.CallingConvention,
6923 param_types: []const InternPool.Index,
66546924 zig_index: u32,
66556925 llvm_index: u32,
66566926 types_len: u32,
66576927 types_buffer: [8]Builder.Type,
66586928 offsets_buffer: [9]u64,
6659 byval_attr: bool,
6929 byval_attr: ?Object.Byval,
66606930
66616931 const Lowering = union(enum) {
66626932 no_bits,
......@@ -6672,88 +6942,78 @@ const ParamTypeIterator = struct {
66726942 };
66736943
66746944 pub fn next(it: *ParamTypeIterator) Allocator.Error!?Lowering {
6675 if (it.zig_index >= it.fn_info.param_types.len) return null;
6676 const ip = &it.object.zcu.intern_pool;
6677 const ty = it.fn_info.param_types.get(ip)[it.zig_index];
6678 it.byval_attr = false;
6945 if (it.zig_index >= it.param_types.len) return null;
6946 const ty = it.param_types[it.zig_index];
6947 it.byval_attr = null;
66796948 return nextInner(it, Type.fromInterned(ty));
66806949 }
66816950
66826951 /// `airCall` uses this instead of `next` so that it can take into account variadic functions.
6683 fn nextCall(it: *ParamTypeIterator, fg: *FuncGen, args: []const Air.Inst.Ref) Allocator.Error!?Lowering {
6684 const ip = &it.object.zcu.intern_pool;
6685 if (it.zig_index >= it.fn_info.param_types.len) {
6686 if (it.zig_index >= args.len) {
6952 fn nextCall(it: *ParamTypeIterator, arg_types: []const InternPool.Index) Allocator.Error!?Lowering {
6953 if (it.zig_index >= it.param_types.len) {
6954 if (it.zig_index >= arg_types.len) {
66876955 return null;
66886956 } else {
6689 return nextInner(it, fg.typeOf(args[it.zig_index]));
6957 return nextInner(it, .fromInterned(arg_types[it.zig_index]));
66906958 }
66916959 } else {
6692 return nextInner(it, Type.fromInterned(it.fn_info.param_types.get(ip)[it.zig_index]));
6960 return nextInner(it, .fromInterned(it.param_types[it.zig_index]));
66936961 }
66946962 }
66956963
66966964 fn nextInner(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering {
66976965 const zcu = it.object.zcu;
6698 const target = zcu.getTarget();
6699
6966 ty.assertHasLayout(zcu);
67006967 if (!ty.hasRuntimeBits(zcu)) {
67016968 it.zig_index += 1;
67026969 return .no_bits;
67036970 }
6704 switch (it.fn_info.cc) {
6971 switch (it.cc) {
67056972 .@"inline" => unreachable,
67066973 .auto => {
67076974 it.zig_index += 1;
67086975 it.llvm_index += 1;
6976
6977 // Match the c calling convention in some cases to avoid llvm bugs.
6978 const target = zcu.getTarget();
6979 if (target.cpu.arch == .x86_64 and ty.isVector(zcu) and ty.childType(zcu).toIntern() == .bool_type) return switch (ty.vectorLen(zcu)) {
6980 0 => .no_bits,
6981 1...32 => .abi_sized_int,
6982 33...64 => {
6983 it.types_buffer[0..1].* = .{.double};
6984 it.offsets_buffer[0..2].* = .{ 0, 8 };
6985 it.types_len = 1;
6986 return .multiple_llvm_types;
6987 },
6988 else => .byval,
6989 };
6990
67096991 if (ty.isSlice(zcu) or
67106992 (ty.zigTypeTag(zcu) == .optional and ty.optionalChild(zcu).isSlice(zcu) and !ty.ptrAllowsZero(zcu)))
67116993 {
67126994 it.llvm_index += 1;
67136995 return .slice;
6714 } else if (isByRef(ty, zcu)) {
6715 return .byref;
6716 } else if (target.cpu.arch.isX86() and
6717 !target.cpu.has(.x86, .avx512f) and
6718 ty.totalVectorBits(zcu) >= 512)
6719 {
6720 // As of LLVM 18, passing a vector byval with fastcc that is 512 bits or more returns
6721 // "512-bit vector arguments require 'avx512f' for AVX512"
6722 return .byref;
6723 } else {
6724 return .byval;
67256996 }
6997 if (isByRef(ty, zcu)) return .byref;
6998 return .byval;
67266999 },
67277000 .async => {
67287001 @panic("TODO implement async function lowering in the LLVM backend");
67297002 },
6730 .x86_64_sysv, .x86_64_x32 => return it.nextSystemV(ty),
6731 .x86_64_win => return it.nextWin64(ty),
6732 .x86_stdcall => {
6733 it.zig_index += 1;
6734 it.llvm_index += 1;
6735
6736 if (isScalar(zcu, ty)) {
6737 return .byval;
6738 } else {
6739 it.byval_attr = true;
6740 return .byref;
6741 }
6742 },
67437003 .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => {
67447004 it.zig_index += 1;
67457005 it.llvm_index += 1;
67467006 switch (aarch64_c_abi.classifyType(ty, zcu)) {
67477007 .memory => return .byref_mut,
6748 .float_array => |len| return Lowering{ .float_array = len },
7008 .float_array => |len| return .{ .float_array = len },
67497009 .byval => return .byval,
67507010 .integer => {
6751 it.types_len = 1;
67527011 it.types_buffer[0..1].* = .{.i64};
67537012 it.offsets_buffer[0..2].* = .{ 0, 8 };
7013 it.types_len = 1;
67547014 return .multiple_llvm_types;
67557015 },
6756 .double_integer => return Lowering{ .i64_array = 2 },
7016 .double_integer => return .{ .i64_array = 2 },
67577017 }
67587018 },
67597019 .arm_aapcs, .arm_aapcs_vfp => {
......@@ -6761,26 +7021,101 @@ const ParamTypeIterator = struct {
67617021 it.llvm_index += 1;
67627022 switch (arm_c_abi.classifyType(ty, zcu, .arg)) {
67637023 .memory => {
6764 it.byval_attr = true;
7024 it.byval_attr = .{};
67657025 return .byref;
67667026 },
67677027 .byval => return .byval,
6768 .i32_array => |size| return Lowering{ .i32_array = size },
6769 .i64_array => |size| return Lowering{ .i64_array = size },
7028 .i32_array => |size| return .{ .i32_array = size },
7029 .i64_array => |size| return .{ .i64_array = size },
67707030 }
67717031 },
7032 .loongarch32_ilp32, .loongarch64_lp64 => switch (loongarch_c_abi.classifyType(ty, zcu)) {
7033 .ignored => {
7034 it.zig_index += 1;
7035 return .no_bits;
7036 },
7037 .gar, .far => {
7038 it.zig_index += 1;
7039 it.llvm_index += 1;
7040 return .byval;
7041 },
7042 .member => |member_ty| {
7043 it.types_buffer[0..1].* = .{
7044 try it.object.lowerType(member_ty, .as_value),
7045 };
7046 it.offsets_buffer[0..2].* = .{ 0, member_ty.abiSize(zcu) };
7047 it.types_len = 1;
7048 it.zig_index += 1;
7049 it.llvm_index += 1;
7050 return .multiple_llvm_types;
7051 },
7052 .member_pair => |member_tys| {
7053 it.types_buffer[0..2].* = .{
7054 try it.object.lowerType(member_tys[0], .as_value),
7055 try it.object.lowerType(member_tys[1], .as_value),
7056 };
7057 const first_size = member_tys[0].abiSize(zcu);
7058 const second_size = member_tys[0].abiSize(zcu);
7059 it.offsets_buffer[0..3].* = .{ 0, first_size, first_size + second_size };
7060 it.types_len = 2;
7061 it.zig_index += 1;
7062 it.llvm_index += 2;
7063 return .multiple_llvm_types;
7064 },
7065 .memory_gar => {
7066 switch (it.cc) {
7067 else => unreachable,
7068 .loongarch32_ilp32 => {
7069 it.types_buffer[0..1].* = .{.i32};
7070 it.offsets_buffer[0..2].* = .{ 0, 4 };
7071 },
7072 .loongarch64_lp64 => {
7073 it.types_buffer[0..1].* = .{.i64};
7074 it.offsets_buffer[0..2].* = .{ 0, 8 };
7075 },
7076 }
7077 it.types_len = 1;
7078 it.zig_index += 1;
7079 it.llvm_index += 1;
7080 return .multiple_llvm_types;
7081 },
7082 .memory_gar_pair => {
7083 it.zig_index += 1;
7084 it.llvm_index += 1;
7085 return switch (it.cc) {
7086 else => unreachable,
7087 .loongarch32_ilp32 => .{ .i32_array = 2 },
7088 .loongarch64_lp64 => .{ .i64_array = 2 },
7089 };
7090 },
7091 .address => {
7092 it.zig_index += 1;
7093 it.llvm_index += 1;
7094 return .byref;
7095 },
7096 },
67727097 .mips_o32 => {
67737098 it.zig_index += 1;
67747099 it.llvm_index += 1;
67757100 switch (mips_c_abi.classifyType(ty, zcu, .arg)) {
67767101 .memory => {
6777 it.byval_attr = true;
7102 it.byval_attr = .{};
67787103 return .byref;
67797104 },
67807105 .byval => return .byval,
6781 .i32_array => |size| return Lowering{ .i32_array = size },
7106 .i32_array => |size| return .{ .i32_array = size },
67827107 }
67837108 },
7109 .powerpc64_elf_v2 => {
7110 it.zig_index += 1;
7111 it.llvm_index += 1;
7112 if (isByRef(ty, zcu)) return switch (ty.abiSize(zcu)) {
7113 1...8 => .abi_sized_int,
7114 9...64 => |abi_size| .{ .i64_array = @intCast(@divCeil(abi_size, 8)) },
7115 else => .byref,
7116 };
7117 return .byval; // TODO
7118 },
67847119 .riscv64_lp64, .riscv32_ilp32 => {
67857120 it.zig_index += 1;
67867121 it.llvm_index += 1;
......@@ -6788,7 +7123,7 @@ const ParamTypeIterator = struct {
67887123 .memory => return .byref_mut,
67897124 .byval => return .byval,
67907125 .integer => return .abi_sized_int,
6791 .double_integer => return Lowering{ .i64_array = 2 },
7126 .double_integer => return .{ .i64_array = 2 },
67927127 .fields => {
67937128 it.types_len = 0;
67947129 var field_it: InternPool.LoadedStructType.RuntimeOrderIterator = if (zcu.typeToStruct(ty)) |loaded_struct|
......@@ -6798,7 +7133,7 @@ const ParamTypeIterator = struct {
67987133 while (field_it.next()) |field_index| {
67997134 const field_ty = ty.fieldType(field_index, zcu);
68007135 if (!field_ty.hasRuntimeBits(zcu)) continue;
6801 it.types_buffer[it.types_len] = try it.object.lowerType(field_ty, .by_value);
7136 it.types_buffer[it.types_len] = try it.object.lowerType(field_ty, .as_value);
68027137 it.offsets_buffer[it.types_len] = ty.structFieldOffset(field_index, zcu);
68037138 it.types_len += 1;
68047139 }
......@@ -6808,28 +7143,105 @@ const ParamTypeIterator = struct {
68087143 },
68097144 }
68107145 },
6811 .wasm_mvp => switch (wasm_c_abi.classifyType(ty, zcu)) {
7146 .s390x_sysv, .s390x_sysv_vx => {
7147 it.zig_index += 1;
7148 switch (s390x_c_abi.classifyType(ty, .arg, zcu)) {
7149 .none => return .no_bits,
7150 .double_or_float, .vector, .simple => {
7151 it.llvm_index += 1;
7152 return .byval;
7153 },
7154 .simple_aggregate => {
7155 it.llvm_index += 1;
7156 return .abi_sized_int;
7157 },
7158 .pointer => {
7159 it.llvm_index += 1;
7160 return .byref_mut;
7161 },
7162 }
7163 },
7164 .wasm_mvp => switch (wasm_c_abi.classifyTypeForLlvm(ty, zcu)) {
68127165 .direct => |scalar_ty| {
68137166 if (isScalar(zcu, ty)) {
68147167 it.zig_index += 1;
68157168 it.llvm_index += 1;
68167169 return .byval;
68177170 } else {
6818 it.types_buffer[0..1].* = .{try it.object.lowerType(scalar_ty, .by_value)};
7171 it.types_buffer[0..1].* = .{try it.object.lowerType(scalar_ty, .as_value)};
68197172 it.offsets_buffer[0..2].* = .{ 0, scalar_ty.abiSize(zcu) };
68207173 it.types_len = 1;
6821 it.llvm_index += 1;
68227174 it.zig_index += 1;
7175 it.llvm_index += 1;
68237176 return .multiple_llvm_types;
68247177 }
68257178 },
68267179 .indirect => {
68277180 it.zig_index += 1;
68287181 it.llvm_index += 1;
6829 it.byval_attr = true;
7182 it.byval_attr = .{};
68307183 return .byref;
68317184 },
68327185 },
7186 .x86_stdcall => {
7187 it.zig_index += 1;
7188 it.llvm_index += 1;
7189
7190 if (isScalar(zcu, ty)) {
7191 return .byval;
7192 } else {
7193 it.byval_attr = .{};
7194 return .byref;
7195 }
7196 },
7197 .x86_sysv, .x86_win, .x86_mingw => {
7198 if (isByRef(ty, zcu)) {
7199 var items_buf: [1]codegen.FlattenedItem = undefined;
7200 if (codegen.flattenType(&items_buf, ty, zcu, .{
7201 .allow_arrays = false,
7202 })) |items| one_float: {
7203 if (items.len != 1 or items[0].offset != 0) break :one_float;
7204 const item_ty = items[0].type orelse break :one_float;
7205 if (!item_ty.isRuntimeFloat()) break :one_float;
7206 it.types_buffer[0..1].*, it.offsets_buffer[0..2].* =
7207 switch (item_ty.floatBits(zcu.getTarget())) {
7208 else => unreachable,
7209 32 => .{ .{.float}, .{ 0, 4 } },
7210 64 => .{ .{.double}, .{ 0, 8 } },
7211 16, 80, 128 => break :one_float,
7212 };
7213 it.types_len = 1;
7214 it.zig_index += 1;
7215 it.llvm_index += 1;
7216 return .multiple_llvm_types;
7217 }
7218 it.zig_index += 1;
7219 it.llvm_index += 1;
7220 it.byval_attr = .{ .alignment = .@"4" };
7221 return .byref;
7222 }
7223 if (ty.isAbiInt(zcu)) switch (ty.intInfo(zcu).bits) {
7224 else => unreachable,
7225 8, 16, 32, 64 => {
7226 it.zig_index += 1;
7227 it.llvm_index += 1;
7228 return .byval;
7229 },
7230 128 => {
7231 it.types_buffer[0..2].* = .{ .i64, .i64 };
7232 it.offsets_buffer[0..3].* = .{ 0, 8, 16 };
7233 it.types_len = 2;
7234 it.zig_index += 1;
7235 it.llvm_index += 2;
7236 return .multiple_llvm_types;
7237 },
7238 };
7239 it.zig_index += 1;
7240 it.llvm_index += 1;
7241 return .byval;
7242 },
7243 .x86_64_sysv, .x86_64_x32 => return try it.next_x86_64_sysv(ty),
7244 .x86_64_win => return it.next_x86_64_win(ty),
68337245 // TODO investigate other callconvs
68347246 else => {
68357247 it.zig_index += 1;
......@@ -6839,7 +7251,7 @@ const ParamTypeIterator = struct {
68397251 }
68407252 }
68417253
6842 fn nextWin64(it: *ParamTypeIterator, ty: Type) ?Lowering {
7254 fn next_x86_64_win(it: *ParamTypeIterator, ty: Type) Lowering {
68437255 const zcu = it.object.zcu;
68447256 switch (x86_64_abi.classifyWindows(ty, zcu, zcu.getTarget(), .arg)) {
68457257 .integer => {
......@@ -6880,119 +7292,114 @@ const ParamTypeIterator = struct {
68807292 }
68817293 }
68827294
6883 fn nextSystemV(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering {
6884 const zcu = it.object.zcu;
6885 const ip = &zcu.intern_pool;
6886 ty.assertHasLayout(zcu);
6887 const classes = x86_64_abi.classifySystemV(ty, zcu, zcu.getTarget(), .arg);
6888 if (classes[0] == .memory) {
6889 it.zig_index += 1;
6890 it.llvm_index += 1;
6891 it.byval_attr = true;
6892 return .byref;
6893 }
6894 if (isScalar(zcu, ty)) {
6895 it.zig_index += 1;
6896 it.llvm_index += 1;
6897 return .byval;
6898 }
6899 var types_index: u32 = 0;
6900 var offset: u64 = 0;
6901 for (classes) |class| {
6902 switch (class) {
6903 .integer => {
6904 it.types_buffer[types_index] = .i64;
6905 it.offsets_buffer[types_index] = offset;
6906 types_index += 1;
6907 },
6908 .sse => {
6909 it.types_buffer[types_index] = .double;
6910 it.offsets_buffer[types_index] = offset;
6911 types_index += 1;
6912 },
6913 .sseup => {
6914 if (it.types_buffer[types_index - 1] == .double) {
6915 it.types_buffer[types_index - 1] = .fp128;
6916 } else {
6917 it.types_buffer[types_index] = .double;
6918 it.offsets_buffer[types_index] = offset;
6919 types_index += 1;
7295 fn next_x86_64_sysv(it: *ParamTypeIterator, ty: Type) Allocator.Error!Lowering {
7296 const o = it.object;
7297 const zcu = o.zcu;
7298 const target = zcu.getTarget();
7299 const classes = x86_64_abi.classifySystemV(ty, zcu, target, .arg);
7300 var types_len: u32 = 0;
7301 const classes_len = for (classes, 0..) |class, class_index| switch (class) {
7302 .integer => {
7303 it.types_buffer[types_len] = try o.builder.intType(@min(8 * ty.abiSize(zcu) - 64 * class_index, 64));
7304 it.offsets_buffer[types_len] = 8 * class_index;
7305 types_len += 1;
7306 },
7307 .sse => {
7308 it.types_buffer[types_len] = .double;
7309 it.offsets_buffer[types_len] = 8 * class_index;
7310 types_len += 1;
7311 },
7312 .sseup => {
7313 if (it.types_buffer[types_len - 1] == .double) {
7314 if (ty.isVector(zcu)) {
7315 it.zig_index += 1;
7316 it.llvm_index += 1;
7317 return .byval;
69207318 }
6921 },
6922 .float => {
6923 it.types_buffer[types_index] = .float;
6924 it.offsets_buffer[types_index] = offset;
6925 types_index += 1;
6926 },
6927 .float_combine => {
6928 it.types_buffer[types_index] = try it.object.builder.vectorType(.normal, 2, .float);
6929 it.offsets_buffer[types_index] = offset;
6930 types_index += 1;
6931 },
6932 .x87 => {
6933 it.zig_index += 1;
6934 it.llvm_index += 1;
6935 it.byval_attr = true;
6936 return .byref;
6937 },
6938 .x87up => unreachable,
6939 .none => break,
6940 .memory => unreachable, // handled above
6941 .win_i128 => unreachable, // windows only
6942 .bool_vector_mask,
6943 .integer_per_element,
6944 .sse_per_element,
6945 .sse_sse_x87_per_qword,
6946 .sse_per_xword,
6947 .sse_per_yword,
6948 .sse_per_zword,
6949 => unreachable, // vectors already handled by `isScalar` above
6950 }
6951 offset += 8;
6952 }
6953 const first_non_integer = std.mem.indexOfNone(x86_64_abi.Class, &classes, &.{.integer});
6954 if (first_non_integer == null or classes[first_non_integer.?] == .none) {
6955 assert(first_non_integer orelse classes.len == types_index);
6956 if (types_index == 1) {
7319 it.types_buffer[types_len - 1] = .fp128;
7320 } else {
7321 it.types_buffer[types_len] = .double;
7322 it.offsets_buffer[types_len] = 8 * class_index;
7323 types_len += 1;
7324 }
7325 },
7326 .float => {
7327 it.types_buffer[types_len] = .float;
7328 it.offsets_buffer[types_len] = 8 * class_index;
7329 types_len += 1;
7330 },
7331 .float_combine => {
7332 it.types_buffer[types_len] = try it.object.builder.vectorType(.normal, 2, .float);
7333 it.offsets_buffer[types_len] = 8 * class_index;
7334 types_len += 1;
7335 },
7336 .x87 => {
69577337 it.zig_index += 1;
69587338 it.llvm_index += 1;
6959 return .abi_sized_int;
6960 }
6961 if (it.llvm_index + types_index > 6) {
7339 it.byval_attr = .{};
7340 return .byref;
7341 },
7342 .x87up => unreachable,
7343 .none => break class_index,
7344 .memory => {
7345 it.zig_index += 1;
7346 it.llvm_index += 1;
7347 it.byval_attr = .{};
7348 return .byref;
7349 },
7350 .win_i128 => unreachable, // windows only
7351 .bool_vector_mask,
7352 .integer_per_element,
7353 .sse_per_element,
7354 .sse_sse_x87_per_qword,
7355 .sse_per_xword,
7356 .sse_per_yword,
7357 .sse_per_zword,
7358 => {
7359 it.zig_index += 1;
7360 it.llvm_index += 1;
7361 return .byval;
7362 },
7363 } else classes.len;
7364 if (types_len > 1) {
7365 if (it.llvm_index + classes_len > 6) {
69627366 it.zig_index += 1;
69637367 it.llvm_index += 1;
6964 it.byval_attr = true;
7368 it.byval_attr = .{};
69657369 return .byref;
69667370 }
6967 switch (ip.indexToKey(ty.toIntern())) {
6968 .struct_type => {
6969 const size = ty.abiSize(zcu);
6970 assert(@divCeil(size, 8) == types_index);
6971 if (size % 8 > 0) {
6972 it.types_buffer[types_index - 1] =
6973 try it.object.builder.intType(@intCast(size % 8 * 8));
6974 }
6975 },
6976 else => {},
7371 } else if (!isByRef(ty, zcu)) {
7372 const llvm_ty = try o.lowerType(ty, .as_value);
7373 if (it.types_buffer[0] == llvm_ty or
7374 (it.types_buffer[0] == .i64 and llvm_ty.isPointer(&o.builder)))
7375 {
7376 it.zig_index += 1;
7377 it.llvm_index += 1;
7378 return .byval;
69777379 }
69787380 }
6979 it.offsets_buffer[types_index] = offset;
6980 it.types_len = types_index;
6981 it.llvm_index += types_index;
7381 it.offsets_buffer[types_len] = 8 * classes_len;
7382 it.types_len = types_len;
7383 it.llvm_index += types_len;
69827384 it.zig_index += 1;
69837385 return .multiple_llvm_types;
69847386 }
69857387};
6986pub fn iterateParamTypes(object: *Object, fn_info: InternPool.Key.FuncType) ParamTypeIterator {
7388pub fn iterateParamTypes(
7389 object: *Object,
7390 cc: std.lang.CallingConvention,
7391 param_types: []const InternPool.Index,
7392) ParamTypeIterator {
69877393 return .{
69887394 .object = object,
6989 .fn_info = fn_info,
7395 .cc = cc,
7396 .param_types = param_types,
69907397 .zig_index = 0,
69917398 .llvm_index = 0,
69927399 .types_len = undefined,
69937400 .types_buffer = undefined,
69947401 .offsets_buffer = undefined,
6995 .byval_attr = false,
7402 .byval_attr = null,
69967403 };
69977404}
69987405
......@@ -7017,54 +7424,68 @@ pub const FnReturnStrat = union(enum) {
70177424/// In order to support the C calling convention, some return types need to be lowered
70187425/// completely differently in the function prototype to honor the C ABI, and then
70197426/// be effectively bitcasted to the actual return type.
7020pub fn fnReturnStrat(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!FnReturnStrat {
7427pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) Allocator.Error!FnReturnStrat {
70217428 const zcu = o.zcu;
7022 const ret_ty: Type = .fromInterned(fn_info.return_type);
70237429 ret_ty.assertHasLayout(zcu);
70247430 if (!ret_ty.hasRuntimeBits(zcu)) return .void;
7025 switch (fn_info.cc) {
7431 return switch (cc) {
70267432 .@"inline" => unreachable,
70277433 .auto => {
7028 if (isByRef(ret_ty, zcu)) return .sret;
7029
7434 // Match the c calling convention in some cases to avoid llvm bugs.
70307435 const target = zcu.getTarget();
7031 if (target.cpu.arch.isX86() and
7032 !target.cpu.has(.x86, .avx512f) and
7033 ret_ty.totalVectorBits(zcu) >= 512)
7034 {
7035 // As of LLVM 18, passing a vector byval with fastcc that is 512 bits or more returns
7036 // "512-bit vector arguments require 'avx512f' for AVX512"
7037 return .sret;
7038 }
7039
7040 return .by_val;
7436 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)) {
7437 0 => .void,
7438 1...8 => .{ .mem_cast = .i8 },
7439 9...16 => .{ .mem_cast = .i16 },
7440 17...32 => .{ .mem_cast = .i32 },
7441 33...64 => .{ .mem_cast = .double },
7442 else => .by_val,
7443 };
7444 return if (isByRef(ret_ty, zcu)) .sret else .by_val;
70417445 },
7042 .x86_64_sysv, .x86_64_x32 => return lowerSystemVFnRetTy(o, fn_info),
7043 .x86_64_win => return lowerWin64FnRetTy(o, fn_info),
7044 .x86_stdcall => if (isScalar(zcu, ret_ty)) {
7045 assert(!isByRef(ret_ty, zcu));
7046 return .by_val;
7047 } else return .sret,
7048 .x86_fastcall => return lowerX86FastcallFnRetTy(o, zcu, ret_ty),
7049 .x86_sysv, .x86_win => return if (isByRef(ret_ty, zcu)) .sret else .by_val,
70507446 .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => switch (aarch64_c_abi.classifyType(ret_ty, zcu)) {
7051 .memory => return .sret,
7052 .float_array, .byval => return .forceByVal(o, ret_ty),
7053 .integer => return .{ .mem_cast = .i64 },
7054 .double_integer => return .{ .mem_cast = try o.builder.arrayType(2, .i64) },
7447 .memory => .sret,
7448 .float_array, .byval => .forceByVal(o, ret_ty),
7449 .integer => .{ .mem_cast = .i64 },
7450 .double_integer => .{ .mem_cast = try o.builder.arrayType(2, .i64) },
70557451 },
70567452 .arm_aapcs, .arm_aapcs_vfp => switch (arm_c_abi.classifyType(ret_ty, zcu, .ret)) {
7057 .memory, .i64_array => return .sret,
7058 .i32_array => |len| return if (len == 1) .{ .mem_cast = .i32 } else .sret,
7059 .byval => return .forceByVal(o, ret_ty),
7453 .memory, .i64_array => .sret,
7454 .i32_array => |len| if (len == 1) .{ .mem_cast = .i32 } else .sret,
7455 .byval => .forceByVal(o, ret_ty),
7456 },
7457 .loongarch32_ilp32, .loongarch64_lp64 => switch (loongarch_c_abi.classifyType(ret_ty, zcu)) {
7458 .ignored => .void,
7459 .gar, .far => .by_val,
7460 .member => |member_ty| .{ .mem_cast = try o.lowerType(member_ty, .as_value) },
7461 .member_pair => |member_tys| .{ .mem_cast = try o.builder.structType(.normal, &.{
7462 try o.lowerType(member_tys[0], .as_value),
7463 try o.lowerType(member_tys[1], .as_value),
7464 }) },
7465 .memory_gar => .{ .mem_cast = switch (cc) {
7466 else => unreachable,
7467 .loongarch32_ilp32 => .i32,
7468 .loongarch64_lp64 => .i64,
7469 } },
7470 .memory_gar_pair => .{ .mem_cast = try o.builder.arrayType(2, switch (cc) {
7471 else => unreachable,
7472 .loongarch32_ilp32 => .i32,
7473 .loongarch64_lp64 => .i64,
7474 }) },
7475 .address => .sret,
70607476 },
70617477 .mips_o32 => switch (mips_c_abi.classifyType(ret_ty, zcu, .ret)) {
7062 .memory, .i32_array => return .sret,
7063 .byval => return .forceByVal(o, ret_ty),
7478 .memory, .i32_array => .sret,
7479 .byval => .forceByVal(o, ret_ty),
70647480 },
7481 .powerpc64_elf_v2 => if (isByRef(ret_ty, zcu)) switch (ret_ty.abiSize(zcu)) {
7482 1...8 => .{ .mem_cast = try o.builder.intType(@intCast(ret_ty.abiSize(zcu) * 8)) },
7483 9...16 => .{ .mem_cast = try o.builder.structType(.normal, &.{ .i64, .i64 }) },
7484 else => .sret,
7485 } else .by_val, // TODO
70657486 .riscv64_lp64, .riscv32_ilp32 => switch (riscv_c_abi.classifyType(ret_ty, zcu)) {
7066 .memory => return .sret,
7067 .integer => return .{ .mem_cast = try o.builder.intType(@intCast(ret_ty.abiSize(zcu) * 8)) },
7487 .memory => .sret,
7488 .integer => .{ .mem_cast = try o.builder.intType(@intCast(ret_ty.abiSize(zcu) * 8)) },
70687489 .double_integer => {
70697490 const integer: Builder.Type = switch (zcu.getTarget().cpu.arch) {
70707491 .riscv64, .riscv64be => .i64,
......@@ -7073,34 +7494,78 @@ pub fn fnReturnStrat(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Err
70737494 };
70747495 return .{ .mem_cast = try o.builder.structType(.normal, &.{ integer, integer }) };
70757496 },
7076 .byval => return .forceByVal(o, ret_ty),
7497 .byval => .forceByVal(o, ret_ty),
70777498 .fields => {
70787499 var types_len: usize = 0;
70797500 var types: [8]Builder.Type = undefined;
70807501 for (0..ret_ty.structFieldCount(zcu)) |field_index| {
70817502 const field_ty = ret_ty.fieldType(field_index, zcu);
70827503 if (!field_ty.hasRuntimeBits(zcu)) continue;
7083 types[types_len] = try o.lowerType(field_ty, .by_value);
7504 types[types_len] = try o.lowerType(field_ty, .as_value);
70847505 types_len += 1;
70857506 }
70867507 return .{ .mem_cast = try o.builder.structType(.normal, types[0..types_len]) };
70877508 },
70887509 },
7089 .wasm_mvp => switch (wasm_c_abi.classifyType(ret_ty, zcu)) {
7510 .s390x_sysv, .s390x_sysv_vx => switch (s390x_c_abi.classifyType(ret_ty, .ret, zcu)) {
7511 .none => .void,
7512 .double_or_float, .vector, .simple => .by_val,
7513 .simple_aggregate => unreachable,
7514 .pointer => .sret,
7515 },
7516 .wasm_mvp => switch (wasm_c_abi.classifyTypeForLlvm(ret_ty, zcu)) {
70907517 .direct => |scalar_ty| if (scalar_ty.toIntern() == ret_ty.toIntern()) {
70917518 assert(!isByRef(ret_ty, zcu));
70927519 return .by_val;
7093 } else {
7094 return .{ .mem_cast = try o.lowerType(scalar_ty, .by_value) };
7095 },
7096 .indirect => return .sret,
7520 } else .{ .mem_cast = try o.lowerType(scalar_ty, .as_value) },
7521 .indirect => .sret,
70977522 },
7523 .x86_stdcall => if (isScalar(zcu, ret_ty)) {
7524 assert(!isByRef(ret_ty, zcu));
7525 return .by_val;
7526 } else .sret,
7527 .x86_fastcall => fnReturnStrat_x86_fastcall(o, zcu, ret_ty),
7528 .x86_sysv, .x86_win, .x86_mingw => if (isByRef(ret_ty, zcu)) {
7529 switch (cc) {
7530 else => unreachable,
7531 .x86_sysv => return .sret,
7532 .x86_win => {},
7533 .x86_mingw => {
7534 var items_buf: [1]codegen.FlattenedItem = undefined;
7535 if (codegen.flattenType(&items_buf, ret_ty, zcu, .{})) |items| one_float: {
7536 if (items.len != 1 or items[0].offset != 0) break :one_float;
7537 const item_ty = items[0].type orelse break :one_float;
7538 if (!item_ty.isRuntimeFloat()) break :one_float;
7539 return .{ .mem_cast = switch (item_ty.floatBits(zcu.getTarget())) {
7540 else => unreachable,
7541 16 => .half,
7542 32 => .float,
7543 64 => .double,
7544 80, 128 => break :one_float,
7545 } };
7546 }
7547 },
7548 }
7549 return switch (ret_ty.abiSize(zcu)) {
7550 0 => .void,
7551 1 => .{ .mem_cast = .i8 },
7552 2 => .{ .mem_cast = .i16 },
7553 4 => .{ .mem_cast = .i32 },
7554 8 => .{ .mem_cast = .i64 },
7555 else => .sret,
7556 };
7557 } else if (ret_ty.isAbiInt(zcu) and ret_ty.intInfo(zcu).bits > 64)
7558 .sret
7559 else
7560 .by_val,
7561 .x86_64_sysv, .x86_64_x32 => fnReturnStrat_x86_64_sysv(o, ret_ty),
7562 .x86_64_win => fnReturnStrat_x86_64_win(o, ret_ty),
70987563 // TODO investigate other callconvs
7099 else => return .forceByVal(o, ret_ty),
7100 }
7564 else => .forceByVal(o, ret_ty),
7565 };
71017566}
71027567
7103fn lowerX86FastcallFnRetTy(o: *Object, zcu: *Zcu, ty: Type) Allocator.Error!FnReturnStrat {
7568fn fnReturnStrat_x86_fastcall(o: *Object, zcu: *Zcu, ty: Type) Allocator.Error!FnReturnStrat {
71047569 if (isScalar(zcu, ty)) {
71057570 assert(!isByRef(ty, zcu));
71067571 return .by_val;
......@@ -7115,9 +7580,8 @@ fn lowerX86FastcallFnRetTy(o: *Object, zcu: *Zcu, ty: Type) Allocator.Error!FnRe
71157580 return .sret;
71167581}
71177582
7118fn lowerWin64FnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!FnReturnStrat {
7583fn fnReturnStrat_x86_64_win(o: *Object, ret_ty: Type) Allocator.Error!FnReturnStrat {
71197584 const zcu = o.zcu;
7120 const ret_ty = Type.fromInterned(fn_info.return_type);
71217585 switch (x86_64_abi.classifyWindows(ret_ty, zcu, zcu.getTarget(), .ret)) {
71227586 .integer => if (isScalar(zcu, ret_ty)) {
71237587 assert(!isByRef(ret_ty, zcu));
......@@ -7150,78 +7614,65 @@ fn lowerWin64FnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Err
71507614 }
71517615}
71527616
7153fn lowerSystemVFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!FnReturnStrat {
7617fn fnReturnStrat_x86_64_sysv(o: *Object, ret_ty: Type) Allocator.Error!FnReturnStrat {
71547618 const zcu = o.zcu;
7155 const ip = &zcu.intern_pool;
7156 const ret_ty = Type.fromInterned(fn_info.return_type);
7157 if (isScalar(zcu, ret_ty)) {
7158 assert(!isByRef(ret_ty, zcu));
7159 return .by_val;
7160 }
71617619 const classes = x86_64_abi.classifySystemV(ret_ty, zcu, zcu.getTarget(), .ret);
7162 var types_index: u32 = 0;
71637620 var types_buffer: [8]Builder.Type = undefined;
7164 for (classes) |class| {
7165 switch (class) {
7166 .integer => {
7167 types_buffer[types_index] = .i64;
7168 types_index += 1;
7169 },
7170 .sse => {
7171 types_buffer[types_index] = .double;
7172 types_index += 1;
7173 },
7174 .sseup => {
7175 if (types_buffer[types_index - 1] == .double) {
7176 types_buffer[types_index - 1] = .fp128;
7177 } else {
7178 types_buffer[types_index] = .double;
7179 types_index += 1;
7180 }
7181 },
7182 .float => {
7183 types_buffer[types_index] = .float;
7184 types_index += 1;
7185 },
7186 .float_combine => {
7187 types_buffer[types_index] = try o.builder.vectorType(.normal, 2, .float);
7188 types_index += 1;
7189 },
7190 .x87 => {
7191 if (types_index != 0 or classes[2] != .none) return .sret;
7192 types_buffer[types_index] = .x86_fp80;
7193 types_index += 1;
7194 },
7195 .x87up => continue,
7196 .none => break,
7197 .memory => return .sret,
7198 .win_i128 => unreachable, // windows only
7199 .bool_vector_mask,
7200 .integer_per_element,
7201 .sse_per_element,
7202 .sse_sse_x87_per_qword,
7203 .sse_per_xword,
7204 .sse_per_yword,
7205 .sse_per_zword,
7206 => unreachable, // vectors already handled by `isScalar` above
7207 }
7208 }
7209 const first_non_integer = std.mem.indexOfNone(x86_64_abi.Class, &classes, &.{.integer});
7210 if (first_non_integer == null or classes[first_non_integer.?] == .none) {
7211 assert(first_non_integer orelse classes.len == types_index);
7212 switch (ip.indexToKey(ret_ty.toIntern())) {
7213 .struct_type => {
7214 const size = ret_ty.abiSize(zcu);
7215 assert(@divCeil(size, 8) == types_index);
7216 if (size % 8 > 0) {
7217 types_buffer[types_index - 1] = try o.builder.intType(@intCast(size % 8 * 8));
7218 }
7219 },
7220 else => {},
7221 }
7222 if (types_index == 1) return .{ .mem_cast = types_buffer[0] };
7621 var types_len: u32 = 0;
7622 for (classes, 0..) |class, class_index| switch (class) {
7623 .integer => {
7624 types_buffer[types_len] = try o.builder.intType(@min(8 * ret_ty.abiSize(zcu) - 64 * class_index, 64));
7625 types_len += 1;
7626 },
7627 .sse => {
7628 types_buffer[types_len] = .double;
7629 types_len += 1;
7630 },
7631 .sseup => {
7632 if (types_buffer[types_len - 1] == .double) {
7633 if (ret_ty.isVector(zcu)) return .by_val;
7634 types_buffer[types_len - 1] = .fp128;
7635 } else {
7636 types_buffer[types_len] = .double;
7637 types_len += 1;
7638 }
7639 },
7640 .float => {
7641 types_buffer[types_len] = .float;
7642 types_len += 1;
7643 },
7644 .float_combine => {
7645 types_buffer[types_len] = try o.builder.vectorType(.normal, 2, .float);
7646 types_len += 1;
7647 },
7648 .x87 => {
7649 if (types_len > 0 or classes[2] != .none) return .sret;
7650 types_buffer[types_len] = .x86_fp80;
7651 types_len += 1;
7652 },
7653 .x87up => continue,
7654 .none => break,
7655 .memory => return if (ret_ty.isVector(zcu)) .by_val else .sret,
7656 .win_i128 => unreachable, // windows only
7657 .bool_vector_mask,
7658 .integer_per_element,
7659 .sse_per_element,
7660 .sse_sse_x87_per_qword,
7661 .sse_per_xword,
7662 .sse_per_yword,
7663 .sse_per_zword,
7664 => return .by_val,
7665 };
7666 if (types_len > 1) return .{ .mem_cast = try o.builder.structType(.normal, types_buffer[0..types_len]) };
7667 if (!isByRef(ret_ty, zcu)) {
7668 const llvm_ty = try o.lowerType(ret_ty, .as_value);
7669 if (types_buffer[0] == llvm_ty) return .by_val;
7670 if (types_buffer[0] == .i64 and llvm_ty.isPointer(&o.builder)) return .by_val;
7671 if (types_buffer[0] == .double and llvm_ty.isVector(&o.builder) and
7672 llvm_ty.vectorLen(&o.builder) == 1 and
7673 llvm_ty.scalarType(&o.builder) == .double) return .by_val;
72237674 }
7224 return .{ .mem_cast = try o.builder.structType(.normal, types_buffer[0..types_index]) };
7675 return .{ .mem_cast = types_buffer[0] };
72257676}
72267677
72277678/// This function deliberately does not handle `_BitInt` because it typically
......@@ -7234,15 +7685,22 @@ pub fn ccAbiPromoteInt(cc: std.lang.CallingConvention, zcu: *Zcu, ty: Type) ?std
72347685 else => {},
72357686 }
72367687
7237 const ty_tag = ty.zigTypeTag(zcu);
7238 const int_info = switch (ty_tag) {
7239 .bool => Type.u1.intInfo(zcu),
7240 else => if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else return null,
7241 };
7688 const target = zcu.getTarget();
7689 const int_info: std.lang.Type.Int = if (ty.toIntern() == .bool_type)
7690 .{ .signedness = .unsigned, .bits = 1 }
7691 else if (ty.isAbiInt(zcu))
7692 ty.intInfo(zcu)
7693 else if (ty.isRuntimeFloat()) switch (ty.floatBits(target)) {
7694 else => unreachable,
7695 16, 32, 64 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) {
7696 .hard => return null,
7697 .soft => .{ .signedness = .unsigned, .bits = bits },
7698 },
7699 80, 128 => return null,
7700 } else return null;
72427701
7243 assert(int_info.bits == 0 or (int_info.bits == 1 and ty_tag == .bool) or std.math.isPowerOfTwo(int_info.bits));
7702 assert(int_info.bits == 0 or (int_info.bits == 1 and ty.toIntern() == .bool_type) or std.math.isPowerOfTwo(int_info.bits));
72447703
7245 const target = zcu.getTarget();
72467704 return switch (target.cpu.arch) {
72477705 .aarch64,
72487706 .aarch64_be,
......@@ -7338,15 +7796,26 @@ pub fn isByRef(ty: Type, zcu: *const Zcu) bool {
73387796 .void,
73397797 .bool,
73407798 .int,
7341 .float,
73427799 .pointer,
73437800 .error_set,
73447801 .@"fn",
73457802 .@"enum",
7346 .vector,
73477803 .@"anyframe",
73487804 => false,
73497805
7806 .float, .vector => {
7807 const target = zcu.getTarget();
7808 const scalar_ty = ty.scalarType(zcu);
7809 return if (scalar_ty.isRuntimeFloat()) switch (scalar_ty.floatBits(target)) {
7810 else => unreachable,
7811 16, 32, 64 => false,
7812 80, 128 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) {
7813 .hard => false,
7814 .soft => true,
7815 },
7816 } else false;
7817 },
7818
73507819 .array,
73517820 .frame,
73527821 => ty.hasRuntimeBits(zcu),
......@@ -7392,7 +7861,7 @@ fn getAtomicAbiType(fg: *const FuncGen, ty: Type, is_rmw_xchg: bool) Allocator.E
73927861fn ptraddConst(fg: *FuncGen, ptr: Builder.Value, offset: u64) Allocator.Error!Builder.Value {
73937862 if (offset == 0) return ptr;
73947863 const o = fg.object;
7395 const llvm_usize_ty = try o.lowerType(.usize, .by_value);
7864 const llvm_usize_ty = try o.lowerType(.usize, .as_value);
73967865 const offset_val = try o.builder.intValue(llvm_usize_ty, offset);
73977866 return fg.wip.gep(.inbounds, .i8, ptr, &.{offset_val}, "");
73987867}
......@@ -7407,12 +7876,19 @@ fn ptraddScaled(fg: *FuncGen, ptr: Builder.Value, index: Builder.Value, scale: u
74077876 return fg.wip.gep(.inbounds, llvm_scale_ty, ptr, &.{index}, "");
74087877}
74097878
7410fn compilerRtIntBits(bits: u16) ?u16 {
7411 inline for (.{ 32, 64, 128 }) |b| {
7412 if (bits <= b) {
7413 return b;
7414 }
7415 }
7879fn compilerRtPromoteInt(int_info: InternPool.Key.IntType) ?Type {
7880 if (int_info.bits <= 32) return switch (int_info.signedness) {
7881 .signed => .i32,
7882 .unsigned => .u32,
7883 };
7884 if (int_info.bits <= 64) return switch (int_info.signedness) {
7885 .signed => .i64,
7886 .unsigned => .u64,
7887 };
7888 if (int_info.bits <= 128) return switch (int_info.signedness) {
7889 .signed => .i128,
7890 .unsigned => .u128,
7891 };
74167892 return null;
74177893}
74187894
......@@ -7471,13 +7947,21 @@ fn appendConstraints(
74717947}
74727948
74737949/// LLVM does not support all relevant intrinsics for all targets, so we
7474/// may need to manually generate a compiler-rt call.
7475fn intrinsicsAllowed(scalar_ty: Type, target: *const std.Target) bool {
7476 return switch (scalar_ty.toIntern()) {
7477 .f16_type => llvm.backendSupportsF16(target),
7478 .f80_type => (target.cTypeBitSize(.longdouble) == 80) and llvm.backendSupportsF80(target),
7479 .f128_type => (target.cTypeBitSize(.longdouble) == 128) and llvm.backendSupportsF128(target),
7480 else => true,
7950/// may need to manually generate a compiler-rt call using a soft type.
7951fn intrinsicsAllowed(kind: enum { compiler_rt, libc }, scalar_ty: Type, target: *const std.Target) bool {
7952 if (!scalar_ty.isRuntimeFloat()) return true;
7953 const bits = scalar_ty.floatBits(target);
7954 // Since upstream musl/msvc do not actually define the *f128 functions, llvm decides
7955 // that it is a much better idea to just emit a call to the entirely wrong function as
7956 // a fallback. We wouldn't want any linker errors when trying to perform an operation
7957 // that isn't actually implemented anywhere, now would we!
7958 if (bits == 128 and target.cpu.arch.isX86() and !target.abi.isGnu()) return switch (kind) {
7959 .compiler_rt => true,
7960 .libc => false,
7961 };
7962 return switch (std.zig.target.compilerRtFloatAbi(target, bits)) {
7963 .hard => true,
7964 .soft => false,
74817965 };
74827966}
74837967
......@@ -7823,12 +8307,14 @@ const Builder = std.zig.llvm.Builder;
78238307const assert = std.debug.assert;
78248308const math = std.math;
78258309
7826const x86_64_abi = @import("../x86_64/abi.zig");
7827const wasm_c_abi = @import("../wasm/abi.zig");
78288310const aarch64_c_abi = @import("../aarch64/abi.zig");
78298311const arm_c_abi = @import("../arm/abi.zig");
7830const riscv_c_abi = @import("../riscv64/abi.zig");
8312const loongarch_c_abi = @import("../loongarch/abi.zig");
78318313const mips_c_abi = @import("../mips/abi.zig");
8314const riscv_c_abi = @import("../riscv64/abi.zig");
8315const s390x_c_abi = @import("../s390x/abi.zig");
8316const wasm_c_abi = @import("../wasm/abi.zig");
8317const x86_64_abi = @import("../x86_64/abi.zig");
78328318
78338319const Zcu = @import("../../Zcu.zig");
78348320const Air = @import("../../Air.zig");
src/codegen/llvm/bindings.zig+2
......@@ -331,6 +331,8 @@ extern fn ZigLLVMWriteArchive(
331331 file_names_ptr: [*]const [*:0]const u8,
332332 file_names_len: usize,
333333 archive_kind: ArchiveKind,
334 err_file_index_out: *usize,
335 err_msg_out: *[*:0]u8,
334336) bool;
335337
336338pub const ParseCommandLineOptions = ZigLLVMParseCommandLineOptions;
src/codegen/loongarch/abi.zig created+133
......@@ -0,0 +1,133 @@
1const std = @import("std");
2const InternPool = @import("../../InternPool.zig");
3const Type = @import("../../Type.zig");
4const Zcu = @import("../../Zcu.zig");
5
6pub const Class = union(enum) {
7 ignored,
8 gar,
9 far,
10 member: Type,
11 member_pair: [2]Type,
12 memory_gar,
13 memory_gar_pair,
14 address,
15
16 fn combineMember(container_class: Class, member_class: Class, member_ty: Type) Class {
17 const second_member_ty = switch (member_class) {
18 .ignored => return container_class,
19 .gar, .far => member_ty,
20 .member => |second_member_ty| second_member_ty,
21 .member_pair, .memory_gar, .memory_gar_pair, .address => return .address,
22 };
23 return switch (container_class) {
24 .ignored => .{ .member = second_member_ty },
25 .gar, .far, .memory_gar, .memory_gar_pair => unreachable,
26 .member => |first_member_ty| .{ .member_pair = .{ first_member_ty, second_member_ty } },
27 .member_pair, .address => .address,
28 };
29 }
30};
31
32pub fn classifyType(ty: Type, zcu: *Zcu) Class {
33 return Classifier.init(zcu).classifyType(ty);
34}
35
36const Classifier = struct {
37 zcu: *Zcu,
38 target: *const std.Target,
39 grlen: u8,
40 frlen: u8,
41
42 fn init(zcu: *Zcu) Classifier {
43 const target = zcu.getTarget();
44 return .{
45 .zcu = zcu,
46 .target = target,
47 .grlen = switch (target.cpu.arch) {
48 else => unreachable,
49 .loongarch32 => 32,
50 .loongarch64 => 64,
51 },
52 .frlen = if (target.cpu.has(.loongarch, .d))
53 64
54 else if (target.cpu.has(.loongarch, .f))
55 32
56 else
57 0,
58 };
59 }
60
61 fn classifyType(c: Classifier, ty: Type) Class {
62 switch (ty.zigTypeTag(c.zcu)) {
63 .type,
64 .comptime_float,
65 .comptime_int,
66 .undefined,
67 .null,
68 .error_union,
69 .error_set,
70 .@"fn",
71 .@"opaque",
72 .frame,
73 .@"anyframe",
74 .enum_literal,
75 .spirv,
76 => unreachable,
77 .void, .noreturn => return .ignored,
78 .bool => return .gar,
79 .int, .@"enum" => {
80 const bits = ty.intInfo(c.zcu).bits;
81 if (bits == 0) return .ignored;
82 if (bits <= c.grlen) return .gar;
83 if (bits <= 2 * c.grlen) return .memory_gar_pair;
84 return .address;
85 },
86 .float => {
87 const bits = ty.floatBits(c.target);
88 if (bits <= c.frlen) return .far;
89 if (bits <= c.grlen) return .gar;
90 if (bits <= 2 * c.grlen) return .memory_gar_pair;
91 return .address;
92 },
93 .pointer, .optional => return .gar,
94 .array => {
95 var class: Class = .ignored;
96 const elem_ty = ty.childType(c.zcu);
97 const elem_class = c.classifyType(elem_ty);
98 for (0..std.math.lossyCast(usize, ty.arrayLenIncludingSentinel(c.zcu))) |_| {
99 class = class.combineMember(elem_class, elem_ty);
100 if (class == .address) break;
101 }
102 if (class != .address) return class;
103 },
104 .@"struct" => switch (ty.containerLayout(c.zcu)) {
105 .auto => unreachable,
106 .@"extern" => {
107 var class: Class = .ignored;
108 var field_it: InternPool.LoadedStructType.RuntimeOrderIterator = if (c.zcu.typeToStruct(ty)) |loaded_struct|
109 loaded_struct.iterateRuntimeOrder(&c.zcu.intern_pool)
110 else
111 .{ .runtime_order = null, .fields_len = ty.structFieldCount(c.zcu), .next_index = 0 };
112 while (field_it.next()) |field_index| {
113 const field_ty = ty.fieldType(field_index, c.zcu);
114 class = class.combineMember(c.classifyType(field_ty), field_ty);
115 if (class == .address) break;
116 }
117 if (class != .address) return class;
118 },
119 .@"packed" => return c.classifyType(ty.backingIntType(c.zcu)),
120 },
121 .@"union" => switch (ty.containerLayout(c.zcu)) {
122 .auto => unreachable,
123 .@"extern" => {},
124 .@"packed" => return c.classifyType(ty.backingIntType(c.zcu)),
125 },
126 .vector => {},
127 }
128 const size = ty.abiSize(c.zcu);
129 if (size <= @divExact(c.grlen, 8)) return .memory_gar;
130 if (size <= @divExact(2 * c.grlen, 8)) return .memory_gar_pair;
131 return .address;
132 }
133};
src/codegen/mips/abi.zig+8-1
......@@ -38,7 +38,14 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
3838 return .byval;
3939 },
4040 .bool => return .byval,
41 .float => return .byval,
41 .float => return switch (ty.floatBits(target)) {
42 else => unreachable,
43 16, 32, 64 => .byval,
44 80, 128 => switch (max_direct_size) {
45 else => unreachable,
46 64 => .memory,
47 },
48 },
4249 .int, .@"enum", .error_set => {
4350 return .byval;
4451 },
src/codegen/riscv64/CodeGen.zig+8-8
......@@ -5036,7 +5036,7 @@ fn airRet(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
50365036 .register_pair,
50375037 => {
50385038 if (ret_ty.isVector(zcu)) {
5039 const bit_size = ret_ty.totalVectorBits(zcu);
5039 const bit_size = ret_ty.bitSize(zcu);
50405040
50415041 // set the vtype to hold the entire vector's contents in a single element
50425042 try func.setVl(.zero, 0, .{
......@@ -6235,8 +6235,8 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void {
62356235 next_op: for (&ops) |*op| {
62366236 const op_str = while (!last_op) {
62376237 const full_str = op_it.next() orelse break :next_op;
6238 const code_str = if (mem.indexOfScalar(u8, full_str, '#') orelse
6239 mem.indexOf(u8, full_str, "//")) |comment|
6238 const code_str = if (mem.findScalar(u8, full_str, '#') orelse
6239 mem.find(u8, full_str, "//")) |comment|
62406240 code: {
62416241 last_op = true;
62426242 break :code full_str[0..comment];
......@@ -6250,7 +6250,7 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void {
62506250 } else if (std.fmt.parseInt(i12, op_str, 10)) |int| {
62516251 op.* = .{ .imm = Immediate.s(int) };
62526252 } else |_| if (mem.startsWith(u8, op_str, "%[")) {
6253 const mod_index = mem.indexOf(u8, op_str, "]@");
6253 const mod_index = mem.find(u8, op_str, "]@");
62546254 const modifier = if (mod_index) |index|
62556255 op_str[index + "]@".len ..]
62566256 else
......@@ -6871,7 +6871,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
68716871 // size to the total size of the vector, and vmv.x.s will work then
68726872 if (src_reg.class() == .vector) {
68736873 try func.setVl(.zero, 0, .{
6874 .vsew = switch (ty.totalVectorBits(zcu)) {
6874 .vsew = switch (ty.bitSize(zcu)) {
68756875 8 => .@"8",
68766876 16 => .@"16",
68776877 32 => .@"32",
......@@ -8339,9 +8339,9 @@ fn resolveCallingConventionValues(
83398339fn wantSafety(func: *Func) bool {
83408340 return switch (func.mod.optimize_mode) {
83418341 .Debug => true,
8342 .ReleaseSafe => true,
8343 .ReleaseFast => false,
8344 .ReleaseSmall => false,
8342 .safe => true,
8343 .fast => false,
8344 .small => false,
83458345 };
83468346}
83478347
src/codegen/riscv64/abi.zig+10-2
......@@ -56,12 +56,20 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class {
5656 return .integer;
5757 },
5858 .bool => return .integer,
59 .float => return .byval,
6059 .int, .@"enum", .error_set => {
6160 const bit_size = ty.bitSize(zcu);
6261 if (bit_size > max_byval_size) return .memory;
6362 return .byval;
6463 },
64 .float => return switch (ty.floatBits(target)) {
65 else => unreachable,
66 16, 32, 64, 128 => .byval,
67 80 => switch (max_byval_size) {
68 else => unreachable,
69 64 => .memory,
70 128 => .double_integer,
71 },
72 },
6573 .vector => {
6674 const bit_size = ty.bitSize(zcu);
6775 if (bit_size > max_byval_size) return .memory;
......@@ -190,7 +198,7 @@ pub fn classifySystem(ty: Type, zcu: *Zcu) [8]SystemClass {
190198 },
191199 .vector => {
192200 // we pass vectors through integer registers if they are small enough to fit.
193 const vec_bits = ty.totalVectorBits(zcu);
201 const vec_bits = ty.bitSize(zcu);
194202 if (vec_bits <= 64) {
195203 result[0] = .integer;
196204 return result;
src/codegen/riscv64/encoding.zig+1-1
......@@ -498,7 +498,7 @@ pub const Instruction = union(Lir.Format) {
498498 extra: u32,
499499
500500 comptime {
501 for (std.meta.fieldTypes(Instruction)) |field_type| {
501 for (@typeInfo(Instruction).@"union".field_types) |field_type| {
502502 assert(@bitSizeOf(field_type) == 32);
503503 }
504504 }
src/codegen/s390x/abi.zig created+85
......@@ -0,0 +1,85 @@
1const assert = std.debug.assert;
2const std = @import("std");
3const InternPool = @import("../../InternPool.zig");
4const Type = @import("../../Type.zig");
5const Zcu = @import("../../Zcu.zig");
6
7pub const Context = enum { ret, arg };
8
9pub const Class = enum {
10 none,
11 double_or_float,
12 vector,
13 simple,
14 simple_aggregate,
15 pointer,
16};
17
18pub fn classifyType(ty: Type, context: Context, zcu: *Zcu) Class {
19 tag: switch (ty.zigTypeTag(zcu)) {
20 .type,
21 .comptime_float,
22 .comptime_int,
23 .undefined,
24 .null,
25 .error_union,
26 .error_set,
27 .@"fn",
28 .@"opaque",
29 .frame,
30 .@"anyframe",
31 .enum_literal,
32 .spirv,
33 => unreachable,
34 .void, .noreturn => return .none,
35 .bool => return .simple,
36 .int, .@"enum" => return switch (ty.intInfo(zcu).bits) {
37 0 => .none,
38 1...64 => .simple,
39 else => .pointer,
40 },
41 .float => switch (ty.floatBits(zcu.getTarget())) {
42 else => unreachable,
43 16, 32, 64 => return .double_or_float,
44 80 => {},
45 128 => return .pointer,
46 },
47 .pointer, .optional => return .simple,
48 .array => {},
49 .@"struct", .@"union" => |tag| switch (ty.containerLayout(zcu)) {
50 .auto => unreachable,
51 .@"extern" => switch (context) {
52 .ret => {},
53 .arg => {
54 var class: Class = .none;
55 for (0..switch (tag) {
56 else => unreachable,
57 .@"struct" => ty.structFieldCount(zcu),
58 .@"union" => ty.unionTagTypeHypothetical(zcu).enumFieldCount(zcu),
59 }) |field_index| {
60 switch (tag) {
61 else => unreachable,
62 .@"struct" => if (ty.structFieldIsComptime(field_index, zcu)) continue,
63 .@"union" => {},
64 }
65 const field_class = classifyType(ty.fieldType(field_index, zcu), context, zcu);
66 if (field_class == .none) continue;
67 if (class != .none) break :tag;
68 class = field_class;
69 }
70 return class;
71 },
72 },
73 .@"packed" => return classifyType(ty.backingIntType(zcu), context, zcu),
74 },
75 .vector => return if (ty.abiSize(zcu) <= 16) .vector else .pointer,
76 }
77 return switch (ty.abiSize(zcu)) {
78 0 => .none,
79 1, 2, 4, 8 => switch (context) {
80 .ret => .pointer,
81 .arg => .simple_aggregate,
82 },
83 else => .pointer,
84 };
85}
src/codegen/sparc64/CodeGen.zig+3-3
......@@ -4764,9 +4764,9 @@ fn truncRegister(
47644764fn wantSafety(self: *Self) bool {
47654765 return switch (self.bin_file.comp.root_mod.optimize_mode) {
47664766 .Debug => true,
4767 .ReleaseSafe => true,
4768 .ReleaseFast => false,
4769 .ReleaseSmall => false,
4767 .safe => true,
4768 .fast => false,
4769 .small => false,
47704770 };
47714771}
47724772
src/codegen/spirv/Assembler.zig+39-38
......@@ -24,8 +24,9 @@ inst: struct {
2424 opcode: Opcode = undefined,
2525 operands: std.ArrayList(Operand) = .empty,
2626 string_bytes: std.ArrayList(u8) = .empty,
27 inst_offset: u32 = 0,
2728
28 fn result(ass: @This()) ?AsmValue.Ref {
29 fn result(ass: *const @This()) ?AsmValue.Ref {
2930 for (ass.operands.items[0..@min(ass.operands.items.len, 2)]) |op| {
3031 switch (op) {
3132 .result_id => |index| return index,
......@@ -35,7 +36,7 @@ inst: struct {
3536 return null;
3637 }
3738} = .{},
38value_map: std.array_hash_map.String(AsmValue) = .{},
39value_map: std.array_hash_map.String(AsmValue) = .empty,
3940inst_map: std.array_hash_map.String(void) = .empty,
4041
4142const Operand = union(enum) {
......@@ -82,7 +83,7 @@ pub fn assemble(ass: *Assembler, src: []const u8) Error!void {
8283 if (ass.inst_map.count() == 0) {
8384 const instructions = spec.InstructionSet.core.instructions();
8485 try ass.inst_map.ensureUnusedCapacity(gpa, @intCast(instructions.len));
85 for (spec.InstructionSet.core.instructions(), 0..) |inst, i| {
86 for (instructions, 0..) |inst, i| {
8687 const entry = try ass.inst_map.getOrPut(gpa, inst.name);
8788 assert(entry.index == i);
8889 }
......@@ -114,12 +115,13 @@ fn addError(ass: *Assembler, offset: u32, comptime fmt: []const u8, args: anytyp
114115}
115116
116117fn fail(ass: *Assembler, offset: u32, comptime fmt: []const u8, args: anytype) Error {
118 @branchHint(.cold);
117119 try ass.addError(offset, fmt, args);
118120 return error.AssembleFail;
119121}
120122
121123fn todo(ass: *Assembler, comptime fmt: []const u8, args: anytype) Error {
122 return ass.fail(0, "todo: " ++ fmt, args);
124 return ass.fail(ass.inst.inst_offset, "todo: " ++ fmt, args);
123125}
124126
125127const AsmValue = union(enum) {
......@@ -177,19 +179,19 @@ fn processInstruction(ass: *Assembler) !void {
177179 const cg = ass.cg;
178180 const result: AsmValue = switch (ass.inst.opcode) {
179181 .OpEntryPoint => {
180 return ass.fail(ass.currentToken().start, "cannot export entry points in assembly", .{});
182 return ass.fail(ass.inst.inst_offset, "cannot export entry points in assembly", .{});
181183 },
182184 .OpExecutionMode, .OpExecutionModeId => {
183 return ass.fail(ass.currentToken().start, "cannot set execution mode in assembly", .{});
185 return ass.fail(ass.inst.inst_offset, "cannot set execution mode in assembly", .{});
184186 },
185187 .OpCapability, .OpExtension => {
186 return ass.fail(ass.currentToken().start, "cannot declare capabilities or extensions in assembly; use -mcpu instead", .{});
188 return ass.fail(ass.inst.inst_offset, "cannot declare capabilities or extensions in assembly; use -mcpu instead", .{});
187189 },
188190 .OpExtInstImport => blk: {
189191 const set_name_offset = ass.inst.operands.items[1].string;
190192 const set_name = std.mem.sliceTo(ass.inst.string_bytes.items[set_name_offset..], 0);
191193 const set_tag = std.meta.stringToEnum(spec.InstructionSet, set_name) orelse {
192 return ass.fail(set_name_offset, "unknown instruction set: {s}", .{set_name});
194 return ass.fail(ass.inst.inst_offset, "unknown instruction set: {s}", .{set_name});
193195 };
194196 break :blk .{ .value = try cg.importInstructionSet(set_tag) };
195197 },
......@@ -209,9 +211,8 @@ fn processInstruction(ass: *Assembler) !void {
209211 switch (ass.value_map.values()[result_ref]) {
210212 .just_declared => ass.value_map.values()[result_ref] = result,
211213 else => {
212 // TODO: Improve source location.
213214 const name = ass.value_map.keys()[result_ref];
214 return ass.fail(0, "duplicate definition of %{s}", .{name});
215 return ass.fail(ass.inst.inst_offset, "duplicate definition of %{s}", .{name});
215216 },
216217 }
217218}
......@@ -229,12 +230,11 @@ fn processTypeInstruction(ass: *Assembler) !AsmValue {
229230 0 => .unsigned,
230231 1 => .signed,
231232 else => {
232 // TODO: Improve source location.
233 return ass.fail(0, "{} is not a valid signedness (expected 0 or 1)", .{operands[2].literal32});
233 return ass.fail(ass.inst.inst_offset, "{} is not a valid signedness (expected 0 or 1)", .{operands[2].literal32});
234234 },
235235 };
236236 const width = std.math.cast(u16, operands[1].literal32) orelse {
237 return ass.fail(0, "int type of {} bits is too large", .{operands[1].literal32});
237 return ass.fail(ass.inst.inst_offset, "int type of {} bits is too large", .{operands[1].literal32});
238238 };
239239 break :blk try cg.intType(signedness, width);
240240 },
......@@ -243,7 +243,7 @@ fn processTypeInstruction(ass: *Assembler) !AsmValue {
243243 switch (bits) {
244244 16, 32, 64 => {},
245245 else => {
246 return ass.fail(0, "{} is not a valid bit count for floats (expected 16, 32 or 64)", .{bits});
246 return ass.fail(ass.inst.inst_offset, "{} is not a valid bit count for floats (expected 16, 32 or 64)", .{bits});
247247 },
248248 }
249249 break :blk try cg.floatType(@intCast(bits));
......@@ -366,38 +366,40 @@ fn processGenericInstruction(ass: *Assembler) !?AsmValue {
366366
367367 var maybe_result_id: ?Id = null;
368368 const first_word = section.instructions.items.len;
369 // At this point we're not quite sure how many operands this instruction is
370 // going to have, so insert 0 and patch up the actual opcode word later.
371 try section.ensureUnusedCapacity(cg.gpa, 1);
369
370 // Pre-calculate exact instruction size to avoid per-operand capacity checks.
371 var total_words: usize = 1; // 1 word for the opcode itself
372 for (operands) |operand| {
373 total_words += switch (operand) {
374 .value, .literal32, .result_id, .ref_id => 1,
375 .literal64 => 2,
376 .string => |offset| blk: {
377 const text = std.mem.sliceTo(ass.inst.string_bytes.items[offset..], 0);
378 break :blk @divCeil(text.len + 1, @sizeOf(Word));
379 },
380 };
381 }
382
383 try section.ensureUnusedCapacity(cg.gpa, total_words);
372384 section.writeWord(0);
373385
374386 for (operands) |operand| {
375387 switch (operand) {
376 .value, .literal32 => |word| {
377 try section.ensureUnusedCapacity(cg.gpa, 1);
378 section.writeWord(word);
379 },
380 .literal64 => |dword| {
381 try section.ensureUnusedCapacity(cg.gpa, 2);
382 section.writeDoubleWord(dword);
383 },
388 .value, .literal32 => |word| section.writeWord(word),
389 .literal64 => |dword| section.writeDoubleWord(dword),
384390 .result_id => {
385391 maybe_result_id = if (maybe_spv_decl_index) |spv_decl_index|
386392 cg.declPtr(spv_decl_index).result_id
387393 else
388394 cg.allocId();
389 try section.ensureUnusedCapacity(cg.gpa, 1);
390395 section.writeOperand(Id, maybe_result_id.?);
391396 },
392397 .ref_id => |index| {
393398 const result = try ass.resolveRef(index);
394 try section.ensureUnusedCapacity(cg.gpa, 1);
395399 section.writeOperand(spec.Id, result.resultId());
396400 },
397401 .string => |offset| {
398402 const text = std.mem.sliceTo(ass.inst.string_bytes.items[offset..], 0);
399 const size = @divCeil(text.len + 1, @sizeOf(Word));
400 try section.ensureUnusedCapacity(cg.gpa, size);
401403 section.writeOperand(spec.LiteralString, text);
402404 },
403405 }
......@@ -445,11 +447,11 @@ fn processSpecConstVector(ass: *Assembler) !?AsmValue {
445447 const gpa = cg.gpa;
446448 const ty_ref = switch (ass.inst.operands.items[0]) {
447449 .ref_id => |i| i,
448 else => return ass.fail(0, "missing result type", .{}),
450 else => return ass.fail(ass.inst.inst_offset, "missing result type", .{}),
449451 };
450452 const composite_ty_id = switch (try ass.resolveRef(ty_ref)) {
451453 .ty => |id| id,
452 else => return ass.fail(0, "%ty must be a type", .{}),
454 else => return ass.fail(ass.inst.inst_offset, "%ty must be a type", .{}),
453455 };
454456
455457 const globals = &cg.sections.globals;
......@@ -483,7 +485,7 @@ fn processSpecConstVector(ass: *Assembler) !?AsmValue {
483485 }
484486
485487 const spec_id_word = std.math.cast(u32, spec_id_base + i) orelse {
486 return ass.fail(0, "SpecId {} does not fit in 32 bits", .{spec_id_base + i});
488 return ass.fail(ass.inst.inst_offset, "SpecId {} does not fit in 32 bits", .{spec_id_base + i});
487489 };
488490 try annotations.emitRaw(gpa, .OpDecorate, 3);
489491 annotations.writeOperand(Id, elem_id);
......@@ -505,8 +507,7 @@ fn resolveMaybeForwardRef(ass: *Assembler, ref: AsmValue.Ref) !AsmValue {
505507 switch (value) {
506508 .just_declared => {
507509 const name = ass.value_map.keys()[ref];
508 // TODO: Improve source location.
509 return ass.fail(0, "ass-referential parameter %{s}", .{name});
510 return ass.fail(ass.inst.inst_offset, "self-referential parameter %{s}", .{name});
510511 },
511512 else => return value,
512513 }
......@@ -518,8 +519,7 @@ fn resolveRef(ass: *Assembler, ref: AsmValue.Ref) !AsmValue {
518519 .just_declared => unreachable,
519520 .unresolved_forward_reference => {
520521 const name = ass.value_map.keys()[ref];
521 // TODO: Improve source location.
522 return ass.fail(0, "reference to undeclared result-id %{s}", .{name});
522 return ass.fail(ass.inst.inst_offset, "reference to undeclared result-id %{s}", .{name});
523523 },
524524 else => return value,
525525 }
......@@ -536,6 +536,7 @@ fn parseInstruction(ass: *Assembler) !void {
536536 ass.inst.opcode = undefined;
537537 ass.inst.operands.clearRetainingCapacity();
538538 ass.inst.string_bytes.clearRetainingCapacity();
539 ass.inst.inst_offset = ass.currentToken().start;
539540
540541 const lhs_result_tok = ass.currentToken();
541542 const maybe_lhs_result: ?AsmValue.Ref = if (ass.eatToken(.result_id_assign)) blk: {
......@@ -589,8 +590,8 @@ fn parseInstruction(ass: *Assembler) !void {
589590 .required => if (ass.isAtInstructionBoundary()) {
590591 return ass.fail(
591592 ass.currentToken().start,
592 "missing required operand", // TODO: Operand name?
593 .{},
593 "missing required operand '{s}'",
594 .{@tagName(operand.kind)},
594595 );
595596 } else {
596597 try ass.parseOperand(operand.kind);
src/codegen/spirv/CodeGen.zig+2-2
......@@ -7280,7 +7280,7 @@ fn structuredBreak(cg: *CodeGen, target_block: Id) !void {
72807280 if (cg.block_terminated) return;
72817281
72827282 const gpa = cg.gpa;
7283 const sblock = cg.block_stack.getLast().?;
7283 const sblock = cg.block_stack.last().?;
72847284 const merge_block = switch (sblock.*) {
72857285 .selection => |*merge| blk: {
72867286 const merge_label = cg.allocId();
......@@ -7447,7 +7447,7 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index)
74477447 .operand_2 = this_block,
74487448 });
74497449
7450 const sblock = cg.block_stack.getLast().?;
7450 const sblock = cg.block_stack.last().?;
74517451
74527452 if (ty.isNoReturn(zcu)) {
74537453 // If this block is noreturn, this instruction is the last of a block,
src/codegen/spirv/Section.zig+6-3
......@@ -49,8 +49,9 @@ pub fn emitRaw(
4949 operand_words: usize,
5050) !void {
5151 const word_count = 1 + operand_words;
52 if (word_count > std.math.maxInt(u16)) return error.OutOfMemory;
5253 try section.instructions.ensureUnusedCapacity(allocator, word_count);
53 section.writeWord((@as(Word, @intCast(word_count << 16))) | @backingInt(opcode));
54 section.writeWord((@as(Word, @intCast(word_count)) << 16) | @backingInt(opcode));
5455}
5556
5657/// Write an entire instruction, including all operands
......@@ -70,7 +71,8 @@ pub fn emitAssumeCapacity(
7071 operands: opcode.Operands(),
7172) !void {
7273 const word_count = instructionSize(opcode, operands);
73 section.writeWord(@as(Word, @intCast(word_count << 16)) | @backingInt(opcode));
74 if (word_count > std.math.maxInt(u16)) return error.OutOfMemory;
75 section.writeWord((@as(Word, @intCast(word_count)) << 16) | @backingInt(opcode));
7476 section.writeOperands(opcode.Operands(), operands);
7577}
7678
......@@ -81,8 +83,9 @@ pub fn emit(
8183 operands: opcode.Operands(),
8284) !void {
8385 const word_count = instructionSize(opcode, operands);
86 if (word_count > std.math.maxInt(u16)) return error.OutOfMemory;
8487 try section.instructions.ensureUnusedCapacity(allocator, word_count);
85 section.writeWord(@as(Word, @intCast(word_count << 16)) | @backingInt(opcode));
88 section.writeWord((@as(Word, @intCast(word_count)) << 16) | @backingInt(opcode));
8689 section.writeOperands(opcode.Operands(), operands);
8790}
8891
src/codegen/wasm/CodeGen.zig+111-65
......@@ -24,12 +24,6 @@ const Alignment = InternPool.Alignment;
2424const errUnionPayloadOffset = codegen.errUnionPayloadOffset;
2525const errUnionErrorOffset = codegen.errUnionErrorOffset;
2626
27const target_util = @import("../../target.zig");
28const libcFloatPrefix = target_util.libcFloatPrefix;
29const libcFloatSuffix = target_util.libcFloatSuffix;
30const compilerRtFloatAbbrev = target_util.compilerRtFloatAbbrev;
31const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev;
32
3327pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
3428 return comptime &.initMany(&.{
3529 .expand_bit_cast_safe,
......@@ -573,7 +567,7 @@ fn addCallIntrinsic(cg: *CodeGen, intrinsic: Mir.Intrinsic) error{OutOfMemory}!v
573567/// Appends entries to `mir_extra` based on the type of `extra`.
574568/// Returns the index into `mir_extra`
575569fn addExtra(cg: *CodeGen, extra: anytype) error{OutOfMemory}!u32 {
576 const field_count = std.meta.fieldNames(@TypeOf(extra)).len;
570 const field_count = @typeInfo(@TypeOf(extra)).@"struct".field_names.len;
577571 try cg.mir_extra.ensureUnusedCapacity(cg.gpa, field_count);
578572 return cg.addExtraAssumeCapacity(extra);
579573}
......@@ -933,21 +927,26 @@ fn resolveCallingConventionValues(
933927 },
934928 .wasm_mvp => {
935929 for (fn_info.param_types.get(ip)) |ty| {
936 if (!Type.fromInterned(ty).hasRuntimeBits(zcu)) {
930 const param_ty: Type = .fromInterned(ty);
931 if (!param_ty.hasRuntimeBits(zcu)) {
937932 continue;
938933 }
939 switch (abi.classifyType(.fromInterned(ty), zcu)) {
940 .direct => |scalar_ty| if (!abi.lowerAsDoubleI64(scalar_ty, zcu)) {
934
935 switch (abi.classifyType(param_ty, zcu, target)) {
936 .direct, .indirect => {
941937 try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } });
942938 result.local_index += 1;
943 } else {
939 },
940 .double_i64 => {
944941 try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } });
945942 try args.append(.{ .local = .{ .value = result.local_index + 1, .references = 1 } });
946943 result.local_index += 2;
947944 },
948 .indirect => {
949 try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } });
950 result.local_index += 1;
945 .unrolled => |vector| {
946 for (0..vector.len) |_| {
947 try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } });
948 result.local_index += 1;
949 }
951950 },
952951 }
953952 }
......@@ -974,9 +973,10 @@ pub fn firstParamSRet(
974973 switch (cc) {
975974 .@"inline" => unreachable,
976975 .auto => return isByRef(return_type, zcu, target),
977 .wasm_mvp => switch (abi.classifyType(return_type, zcu)) {
978 .direct => |scalar_ty| return abi.lowerAsDoubleI64(scalar_ty, zcu),
979 .indirect => return true,
976 .wasm_mvp => switch (abi.classifyType(return_type, zcu, target)) {
977 .direct => return false,
978 .double_i64, .indirect => return true,
979 .unrolled => |vector| return vector.len > 1,
980980 },
981981 else => return false,
982982 }
......@@ -991,18 +991,15 @@ fn lowerArg(cg: *CodeGen, cc: std.lang.CallingConvention, ty: Type, value: WValu
991991
992992 const zcu = cg.pt.zcu;
993993
994 switch (abi.classifyType(ty, zcu)) {
995 .direct => |scalar_type| if (!abi.lowerAsDoubleI64(scalar_type, zcu)) {
994 switch (abi.classifyType(ty, zcu, cg.target)) {
995 .direct => |scalar_ty| {
996996 if (!isByRef(ty, zcu, cg.target)) {
997997 return cg.lowerToStack(value);
998998 } else {
999 switch (value) {
1000 .nav_ref, .stack_offset => _ = try cg.load(value, scalar_type, 0),
1001 .dead => unreachable,
1002 else => try cg.emitWValue(value),
1003 }
999 _ = try cg.load(value, scalar_ty, 0);
10041000 }
1005 } else {
1001 },
1002 .double_i64 => {
10061003 assert(ty.abiSize(zcu) == 16);
10071004 // in this case we have an integer or float that must be lowered as 2 i64's.
10081005 try cg.emitWValue(value);
......@@ -1010,7 +1007,17 @@ fn lowerArg(cg: *CodeGen, cc: std.lang.CallingConvention, ty: Type, value: WValu
10101007 try cg.emitWValue(value);
10111008 try cg.addMemArg(.i64_load, .{ .offset = value.offset() + 8, .alignment = 8 });
10121009 },
1013 .indirect => return cg.lowerToStack(value),
1010 .indirect => {
1011 const stack_copy = try cg.allocStack(ty);
1012 try cg.store(stack_copy, value, ty, 0);
1013 return cg.lowerToStack(stack_copy);
1014 },
1015 .unrolled => |vector| {
1016 const elem_size: u32 = @intCast(vector.elem_type.abiSize(zcu));
1017 for (0..vector.len) |index| {
1018 _ = try cg.load(value, vector.elem_type, @intCast(index * elem_size));
1019 }
1020 },
10141021 }
10151022}
10161023
......@@ -1953,16 +1960,19 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
19531960 if (cg.return_value != .none) {
19541961 try cg.store(cg.return_value, operand, ret_ty, 0);
19551962 } else if (fn_info.cc == .wasm_mvp and ret_ty.hasRuntimeBits(zcu)) {
1956 switch (abi.classifyType(ret_ty, zcu)) {
1963 switch (abi.classifyType(ret_ty, zcu, cg.target)) {
19571964 .direct => |scalar_type| {
1958 assert(!abi.lowerAsDoubleI64(scalar_type, zcu));
19591965 if (!isByRef(ret_ty, zcu, cg.target)) {
19601966 try cg.emitWValue(operand);
19611967 } else {
19621968 _ = try cg.load(operand, scalar_type, 0);
19631969 }
19641970 },
1965 .indirect => unreachable,
1971 .double_i64, .indirect => unreachable,
1972 .unrolled => |vector| {
1973 assert(vector.len == 1);
1974 _ = try cg.load(operand, vector.elem_type, 0);
1975 },
19661976 }
19671977 } else {
19681978 if (!ret_ty.hasRuntimeBits(zcu) and ret_ty.isError(zcu)) {
......@@ -2009,8 +2019,18 @@ fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
20092019 try cg.addImm32(0);
20102020 }
20112021 } else if (!firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), zcu, cg.target)) {
2012 // leave on the stack
2013 _ = try cg.load(operand, ret_ty, 0);
2022 if (fn_info.cc == .wasm_mvp) {
2023 switch (abi.classifyType(ret_ty, zcu, cg.target)) {
2024 .direct => |scalar_type| _ = try cg.load(operand, scalar_type, 0),
2025 .double_i64, .indirect => unreachable,
2026 .unrolled => |vector| {
2027 assert(vector.len == 1);
2028 _ = try cg.load(operand, vector.elem_type, 0);
2029 },
2030 }
2031 } else {
2032 _ = try cg.load(operand, ret_ty, 0);
2033 }
20142034 }
20152035
20162036 try cg.restoreStackPointer();
......@@ -2138,22 +2158,30 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier)
21382158 } else if (first_param_sret) {
21392159 break :result_value sret;
21402160 } else if (zcu.typeToFunc(fn_ty).?.cc == .wasm_mvp) {
2141 switch (abi.classifyType(ret_ty, zcu)) {
2161 switch (abi.classifyType(ret_ty, zcu, cg.target)) {
21422162 .direct => |scalar_type| {
2143 assert(!abi.lowerAsDoubleI64(scalar_type, zcu));
21442163 if (!isByRef(ret_ty, zcu, cg.target)) {
21452164 const result_local = try cg.allocLocal(ret_ty);
21462165 try cg.addLocal(.local_set, result_local.local.value);
21472166 break :result_value result_local;
21482167 } else {
2149 const result_local = try cg.allocLocal(ret_ty);
2168 const result_local = try cg.allocLocal(scalar_type);
21502169 try cg.addLocal(.local_set, result_local.local.value);
21512170 const result = try cg.allocStack(ret_ty);
21522171 try cg.store(result, result_local, scalar_type, 0);
21532172 break :result_value result;
21542173 }
21552174 },
2156 .indirect => unreachable,
2175 .double_i64, .indirect => unreachable,
2176 .unrolled => |vector| {
2177 assert(vector.len == 1);
2178 const result_local = try cg.allocLocal(vector.elem_type);
2179 // save call result from operand stack
2180 try cg.addLocal(.local_set, result_local.local.value);
2181 const result = try cg.allocStack(ret_ty);
2182 try cg.store(result, result_local, vector.elem_type, 0);
2183 break :result_value result;
2184 },
21572185 }
21582186 } else {
21592187 const result_local = try cg.allocLocal(ret_ty);
......@@ -2456,17 +2484,32 @@ fn airArg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
24562484 const cc = zcu.typeToFunc(zcu.navValue(cg.owner_nav).typeOf(zcu)).?.cc;
24572485 const arg_ty = cg.typeOfIndex(inst);
24582486 if (cc == .wasm_mvp) {
2459 switch (abi.classifyType(arg_ty, zcu)) {
2460 .direct => |scalar_ty| if (!abi.lowerAsDoubleI64(scalar_ty, zcu)) {
2487 switch (abi.classifyType(arg_ty, zcu, cg.target)) {
2488 .direct => |scalar_type| {
24612489 cg.arg_index += 1;
2462 } else {
2490 if (isByRef(arg_ty, zcu, cg.target)) {
2491 const result = try cg.allocStack(arg_ty);
2492 try cg.store(result, arg, scalar_type, 0);
2493 return cg.finishAir(inst, result, &.{});
2494 }
2495 },
2496 .indirect => cg.arg_index += 1,
2497 .double_i64 => {
24632498 cg.arg_index += 2;
24642499 const result = try cg.allocStack(arg_ty);
24652500 try cg.store(result, arg, Type.u64, 0);
24662501 try cg.store(result, cg.args[arg_index + 1], Type.u64, 8);
24672502 return cg.finishAir(inst, result, &.{});
24682503 },
2469 .indirect => cg.arg_index += 1,
2504 .unrolled => |vector| {
2505 const result = try cg.allocStack(arg_ty);
2506 const elem_size: u32 = @intCast(vector.elem_type.abiSize(zcu));
2507 for (0..vector.len) |index| {
2508 try cg.store(result, cg.args[cg.arg_index], vector.elem_type, @intCast(index * elem_size));
2509 cg.arg_index += 1;
2510 }
2511 return cg.finishAir(inst, result, &.{});
2512 },
24702513 }
24712514 } else {
24722515 cg.arg_index += 1;
......@@ -2515,15 +2558,15 @@ const IntType = struct {
25152558 .anyerror, .adhoc_inferred_error_set => .{ .is_signed = false, .bits = zcu.errorSetBits() },
25162559 .isize => .{ .is_signed = true, .bits = cg.target.ptrBitWidth() },
25172560 .usize => .{ .is_signed = false, .bits = cg.target.ptrBitWidth() },
2518 .c_char => .{ .is_signed = cg.target.cCharSignedness() == .signed, .bits = cg.target.cTypeBitSize(.char) },
2519 .c_short => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.short) },
2520 .c_ushort => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.short) },
2521 .c_int => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.int) },
2522 .c_uint => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.int) },
2523 .c_long => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.long) },
2524 .c_ulong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.long) },
2525 .c_longlong => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.longlong) },
2526 .c_ulonglong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.longlong) },
2561 .c_char => .{ .is_signed = cg.target.cCharSignedness().? == .signed, .bits = cg.target.cTypeBitSize(.char).? },
2562 .c_short => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.short).? },
2563 .c_ushort => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.short).? },
2564 .c_int => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.int).? },
2565 .c_uint => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.int).? },
2566 .c_long => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.long).? },
2567 .c_ulong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.long).? },
2568 .c_longlong => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.longlong).? },
2569 .c_ulonglong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.longlong).? },
25272570 .f16, .f32, .f64, .f80, .f128, .c_longdouble => unreachable,
25282571 .anyopaque, .void, .type, .comptime_int, .comptime_float, .noreturn, .null, .undefined, .enum_literal, .generic_poison => unreachable,
25292572 },
......@@ -4340,7 +4383,7 @@ fn floatRem(cg: *CodeGen, ty: FloatType, lhs: WValue, rhs: WValue) InnerError!WV
43404383 .f32 => return cg.callIntrinsic(.fmodf, &.{ .f32_type, .f32_type }, Type.f32, &.{ lhs, rhs }),
43414384 .f64 => return cg.callIntrinsic(.fmod, &.{ .f64_type, .f64_type }, Type.f64, &.{ lhs, rhs }),
43424385 .f80 => return cg.callIntrinsic(.__fmodx, &.{ .f80_type, .f80_type }, Type.f80, &.{ lhs, rhs }),
4343 .f128 => return cg.callIntrinsic(.fmodq, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }),
4386 .f128 => return cg.callIntrinsic(.fmodf128, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }),
43444387 }
43454388}
43464389
......@@ -4376,7 +4419,7 @@ fn floatMax(cg: *CodeGen, ty: FloatType, lhs: WValue, rhs: WValue) InnerError!WV
43764419 .f32 => return cg.callIntrinsic(.fmaxf, &.{ .f32_type, .f32_type }, Type.f32, &.{ lhs, rhs }),
43774420 .f64 => return cg.callIntrinsic(.fmax, &.{ .f64_type, .f64_type }, Type.f64, &.{ lhs, rhs }),
43784421 .f80 => return cg.callIntrinsic(.__fmaxx, &.{ .f80_type, .f80_type }, Type.f80, &.{ lhs, rhs }),
4379 .f128 => return cg.callIntrinsic(.fmaxq, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }),
4422 .f128 => return cg.callIntrinsic(.fmaxf128, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }),
43804423 }
43814424}
43824425
......@@ -4387,7 +4430,7 @@ fn floatMin(cg: *CodeGen, ty: FloatType, lhs: WValue, rhs: WValue) InnerError!WV
43874430 .f32 => return cg.callIntrinsic(.fminf, &.{ .f32_type, .f32_type }, Type.f32, &.{ lhs, rhs }),
43884431 .f64 => return cg.callIntrinsic(.fmin, &.{ .f64_type, .f64_type }, Type.f64, &.{ lhs, rhs }),
43894432 .f80 => return cg.callIntrinsic(.__fminx, &.{ .f80_type, .f80_type }, Type.f80, &.{ lhs, rhs }),
4390 .f128 => return cg.callIntrinsic(.fminq, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }),
4433 .f128 => return cg.callIntrinsic(.fminf128, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }),
43914434 }
43924435}
43934436
......@@ -4405,7 +4448,7 @@ fn floatSqrt(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
44054448 return .stack;
44064449 },
44074450 .f80 => return cg.callIntrinsic(.__sqrtx, &.{.f80_type}, Type.f80, &.{arg}),
4408 .f128 => return cg.callIntrinsic(.sqrtq, &.{.f128_type}, Type.f128, &.{arg}),
4451 .f128 => return cg.callIntrinsic(.sqrtf128, &.{.f128_type}, Type.f128, &.{arg}),
44094452 }
44104453}
44114454
......@@ -4415,7 +4458,7 @@ fn floatSin(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
44154458 .f32 => return cg.callIntrinsic(.sinf, &.{.f32_type}, Type.f32, &.{arg}),
44164459 .f64 => return cg.callIntrinsic(.sin, &.{.f64_type}, Type.f64, &.{arg}),
44174460 .f80 => return cg.callIntrinsic(.__sinx, &.{.f80_type}, Type.f80, &.{arg}),
4418 .f128 => return cg.callIntrinsic(.sinq, &.{.f128_type}, Type.f128, &.{arg}),
4461 .f128 => return cg.callIntrinsic(.sinf128, &.{.f128_type}, Type.f128, &.{arg}),
44194462 }
44204463}
44214464
......@@ -4425,7 +4468,7 @@ fn floatCos(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
44254468 .f32 => return cg.callIntrinsic(.cosf, &.{.f32_type}, Type.f32, &.{arg}),
44264469 .f64 => return cg.callIntrinsic(.cos, &.{.f64_type}, Type.f64, &.{arg}),
44274470 .f80 => return cg.callIntrinsic(.__cosx, &.{.f80_type}, Type.f80, &.{arg}),
4428 .f128 => return cg.callIntrinsic(.cosq, &.{.f128_type}, Type.f128, &.{arg}),
4471 .f128 => return cg.callIntrinsic(.cosf128, &.{.f128_type}, Type.f128, &.{arg}),
44294472 }
44304473}
44314474
......@@ -4435,7 +4478,7 @@ fn floatTan(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
44354478 .f32 => return cg.callIntrinsic(.tanf, &.{.f32_type}, Type.f32, &.{arg}),
44364479 .f64 => return cg.callIntrinsic(.tan, &.{.f64_type}, Type.f64, &.{arg}),
44374480 .f80 => return cg.callIntrinsic(.__tanx, &.{.f80_type}, Type.f80, &.{arg}),
4438 .f128 => return cg.callIntrinsic(.tanq, &.{.f128_type}, Type.f128, &.{arg}),
4481 .f128 => return cg.callIntrinsic(.tanf128, &.{.f128_type}, Type.f128, &.{arg}),
44394482 }
44404483}
44414484
......@@ -4445,7 +4488,7 @@ fn floatExp(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
44454488 .f32 => return cg.callIntrinsic(.expf, &.{.f32_type}, Type.f32, &.{arg}),
44464489 .f64 => return cg.callIntrinsic(.exp, &.{.f64_type}, Type.f64, &.{arg}),
44474490 .f80 => return cg.callIntrinsic(.__expx, &.{.f80_type}, Type.f80, &.{arg}),
4448 .f128 => return cg.callIntrinsic(.expq, &.{.f128_type}, Type.f128, &.{arg}),
4491 .f128 => return cg.callIntrinsic(.expf128, &.{.f128_type}, Type.f128, &.{arg}),
44494492 }
44504493}
44514494
......@@ -4455,7 +4498,7 @@ fn floatExp2(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
44554498 .f32 => return cg.callIntrinsic(.exp2f, &.{.f32_type}, Type.f32, &.{arg}),
44564499 .f64 => return cg.callIntrinsic(.exp2, &.{.f64_type}, Type.f64, &.{arg}),
44574500 .f80 => return cg.callIntrinsic(.__exp2x, &.{.f80_type}, Type.f80, &.{arg}),
4458 .f128 => return cg.callIntrinsic(.exp2q, &.{.f128_type}, Type.f128, &.{arg}),
4501 .f128 => return cg.callIntrinsic(.exp2f128, &.{.f128_type}, Type.f128, &.{arg}),
44594502 }
44604503}
44614504
......@@ -4465,7 +4508,7 @@ fn floatLog(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
44654508 .f32 => return cg.callIntrinsic(.logf, &.{.f32_type}, Type.f32, &.{arg}),
44664509 .f64 => return cg.callIntrinsic(.log, &.{.f64_type}, Type.f64, &.{arg}),
44674510 .f80 => return cg.callIntrinsic(.__logx, &.{.f80_type}, Type.f80, &.{arg}),
4468 .f128 => return cg.callIntrinsic(.logq, &.{.f128_type}, Type.f128, &.{arg}),
4511 .f128 => return cg.callIntrinsic(.logf128, &.{.f128_type}, Type.f128, &.{arg}),
44694512 }
44704513}
44714514
......@@ -4475,7 +4518,7 @@ fn floatLog2(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
44754518 .f32 => return cg.callIntrinsic(.log2f, &.{.f32_type}, Type.f32, &.{arg}),
44764519 .f64 => return cg.callIntrinsic(.log2, &.{.f64_type}, Type.f64, &.{arg}),
44774520 .f80 => return cg.callIntrinsic(.__log2x, &.{.f80_type}, Type.f80, &.{arg}),
4478 .f128 => return cg.callIntrinsic(.log2q, &.{.f128_type}, Type.f128, &.{arg}),
4521 .f128 => return cg.callIntrinsic(.log2f128, &.{.f128_type}, Type.f128, &.{arg}),
44794522 }
44804523}
44814524
......@@ -4485,7 +4528,7 @@ fn floatLog10(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
44854528 .f32 => return cg.callIntrinsic(.log10f, &.{.f32_type}, Type.f32, &.{arg}),
44864529 .f64 => return cg.callIntrinsic(.log10, &.{.f64_type}, Type.f64, &.{arg}),
44874530 .f80 => return cg.callIntrinsic(.__log10x, &.{.f80_type}, Type.f80, &.{arg}),
4488 .f128 => return cg.callIntrinsic(.log10q, &.{.f128_type}, Type.f128, &.{arg}),
4531 .f128 => return cg.callIntrinsic(.log10f128, &.{.f128_type}, Type.f128, &.{arg}),
44894532 }
44904533}
44914534
......@@ -4503,7 +4546,7 @@ fn floatFloor(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
45034546 return .stack;
45044547 },
45054548 .f80 => return cg.callIntrinsic(.__floorx, &.{.f80_type}, Type.f80, &.{arg}),
4506 .f128 => return cg.callIntrinsic(.floorq, &.{.f128_type}, Type.f128, &.{arg}),
4549 .f128 => return cg.callIntrinsic(.floorf128, &.{.f128_type}, Type.f128, &.{arg}),
45074550 }
45084551}
45094552
......@@ -4521,7 +4564,7 @@ fn floatCeil(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
45214564 return .stack;
45224565 },
45234566 .f80 => return cg.callIntrinsic(.__ceilx, &.{.f80_type}, Type.f80, &.{arg}),
4524 .f128 => return cg.callIntrinsic(.ceilq, &.{.f128_type}, Type.f128, &.{arg}),
4567 .f128 => return cg.callIntrinsic(.ceilf128, &.{.f128_type}, Type.f128, &.{arg}),
45254568 }
45264569}
45274570
......@@ -4539,7 +4582,7 @@ fn floatRound(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
45394582 return .stack;
45404583 },
45414584 .f80 => return cg.callIntrinsic(.__roundx, &.{.f80_type}, Type.f80, &.{arg}),
4542 .f128 => return cg.callIntrinsic(.roundq, &.{.f128_type}, Type.f128, &.{arg}),
4585 .f128 => return cg.callIntrinsic(.roundf128, &.{.f128_type}, Type.f128, &.{arg}),
45434586 }
45444587}
45454588
......@@ -4557,7 +4600,7 @@ fn floatTrunc(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
45574600 return .stack;
45584601 },
45594602 .f80 => return cg.callIntrinsic(.__truncx, &.{.f80_type}, Type.f80, &.{arg}),
4560 .f128 => return cg.callIntrinsic(.truncq, &.{.f128_type}, Type.f128, &.{arg}),
4603 .f128 => return cg.callIntrinsic(.truncf128, &.{.f128_type}, Type.f128, &.{arg}),
45614604 }
45624605}
45634606
......@@ -4929,7 +4972,8 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro
49294972 const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr;
49304973 const offset: u64 = prev_offset + ptr.byte_offset;
49314974 return switch (ptr.base_addr) {
4932 .nav => |nav| return if (Type.fromInterned(ip.getNav(nav).resolved.?.type).isRuntimeFnOrHasRuntimeBits(zcu))
4975 .nav => |nav| return if (ip.getNav(nav).getExtern(ip) != null or
4976 Type.fromInterned(ip.getNav(nav).resolved.?.type).isRuntimeFnOrHasRuntimeBits(zcu))
49334977 .{ .nav_ref = .{ .nav_index = nav, .offset = @intCast(offset) } }
49344978 else
49354979 .{ .imm32 = @intCast(zcu.navAlignment(nav).forward(@as(u32, 0xaaaaaaaa))) },
......@@ -5613,6 +5657,8 @@ fn bitcastClass(cg: *CodeGen, ty: Type) BitcastClass {
56135657}
56145658
56155659fn bitcast(cg: *CodeGen, dest_ty: Type, src_ty: Type, operand: WValue) InnerError!?WValue {
5660 if (dest_ty.eql(src_ty)) return null;
5661
56165662 const zcu = cg.pt.zcu;
56175663 const src_class = cg.bitcastClass(src_ty);
56185664 const dest_class = cg.bitcastClass(dest_ty);
src/codegen/wasm/Emit.zig+125-49
......@@ -21,7 +21,7 @@ pub const Error = error{
2121 OutOfMemory,
2222};
2323
24pub fn lowerToCode(emit: *Emit) Error!void {
24pub fn lower(emit: *Emit) Error!void {
2525 const mir = &emit.mir;
2626 const code = emit.code;
2727 const wasm = emit.wasm;
......@@ -31,6 +31,47 @@ pub fn lowerToCode(emit: *Emit) Error!void {
3131 const target = &comp.root_mod.resolved_target.result;
3232 const is_wasm32 = target.cpu.arch == .wasm32;
3333
34 // Write the locals in the prologue of the function body.
35 try code.ensureUnusedCapacity(gpa, 5 + mir.locals.len * 6 + 38);
36
37 writeUleb128(code, @as(u32, @intCast(mir.locals.len)));
38
39 for (mir.locals) |local| {
40 writeUleb128(code, @as(u32, 1));
41 code.appendAssumeCapacity(@backingInt(local));
42 }
43
44 // Stack management section of function prologue.
45 const stack_alignment = mir.prologue.flags.stack_alignment;
46 if (stack_alignment.toByteUnits()) |align_bytes| {
47 // load stack pointer
48 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.global_get));
49 try appendStackPointerGlobalIndex(wasm, code, is_obj);
50 // store stack pointer so we can restore it when we return from the function
51 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.local_tee));
52 writeUleb128(code, mir.prologue.sp_local);
53 // get the total stack size
54 const aligned_stack: i32 = @intCast(stack_alignment.forward(mir.prologue.stack_size));
55 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.i32_const));
56 writeSleb128(code, aligned_stack);
57 // subtract it from the current stack pointer
58 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.i32_sub));
59 // Get negative stack alignment
60 const neg_stack_align = @as(i32, @intCast(align_bytes)) * -1;
61 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.i32_const));
62 writeSleb128(code, neg_stack_align);
63 // Bitwise-and the value to get the new stack pointer to ensure the
64 // pointers are aligned with the abi alignment.
65 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.i32_and));
66 // The bottom will be used to calculate all stack pointer offsets.
67 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.local_tee));
68 writeUleb128(code, mir.prologue.bottom_stack_local);
69 // Store the current stack pointer value into the global stack pointer so other function calls will
70 // start from this value instead and not overwrite the current stack.
71 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.global_set));
72 try appendStackPointerGlobalIndex(wasm, code, is_obj);
73 }
74
3475 const tags = mir.instructions.items(.tag);
3576 const datas = mir.instructions.items(.data);
3677 var inst: u32 = 0;
......@@ -78,14 +119,21 @@ pub fn lowerToCode(emit: *Emit) Error!void {
78119 continue :loop tags[inst];
79120 },
80121 .func_ref => {
81 const indirect_func_idx: Wasm.ZcuIndirectFunctionSetIndex = @fromBackingInt(@intCast(
82 wasm.zcu_indirect_function_set.getIndex(datas[inst].nav_index).?,
83 ));
84 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.i32_const));
122 try code.ensureUnusedCapacity(gpa, 11);
123 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;
124 code.appendAssumeCapacity(@backingInt(opcode));
85125 if (is_obj) {
86 @panic("TODO");
126 try wasm.zcu_relocations.append(gpa, .{
127 .offset = @intCast(code.items.len),
128 .pointee = .{ .function_nav = datas[inst].nav_index },
129 .tag = if (is_wasm32) .table_index_sleb else .table_index_sleb64,
130 .addend = 0,
131 });
132 appendSlebRelocPlaceholder(code, is_wasm32);
87133 } else {
88 writeSleb128(code, 1 + @backingInt(indirect_func_idx));
134 const function_index = Wasm.OutputFunctionIndex.fromIpNav(wasm, datas[inst].nav_index);
135 const table_index = wasm.flush_buffer.indirect_function_table.getIndex(function_index).? + 1;
136 writeSleb128(code, table_index);
89137 }
90138 inst += 1;
91139 continue :loop tags[inst];
......@@ -105,18 +153,17 @@ pub fn lowerToCode(emit: *Emit) Error!void {
105153 continue :loop tags[inst];
106154 },
107155 .error_name_table_ref => {
108 wasm.error_name_table_ref_count += 1;
109156 try code.ensureUnusedCapacity(gpa, 11);
110157 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;
111158 code.appendAssumeCapacity(@backingInt(opcode));
112159 if (is_obj) {
113 try wasm.out_relocs.append(gpa, .{
160 try wasm.zcu_relocations.append(gpa, .{
114161 .offset = @intCast(code.items.len),
115 .pointee = .{ .symbol_index = try wasm.errorNameTableSymbolIndex() },
116 .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64,
162 .pointee = .{ .data_resolution = .__zig_error_name_table },
163 .tag = if (is_wasm32) .memory_addr_sleb else .memory_addr_sleb64,
117164 .addend = 0,
118165 });
119 code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10);
166 appendSlebRelocPlaceholder(code, is_wasm32);
120167
121168 inst += 1;
122169 continue :loop tags[inst];
......@@ -164,13 +211,13 @@ pub fn lowerToCode(emit: *Emit) Error!void {
164211 try code.ensureUnusedCapacity(gpa, 6);
165212 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call));
166213 if (is_obj) {
167 try wasm.out_relocs.append(gpa, .{
214 try wasm.zcu_relocations.append(gpa, .{
168215 .offset = @intCast(code.items.len),
169 .pointee = .{ .symbol_index = try wasm.navSymbolIndex(datas[inst].nav_index) },
216 .pointee = .{ .function_nav = datas[inst].nav_index },
170217 .tag = .function_index_leb,
171218 .addend = 0,
172219 });
173 code.appendNTimesAssumeCapacity(0, 5);
220 appendUlebRelocPlaceholder(code);
174221 } else {
175222 appendOutputFunctionIndex(code, .fromIpNav(wasm, datas[inst].nav_index));
176223 }
......@@ -191,13 +238,13 @@ pub fn lowerToCode(emit: *Emit) Error!void {
191238 ).?;
192239 if (is_obj) {
193240 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call_indirect));
194 try wasm.out_relocs.append(gpa, .{
241 try wasm.zcu_relocations.append(gpa, .{
195242 .offset = @intCast(code.items.len),
196243 .pointee = .{ .type_index = func_ty_index },
197244 .tag = .type_index_leb,
198245 .addend = 0,
199246 });
200 code.appendNTimesAssumeCapacity(0, 5);
247 appendUlebRelocPlaceholder(code);
201248 } else {
202249 const index: Wasm.Flush.FuncTypeIndex = @fromBackingInt(@intCast(wasm.flush_buffer.func_types.getIndex(func_ty_index) orelse {
203250 // In this case we tried to call a function pointer for
......@@ -224,13 +271,13 @@ pub fn lowerToCode(emit: *Emit) Error!void {
224271 try code.ensureUnusedCapacity(gpa, 6);
225272 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call));
226273 if (is_obj) {
227 try wasm.out_relocs.append(gpa, .{
274 try wasm.zcu_relocations.append(gpa, .{
228275 .offset = @intCast(code.items.len),
229 .pointee = .{ .symbol_index = try wasm.tagTableIndexSymbolIndex(datas[inst].ip_index) },
276 .pointee = .{ .tag_function = datas[inst].ip_index },
230277 .tag = .function_index_leb,
231278 .addend = 0,
232279 });
233 code.appendNTimesAssumeCapacity(0, 5);
280 appendUlebRelocPlaceholder(code);
234281 } else {
235282 appendOutputFunctionIndex(code, .fromTagIndexType(wasm, datas[inst].ip_index));
236283 }
......@@ -244,14 +291,20 @@ pub fn lowerToCode(emit: *Emit) Error!void {
244291 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;
245292 code.appendAssumeCapacity(@backingInt(opcode));
246293 if (is_obj) {
247 @panic("TODO");
294 try wasm.zcu_relocations.append(gpa, .{
295 .offset = @intCast(code.items.len),
296 .pointee = .{ .data_resolution = .__zig_tag_name_table },
297 .tag = if (is_wasm32) .memory_addr_sleb else .memory_addr_sleb64,
298 .addend = @intCast(wasm.tagIndexTableOffset(datas[inst].ip_index)),
299 });
300 appendSlebRelocPlaceholder(code, is_wasm32);
248301 } else {
249302 const addr: u32 = wasm.tagIndexTableAddr(datas[inst].ip_index);
250303 writeSleb128(code, addr);
251
252 inst += 1;
253 continue :loop tags[inst];
254304 }
305
306 inst += 1;
307 continue :loop tags[inst];
255308 },
256309
257310 .call_intrinsic => {
......@@ -263,13 +316,13 @@ pub fn lowerToCode(emit: *Emit) Error!void {
263316 try code.ensureUnusedCapacity(gpa, 6);
264317 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call));
265318 if (is_obj) {
266 try wasm.out_relocs.append(gpa, .{
319 try wasm.zcu_relocations.append(gpa, .{
267320 .offset = @intCast(code.items.len),
268 .pointee = .{ .symbol_index = try wasm.symbolNameIndex(symbol_name) },
321 .pointee = .{ .function_name = symbol_name },
269322 .tag = .function_index_leb,
270323 .addend = 0,
271324 });
272 code.appendNTimesAssumeCapacity(0, 5);
325 appendUlebRelocPlaceholder(code);
273326 } else {
274327 appendOutputFunctionIndex(code, .fromSymbolName(wasm, symbol_name));
275328 }
......@@ -281,18 +334,7 @@ pub fn lowerToCode(emit: *Emit) Error!void {
281334 .global_set_sp => {
282335 try code.ensureUnusedCapacity(gpa, 6);
283336 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.global_set));
284 if (is_obj) {
285 try wasm.out_relocs.append(gpa, .{
286 .offset = @intCast(code.items.len),
287 .pointee = .{ .symbol_index = try wasm.stackPointerSymbolIndex() },
288 .tag = .global_index_leb,
289 .addend = 0,
290 });
291 code.appendNTimesAssumeCapacity(0, 5);
292 } else {
293 const sp_global: Wasm.GlobalIndex = .stack_pointer;
294 writeUleb128(code, @backingInt(sp_global));
295 }
337 try appendStackPointerGlobalIndex(wasm, code, is_obj);
296338
297339 inst += 1;
298340 continue :loop tags[inst];
......@@ -960,13 +1002,13 @@ fn uavRefObj(wasm: *Wasm, code: *ArrayList(u8), value: InternPool.Index, offset:
9601002 try code.ensureUnusedCapacity(gpa, 11);
9611003 code.appendAssumeCapacity(@backingInt(opcode));
9621004
963 try wasm.out_relocs.append(gpa, .{
1005 try wasm.zcu_relocations.append(gpa, .{
9641006 .offset = @intCast(code.items.len),
965 .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(value) },
966 .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64,
1007 .pointee = .{ .data_uav = value },
1008 .tag = if (is_wasm32) .memory_addr_sleb else .memory_addr_sleb64,
9671009 .addend = offset,
9681010 });
969 code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10);
1011 appendSlebRelocPlaceholder(code, is_wasm32);
9701012}
9711013
9721014fn uavRefExe(wasm: *Wasm, code: *ArrayList(u8), value: InternPool.Index, offset: i32, is_wasm32: bool) !void {
......@@ -978,7 +1020,7 @@ fn uavRefExe(wasm: *Wasm, code: *ArrayList(u8), value: InternPool.Index, offset:
9781020 code.appendAssumeCapacity(@backingInt(opcode));
9791021
9801022 const addr = wasm.uavAddr(value);
981 writeUleb128(code, @as(u32, @intCast(@as(i64, addr) + offset)));
1023 writeSleb128(code, @as(u32, @intCast(@as(i64, addr) + offset)));
9821024}
9831025
9841026fn navRefOff(wasm: *Wasm, code: *ArrayList(u8), data: Mir.NavRefOff, is_wasm32: bool) !void {
......@@ -995,16 +1037,16 @@ fn navRefOff(wasm: *Wasm, code: *ArrayList(u8), data: Mir.NavRefOff, is_wasm32:
9951037 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;
9961038 code.appendAssumeCapacity(@backingInt(opcode));
9971039 if (is_obj) {
998 try wasm.out_relocs.append(gpa, .{
1040 try wasm.zcu_relocations.append(gpa, .{
9991041 .offset = @intCast(code.items.len),
1000 .pointee = .{ .symbol_index = try wasm.navSymbolIndex(data.nav_index) },
1001 .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64,
1042 .pointee = .{ .data_nav = data.nav_index },
1043 .tag = if (is_wasm32) .memory_addr_sleb else .memory_addr_sleb64,
10021044 .addend = data.offset,
10031045 });
1004 code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10);
1046 appendSlebRelocPlaceholder(code, is_wasm32);
10051047 } else {
10061048 const addr = wasm.navAddr(data.nav_index);
1007 writeUleb128(code, @as(u32, @intCast(@as(i64, addr) + data.offset)));
1049 writeSleb128(code, @as(u32, @intCast(@as(i64, addr) + data.offset)));
10081050 }
10091051}
10101052
......@@ -1012,6 +1054,40 @@ fn appendOutputFunctionIndex(code: *ArrayList(u8), i: Wasm.OutputFunctionIndex)
10121054 writeUleb128(code, @backingInt(i));
10131055}
10141056
1057fn appendStackPointerGlobalIndex(
1058 wasm: *Wasm,
1059 code: *ArrayList(u8),
1060 is_obj: bool,
1061) Error!void {
1062 if (is_obj) {
1063 try wasm.zcu_relocations.append(wasm.base.comp.gpa, .{
1064 .offset = @intCast(code.items.len),
1065 .pointee = .stack_pointer,
1066 .tag = .global_index_leb,
1067 .addend = 0,
1068 });
1069 appendUlebRelocPlaceholder(code);
1070 } else {
1071 const sp_global: Wasm.GlobalIndex = .stack_pointer;
1072 writeUleb128(code, @backingInt(sp_global));
1073 }
1074}
1075
1076fn appendUlebRelocPlaceholder(code: *ArrayList(u8)) void {
1077 code.appendSliceAssumeCapacity(&.{ 0x80, 0x80, 0x80, 0x80, 0x00 });
1078}
1079
1080fn appendSlebRelocPlaceholder(code: *ArrayList(u8), is_wasm32: bool) void {
1081 if (is_wasm32) {
1082 code.appendSliceAssumeCapacity(&.{ 0x80, 0x80, 0x80, 0x80, 0x00 });
1083 } else {
1084 code.appendSliceAssumeCapacity(&.{
1085 0x80, 0x80, 0x80, 0x80, 0x80,
1086 0x80, 0x80, 0x80, 0x80, 0x00,
1087 });
1088 }
1089}
1090
10151091fn writeUleb128(code: *ArrayList(u8), arg: anytype) void {
10161092 var w: std.Io.Writer = .fixed(code.unusedCapacitySlice());
10171093 w.writeUleb128(arg) catch unreachable;
src/codegen/wasm/Mir.zig+22-70
......@@ -114,7 +114,7 @@ pub const Inst = struct {
114114 ///
115115 /// Uses `payload` pointing to a `NavRefOff`.
116116 nav_ref_off,
117 /// Lowers to an i32_const which is the index of the function in the
117 /// Lowers to an iNN_const which is the index of the function in the
118118 /// table section.
119119 ///
120120 /// Uses `nav_index`.
......@@ -661,8 +661,8 @@ pub const Inst = struct {
661661
662662 comptime {
663663 switch (builtin.mode) {
664 .Debug, .ReleaseSafe => {},
665 .ReleaseFast, .ReleaseSmall => assert(@sizeOf(Data) == 4),
664 .debug, .safe => {},
665 .fast, .small => assert(@sizeOf(Data) == 4),
666666 }
667667 }
668668 };
......@@ -679,60 +679,12 @@ pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
679679}
680680
681681pub fn lower(mir: *const Mir, wasm: *Wasm, code: *std.ArrayList(u8)) std.mem.Allocator.Error!void {
682 const gpa = wasm.base.comp.gpa;
683
684 // Write the locals in the prologue of the function body.
685 try code.ensureUnusedCapacity(gpa, 5 + mir.locals.len * 6 + 38);
686
687 var w: std.Io.Writer = .fixed(code.unusedCapacitySlice());
688
689 w.writeLeb128(@as(u32, @intCast(mir.locals.len))) catch unreachable;
690
691 for (mir.locals) |local| {
692 w.writeLeb128(@as(u32, 1)) catch unreachable;
693 w.writeByte(@backingInt(local)) catch unreachable;
694 }
695
696 // Stack management section of function prologue.
697 const stack_alignment = mir.prologue.flags.stack_alignment;
698 if (stack_alignment.toByteUnits()) |align_bytes| {
699 const sp_global: Wasm.GlobalIndex = .stack_pointer;
700 // load stack pointer
701 w.writeByte(@backingInt(std.wasm.Opcode.global_get)) catch unreachable;
702 w.writeUleb128(@backingInt(sp_global)) catch unreachable;
703 // store stack pointer so we can restore it when we return from the function
704 w.writeByte(@backingInt(std.wasm.Opcode.local_tee)) catch unreachable;
705 w.writeUleb128(mir.prologue.sp_local) catch unreachable;
706 // get the total stack size
707 const aligned_stack: i32 = @intCast(stack_alignment.forward(mir.prologue.stack_size));
708 w.writeByte(@backingInt(std.wasm.Opcode.i32_const)) catch unreachable;
709 w.writeSleb128(aligned_stack) catch unreachable;
710 // subtract it from the current stack pointer
711 w.writeByte(@backingInt(std.wasm.Opcode.i32_sub)) catch unreachable;
712 // Get negative stack alignment
713 const neg_stack_align = @as(i32, @intCast(align_bytes)) * -1;
714 w.writeByte(@backingInt(std.wasm.Opcode.i32_const)) catch unreachable;
715 w.writeSleb128(neg_stack_align) catch unreachable;
716 // Bitwise-and the value to get the new stack pointer to ensure the
717 // pointers are aligned with the abi alignment.
718 w.writeByte(@backingInt(std.wasm.Opcode.i32_and)) catch unreachable;
719 // The bottom will be used to calculate all stack pointer offsets.
720 w.writeByte(@backingInt(std.wasm.Opcode.local_tee)) catch unreachable;
721 w.writeUleb128(mir.prologue.bottom_stack_local) catch unreachable;
722 // Store the current stack pointer value into the global stack pointer so other function calls will
723 // start from this value instead and not overwrite the current stack.
724 w.writeByte(@backingInt(std.wasm.Opcode.global_set)) catch unreachable;
725 w.writeUleb128(@backingInt(sp_global)) catch unreachable;
726 }
727
728 code.items.len += w.end;
729
730682 var emit: Emit = .{
731683 .mir = mir.*,
732684 .wasm = wasm,
733685 .code = code,
734686 };
735 try emit.lowerToCode();
687 try emit.lower();
736688}
737689
738690pub fn extraData(self: *const Mir, comptime T: type, index: usize) struct { data: T, end: usize } {
......@@ -991,48 +943,48 @@ pub const Intrinsic = enum(u32) {
991943 __udivti3,
992944 __umodei5,
993945 __umodti3,
994 ceilq,
946 ceilf128,
995947 cos,
996948 cosf,
997 cosq,
949 cosf128,
998950 exp,
999951 exp2,
1000952 exp2f,
1001 exp2q,
953 exp2f128,
1002954 expf,
1003 expq,
1004 fabsq,
1005 floorq,
955 expf128,
956 fabsf128,
957 floorf128,
1006958 fma,
1007959 fmaf,
1008 fmaq,
960 fmaf128,
1009961 fmax,
1010962 fmaxf,
1011 fmaxq,
963 fmaxf128,
1012964 fmin,
1013965 fminf,
1014 fminq,
966 fminf128,
1015967 fmod,
1016968 fmodf,
1017 fmodq,
969 fmodf128,
1018970 log,
1019971 log10,
1020972 log10f,
1021 log10q,
973 log10f128,
1022974 log2,
1023975 log2f,
1024 log2q,
976 log2f128,
1025977 logf,
1026 logq,
1027 roundq,
978 logf128,
979 roundf128,
1028980 sin,
1029981 sinf,
1030 sinq,
1031 sqrtq,
982 sinf128,
983 sqrtf128,
1032984 tan,
1033985 tanf,
1034 tanq,
1035 truncq,
986 tanf128,
987 truncf128,
1036988 memcpy,
1037989 memmove,
1038990 memset,
src/codegen/wasm/abi.zig+72-22
......@@ -11,21 +11,53 @@ const assert = std.debug.assert;
1111const Type = @import("../../Type.zig");
1212const Zcu = @import("../../Zcu.zig");
1313
14/// Defines how to pass a type as part of a function signature,
15/// both for parameters as well as return values.
14/// Describes how the Wasm backend represents a C ABI value.
1615pub const Class = union(enum) {
1716 direct: Type,
17 double_i64,
1818 indirect,
19 unrolled: struct {
20 elem_type: Type,
21 len: u32,
22 },
1923};
2024
21/// Classifies a given Zig type to determine how they must be passed
22/// or returned as value within a wasm function.
23pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
25pub const LlvmClass = union(enum) {
26 direct: Type,
27 indirect,
28};
29
30pub fn classifyType(ty: Type, zcu: *const Zcu, target: *const Target) Class {
31 if (ty.zigTypeTag(zcu) == .vector) {
32 if (!(ty.bitSize(zcu) == 128 and target.cpu.has(.wasm, .simd128))) {
33 const elem_type = ty.childType(zcu);
34 return .{ .unrolled = .{
35 .elem_type = elem_type,
36 .len = ty.vectorLen(zcu),
37 } };
38 }
39 return .{ .direct = ty };
40 }
41
42 return switch (classifyTypeForLlvm(ty, zcu)) {
43 .direct => |scalar_ty| if (scalar_ty.bitSize(zcu) > 64)
44 .double_i64
45 else
46 .{ .direct = scalar_ty },
47 .indirect => .indirect,
48 };
49}
50
51pub fn classifyTypeForLlvm(ty: Type, zcu: *const Zcu) LlvmClass {
2452 const ip = &zcu.intern_pool;
2553 assert(ty.hasRuntimeBits(zcu));
2654 switch (ty.zigTypeTag(zcu)) {
2755 .int, .@"enum", .error_set => return .{ .direct = ty },
28 .float => return .{ .direct = ty },
56 .float => return switch (ty.floatBits(zcu.getTarget())) {
57 else => unreachable,
58 16, 32, 64, 128 => .{ .direct = ty },
59 80 => .indirect,
60 },
2961 .bool => return .{ .direct = ty },
3062 .vector => return .{ .direct = ty },
3163 .array => return .indirect,
......@@ -39,20 +71,35 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
3971 },
4072 .@"struct" => {
4173 const struct_type = zcu.typeToStruct(ty).?;
42 if (struct_type.layout == .@"packed") {
43 return .{ .direct = ty };
44 }
45 if (struct_type.field_types.len > 1) {
46 // The struct type is non-scalar.
47 return .indirect;
74 switch (struct_type.layout) {
75 .auto => unreachable,
76 .@"packed" => return .{ .direct = ty },
77 .@"extern" => {},
4878 }
49 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[0]);
50 const explicit_align = struct_type.field_aligns.getOrNone(ip, 0);
51 if (explicit_align != .none) {
52 if (explicit_align.compareStrict(.gt, field_ty.abiAlignment(zcu)))
79 var opt_single_field_ty: ?Type = null;
80 for (struct_type.field_types.get(ip), 0..) |field_ty_index, field_index| {
81 const field_ty: Type = .fromInterned(field_ty_index);
82 if (!field_ty.hasRuntimeBits(zcu)) continue;
83
84 if (opt_single_field_ty != null) {
85 return .indirect;
86 }
87
88 const field_align = struct_type.field_aligns.getOrNone(ip, field_index);
89 if (field_align != .none and field_align.compareStrict(.gt, field_ty.abiAlignment(zcu))) {
5390 return .indirect;
91 }
92 opt_single_field_ty = field_ty;
5493 }
55 return classifyType(field_ty, zcu);
94 const single_field_ty = opt_single_field_ty.?;
95 if (single_field_ty.zigTypeTag(zcu) == .array) {
96 switch (single_field_ty.arrayLenIncludingSentinel(zcu)) {
97 0 => unreachable,
98 1 => return classifyTypeForLlvm(single_field_ty.childType(zcu), zcu),
99 else => {},
100 }
101 }
102 return classifyTypeForLlvm(single_field_ty, zcu);
56103 },
57104 .@"union" => {
58105 const union_obj = zcu.typeToUnion(ty).?;
......@@ -63,7 +110,14 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
63110 assert(layout.tag_size == 0);
64111 if (union_obj.field_types.len > 1) return .indirect;
65112 const first_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]);
66 return classifyType(first_field_ty, zcu);
113 if (first_field_ty.zigTypeTag(zcu) == .array) {
114 switch (first_field_ty.arrayLenIncludingSentinel(zcu)) {
115 0 => unreachable,
116 1 => return classifyTypeForLlvm(first_field_ty.childType(zcu), zcu),
117 else => {},
118 }
119 }
120 return classifyTypeForLlvm(first_field_ty, zcu);
67121 },
68122 .error_union,
69123 .frame,
......@@ -82,7 +136,3 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
82136 => unreachable,
83137 }
84138}
85
86pub fn lowerAsDoubleI64(scalar_ty: Type, zcu: *const Zcu) bool {
87 return scalar_ty.bitSize(zcu) > 64;
88}
src/codegen/x86_64/CodeGen.zig+194-312
......@@ -1301,7 +1301,7 @@ fn addInst(self: *CodeGen, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {
13011301}
13021302
13031303fn addExtra(self: *CodeGen, extra: anytype) Allocator.Error!u32 {
1304 const field_count = std.meta.fieldNames(@TypeOf(extra)).len;
1304 const field_count = @typeInfo(@TypeOf(extra)).@"struct".field_names.len;
13051305 try self.mir_extra.ensureUnusedCapacity(self.gpa, field_count);
13061306 return self.addExtraAssumeCapacity(extra);
13071307}
......@@ -2152,7 +2152,7 @@ fn gen(
21522152
21532153 const epilogue = if (self.epilogue_relocs.items.len > 0) epilogue: {
21542154 var last_inst: Mir.Inst.Index = @intCast(self.mir_instructions.len - 1);
2155 while (self.epilogue_relocs.getLast() == last_inst) {
2155 while (self.epilogue_relocs.last() == last_inst) {
21562156 self.epilogue_relocs.items.len -= 1;
21572157 self.mir_instructions.set(last_inst, .{
21582158 .tag = .pseudo,
......@@ -34436,7 +34436,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3443634436 .call_frame = .{ .alignment = .@"16" },
3443734437 .extra_temps = .{
3443834438 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
34439 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
34439 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
3444034440 .unused,
3444134441 .unused,
3444234442 .unused,
......@@ -34470,7 +34470,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3447034470 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3447134471 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3447234472 .{ .type = .f128, .kind = .mem },
34473 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
34473 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
3447434474 .unused,
3447534475 .unused,
3447634476 .unused,
......@@ -34505,7 +34505,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3450534505 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3450634506 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3450734507 .{ .type = .f128, .kind = .mem },
34508 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
34508 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
3450934509 .unused,
3451034510 .unused,
3451134511 .unused,
......@@ -34540,7 +34540,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3454034540 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3454134541 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3454234542 .{ .type = .f128, .kind = .mem },
34543 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
34543 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
3454434544 .unused,
3454534545 .unused,
3454634546 .unused,
......@@ -34575,7 +34575,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3457534575 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3457634576 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3457734577 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
34578 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
34578 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
3457934579 .unused,
3458034580 .unused,
3458134581 .unused,
......@@ -34612,7 +34612,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3461234612 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3461334613 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3461434614 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
34615 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
34615 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
3461634616 .unused,
3461734617 .unused,
3461834618 .unused,
......@@ -34649,7 +34649,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3464934649 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3465034650 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3465134651 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
34652 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
34652 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
3465334653 .unused,
3465434654 .unused,
3465534655 .unused,
......@@ -34688,7 +34688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3468834688 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3468934689 .{ .type = .f128, .kind = .mem },
3469034690 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
34691 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
34691 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
3469234692 .unused,
3469334693 .unused,
3469434694 .unused,
......@@ -34727,7 +34727,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3472734727 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3472834728 .{ .type = .f128, .kind = .mem },
3472934729 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
34730 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
34730 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
3473134731 .unused,
3473234732 .unused,
3473334733 .unused,
......@@ -34766,7 +34766,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3476634766 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3476734767 .{ .type = .f128, .kind = .mem },
3476834768 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
34769 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
34769 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
3477034770 .unused,
3477134771 .unused,
3477234772 .unused,
......@@ -35960,8 +35960,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3596035960 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3596135961 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3596235962 else => unreachable,
35963 .zero => "truncq",
35964 .down => "floorq",
35963 .zero => "truncf128",
35964 .down => "floorf128",
3596535965 } } },
3596635966 .unused,
3596735967 .unused,
......@@ -35998,8 +35998,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3599835998 .{ .type = .f128, .kind = .mem },
3599935999 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3600036000 else => unreachable,
36001 .zero => "truncq",
36002 .down => "floorq",
36001 .zero => "truncf128",
36002 .down => "floorf128",
3600336003 } } },
3600436004 .unused,
3600536005 .unused,
......@@ -36037,8 +36037,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3603736037 .{ .type = .f128, .kind = .mem },
3603836038 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3603936039 else => unreachable,
36040 .zero => "truncq",
36041 .down => "floorq",
36040 .zero => "truncf128",
36041 .down => "floorf128",
3604236042 } } },
3604336043 .unused,
3604436044 .unused,
......@@ -36076,8 +36076,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3607636076 .{ .type = .f128, .kind = .mem },
3607736077 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3607836078 else => unreachable,
36079 .zero => "truncq",
36080 .down => "floorq",
36079 .zero => "truncf128",
36080 .down => "floorf128",
3608136081 } } },
3608236082 .unused,
3608336083 .unused,
......@@ -36115,8 +36115,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3611536115 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3611636116 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3611736117 else => unreachable,
36118 .zero => "truncq",
36119 .down => "floorq",
36118 .zero => "truncf128",
36119 .down => "floorf128",
3612036120 } } },
3612136121 .unused,
3612236122 .unused,
......@@ -36156,8 +36156,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3615636156 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3615736157 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3615836158 else => unreachable,
36159 .zero => "truncq",
36160 .down => "floorq",
36159 .zero => "truncf128",
36160 .down => "floorf128",
3616136161 } } },
3616236162 .unused,
3616336163 .unused,
......@@ -36197,8 +36197,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3619736197 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3619836198 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3619936199 else => unreachable,
36200 .zero => "truncq",
36201 .down => "floorq",
36200 .zero => "truncf128",
36201 .down => "floorf128",
3620236202 } } },
3620336203 .unused,
3620436204 .unused,
......@@ -36240,8 +36240,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3624036240 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3624136241 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3624236242 else => unreachable,
36243 .zero => "truncq",
36244 .down => "floorq",
36243 .zero => "truncf128",
36244 .down => "floorf128",
3624536245 } } },
3624636246 .unused,
3624736247 .unused,
......@@ -36283,8 +36283,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3628336283 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3628436284 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3628536285 else => unreachable,
36286 .zero => "truncq",
36287 .down => "floorq",
36286 .zero => "truncf128",
36287 .down => "floorf128",
3628836288 } } },
3628936289 .unused,
3629036290 .unused,
......@@ -36326,8 +36326,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3632636326 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3632736327 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3632836328 else => unreachable,
36329 .zero => "truncq",
36330 .down => "floorq",
36329 .zero => "truncf128",
36330 .down => "floorf128",
3633136331 } } },
3633236332 .unused,
3633336333 .unused,
......@@ -37691,7 +37691,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3769137691 .call_frame = .{ .alignment = .@"16" },
3769237692 .extra_temps = .{
3769337693 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
37694 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
37694 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
3769537695 .unused,
3769637696 .unused,
3769737697 .unused,
......@@ -37725,7 +37725,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3772537725 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3772637726 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3772737727 .{ .type = .f128, .kind = .mem },
37728 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
37728 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
3772937729 .unused,
3773037730 .unused,
3773137731 .unused,
......@@ -37760,7 +37760,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3776037760 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3776137761 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3776237762 .{ .type = .f128, .kind = .mem },
37763 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
37763 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
3776437764 .unused,
3776537765 .unused,
3776637766 .unused,
......@@ -37795,7 +37795,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3779537795 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3779637796 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3779737797 .{ .type = .f128, .kind = .mem },
37798 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
37798 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
3779937799 .unused,
3780037800 .unused,
3780137801 .unused,
......@@ -37830,7 +37830,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3783037830 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3783137831 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3783237832 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
37833 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
37833 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
3783437834 .unused,
3783537835 .unused,
3783637836 .unused,
......@@ -37867,7 +37867,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3786737867 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3786837868 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3786937869 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
37870 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
37870 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
3787137871 .unused,
3787237872 .unused,
3787337873 .unused,
......@@ -37904,7 +37904,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3790437904 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3790537905 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3790637906 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
37907 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
37907 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
3790837908 .unused,
3790937909 .unused,
3791037910 .unused,
......@@ -37943,7 +37943,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3794337943 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3794437944 .{ .type = .f128, .kind = .mem },
3794537945 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
37946 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
37946 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
3794737947 .unused,
3794837948 .unused,
3794937949 .unused,
......@@ -37982,7 +37982,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3798237982 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3798337983 .{ .type = .f128, .kind = .mem },
3798437984 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
37985 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
37985 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
3798637986 .unused,
3798737987 .unused,
3798837988 .unused,
......@@ -38021,7 +38021,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3802138021 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3802238022 .{ .type = .f128, .kind = .mem },
3802338023 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
38024 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
38024 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
3802538025 .unused,
3802638026 .unused,
3802738027 .unused,
......@@ -39558,7 +39558,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3955839558 },
3955939559 .call_frame = .{ .alignment = .@"16" },
3956039560 .extra_temps = .{
39561 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
39561 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
3956239562 .unused,
3956339563 .unused,
3956439564 .unused,
......@@ -39590,7 +39590,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3959039590 .extra_temps = .{
3959139591 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3959239592 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
39593 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
39593 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
3959439594 .unused,
3959539595 .unused,
3959639596 .unused,
......@@ -39623,7 +39623,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3962339623 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
3962439624 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3962539625 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
39626 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
39626 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
3962739627 .unused,
3962839628 .unused,
3962939629 .unused,
......@@ -39659,7 +39659,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3965939659 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
3966039660 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3966139661 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
39662 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
39662 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
3966339663 .unused,
3966439664 .unused,
3966539665 .unused,
......@@ -39695,7 +39695,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3969539695 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
3969639696 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3969739697 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
39698 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
39698 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
3969939699 .unused,
3970039700 .unused,
3970139701 .unused,
......@@ -39731,7 +39731,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3973139731 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
3973239732 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3973339733 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
39734 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
39734 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
3973539735 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3973639736 .unused,
3973739737 .unused,
......@@ -39767,7 +39767,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3976739767 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
3976839768 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3976939769 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
39770 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
39770 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
3977139771 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3977239772 .unused,
3977339773 .unused,
......@@ -39803,7 +39803,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3980339803 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
3980439804 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3980539805 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
39806 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
39806 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
3980739807 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3980839808 .unused,
3980939809 .unused,
......@@ -42803,7 +42803,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4280342803 .call_frame = .{ .alignment = .@"16" },
4280442804 .extra_temps = .{
4280542805 .{ .type = .f128, .kind = .mem },
42806 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
42806 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4280742807 .{ .type = .u64, .kind = .{ .reg = .rcx } },
4280842808 .{ .type = .u64, .kind = .{ .reg = .rdx } },
4280942809 .{ .type = .u64, .kind = .{ .reg = .rax } },
......@@ -42849,7 +42849,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4284942849 .call_frame = .{ .alignment = .@"16" },
4285042850 .extra_temps = .{
4285142851 .{ .type = .f128, .kind = .mem },
42852 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
42852 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4285342853 .{ .type = .u64, .kind = .{ .reg = .rcx } },
4285442854 .{ .type = .u64, .kind = .{ .reg = .rdx } },
4285542855 .{ .type = .u64, .kind = .{ .reg = .rax } },
......@@ -42895,7 +42895,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4289542895 .call_frame = .{ .alignment = .@"16" },
4289642896 .extra_temps = .{
4289742897 .{ .type = .f128, .kind = .mem },
42898 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
42898 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4289942899 .{ .type = .u64, .kind = .{ .reg = .rcx } },
4290042900 .{ .type = .u64, .kind = .{ .reg = .rdx } },
4290142901 .{ .type = .u64, .kind = .{ .reg = .rax } },
......@@ -42942,7 +42942,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4294242942 .call_frame = .{ .alignment = .@"16" },
4294342943 .extra_temps = .{
4294442944 .{ .type = .f128, .kind = .mem },
42945 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
42945 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4294642946 .{ .type = .u64, .kind = .{ .reg = .rdx } },
4294742947 .{ .type = .f128, .kind = .mem },
4294842948 .{ .type = .u64, .kind = .{ .reg = .rax } },
......@@ -42984,7 +42984,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4298442984 .extra_temps = .{
4298542985 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4298642986 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
42987 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
42987 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4298842988 .{ .type = .f128, .kind = .mem },
4298942989 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
4299042990 .{ .type = .u64, .kind = .{ .reg = .rax } },
......@@ -43029,7 +43029,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4302943029 .extra_temps = .{
4303043030 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4303143031 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
43032 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
43032 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4303343033 .{ .type = .f128, .kind = .mem },
4303443034 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
4303543035 .{ .type = .u64, .kind = .{ .reg = .rax } },
......@@ -43074,7 +43074,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4307443074 .extra_temps = .{
4307543075 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4307643076 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
43077 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
43077 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4307843078 .{ .type = .f128, .kind = .mem },
4307943079 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
4308043080 .{ .type = .u64, .kind = .{ .reg = .rax } },
......@@ -43120,7 +43120,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4312043120 .extra_temps = .{
4312143121 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4312243122 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
43123 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
43123 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4312443124 .{ .type = .f128, .kind = .mem },
4312543125 .{ .type = .usize, .kind = .{ .reg = .rax } },
4312643126 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
......@@ -43164,7 +43164,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4316443164 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4316543165 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4316643166 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
43167 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
43167 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4316843168 .{ .type = .f128, .kind = .{ .reg = .rcx } },
4316943169 .{ .type = .f128, .kind = .{ .reg = .rdx } },
4317043170 .{ .type = .f128, .kind = .{ .reg = .rax } },
......@@ -43211,7 +43211,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4321143211 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4321243212 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4321343213 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
43214 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
43214 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4321543215 .{ .type = .f128, .kind = .{ .reg = .rcx } },
4321643216 .{ .type = .f128, .kind = .{ .reg = .rdx } },
4321743217 .{ .type = .f128, .kind = .{ .reg = .rax } },
......@@ -43258,7 +43258,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4325843258 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4325943259 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4326043260 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
43261 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
43261 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4326243262 .{ .type = .f128, .kind = .{ .reg = .rcx } },
4326343263 .{ .type = .f128, .kind = .{ .reg = .rdx } },
4326443264 .{ .type = .f128, .kind = .{ .reg = .rax } },
......@@ -43306,7 +43306,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4330643306 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4330743307 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4330843308 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
43309 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
43309 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4331043310 .{ .type = .f128, .kind = .{ .reg = .rdx } },
4331143311 .{ .type = .f128, .kind = .mem },
4331243312 .{ .type = .f128, .kind = .{ .reg = .rax } },
......@@ -47623,7 +47623,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4762347623 },
4762447624 .call_frame = .{ .alignment = .@"16" },
4762547625 .extra_temps = .{
47626 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
47626 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
4762747627 .unused,
4762847628 .unused,
4762947629 .unused,
......@@ -47655,7 +47655,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4765547655 .extra_temps = .{
4765647656 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4765747657 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
47658 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
47658 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
4765947659 .unused,
4766047660 .unused,
4766147661 .unused,
......@@ -47688,7 +47688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4768847688 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
4768947689 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4769047690 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
47691 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
47691 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
4769247692 .unused,
4769347693 .unused,
4769447694 .unused,
......@@ -47724,7 +47724,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4772447724 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
4772547725 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4772647726 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
47727 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
47727 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
4772847728 .unused,
4772947729 .unused,
4773047730 .unused,
......@@ -47760,7 +47760,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4776047760 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
4776147761 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4776247762 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
47763 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
47763 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
4776447764 .unused,
4776547765 .unused,
4776647766 .unused,
......@@ -47796,7 +47796,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4779647796 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
4779747797 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4779847798 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
47799 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
47799 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
4780047800 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4780147801 .unused,
4780247802 .unused,
......@@ -47832,7 +47832,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4783247832 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
4783347833 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4783447834 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
47835 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
47835 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
4783647836 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4783747837 .unused,
4783847838 .unused,
......@@ -47868,7 +47868,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4786847868 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
4786947869 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4787047870 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
47871 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
47871 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
4787247872 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4787347873 .unused,
4787447874 .unused,
......@@ -51926,7 +51926,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5192651926 },
5192751927 .call_frame = .{ .alignment = .@"16" },
5192851928 .extra_temps = .{
51929 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
51929 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
5193051930 .unused,
5193151931 .unused,
5193251932 .unused,
......@@ -51958,7 +51958,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5195851958 .extra_temps = .{
5195951959 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
5196051960 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
51961 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
51961 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
5196251962 .unused,
5196351963 .unused,
5196451964 .unused,
......@@ -51991,7 +51991,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5199151991 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
5199251992 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
5199351993 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
51994 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
51994 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
5199551995 .unused,
5199651996 .unused,
5199751997 .unused,
......@@ -52027,7 +52027,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5202752027 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
5202852028 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
5202952029 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
52030 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
52030 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
5203152031 .unused,
5203252032 .unused,
5203352033 .unused,
......@@ -52063,7 +52063,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5206352063 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
5206452064 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
5206552065 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
52066 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
52066 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
5206752067 .unused,
5206852068 .unused,
5206952069 .unused,
......@@ -52099,7 +52099,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5209952099 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
5210052100 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
5210152101 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
52102 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
52102 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
5210352103 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
5210452104 .unused,
5210552105 .unused,
......@@ -52135,7 +52135,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5213552135 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
5213652136 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
5213752137 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
52138 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
52138 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
5213952139 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
5214052140 .unused,
5214152141 .unused,
......@@ -52171,7 +52171,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5217152171 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
5217252172 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
5217352173 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
52174 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
52174 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
5217552175 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
5217652176 .unused,
5217752177 .unused,
......@@ -76457,7 +76457,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7645776457 },
7645876458 .call_frame = .{ .alignment = .@"16" },
7645976459 .extra_temps = .{
76460 .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
76460 .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } },
7646176461 .unused,
7646276462 .unused,
7646376463 .unused,
......@@ -76484,7 +76484,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7648476484 .call_frame = .{ .alignment = .@"16" },
7648576485 .extra_temps = .{
7648676486 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
76487 .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
76487 .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } },
7648876488 .unused,
7648976489 .unused,
7649076490 .unused,
......@@ -76512,7 +76512,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7651276512 .extra_temps = .{
7651376513 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7651476514 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
76515 .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
76515 .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } },
7651676516 .unused,
7651776517 .unused,
7651876518 .unused,
......@@ -76543,7 +76543,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7654376543 .extra_temps = .{
7654476544 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7654576545 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
76546 .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
76546 .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } },
7654776547 .unused,
7654876548 .unused,
7654976549 .unused,
......@@ -76574,7 +76574,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7657476574 .extra_temps = .{
7657576575 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7657676576 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
76577 .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
76577 .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } },
7657876578 .unused,
7657976579 .unused,
7658076580 .unused,
......@@ -76605,7 +76605,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7660576605 .extra_temps = .{
7660676606 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7660776607 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
76608 .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
76608 .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } },
7660976609 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
7661076610 .unused,
7661176611 .unused,
......@@ -76636,7 +76636,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7663676636 .extra_temps = .{
7663776637 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7663876638 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
76639 .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
76639 .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } },
7664076640 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
7664176641 .unused,
7664276642 .unused,
......@@ -76667,7 +76667,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7666776667 .extra_temps = .{
7666876668 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7666976669 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
76670 .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
76670 .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } },
7667176671 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
7667276672 .unused,
7667376673 .unused,
......@@ -77306,7 +77306,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7730677306 },
7730777307 .call_frame = .{ .alignment = .@"16" },
7730877308 .extra_temps = .{
77309 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
77309 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } },
7731077310 .unused,
7731177311 .unused,
7731277312 .unused,
......@@ -77333,7 +77333,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7733377333 .call_frame = .{ .alignment = .@"16" },
7733477334 .extra_temps = .{
7733577335 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
77336 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
77336 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } },
7733777337 .unused,
7733877338 .unused,
7733977339 .unused,
......@@ -77361,7 +77361,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7736177361 .extra_temps = .{
7736277362 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7736377363 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
77364 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
77364 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } },
7736577365 .unused,
7736677366 .unused,
7736777367 .unused,
......@@ -77392,7 +77392,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7739277392 .extra_temps = .{
7739377393 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7739477394 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
77395 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
77395 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } },
7739677396 .unused,
7739777397 .unused,
7739877398 .unused,
......@@ -77423,7 +77423,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7742377423 .extra_temps = .{
7742477424 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7742577425 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
77426 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
77426 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } },
7742777427 .unused,
7742877428 .unused,
7742977429 .unused,
......@@ -77454,7 +77454,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7745477454 .extra_temps = .{
7745577455 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7745677456 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
77457 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
77457 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } },
7745877458 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
7745977459 .unused,
7746077460 .unused,
......@@ -77485,7 +77485,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7748577485 .extra_temps = .{
7748677486 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7748777487 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
77488 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
77488 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } },
7748977489 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
7749077490 .unused,
7749177491 .unused,
......@@ -77516,7 +77516,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7751677516 .extra_temps = .{
7751777517 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7751877518 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
77519 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
77519 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } },
7752077520 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
7752177521 .unused,
7752277522 .unused,
......@@ -80155,9 +80155,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8015580155 .extra_temps = .{
8015680156 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
8015780157 else => unreachable,
80158 .down => "floorq",
80159 .up => "ceilq",
80160 .zero => "truncq",
80158 .down => "floorf128",
80159 .up => "ceilf128",
80160 .zero => "truncf128",
8016180161 } } },
8016280162 .unused,
8016380163 .unused,
......@@ -80187,9 +80187,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8018780187 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
8018880188 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
8018980189 else => unreachable,
80190 .down => "floorq",
80191 .up => "ceilq",
80192 .zero => "truncq",
80190 .down => "floorf128",
80191 .up => "ceilf128",
80192 .zero => "truncf128",
8019380193 } } },
8019480194 .unused,
8019580195 .unused,
......@@ -80220,9 +80220,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8022080220 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
8022180221 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
8022280222 else => unreachable,
80223 .down => "floorq",
80224 .up => "ceilq",
80225 .zero => "truncq",
80223 .down => "floorf128",
80224 .up => "ceilf128",
80225 .zero => "truncf128",
8022680226 } } },
8022780227 .unused,
8022880228 .unused,
......@@ -80256,9 +80256,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8025680256 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
8025780257 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
8025880258 else => unreachable,
80259 .down => "floorq",
80260 .up => "ceilq",
80261 .zero => "truncq",
80259 .down => "floorf128",
80260 .up => "ceilf128",
80261 .zero => "truncf128",
8026280262 } } },
8026380263 .unused,
8026480264 .unused,
......@@ -80292,9 +80292,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8029280292 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
8029380293 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
8029480294 else => unreachable,
80295 .down => "floorq",
80296 .up => "ceilq",
80297 .zero => "truncq",
80295 .down => "floorf128",
80296 .up => "ceilf128",
80297 .zero => "truncf128",
8029880298 } } },
8029980299 .unused,
8030080300 .unused,
......@@ -80328,9 +80328,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8032880328 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
8032980329 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
8033080330 else => unreachable,
80331 .down => "floorq",
80332 .up => "ceilq",
80333 .zero => "truncq",
80331 .down => "floorf128",
80332 .up => "ceilf128",
80333 .zero => "truncf128",
8033480334 } } },
8033580335 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
8033680336 .unused,
......@@ -80364,9 +80364,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8036480364 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
8036580365 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
8036680366 else => unreachable,
80367 .down => "floorq",
80368 .up => "ceilq",
80369 .zero => "truncq",
80367 .down => "floorf128",
80368 .up => "ceilf128",
80369 .zero => "truncf128",
8037080370 } } },
8037180371 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
8037280372 .unused,
......@@ -80400,9 +80400,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8040080400 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
8040180401 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
8040280402 else => unreachable,
80403 .down => "floorq",
80404 .up => "ceilq",
80405 .zero => "truncq",
80403 .down => "floorf128",
80404 .up => "ceilf128",
80405 .zero => "truncf128",
8040680406 } } },
8040780407 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
8040880408 .unused,
......@@ -125531,7 +125531,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
125531125531 .{ ._, ._, .call, .tmp1d, ._, ._, ._ },
125532125532 } },
125533125533 }, .{
125534 .required_cc_abi = .sysv64,
125535125534 .required_features = .{ .sse, null, null, null },
125536125535 .src_constraints = .{ .{ .unsigned_int = .xword }, .any, .any },
125537125536 .dst_constraints = .{ .{ .float = .xword }, .any },
......@@ -125557,34 +125556,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
125557125556 .each = .{ .once = &.{
125558125557 .{ ._, ._, .call, .tmp0d, ._, ._, ._ },
125559125558 } },
125560 }, .{
125561 .required_cc_abi = .win64,
125562 .required_features = .{ .sse, null, null, null },
125563 .src_constraints = .{ .{ .unsigned_int = .xword }, .any, .any },
125564 .dst_constraints = .{ .{ .float = .xword }, .any },
125565 .patterns = &.{
125566 .{ .src = .{ .to_mem, .none, .none } },
125567 },
125568 .call_frame = .{ .alignment = .@"16" },
125569 .extra_temps = .{
125570 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
125571 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } },
125572 .unused,
125573 .unused,
125574 .unused,
125575 .unused,
125576 .unused,
125577 .unused,
125578 .unused,
125579 .unused,
125580 .unused,
125581 },
125582 .dst_temps = .{ .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } }, .unused },
125583 .clobbers = .{ .eflags = true, .caller_preserved = .ccc },
125584 .each = .{ .once = &.{
125585 .{ ._, ._, .lea, .tmp0p, .mem(.src0), ._, ._ },
125586 .{ ._, ._, .call, .tmp1d, ._, ._, ._ },
125587 } },
125588125559 }, .{
125589125560 .required_features = .{ .@"64bit", .sse, null, null },
125590125561 .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 {
126791126762 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
126792126763 } },
126793126764 }, .{
126794 .required_cc_abi = .sysv64,
126795126765 .required_features = .{ .avx, null, null, null },
126796126766 .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any },
126797126767 .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 {
126824126794 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
126825126795 } },
126826126796 }, .{
126827 .required_cc_abi = .win64,
126828 .required_features = .{ .avx, null, null, null },
126829 .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any },
126830 .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any },
126831 .patterns = &.{
126832 .{ .src = .{ .to_mem, .none, .none } },
126833 },
126834 .call_frame = .{ .alignment = .@"16" },
126835 .extra_temps = .{
126836 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
126837 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
126838 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } },
126839 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
126840 .unused,
126841 .unused,
126842 .unused,
126843 .unused,
126844 .unused,
126845 .unused,
126846 .unused,
126847 },
126848 .dst_temps = .{ .mem, .unused },
126849 .clobbers = .{ .eflags = true, .caller_preserved = .ccc },
126850 .each = .{ .once = &.{
126851 .{ ._, ._, .mov, .tmp0d, .sia(-16, .src0, .add_unaligned_size), ._, ._ },
126852 .{ .@"0:", ._, .lea, .tmp1p, .memi(.src0, .tmp0), ._, ._ },
126853 .{ ._, ._, .call, .tmp2d, ._, ._, ._ },
126854 .{ ._, .v_dqa, .mov, .memi(.dst0x, .tmp0), .tmp3x, ._, ._ },
126855 .{ ._, ._, .sub, .tmp0d, .si(16), ._, ._ },
126856 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
126857 } },
126858 }, .{
126859 .required_cc_abi = .sysv64,
126860126797 .required_features = .{ .sse2, null, null, null },
126861126798 .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any },
126862126799 .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 {
126889126826 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
126890126827 } },
126891126828 }, .{
126892 .required_cc_abi = .win64,
126893 .required_features = .{ .sse2, null, null, null },
126894 .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any },
126895 .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any },
126896 .patterns = &.{
126897 .{ .src = .{ .to_mem, .none, .none } },
126898 },
126899 .call_frame = .{ .alignment = .@"16" },
126900 .extra_temps = .{
126901 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
126902 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
126903 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } },
126904 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
126905 .unused,
126906 .unused,
126907 .unused,
126908 .unused,
126909 .unused,
126910 .unused,
126911 .unused,
126912 },
126913 .dst_temps = .{ .mem, .unused },
126914 .clobbers = .{ .eflags = true, .caller_preserved = .ccc },
126915 .each = .{ .once = &.{
126916 .{ ._, ._, .mov, .tmp0d, .sia(-16, .src0, .add_unaligned_size), ._, ._ },
126917 .{ .@"0:", ._, .lea, .tmp1p, .memi(.src0, .tmp0), ._, ._ },
126918 .{ ._, ._, .call, .tmp2d, ._, ._, ._ },
126919 .{ ._, ._dqa, .mov, .memi(.dst0x, .tmp0), .tmp3x, ._, ._ },
126920 .{ ._, ._, .sub, .tmp0d, .si(16), ._, ._ },
126921 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
126922 } },
126923 }, .{
126924 .required_cc_abi = .sysv64,
126925126829 .required_features = .{ .sse, null, null, null },
126926126830 .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any },
126927126831 .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 {
126953126857 .{ ._, ._, .sub, .tmp0d, .si(16), ._, ._ },
126954126858 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
126955126859 } },
126956 }, .{
126957 .required_cc_abi = .win64,
126958 .required_features = .{ .sse, null, null, null },
126959 .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any },
126960 .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any },
126961 .patterns = &.{
126962 .{ .src = .{ .to_mem, .none, .none } },
126963 },
126964 .call_frame = .{ .alignment = .@"16" },
126965 .extra_temps = .{
126966 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
126967 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
126968 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } },
126969 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
126970 .unused,
126971 .unused,
126972 .unused,
126973 .unused,
126974 .unused,
126975 .unused,
126976 .unused,
126977 },
126978 .dst_temps = .{ .mem, .unused },
126979 .clobbers = .{ .eflags = true, .caller_preserved = .ccc },
126980 .each = .{ .once = &.{
126981 .{ ._, ._, .mov, .tmp0d, .sia(-16, .src0, .add_unaligned_size), ._, ._ },
126982 .{ .@"0:", ._, .lea, .tmp1p, .memi(.src0, .tmp0), ._, ._ },
126983 .{ ._, ._, .call, .tmp2d, ._, ._, ._ },
126984 .{ ._, ._ps, .mova, .memi(.dst0x, .tmp0), .tmp3x, ._, ._ },
126985 .{ ._, ._, .sub, .tmp0d, .si(16), ._, ._ },
126986 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
126987 } },
126988126860 }, .{
126989126861 .required_features = .{ .@"64bit", .avx, null, null },
126990126862 .src_constraints = .{ .{ .scalar_remainder_signed_int = .{ .of = .dword, .is = .dword } }, .any, .any },
......@@ -142552,7 +142424,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
142552142424 .extra_temps = .{
142553142425 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
142554142426 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
142555 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
142427 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
142556142428 .unused,
142557142429 .unused,
142558142430 .unused,
......@@ -142584,7 +142456,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
142584142456 .extra_temps = .{
142585142457 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
142586142458 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
142587 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
142459 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
142588142460 .unused,
142589142461 .unused,
142590142462 .unused,
......@@ -142616,7 +142488,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
142616142488 .extra_temps = .{
142617142489 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
142618142490 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
142619 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
142491 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
142620142492 .unused,
142621142493 .unused,
142622142494 .unused,
......@@ -142649,7 +142521,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
142649142521 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
142650142522 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
142651142523 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
142652 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
142524 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
142653142525 .{ .type = .f128, .kind = .mem },
142654142526 .unused,
142655142527 .unused,
......@@ -142683,7 +142555,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
142683142555 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
142684142556 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
142685142557 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
142686 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
142558 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
142687142559 .{ .type = .f128, .kind = .mem },
142688142560 .unused,
142689142561 .unused,
......@@ -142717,7 +142589,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
142717142589 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
142718142590 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
142719142591 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
142720 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
142592 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
142721142593 .{ .type = .f128, .kind = .mem },
142722142594 .unused,
142723142595 .unused,
......@@ -152785,7 +152657,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
152785152657 .extra_temps = .{
152786152658 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
152787152659 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
152788 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
152660 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
152789152661 .unused,
152790152662 .unused,
152791152663 .unused,
......@@ -152817,7 +152689,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
152817152689 .extra_temps = .{
152818152690 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
152819152691 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
152820 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
152692 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
152821152693 .unused,
152822152694 .unused,
152823152695 .unused,
......@@ -152849,7 +152721,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
152849152721 .extra_temps = .{
152850152722 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
152851152723 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
152852 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
152724 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
152853152725 .unused,
152854152726 .unused,
152855152727 .unused,
......@@ -152882,7 +152754,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
152882152754 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
152883152755 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
152884152756 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
152885 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
152757 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
152886152758 .{ .type = .f128, .kind = .mem },
152887152759 .unused,
152888152760 .unused,
......@@ -152916,7 +152788,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
152916152788 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
152917152789 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
152918152790 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
152919 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
152791 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
152920152792 .{ .type = .f128, .kind = .mem },
152921152793 .unused,
152922152794 .unused,
......@@ -152950,7 +152822,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
152950152822 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
152951152823 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
152952152824 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
152953 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
152825 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
152954152826 .{ .type = .f128, .kind = .mem },
152955152827 .unused,
152956152828 .unused,
......@@ -163019,7 +162891,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
163019162891 .extra_temps = .{
163020162892 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
163021162893 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
163022 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
162894 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
163023162895 .unused,
163024162896 .unused,
163025162897 .unused,
......@@ -163051,7 +162923,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
163051162923 .extra_temps = .{
163052162924 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
163053162925 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
163054 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
162926 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
163055162927 .unused,
163056162928 .unused,
163057162929 .unused,
......@@ -163083,7 +162955,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
163083162955 .extra_temps = .{
163084162956 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
163085162957 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
163086 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
162958 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
163087162959 .unused,
163088162960 .unused,
163089162961 .unused,
......@@ -163116,7 +162988,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
163116162988 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
163117162989 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
163118162990 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
163119 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
162991 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
163120162992 .{ .type = .f128, .kind = .mem },
163121162993 .unused,
163122162994 .unused,
......@@ -163150,7 +163022,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
163150163022 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
163151163023 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
163152163024 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
163153 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
163025 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
163154163026 .{ .type = .f128, .kind = .mem },
163155163027 .unused,
163156163028 .unused,
......@@ -163184,7 +163056,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
163184163056 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
163185163057 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
163186163058 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
163187 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
163059 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
163188163060 .{ .type = .f128, .kind = .mem },
163189163061 .unused,
163190163062 .unused,
......@@ -164816,7 +164688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
164816164688 .extra_temps = .{
164817164689 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
164818164690 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
164819 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
164691 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
164820164692 .unused,
164821164693 .unused,
164822164694 .unused,
......@@ -164848,7 +164720,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
164848164720 .extra_temps = .{
164849164721 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
164850164722 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
164851 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
164723 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
164852164724 .unused,
164853164725 .unused,
164854164726 .unused,
......@@ -164880,7 +164752,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
164880164752 .extra_temps = .{
164881164753 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
164882164754 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
164883 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
164755 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
164884164756 .unused,
164885164757 .unused,
164886164758 .unused,
......@@ -164913,7 +164785,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
164913164785 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
164914164786 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
164915164787 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
164916 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
164788 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
164917164789 .{ .type = .f128, .kind = .mem },
164918164790 .unused,
164919164791 .unused,
......@@ -164947,7 +164819,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
164947164819 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
164948164820 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
164949164821 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
164950 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
164822 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
164951164823 .{ .type = .f128, .kind = .mem },
164952164824 .unused,
164953164825 .unused,
......@@ -164981,7 +164853,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
164981164853 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
164982164854 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
164983164855 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
164984 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
164856 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
164985164857 .{ .type = .f128, .kind = .mem },
164986164858 .unused,
164987164859 .unused,
......@@ -172785,7 +172657,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
172785172657 },
172786172658 .call_frame = .{ .alignment = .@"16" },
172787172659 .extra_temps = .{
172788 .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
172660 .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } },
172789172661 .unused,
172790172662 .unused,
172791172663 .unused,
......@@ -172818,7 +172690,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
172818172690 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
172819172691 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
172820172692 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 2, .at = 2 } } },
172821 .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
172693 .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } },
172822172694 .unused,
172823172695 .unused,
172824172696 .unused,
......@@ -172852,7 +172724,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
172852172724 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
172853172725 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
172854172726 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 2, .at = 2 } } },
172855 .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
172727 .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } },
172856172728 .unused,
172857172729 .unused,
172858172730 .unused,
......@@ -172889,7 +172761,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
172889172761 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
172890172762 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
172891172763 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 2, .at = 2 } } },
172892 .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
172764 .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } },
172893172765 .unused,
172894172766 .unused,
172895172767 .unused,
......@@ -172926,7 +172798,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
172926172798 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
172927172799 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
172928172800 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 2, .at = 2 } } },
172929 .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
172801 .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } },
172930172802 .unused,
172931172803 .unused,
172932172804 .unused,
......@@ -172963,7 +172835,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
172963172835 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
172964172836 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
172965172837 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 2, .at = 2 } } },
172966 .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
172838 .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } },
172967172839 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
172968172840 .unused,
172969172841 .unused,
......@@ -173000,7 +172872,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
173000172872 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
173001172873 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
173002172874 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 2, .at = 2 } } },
173003 .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
172875 .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } },
173004172876 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
173005172877 .unused,
173006172878 .unused,
......@@ -173037,7 +172909,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
173037172909 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
173038172910 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
173039172911 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 2, .at = 2 } } },
173040 .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
172912 .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } },
173041172913 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
173042172914 .unused,
173043172915 .unused,
......@@ -176621,10 +176493,20 @@ fn genCall(cg: *CodeGen, info: union(enum) {
176621176493
176622176494 for (call_info.args, arg_types, args, frame_indices) |dst_arg, arg_ty, src_arg, frame_index| switch (dst_arg) {
176623176495 .none, .load_frame, .indirect_load_frame => {},
176624 .register => |dst_reg| try cg.genSetReg(registerAlias(
176625 dst_reg,
176626 @intCast(cg.unalignedSize(arg_ty)),
176627 ), arg_ty, src_arg, opts),
176496 .register => |dst_reg| switch (fn_info.cc) {
176497 else => try cg.genSetReg(registerAlias(
176498 dst_reg,
176499 @intCast(cg.unalignedSize(arg_ty)),
176500 ), arg_ty, src_arg, opts),
176501 .x86_64_sysv, .x86_64_win => {
176502 const promoted_ty = cg.promoteInt(arg_ty);
176503 const promoted_unaligned_size: u32 = @intCast(cg.unalignedSize(promoted_ty));
176504 const dst_alias = registerAlias(dst_reg, promoted_unaligned_size);
176505 try cg.genSetReg(dst_alias, promoted_ty, src_arg, opts);
176506 if (promoted_ty.toIntern() != arg_ty.toIntern())
176507 try cg.truncateRegister(arg_ty, dst_alias);
176508 },
176509 },
176628176510 .register_pair,
176629176511 .register_triple,
176630176512 .register_quadruple,
......@@ -177096,7 +176978,7 @@ fn lowerBlock(self: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index
177096176978 defer block_data.value.deinit(self.gpa);
177097176979 if (block_data.value.relocs.items.len > 0) {
177098176980 var last_inst: Mir.Inst.Index = @intCast(self.mir_instructions.len - 1);
177099 while (block_data.value.relocs.getLast() == last_inst) {
176981 while (block_data.value.relocs.last() == last_inst) {
177100176982 block_data.value.relocs.items.len -= 1;
177101176983 self.mir_instructions.set(last_inst, .{
177102176984 .tag = .pseudo,
......@@ -178017,7 +177899,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
178017177899 else if (std.mem.endsWith(u8, mnem_str, "l"))
178018177900 .dword
178019177901 else if (std.mem.endsWith(u8, mnem_str, "q") and
178020 (std.mem.indexOfScalar(u8, "vp", mnem_str[0]) == null or
177902 (std.mem.findScalar(u8, "vp", mnem_str[0]) == null or
178021177903 !std.mem.endsWith(u8, mnem_str, "dq")))
178022177904 .qword
178023177905 else if (std.mem.endsWith(u8, mnem_str, "t"))
......@@ -178084,8 +177966,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
178084177966 }) + 1,
178085177967 }
178086177968 };
178087 const untrimmed_op_str = if (std.mem.indexOfScalar(u8, full_op_str, '#') orelse
178088 std.mem.indexOf(u8, full_op_str, "//")) |comment|
177969 const untrimmed_op_str = if (std.mem.findScalar(u8, full_op_str, '#') orelse
177970 std.mem.find(u8, full_op_str, "//")) |comment|
178089177971 untrimmed_op_str: {
178090177972 ops_index = ops_str.len;
178091177973 break :untrimmed_op_str full_op_str[0..comment];
......@@ -178094,7 +177976,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
178094177976 if (trimmed_op_str.len > 0) break trimmed_op_str;
178095177977 };
178096177978 if (std.mem.startsWith(u8, op_str, "%%")) {
178097 const colon = std.mem.indexOfScalarPos(u8, op_str, "%%".len + 2, ':');
177979 const colon = std.mem.findScalarPos(u8, op_str, "%%".len + 2, ':');
178098177980 const reg = parseRegName(op_str["%%".len .. colon orelse op_str.len]) orelse
178099177981 return self.fail("invalid register: '{s}'", .{op_str});
178100177982 if (colon) |colon_pos| {
......@@ -178115,7 +177997,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
178115177997 op.* = .{ .reg = reg };
178116177998 }
178117177999 } else if (std.mem.startsWith(u8, op_str, "%[") and std.mem.endsWith(u8, op_str, "]")) {
178118 const colon = std.mem.indexOfScalarPos(u8, op_str, "%[".len, ':');
178000 const colon = std.mem.findScalarPos(u8, op_str, "%[".len, ':');
178119178001 const modifier = if (colon) |colon_pos|
178120178002 op_str[colon_pos + ":".len .. op_str.len - "]".len]
178121178003 else
......@@ -178198,7 +178080,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
178198178080 else |_|
178199178081 return self.fail("invalid immediate: '{s}'", .{op_str});
178200178082 } else if (std.mem.endsWith(u8, op_str, ")")) {
178201 const open = std.mem.indexOfScalar(u8, op_str, '(') orelse
178083 const open = std.mem.findScalar(u8, op_str, '(') orelse
178202178084 return self.fail("invalid operand: '{s}'", .{op_str});
178203178085 var sib_it =
178204178086 std.mem.splitScalar(u8, op_str[open + "(".len .. op_str.len - ")".len], ',');
......@@ -178259,7 +178141,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
178259178141 .disp = if (std.mem.startsWith(u8, op_str[0..open], "%[") and
178260178142 std.mem.endsWith(u8, op_str[0..open], "]"))
178261178143 disp: {
178262 const colon = std.mem.indexOfScalarPos(u8, op_str[0..open], "%[".len, ':');
178144 const colon = std.mem.findScalarPos(u8, op_str[0..open], "%[".len, ':');
178263178145 const modifier = if (colon) |colon_pos|
178264178146 op_str[colon_pos + ":".len .. open - "]".len]
178265178147 else
......@@ -178328,14 +178210,14 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
178328178210 .{ ._, .pseudo }
178329178211 else for (std.enums.values(Mir.Inst.Fixes)) |fixes| {
178330178212 const fixes_name = @tagName(fixes);
178331 const space_index = std.mem.indexOfScalar(u8, fixes_name, ' ');
178213 const space_index = std.mem.findScalar(u8, fixes_name, ' ');
178332178214 const fixes_prefix = if (space_index) |index|
178333178215 std.meta.stringToEnum(encoder.Instruction.Prefix, fixes_name[0..index]).?
178334178216 else
178335178217 .none;
178336178218 if (fixes_prefix != prefix) continue;
178337178219 const pattern = fixes_name[if (space_index) |index| index + " ".len else 0..];
178338 const wildcard_index = std.mem.indexOfScalar(u8, pattern, '_').?;
178220 const wildcard_index = std.mem.findScalar(u8, pattern, '_').?;
178339178221 const mnem_prefix = pattern[0..wildcard_index];
178340178222 const mnem_suffix = pattern[wildcard_index + "_".len ..];
178341178223 if (!std.mem.startsWith(u8, mnem_name, mnem_prefix)) continue;
......@@ -178581,11 +178463,11 @@ fn moveStrategy(cg: *CodeGen, ty: Type, class: Register.Class, aligned: bool) !M
178581178463 .sse => switch (ty.zigTypeTag(zcu)) {
178582178464 else => {
178583178465 const classes = std.mem.sliceTo(&abi.classifySystemV(ty, zcu, cg.target, .other), .none);
178584 assert(std.mem.indexOfNone(abi.Class, classes, &.{
178466 assert(std.mem.findNone(abi.Class, classes, &.{
178585178467 .integer, .sse, .sseup, .memory, .float, .float_combine,
178586178468 }) == null);
178587178469 const abi_size = ty.abiSize(zcu);
178588 if (abi_size < 4 or std.mem.indexOfScalar(abi.Class, classes, .integer) != null) switch (abi_size) {
178470 if (abi_size < 4 or std.mem.findScalar(abi.Class, classes, .integer) != null) switch (abi_size) {
178589178471 1 => return if (cg.hasFeature(.avx)) .{ .vex_insert_extract = .{
178590178472 .insert = .{ .vp_b, .insr },
178591178473 .extract = .{ .vp_b, .extr },
......@@ -181994,7 +181876,7 @@ fn resolveCallingConventionValues(
181994181876 }
181995181877
181996181878 const save_param_gpr_index = param_gpr_index;
181997 const save_param_sse_index = param_gpr_index;
181879 const save_param_sse_index = param_sse_index;
181998181880
181999181881 var arg_mcv: [4]MCValue = undefined;
182000181882 var arg_mcv_len: u32 = 0;
......@@ -182502,8 +182384,8 @@ fn hasFeature(cg: *CodeGen, feature: std.Target.x86.Feature) bool {
182502182384 .slow_unaligned_mem_16,
182503182385 .slow_unaligned_mem_32,
182504182386 => switch (cg.mod.optimize_mode) {
182505 .Debug, .ReleaseSafe, .ReleaseFast => null,
182506 .ReleaseSmall => false,
182387 .debug, .safe, .fast => null,
182388 .small => false,
182507182389 },
182508182390 .fast_11bytenop,
182509182391 .fast_15bytenop,
......@@ -182523,8 +182405,8 @@ fn hasFeature(cg: *CodeGen, feature: std.Target.x86.Feature) bool {
182523182405 .fast_vector_fsqrt,
182524182406 .fast_vector_shift_masks,
182525182407 => switch (cg.mod.optimize_mode) {
182526 .Debug, .ReleaseSafe, .ReleaseFast => null,
182527 .ReleaseSmall => true,
182408 .debug, .safe, .fast => null,
182409 .small => true,
182528182410 },
182529182411 .mmx => false,
182530182412 .sahf => switch (cg.target.cpu.arch) {
......@@ -182626,15 +182508,15 @@ fn intInfo(cg: *CodeGen, ty: Type) ?std.lang.Type.Int {
182626182508 .anyerror => .{ .signedness = .unsigned, .bits = zcu.errorSetBits() },
182627182509 .isize => .{ .signedness = .signed, .bits = cg.target.ptrBitWidth() },
182628182510 .usize => .{ .signedness = .unsigned, .bits = cg.target.ptrBitWidth() },
182629 .c_char => .{ .signedness = cg.target.cCharSignedness(), .bits = cg.target.cTypeBitSize(.char) },
182630 .c_short => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.short) },
182631 .c_ushort => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.short) },
182632 .c_int => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.int) },
182633 .c_uint => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.int) },
182634 .c_long => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.long) },
182635 .c_ulong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.long) },
182636 .c_longlong => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.longlong) },
182637 .c_ulonglong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.longlong) },
182511 .c_char => .{ .signedness = cg.target.cCharSignedness().?, .bits = cg.target.cTypeBitSize(.char).? },
182512 .c_short => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.short).? },
182513 .c_ushort => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.short).? },
182514 .c_int => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.int).? },
182515 .c_uint => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.int).? },
182516 .c_long => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.long).? },
182517 .c_ulong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.long).? },
182518 .c_longlong => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.longlong).? },
182519 .c_ulonglong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.longlong).? },
182638182520 .f16, .f32, .f64, .f80, .f128, .c_longdouble => null,
182639182521 .anyopaque,
182640182522 .void,
......@@ -183696,8 +183578,8 @@ const Temp = struct {
183696183578 const class = classes[class_index];
183697183579 next_class_index = @intCast(switch (class) {
183698183580 .integer, .memory, .float, .float_combine => class_index + 1,
183699 .sse => std.mem.indexOfNonePos(abi.Class, classes, class_index + 1, &.{.sseup}) orelse classes.len,
183700 .x87 => std.mem.indexOfNonePos(abi.Class, classes, class_index + 1, &.{.x87up}) orelse classes.len,
183581 .sse => std.mem.findNonePos(abi.Class, classes, class_index + 1, &.{.sseup}) orelse classes.len,
183582 .x87 => std.mem.findNonePos(abi.Class, classes, class_index + 1, &.{.x87up}) orelse classes.len,
183701183583 .sseup,
183702183584 .x87up,
183703183585 .none,
......@@ -189943,7 +189825,7 @@ const Select = struct {
189943189825 s.cg.asmOps(mir_tag, mir_ops) catch |err| switch (err) {
189944189826 error.InvalidInstruction => {
189945189827 const fixes = @tagName(mir_tag[0]);
189946 const fixes_blank = std.mem.indexOfScalar(u8, fixes, '_').?;
189828 const fixes_blank = std.mem.findScalar(u8, fixes, '_').?;
189947189829 return s.cg.fail("invalid instruction: '{s}{s}{s} {s} {s} {s} {s}'", .{
189948189830 fixes[0..fixes_blank],
189949189831 @tagName(mir_tag[1]),
......@@ -190023,7 +189905,7 @@ const Select = struct {
190023189905 .add, .com, .comi, .div, .divr, .mul, .st, .sub, .subr, .ucom, .ucomi => s.top +%= 1,
190024189906 else => {
190025189907 const fixes = @tagName(mir_tag[0]);
190026 const fixes_blank = std.mem.indexOfScalar(u8, fixes, '_').?;
189908 const fixes_blank = std.mem.findScalar(u8, fixes, '_').?;
190027189909 std.debug.panic("{s}: {s}{s}{s}\n", .{
190028189910 @src().fn_name,
190029189911 fixes[0..fixes_blank],
src/codegen/x86_64/Lower.zig+5-5
......@@ -435,11 +435,11 @@ const mnemonic_table: [inst_tags_len * inst_fixes_len]?Mnemonic = table: {
435435 for (0..inst_fixes_len) |fixes_i| {
436436 const fixes: Mir.Inst.Fixes = @fromBackingInt(@intCast(fixes_i));
437437 const prefix, const suffix = affix: {
438 const pattern = if (std.mem.indexOfScalar(u8, @tagName(fixes), ' ')) |i|
438 const pattern = if (std.mem.findScalar(u8, @tagName(fixes), ' ')) |i|
439439 @tagName(fixes)[i + 1 ..]
440440 else
441441 @tagName(fixes);
442 const wildcard_idx = std.mem.indexOfScalar(u8, pattern, '_').?;
442 const wildcard_idx = std.mem.findScalar(u8, pattern, '_').?;
443443 break :affix .{ pattern[0..wildcard_idx], pattern[wildcard_idx + 1 ..] };
444444 };
445445 for (0..inst_tags_len) |inst_tag_i| {
......@@ -477,7 +477,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
477477 else => return lower.fail("TODO lower .{s}", .{@tagName(inst.ops)}),
478478 };
479479 try lower.encode(switch (fixes) {
480 inline else => |tag| comptime if (std.mem.indexOfScalar(u8, @tagName(tag), ' ')) |space|
480 inline else => |tag| comptime if (std.mem.findScalar(u8, @tagName(tag), ' ')) |space|
481481 @field(Prefix, @tagName(tag)[0..space])
482482 else
483483 .none,
......@@ -487,8 +487,8 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
487487 }
488488 // This combination is invalid; make the theoretical mnemonic name and emit an error with it.
489489 const fixes_name = @tagName(fixes);
490 const pattern = fixes_name[if (std.mem.indexOfScalar(u8, fixes_name, ' ')) |i| i + " ".len else 0..];
491 const wildcard_index = std.mem.indexOfScalar(u8, pattern, '_').?;
490 const pattern = fixes_name[if (std.mem.findScalar(u8, fixes_name, ' ')) |i| i + " ".len else 0..];
491 const wildcard_index = std.mem.findScalar(u8, pattern, '_').?;
492492 return lower.fail("unsupported mnemonic: '{s}{s}{s}'", .{
493493 pattern[0..wildcard_index],
494494 @tagName(inst.tag),
src/codegen/x86_64/Mir.zig+3-3
......@@ -1745,8 +1745,8 @@ pub const Inst = struct {
17451745 for (@typeInfo(Mnemonic).@"enum".field_names) |mnemonic_name| {
17461746 if (mnemonic_name[0] == '.') continue;
17471747 for (@typeInfo(Fixes).@"enum".field_names) |fixes_name| {
1748 const pattern = fixes_name[if (std.mem.indexOfScalar(u8, fixes_name, ' ')) |index| index + " ".len else 0..];
1749 const wildcard_index = std.mem.indexOfScalar(u8, pattern, '_').?;
1748 const pattern = fixes_name[if (std.mem.findScalar(u8, fixes_name, ' ')) |index| index + " ".len else 0..];
1749 const wildcard_index = std.mem.findScalar(u8, pattern, '_').?;
17501750 const mnem_prefix = pattern[0..wildcard_index];
17511751 const mnem_suffix = pattern[wildcard_index + "_".len ..];
17521752 if (!std.mem.startsWith(u8, mnemonic_name, mnem_prefix)) continue;
......@@ -1823,7 +1823,7 @@ pub const NullTerminatedString = enum(u32) {
18231823 pub fn toSlice(nts: NullTerminatedString, mir: *const Mir) ?[:0]const u8 {
18241824 if (nts == .none) return null;
18251825 const string_bytes = mir.string_bytes[@backingInt(nts)..];
1826 return string_bytes[0..std.mem.indexOfScalar(u8, string_bytes, 0).? :0];
1826 return string_bytes[0..std.mem.findScalar(u8, string_bytes, 0).? :0];
18271827 }
18281828};
18291829
src/codegen/x86_64/abi.zig+39-16
......@@ -133,7 +133,7 @@ pub fn classifyWindows(init_ty: Type, zcu: *Zcu, target: *const std.Target, ctx:
133133 .float => switch (ty.floatBits(target)) {
134134 16, 32, 64 => .sse,
135135 80 => .memory,
136 128 => if (ctx == .arg) .memory else .sse,
136 128 => .win_i128,
137137 else => unreachable,
138138 },
139139 .vector => {
......@@ -238,16 +238,18 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont
238238 };
239239 const unaligned_size = elem_ty.abiSize(zcu) * len;
240240 if (unaligned_size <= 4) return Class.one_integer;
241 if (ctx == .arg and unaligned_size == 8 * 1 * 1 and len == 1 and
242 elem_ty.isRuntimeFloat()) return Class.stack; // what
241 if (unaligned_size == 8 * 1 * 1 and len == 1) {
242 if (ctx == .arg and elem_ty.isRuntimeFloat()) return Class.stack; // what?
243 if (ctx != .other and !elem_ty.isRuntimeFloat() and target.os.tag == .freebsd) return Class.one_integer; // who?
244 }
243245 if (unaligned_size <= 8 * 1) return .{ .sse, .none, .none, .none, .none, .none, .none, .none };
244246 if (unaligned_size <= 8 * 2) return .{ .sse, .sseup, .none, .none, .none, .none, .none, .none };
245247 if (!target.cpu.has(.x86, .avx)) {
246248 if (ctx == .ret) switch (unaligned_size) {
247249 else => {},
248250 8 * 3 => if (len == 3) return if (elem_ty.isRuntimeFloat()) .{
249 .sse_sse_x87_per_qword, .none, .none, .none, .none, .none, .none, .none, // how
250 } else Class.len_integers, // why
251 .sse_sse_x87_per_qword, .none, .none, .none, .none, .none, .none, .none, // how?
252 } else Class.len_integers, // why?
251253 8 * 2 * 2, 8 * 2 * 4 => return .{ .sse_per_xword, .none, .none, .none, .none, .none, .none, .none },
252254 };
253255 return Class.stack;
......@@ -316,7 +318,7 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont
316318 // byte isn't SSE or any other eightbyte isn't SSEUP, the whole argument
317319 // is passed in memory."
318320 if (ty_size > 16 and (result[0] != .sse or
319 std.mem.indexOfNone(Class, result[1..], &.{ .sseup, .none }) != null)) return Class.stack;
321 std.mem.findNone(Class, result[1..], &.{ .sseup, .none }) != null)) return Class.stack;
320322
321323 // "If SSEUP is not preceded by SSE or SSEUP, it is converted to SSE."
322324 for (&result, 0..) |*class, i| switch (class.*) {
......@@ -356,11 +358,10 @@ fn classifySystemVStruct(
356358 while (field_it.next()) |field_index| {
357359 const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]);
358360 const field_align = loaded_struct.field_aligns.getOrNone(ip, field_index);
359 byte_offset = std.mem.alignForward(
360 u64,
361 byte_offset,
362 field_align.toByteUnits() orelse field_ty.abiAlignment(zcu).toByteUnits().?,
363 );
361 byte_offset = switch (field_align) {
362 .none => field_ty.abiAlignment(zcu),
363 else => field_align,
364 }.forward(byte_offset);
364365 if (zcu.typeToStruct(field_ty)) |field_loaded_struct| {
365366 switch (field_loaded_struct.layout) {
366367 .auto => unreachable,
......@@ -379,6 +380,9 @@ fn classifySystemVStruct(
379380 },
380381 .@"packed" => {},
381382 }
383 } else if (field_ty.zigTypeTag(zcu) == .array) {
384 byte_offset = classifySystemVArray(result, byte_offset, field_ty, zcu, target);
385 continue;
382386 }
383387 const field_classes = std.mem.sliceTo(&classifySystemV(field_ty, zcu, target, .other), .none);
384388 for (result[@intCast(byte_offset / 8)..][0..field_classes.len], field_classes) |*result_class, field_class|
......@@ -386,11 +390,7 @@ fn classifySystemVStruct(
386390 byte_offset += field_ty.abiSize(zcu);
387391 }
388392 const final_byte_offset = starting_byte_offset + loaded_struct.size;
389 std.debug.assert(final_byte_offset == std.mem.alignForward(
390 u64,
391 byte_offset,
392 loaded_struct.alignment.toByteUnits().?,
393 ));
393 std.debug.assert(final_byte_offset == loaded_struct.alignment.forward(byte_offset));
394394 return final_byte_offset;
395395}
396396
......@@ -422,6 +422,9 @@ fn classifySystemVUnion(
422422 },
423423 .@"packed" => {},
424424 }
425 } else if (field_ty.zigTypeTag(zcu) == .array) {
426 _ = classifySystemVArray(result, starting_byte_offset, field_ty, zcu, target);
427 continue;
425428 }
426429 const field_classes = std.mem.sliceTo(&classifySystemV(field_ty, zcu, target, .other), .none);
427430 for (result[@intCast(starting_byte_offset / 8)..][0..field_classes.len], field_classes) |*result_class, field_class|
......@@ -430,6 +433,26 @@ fn classifySystemVUnion(
430433 return starting_byte_offset + loaded_union.size;
431434}
432435
436fn classifySystemVArray(
437 result: *[8]Class,
438 starting_byte_offset: u64,
439 array_ty: Type,
440 zcu: *Zcu,
441 target: *const std.Target,
442) u64 {
443 const field_classes = std.mem.sliceTo(&classifySystemV(array_ty.childType(zcu), zcu, target, .other), .none);
444 var byte_offset = starting_byte_offset;
445 const elem_size = array_ty.childType(zcu).abiSize(zcu);
446 for (0..@intCast(array_ty.arrayLenIncludingSentinel(zcu))) |_| {
447 for (result[@intCast(byte_offset / 8)..][0..field_classes.len], field_classes) |*result_class, field_class|
448 result_class.* = result_class.combineSystemV(field_class);
449 byte_offset += elem_size;
450 }
451 const final_byte_offset = starting_byte_offset + array_ty.abiSize(zcu);
452 assert(final_byte_offset == byte_offset);
453 return final_byte_offset;
454}
455
433456pub const zigcc = struct {
434457 pub const stack_align: ?InternPool.Alignment = null;
435458 pub const return_in_regs = true;
src/codegen/x86_64/encoder.zig+1-1
......@@ -1171,7 +1171,7 @@ fn expectEqualHexStrings(expected: []const u8, given: []const u8, assembly: []co
11711171 defer testing.allocator.free(expected_fmt);
11721172 const given_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{given});
11731173 defer testing.allocator.free(given_fmt);
1174 const idx = std.mem.indexOfDiff(u8, expected_fmt, given_fmt).?;
1174 const idx = std.mem.findDiff(u8, expected_fmt, given_fmt).?;
11751175 const padding = try testing.allocator.alloc(u8, idx + 5);
11761176 defer testing.allocator.free(padding);
11771177 @memset(padding, ' ');
src/libs/freebsd.zig-1
......@@ -1077,7 +1077,6 @@ fn buildSharedLib(
10771077 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,
10781078 .valgrind = false,
10791079 .optimize_mode = optimize_mode,
1080 .structured_cfg = comp.root_mod.structured_cfg,
10811080 },
10821081 .global = config,
10831082 .cc_argv = &.{},
src/libs/glibc.zig+1-4
......@@ -398,7 +398,7 @@ fn start_asm_path(comp: *Compilation, arena: Allocator, basename: []const u8) ![
398398 try result.appendSlice("powerpc" ++ s ++ "powerpc32");
399399 }
400400 } else if (arch == .s390x) {
401 try result.appendSlice("s390" ++ s ++ "s390-64");
401 try result.appendSlice("s390");
402402 } else if (arch.isLoongArch()) {
403403 try result.appendSlice("loongarch");
404404 } else if (arch == .m68k) {
......@@ -607,8 +607,6 @@ fn add_include_dirs_arch(
607607 try args.append("-I");
608608 try args.append(try path.join(arena, &[_][]const u8{ dir, "s390", nptl }));
609609 } else {
610 try args.append("-I");
611 try args.append(try path.join(arena, &[_][]const u8{ dir, "s390" ++ s ++ "s390-64" }));
612610 try args.append("-I");
613611 try args.append(try path.join(arena, &[_][]const u8{ dir, "s390" }));
614612 }
......@@ -1223,7 +1221,6 @@ fn buildSharedLib(
12231221 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,
12241222 .valgrind = false,
12251223 .optimize_mode = optimize_mode,
1226 .structured_cfg = comp.root_mod.structured_cfg,
12271224 },
12281225 .global = config,
12291226 .cc_argv = &.{},
src/libs/libcxx.zig+3-5
......@@ -172,7 +172,6 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
172172 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,
173173 .valgrind = false,
174174 .optimize_mode = optimize_mode,
175 .structured_cfg = comp.root_mod.structured_cfg,
176175 .pic = if (target_util.supports_fpic(target)) true else null,
177176 .code_model = comp.root_mod.code_model,
178177 },
......@@ -366,7 +365,6 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
366365 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,
367366 .valgrind = false,
368367 .optimize_mode = optimize_mode,
369 .structured_cfg = comp.root_mod.structured_cfg,
370368 .unwind_tables = unwind_tables,
371369 .pic = if (target_util.supports_fpic(target)) true else null,
372370 .code_model = comp.root_mod.code_model,
......@@ -539,15 +537,15 @@ pub fn addCxxArgs(
539537 // is simple and works everywhere.
540538 try cflags.append("-D_LIBCPP_PSTL_BACKEND_SERIAL");
541539 switch (optimize_mode) {
542 .Debug => {
540 .debug => {
543541 try cflags.append("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG");
544542 try cflags.append("-D_LIBCPP_ASSERTION_SEMANTIC_DEFAULT=_LIBCPP_ASSERTION_SEMANTIC_ENFORCE");
545543 },
546 .ReleaseFast, .ReleaseSmall => {
544 .fast, .small => {
547545 try cflags.append("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_NONE");
548546 try cflags.append("-D_LIBCPP_ASSERTION_SEMANTIC_DEFAULT=_LIBCPP_ASSERTION_SEMANTIC_IGNORE");
549547 },
550 .ReleaseSafe => {
548 .safe => {
551549 try cflags.append("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST");
552550 try cflags.append("-D_LIBCPP_ASSERTION_SEMANTIC_DEFAULT=_LIBCPP_ASSERTION_SEMANTIC_ENFORCE");
553551 },
src/libs/libtsan.zig-1
......@@ -100,7 +100,6 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
100100 .valgrind = false,
101101 .unwind_tables = unwind_tables,
102102 .optimize_mode = optimize_mode,
103 .structured_cfg = comp.root_mod.structured_cfg,
104103 .pic = true,
105104 .no_builtin = true,
106105 .code_model = comp.root_mod.code_model,
src/libs/libunwind.zig+1-1
......@@ -118,7 +118,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
118118 // defines will be correct.
119119 try cflags.append("-D_LIBUNWIND_IS_NATIVE_ONLY");
120120
121 if (comp.root_mod.optimize_mode == .Debug) {
121 if (comp.root_mod.optimize_mode == .debug) {
122122 try cflags.append("-D_DEBUG");
123123 }
124124 if (!comp.config.any_non_single_threaded) {
src/libs/mingw.zig+2-2
......@@ -135,8 +135,8 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
135135 });
136136
137137 switch (comp.compilerRtOptMode()) {
138 .Debug, .ReleaseSafe => try winpthreads_args.append("-DWINPTHREAD_DBG"),
139 .ReleaseFast, .ReleaseSmall => {},
138 .debug, .safe => try winpthreads_args.append("-DWINPTHREAD_DBG"),
139 .fast, .small => {},
140140 }
141141
142142 for (mingw32_winpthreads_src) |dep| {
src/libs/mingw/Preprocessor.zig+4-4
......@@ -15,7 +15,7 @@ const RawTokenList = std.ArrayList(Token);
1515const ExpandBuf = std.ArrayList(Token);
1616
1717const Preprocessor = @This();
18const DefineMap = std.StringArrayHashMapUnmanaged(Macro);
18const DefineMap = std.array_hash_map.String(Macro);
1919
2020const GeneratedTokens = std.ArrayList(u8);
2121
......@@ -29,7 +29,7 @@ pub const Source = struct {
2929 buf: []const u8,
3030};
3131
32sources: std.StringArrayHashMapUnmanaged(Source) = .empty,
32sources: std.array_hash_map.String(Source) = .empty,
3333
3434arena: Allocator,
3535io: std.Io,
......@@ -91,9 +91,9 @@ fn addTokenAssumeCapacity(pp: *Preprocessor, tok: Token) void {
9191
9292fn defineBuiltins(pp: *Preprocessor) !void {
9393 var buf: [5]u8 = undefined;
94 var val = std.fmt.bufPrint(&buf, "{d}", .{pp.target.cTypeBitSize(.longdouble)}) catch unreachable;
94 var val = std.fmt.bufPrint(&buf, "{d}", .{pp.target.cTypeByteSize(.longdouble).?}) catch unreachable;
9595 try pp.defineBuiltinValue("__SIZEOF_LONG_DOUBLE__", val, .pp_num);
96 val = std.fmt.bufPrint(&buf, "{d}", .{pp.target.cTypeBitSize(.double)}) catch unreachable;
96 val = std.fmt.bufPrint(&buf, "{d}", .{pp.target.cTypeByteSize(.double).?}) catch unreachable;
9797 try pp.defineBuiltinValue("__SIZEOF_DOUBLE__", val, .pp_num);
9898
9999 if (pp.target.abi.isGnu()) {
src/libs/mingw/def.zig+4-4
......@@ -61,7 +61,7 @@ pub const ModuleDefinition = struct {
6161 // or ? for C++ functions). Vectorcall functions won't have any
6262 // fixed prefix, but the function base name will still be at least
6363 // one char.
64 const name_len_without_at_suffix = std.mem.indexOfScalarPos(u8, e.name, 1, '@') orelse e.name.len;
64 const name_len_without_at_suffix = std.mem.findScalarPos(u8, e.name, 1, '@') orelse e.name.len;
6565 e.name = e.name[0..name_len_without_at_suffix];
6666 }
6767 }
......@@ -452,7 +452,7 @@ pub const Parser = struct {
452452 var ext_name_needs_underscore = false;
453453 if (self.machine_type == .I386) {
454454 const is_decorated = isDecorated(name_tok.slice(self.tokenizer.source), self.module_definition_type);
455 const is_forward_target = ext_name_tok != null and std.mem.indexOfScalar(u8, name_tok.slice(self.tokenizer.source), '.') != null;
455 const is_forward_target = ext_name_tok != null and std.mem.findScalar(u8, name_tok.slice(self.tokenizer.source), '.') != null;
456456 name_needs_underscore = !is_decorated and !is_forward_target;
457457
458458 if (ext_name_tok) |ext_name| {
......@@ -578,9 +578,9 @@ pub const Parser = struct {
578578 // themselves can start with an underscore, while a second one still needs
579579 // to be added.
580580 if (std.mem.startsWith(u8, symbol, "@")) return true;
581 if (std.mem.indexOf(u8, symbol, "@@") != null) return true;
581 if (std.mem.find(u8, symbol, "@@") != null) return true;
582582 if (std.mem.startsWith(u8, symbol, "?")) return true;
583 if (module_definition_type != .mingw and std.mem.indexOfScalar(u8, symbol, '@') != null) return true;
583 if (module_definition_type != .mingw and std.mem.findScalar(u8, symbol, '@') != null) return true;
584584 return false;
585585 }
586586
src/libs/mingw/implib.zig+1-1
......@@ -351,7 +351,7 @@ fn getNameType(
351351 // the leading underscore. In MinGW on the other hand, a decorated
352352 // stdcall function still omits the underscore (IMPORT_NAME_NOPREFIX).
353353 if (std.mem.startsWith(u8, ext_name, "_") and
354 std.mem.indexOfScalar(u8, ext_name, '@') != null and
354 std.mem.findScalar(u8, ext_name, '@') != null and
355355 module_definition_type != .mingw)
356356 return .NAME;
357357 if (!std.mem.eql(u8, symbol, ext_name))
src/libs/musl.zig-1
......@@ -225,7 +225,6 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
225225 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,
226226 .valgrind = false,
227227 .optimize_mode = optimize_mode,
228 .structured_cfg = comp.root_mod.structured_cfg,
229228 },
230229 .global = config,
231230 .cc_argv = cc_argv,
src/libs/netbsd.zig-1
......@@ -727,7 +727,6 @@ fn buildSharedLib(
727727 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,
728728 .valgrind = false,
729729 .optimize_mode = optimize_mode,
730 .structured_cfg = comp.root_mod.structured_cfg,
731730 },
732731 .global = config,
733732 .cc_argv = &.{},
src/libs/openbsd.zig-1
......@@ -647,7 +647,6 @@ fn buildSharedLib(
647647 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,
648648 .valgrind = false,
649649 .optimize_mode = optimize_mode,
650 .structured_cfg = comp.root_mod.structured_cfg,
651650 },
652651 .global = config,
653652 .cc_argv = &.{},
src/link.zig+57-3
......@@ -1238,11 +1238,11 @@ pub const File = struct {
12381238 }
12391239
12401240 switch (base.tag) {
1241 inline .elf2, .coff2, .wasm => |tag| {
1241 inline .elf2, .coff2, .wasm, .c => |tag| {
12421242 dev.check(tag.devFeature());
12431243 try @as(*tag.Type(), @fieldParentPtr("base", base)).prelink(base.comp.link_prog_node);
12441244 },
1245 else => {},
1245 else => base.comp.link_prog_node.completeOne(),
12461246 }
12471247
12481248 base.post_prelink = true;
......@@ -2127,7 +2127,7 @@ pub fn resolveInputs(
21272127 continue;
21282128 },
21292129 }
2130 @compileError("unreachable");
2130 comptime unreachable;
21312131 }
21322132
21332133 if (failed_libs.items.len > 0) {
......@@ -2239,6 +2239,60 @@ fn resolveLibInput(
22392239 return finishResolveLibInput(io, resolved_inputs, archive_dedup, test_path, file, link_mode, name_query.query);
22402240 }
22412241
2242 // In the case of OpenBSD, dynamic libraries are always versioned, without
2243 // unversioned symlinks. OpenBSD patches LLD to select the highest-versioned
2244 // shared library, and this code is intended to match that upstream behavior.
2245 if (target.isOpenBSDLibC() and link_mode == .dynamic) versioned: {
2246 const prefix = try std.fmt.allocPrint(arena, "lib{s}.so.", .{lib_name});
2247
2248 var dir = lib_directory.handle.openDir(io, ".", .{ .iterate = true }) catch |err| switch (err) {
2249 error.NotDir, error.FileNotFound => break :versioned,
2250 else => |e| fatal("unable to search for shared library '{s}.*': {s}", .{ prefix, @errorName(e) }),
2251 };
2252 defer dir.close(io);
2253
2254 var best_match_major: u32 = 0;
2255 var best_match_minor: u32 = 0;
2256 var best_match: ?[]const u8 = null;
2257
2258 var iter = dir.iterate();
2259 while (iter.next(io) catch |err| {
2260 fatal("unable to scan library directory '{s}'", .{@errorName(err)});
2261 }) |entry| {
2262 if (entry.kind != .file) continue;
2263 if (!std.mem.startsWith(u8, entry.name, prefix)) continue;
2264
2265 const rest = entry.name[prefix.len..];
2266 var sit = std.mem.splitScalar(u8, rest, '.');
2267 const major_str = sit.next() orelse continue;
2268 const minor_str = sit.next() orelse continue;
2269 if (sit.next() != null) continue;
2270 const major = std.fmt.parseInt(u32, major_str, 10) catch continue;
2271 const minor = std.fmt.parseInt(u32, minor_str, 10) catch continue;
2272
2273 if (major > best_match_major or (major == best_match_major and minor >= best_match_minor)) {
2274 best_match_major = major;
2275 best_match_minor = minor;
2276 best_match = try arena.dupe(u8, entry.name);
2277 }
2278 }
2279
2280 if (best_match) |found| {
2281 const test_path: Path = .{
2282 .root_dir = lib_directory,
2283 .sub_path = found,
2284 };
2285 try checked_paths.print(gpa, "\n {f}", .{test_path});
2286 switch (try resolvePathInputLib(gpa, arena, io, unresolved_inputs, resolved_inputs, ld_script_bytes, archive_dedup, target, .{
2287 .path = test_path,
2288 .query = name_query.query,
2289 }, link_mode, color)) {
2290 .no_match => {},
2291 .ok => return .ok,
2292 }
2293 }
2294 }
2295
22422296 return .no_match;
22432297}
22442298
src/link/C.zig+26-25
......@@ -43,6 +43,8 @@ type_dependencies: std.ArrayList(link.ConstPool.Index),
4343/// one array.
4444align_dependency_masks: std.ArrayList(u64),
4545
46/// Emitted at the top of the file. This can be cached since it only depends on the target.
47header: String,
4648/// All NAVs, regardless of whether they are functions or simple constants, are put in this map.
4749navs: std.array_hash_map.Auto(InternPool.Nav.Index, RenderedDecl),
4850/// 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(
404406 emit: Path,
405407 options: link.File.OpenOptions,
406408) !*C {
409 assert(comp.root_mod.resolved_target.result.ofmt == .c);
407410 const io = comp.io;
408 const target = &comp.root_mod.resolved_target.result;
409 assert(target.ofmt == .c);
410411 const optimize_mode = comp.root_mod.optimize_mode;
411412 const use_lld = build_options.have_llvm and comp.config.use_lld;
412413 const use_llvm = comp.config.use_llvm;
......@@ -422,14 +423,13 @@ pub fn createEmpty(
422423 });
423424 errdefer file.close(io);
424425
425 const c_file = try arena.create(C);
426
427 c_file.* = .{
426 const c = try arena.create(C);
427 c.* = .{
428428 .base = .{
429429 .tag = .c,
430430 .comp = comp,
431431 .emit = emit,
432 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),
432 .gc_sections = options.gc_sections orelse (optimize_mode != .debug and output_mode != .Obj),
433433 .print_gc_sections = options.print_gc_sections,
434434 .stack_size = options.stack_size orelse 16777216,
435435 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
......@@ -439,6 +439,7 @@ pub fn createEmpty(
439439 .string_bytes = .empty,
440440 .type_dependencies = .empty,
441441 .align_dependency_masks = .empty,
442 .header = .empty,
442443 .navs = .empty,
443444 .uavs = .empty,
444445 .type_pool = .empty,
......@@ -447,8 +448,7 @@ pub fn createEmpty(
447448 .exported_navs = .empty,
448449 .exported_uavs = .empty,
449450 };
450
451 return c_file;
451 return c;
452452}
453453
454454pub fn deinit(c: *C) void {
......@@ -469,6 +469,21 @@ pub fn deinit(c: *C) void {
469469 c.exported_uavs.deinit(gpa);
470470}
471471
472pub fn prelink(c: *C, prog_node: std.Progress.Node) !void {
473 const comp = c.base.comp;
474
475 const sub_prog_node = prog_node.start("Generate Header", 0);
476 defer sub_prog_node.end();
477
478 var header_aw: std.Io.Writer.Allocating = .init(comp.gpa);
479 defer header_aw.deinit();
480 codegen.genHeader(comp.zcu.?, &header_aw.writer) catch |err| switch (err) {
481 error.WriteFailed => return error.OutOfMemory,
482 else => |e| return e,
483 };
484 c.header = try c.addString(&.{header_aw.written()});
485}
486
472487pub fn updateContainerType(
473488 c: *C,
474489 pt: Zcu.PerThread,
......@@ -727,7 +742,6 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
727742 const io = comp.io;
728743 const zcu = c.base.comp.zcu.?;
729744 const ip = &zcu.intern_pool;
730 const target = zcu.getTarget();
731745 const active = zcu.activate(tid);
732746 defer active.deactivate();
733747 const pt = active.pt;
......@@ -943,7 +957,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
943957 // We have discovered the full set of NAVs, UAVs, and types we need to emit, and will now begin
944958 // to build the output buffer. Our strategy is to emit the C source in this order:
945959 //
946 // * ABI defines and `#include "zig.h"`
960 // * Header
947961 // * Big-int type definitions
948962 // * Other CType definitions (traversing the dependency graph to sort topologically)
949963 // * Global assembly
......@@ -968,7 +982,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
968982
969983 // We know exactly what we'll be emitting, so can reserve capacity for all of our buffers!
970984
971 try f.all_buffers.ensureUnusedCapacity(gpa, 3 + // ABI defines and `#include "zig.h"`
985 try f.all_buffers.ensureUnusedCapacity(gpa, 1 + // Header
972986 1 + // Big-int type definitions
973987 need_types.count() + // `RenderedType.fwd_decl` (worst-case)
974988 need_types.count() + // `RenderedType.definition`
......@@ -984,20 +998,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
984998 need_uavs.count() * 3 + // UAV definitions ("static ", "zig_align(4)", "<definition body>")
985999 need_navs.count() * 2); // NAV definitions ("static ", "<definition body>")
9861000
987 // ABI defines and `#include "zig.h"`
988 switch (target.abi) {
989 .msvc, .itanium => f.appendBufAssumeCapacity("#define ZIG_TARGET_ABI_MSVC\n"),
990 else => {},
991 }
992 f.appendBufAssumeCapacity(try std.fmt.allocPrint(
993 arena,
994 "#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n",
995 .{target.cMaxIntAlignment()},
996 ));
997 f.appendBufAssumeCapacity(
998 \\#include "zig.h"
999 \\
1000 );
1001 f.appendBufAssumeCapacity(c.header.get(c));
10011002
10021003 // Big-int type definitions
10031004 var bigint_aw: std.Io.Writer.Allocating = .init(gpa);
src/link/Coff.zig+22-18
......@@ -621,7 +621,7 @@ pub const LongNamesTable = struct {
621621 }
622622
623623 pub fn hash(_: Adapter, key: []const u8) u32 {
624 assert(std.mem.indexOfScalar(u8, key, 0) == null);
624 assert(std.mem.findScalar(u8, key, 0) == null);
625625 return std.array_hash_map.hashString(key);
626626 }
627627 };
......@@ -711,7 +711,7 @@ pub const ExportTable = struct {
711711 }
712712
713713 pub fn hash(_: Adapter, key: []const u8) u32 {
714 assert(std.mem.indexOfScalar(u8, key, 0) == null);
714 assert(std.mem.findScalar(u8, key, 0) == null);
715715 return std.array_hash_map.hashString(key);
716716 }
717717 };
......@@ -759,7 +759,7 @@ pub const ImportTable = struct {
759759 }
760760
761761 pub fn hash(_: Adapter, key: []const u8) u32 {
762 assert(std.mem.indexOfScalar(u8, key, 0) == null);
762 assert(std.mem.findScalar(u8, key, 0) == null);
763763 return std.array_hash_map.hashString(key);
764764 }
765765 };
......@@ -822,7 +822,7 @@ pub const String = enum(u32) {
822822
823823 pub fn toSlice(s: String, coff: *Coff) [:0]const u8 {
824824 const slice = coff.string_bytes.items[@backingInt(s)..];
825 return slice[0..std.mem.indexOfScalar(u8, slice, 0).? :0];
825 return slice[0..std.mem.findScalar(u8, slice, 0).? :0];
826826 }
827827
828828 pub fn toOptional(s: String) String.Optional {
......@@ -3535,7 +3535,7 @@ fn objectSectionParentName(coff: *Coff, name: []const u8) []const u8 {
35353535 // Otherwise, we want to keep the full name so that this sort can occur correctly when
35363536 // the object is finally linked into an image.
35373537 return if (coff.isImage())
3538 name[0 .. std.mem.indexOfScalar(u8, name, '$') orelse name.len]
3538 name[0 .. std.mem.findScalar(u8, name, '$') orelse name.len]
35393539 else
35403540 name;
35413541}
......@@ -3654,7 +3654,7 @@ fn verifyParentSectionAttributes(
36543654 parent.name(coff).toSlice(coff),
36553655 });
36563656
3657 inline for (comptime std.meta.fieldNames(ObjectSectionAttributes)) |field| {
3657 inline for (@typeInfo(ObjectSectionAttributes).@"struct".field_names) |field| {
36583658 if (@field(child_attrs, field) != @field(parent_attrs, field)) {
36593659 err.addNote("flags.{s} was {d} in {s}, but {d} in {s}", .{
36603660 field,
......@@ -5370,7 +5370,9 @@ fn loadDll(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) LoadInp
53705370}
53715371
53725372pub fn prelink(coff: *Coff, prog_node: std.Progress.Node) link.Error!void {
5373 _ = prog_node;
5373 const sub_prog_node = prog_node.start("COFF Prelink", 0);
5374 defer sub_prog_node.end();
5375
53745376 const base = coff.base;
53755377 const comp = base.comp;
53765378
......@@ -5598,11 +5600,11 @@ fn updateFuncInner(
55985600 const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{
55995601 .alignment = switch (nav.resolved.?.@"align") {
56005602 .none => switch (mod.optimize_mode) {
5601 .Debug,
5602 .ReleaseSafe,
5603 .ReleaseFast,
5603 .debug,
5604 .safe,
5605 .fast,
56045606 => target_util.defaultFunctionAlignment(target),
5605 .ReleaseSmall => target_util.minFunctionAlignment(target),
5607 .small => target_util.minFunctionAlignment(target),
56065608 },
56075609 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
56085610 }.toStdMem(),
......@@ -5735,7 +5737,7 @@ fn reportUndefs(coff: *Coff, tid: Zcu.PerThread.Id) !void {
57355737 const gpa = comp.gpa;
57365738 const max_notes = 4;
57375739
5738 var undef_indices: std.ArrayListUnmanaged(u32) = .empty;
5740 var undef_indices: std.ArrayList(u32) = .empty;
57395741 for (coff.relocs.items, 0..) |reloc, reloc_i| {
57405742 if (reloc.flags.free) continue;
57415743 const target_sym = reloc.target.get(coff);
......@@ -5886,7 +5888,9 @@ pub fn flush(
58865888 prog_node: std.Progress.Node,
58875889) link.Error!void {
58885890 _ = arena;
5889 _ = prog_node;
5891 const sub_prog_node = prog_node.start("COFF Flush", 0);
5892 defer sub_prog_node.end();
5893
58905894 const comp = coff.base.comp;
58915895
58925896 // TODO: When https://github.com/ziglang/zig/issues/23617 is in,
......@@ -6649,11 +6653,11 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
66496653
66506654 const target = &comp.root_mod.resolved_target.result;
66516655 const alignment = switch (comp.root_mod.optimize_mode) {
6652 .Debug,
6653 .ReleaseSafe,
6654 .ReleaseFast,
6656 .debug,
6657 .safe,
6658 .fast,
66556659 => target_util.defaultFunctionAlignment(target),
6656 .ReleaseSmall => target_util.minFunctionAlignment(target),
6660 .small => target_util.minFunctionAlignment(target),
66576661 }.toStdMem();
66586662 const parent_si = (try coff.pseudoSectionMapIndex(
66596663 .@".thunks",
......@@ -6983,7 +6987,7 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void {
69836987 continue;
69846988
69856989 import_hint_name_index = @intCast(import_hint_name_align.forward(
6986 std.mem.indexOfScalarPos(
6990 std.mem.findScalarPos(
69876991 u8,
69886992 import_hint_name_slice,
69896993 import_hint_name_index,
src/link/Dwarf.zig+3-2
......@@ -4151,8 +4151,8 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
41514151 .x86_64_regcall_v3_sysv => .LLVM_X86RegCall,
41524152 .x86_64_regcall_v4_win => .LLVM_X86RegCall,
41534153 .x86_64_vectorcall => .LLVM_vectorcall,
4154 .x86_sysv => .normal,
4155 .x86_win => .normal,
4154 .x86_sysv, .x86_win, .x86_mingw => .normal,
4155 .x86_64_preserve_none => .LLVM_PreserveNone,
41564156 .x86_stdcall => .BORLAND_stdcall,
41574157 .x86_fastcall => .BORLAND_msfastcall,
41584158 .x86_thiscall => .BORLAND_thiscall,
......@@ -4166,6 +4166,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
41664166 .aarch64_aapcs_win => .normal,
41674167 .aarch64_vfabi => .LLVM_AAPCS,
41684168 .aarch64_vfabi_sve => .LLVM_AAPCS,
4169 .aarch64_preserve_none => .LLVM_PreserveNone,
41694170
41704171 .arm_aapcs => .LLVM_AAPCS,
41714172 .arm_aapcs_vfp => .LLVM_AAPCS_VFP,
src/link/Elf.zig+136-137
......@@ -127,7 +127,7 @@ const SectionIndexes = struct {
127127 symtab: ?u32 = null,
128128};
129129
130const ProgramHeaderList = std.ArrayList(elf.Elf64_Phdr);
130const ProgramHeaderList = std.ArrayList(elf.Elf64.Phdr);
131131
132132const OptionalProgramHeaderIndex = enum(u16) {
133133 none = std.math.maxInt(u16),
......@@ -159,21 +159,21 @@ const ProgramHeaderIndex = enum(u16) {
159159};
160160
161161const ProgramHeaderIndexes = struct {
162 /// PT_PHDR
162 /// PT.PHDR
163163 table: OptionalProgramHeaderIndex = .none,
164 /// PT_LOAD for PHDR table
164 /// PT.LOAD for PHDR table
165165 /// We add this special load segment to ensure the EHDR and PHDR table are always
166166 /// loaded into memory.
167167 table_load: OptionalProgramHeaderIndex = .none,
168 /// PT_INTERP
168 /// PT.INTERP
169169 interp: OptionalProgramHeaderIndex = .none,
170 /// PT_DYNAMIC
170 /// PT.DYNAMIC
171171 dynamic: OptionalProgramHeaderIndex = .none,
172 /// PT_GNU_EH_FRAME
172 /// PT.GNU_EH_FRAME
173173 gnu_eh_frame: OptionalProgramHeaderIndex = .none,
174 /// PT_GNU_STACK
174 /// PT.GNU_STACK
175175 gnu_stack: OptionalProgramHeaderIndex = .none,
176 /// PT_TLS
176 /// PT.TLS
177177 /// TODO I think ELF permits multiple TLS segments but for now, assume one per file.
178178 tls: OptionalProgramHeaderIndex = .none,
179179};
......@@ -260,7 +260,7 @@ pub fn createEmpty(
260260 .tag = .elf,
261261 .comp = comp,
262262 .emit = emit,
263 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),
263 .gc_sections = options.gc_sections orelse (optimize_mode != .debug and output_mode != .Obj),
264264 .print_gc_sections = options.print_gc_sections,
265265 .stack_size = options.stack_size orelse 16777216,
266266 .allow_shlib_undefined = options.allow_shlib_undefined orelse !is_native_os,
......@@ -334,23 +334,23 @@ pub fn createEmpty(
334334 if (!is_obj_or_ar) {
335335 try self.dynstrtab.append(gpa, 0);
336336
337 // Initialize PT_PHDR program header
337 // Initialize PT.PHDR program header
338338 const p_align: u16 = switch (self.ptr_width) {
339 .p32 => @alignOf(elf.Elf32_Phdr),
340 .p64 => @alignOf(elf.Elf64_Phdr),
339 .p32 => @alignOf(elf.Elf32.Phdr),
340 .p64 => @alignOf(elf.Elf64.Phdr),
341341 };
342342 const ehsize: u64 = switch (self.ptr_width) {
343343 .p32 => @sizeOf(elf.Elf32_Ehdr),
344344 .p64 => @sizeOf(elf.Elf64_Ehdr),
345345 };
346346 const phsize: u64 = switch (self.ptr_width) {
347 .p32 => @sizeOf(elf.Elf32_Phdr),
348 .p64 => @sizeOf(elf.Elf64_Phdr),
347 .p32 => @sizeOf(elf.Elf32.Phdr),
348 .p64 => @sizeOf(elf.Elf64.Phdr),
349349 };
350350 const max_nphdrs = comptime getMaxNumberOfPhdrs();
351351 const reserved: u64 = mem.alignForward(u64, padToIdeal(max_nphdrs * phsize), self.page_size);
352352 self.phdr_indexes.table = (try self.addPhdr(.{
353 .type = elf.PT_PHDR,
353 .type = @backingInt(elf.PT.PHDR),
354354 .flags = elf.PF_R,
355355 .@"align" = p_align,
356356 .addr = self.image_base + ehsize,
......@@ -359,7 +359,7 @@ pub fn createEmpty(
359359 .memsz = reserved,
360360 })).toOptional();
361361 self.phdr_indexes.table_load = (try self.addPhdr(.{
362 .type = elf.PT_LOAD,
362 .type = @backingInt(elf.PT.LOAD),
363363 .flags = elf.PF_R,
364364 .@"align" = self.page_size,
365365 .addr = self.image_base,
......@@ -514,11 +514,11 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 {
514514 }
515515
516516 for (self.phdrs.items) |phdr| {
517 if (phdr.p_type != elf.PT_LOAD) continue;
518 const increased_size = padToIdeal(phdr.p_filesz);
519 const test_end = phdr.p_offset +| increased_size;
517 if (phdr.type != .LOAD) continue;
518 const increased_size = padToIdeal(phdr.filesz);
519 const test_end = phdr.offset +| increased_size;
520520 if (start < test_end) {
521 if (end > phdr.p_offset) return test_end;
521 if (end > phdr.offset) return test_end;
522522 if (test_end < std.math.maxInt(u64)) at_end = false;
523523 }
524524 }
......@@ -538,8 +538,8 @@ pub fn allocatedSize(self: *Elf, start: u64) u64 {
538538 if (section.sh_offset < min_pos) min_pos = section.sh_offset;
539539 }
540540 for (self.phdrs.items) |phdr| {
541 if (phdr.p_offset <= start) continue;
542 if (phdr.p_offset < min_pos) min_pos = phdr.p_offset;
541 if (phdr.offset <= start) continue;
542 if (phdr.offset < min_pos) min_pos = phdr.offset;
543543 }
544544 return min_pos - start;
545545}
......@@ -714,7 +714,6 @@ pub fn loadInput(self: *Elf, input: link.Input) !void {
714714 const target = self.getTarget();
715715 const debug_fmt_strip = comp.config.debug_format == .strip;
716716 const default_sym_version = self.default_sym_version;
717 const is_static_lib = self.base.isStaticLib();
718717
719718 if (comp.verbose_link) {
720719 comp.mutex.lockUncancelable(io); // protect comp.arena
......@@ -733,7 +732,11 @@ pub fn loadInput(self: *Elf, input: link.Input) !void {
733732 .res => unreachable,
734733 .dso_exact => @panic("TODO"),
735734 .object => |obj| try parseObject(self, obj),
736 .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),
735 .archive => |obj| if (self.base.isStaticLib()) {
736 // Ignore static library inputs when generating a static library.
737 } else {
738 try parseArchive(gpa, io, diags, &self.file_handles, &self.files, target, debug_fmt_strip, default_sym_version, &self.objects, obj);
739 },
737740 .dso => |dso| try parseDso(gpa, io, diags, dso, &self.shared_objects, &self.files, target),
738741 }
739742}
......@@ -1083,7 +1086,6 @@ fn parseArchive(
10831086 default_sym_version: elf.Versym,
10841087 objects: *std.ArrayList(File.Index),
10851088 obj: link.Input.Object,
1086 is_static_lib: bool,
10871089) !void {
10881090 const tracy = trace(@src());
10891091 defer tracy.end();
......@@ -1092,17 +1094,14 @@ fn parseArchive(
10921094 var archive = try Archive.parse(gpa, io, diags, file_handles, obj.path, fh);
10931095 defer archive.deinit(gpa);
10941096
1095 const init_alive = if (is_static_lib) true else obj.must_link;
1096
10971097 for (archive.objects) |extracted| {
10981098 const index: File.Index = @intCast(try files.addOne(gpa));
10991099 files.set(index, .{ .object = extracted });
11001100 const object = &files.items(.data)[index].object;
11011101 object.index = index;
1102 object.alive = init_alive;
1102 object.alive = obj.must_link;
11031103 try object.parseCommon(gpa, io, diags, obj.path, obj.file, target);
1104 if (!is_static_lib)
1105 try object.parse(gpa, io, diags, obj.path, obj.file, target, debug_fmt_strip, default_sym_version);
1104 try object.parse(gpa, io, diags, obj.path, obj.file, target, debug_fmt_strip, default_sym_version);
11061105 try objects.append(gpa, index);
11071106 }
11081107}
......@@ -1471,34 +1470,34 @@ fn writePhdrTable(self: *Elf) !void {
14711470 const phdr_table = &self.phdrs.items[self.phdr_indexes.table.int().?];
14721471
14731472 log.debug("writing program headers from 0x{x} to 0x{x}", .{
1474 phdr_table.p_offset,
1475 phdr_table.p_offset + phdr_table.p_filesz,
1473 phdr_table.offset,
1474 phdr_table.offset + phdr_table.filesz,
14761475 });
14771476
14781477 switch (self.ptr_width) {
14791478 .p32 => {
1480 const buf = try gpa.alloc(elf.Elf32_Phdr, self.phdrs.items.len);
1479 const buf = try gpa.alloc(elf.Elf32.Phdr, self.phdrs.items.len);
14811480 defer gpa.free(buf);
14821481
14831482 for (buf, 0..) |*phdr, i| {
14841483 phdr.* = phdrTo32(self.phdrs.items[i]);
14851484 if (foreign_endian) {
1486 mem.byteSwapAllFields(elf.Elf32_Phdr, phdr);
1485 mem.byteSwapAllFields(elf.Elf32.Phdr, phdr);
14871486 }
14881487 }
1489 try self.pwriteAll(@ptrCast(buf), phdr_table.p_offset);
1488 try self.pwriteAll(@ptrCast(buf), phdr_table.offset);
14901489 },
14911490 .p64 => {
1492 const buf = try gpa.alloc(elf.Elf64_Phdr, self.phdrs.items.len);
1491 const buf = try gpa.alloc(elf.Elf64.Phdr, self.phdrs.items.len);
14931492 defer gpa.free(buf);
14941493
14951494 for (buf, 0..) |*phdr, i| {
14961495 phdr.* = self.phdrs.items[i];
14971496 if (foreign_endian) {
1498 mem.byteSwapAllFields(elf.Elf64_Phdr, phdr);
1497 mem.byteSwapAllFields(elf.Elf64.Phdr, phdr);
14991498 }
15001499 }
1501 try self.pwriteAll(@ptrCast(buf), phdr_table.p_offset);
1500 try self.pwriteAll(@ptrCast(buf), phdr_table.offset);
15021501 },
15031502 }
15041503}
......@@ -1581,7 +1580,7 @@ pub fn writeElfHeader(self: *Elf) !void {
15811580 const entry_sym = obj.entrySymbol(self) orelse break :blk 0;
15821581 break :blk @intCast(entry_sym.address(.{}, self));
15831582 } else 0;
1584 const phdr_table_offset = if (self.phdr_indexes.table.int()) |phndx| self.phdrs.items[phndx].p_offset else 0;
1583 const phdr_table_offset = if (self.phdr_indexes.table.int()) |phndx| self.phdrs.items[phndx].offset else 0;
15851584 switch (self.ptr_width) {
15861585 .p32 => {
15871586 mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(e_entry), endian);
......@@ -1622,8 +1621,8 @@ pub fn writeElfHeader(self: *Elf) !void {
16221621 index += 2;
16231622
16241623 const e_phentsize: u16 = switch (self.ptr_width) {
1625 .p32 => @sizeOf(elf.Elf32_Phdr),
1626 .p64 => @sizeOf(elf.Elf64_Phdr),
1624 .p32 => @sizeOf(elf.Elf32.Phdr),
1625 .p64 => @sizeOf(elf.Elf64.Phdr),
16271626 };
16281627 mem.writeInt(u16, hdr_buf[index..][0..2], e_phentsize, endian);
16291628 index += 2;
......@@ -2091,26 +2090,26 @@ fn initSpecialPhdrs(self: *Elf) !void {
20912090
20922091 if (self.section_indexes.interp != null and self.phdr_indexes.interp == .none) {
20932092 self.phdr_indexes.interp = (try self.addPhdr(.{
2094 .type = elf.PT_INTERP,
2093 .type = @backingInt(elf.PT.INTERP),
20952094 .flags = elf.PF_R,
20962095 .@"align" = 1,
20972096 })).toOptional();
20982097 }
20992098 if (self.section_indexes.dynamic != null and self.phdr_indexes.dynamic == .none) {
21002099 self.phdr_indexes.dynamic = (try self.addPhdr(.{
2101 .type = elf.PT_DYNAMIC,
2100 .type = @backingInt(elf.PT.DYNAMIC),
21022101 .flags = elf.PF_R | elf.PF_W,
21032102 })).toOptional();
21042103 }
21052104 if (self.section_indexes.eh_frame_hdr != null and self.phdr_indexes.gnu_eh_frame == .none) {
21062105 self.phdr_indexes.gnu_eh_frame = (try self.addPhdr(.{
2107 .type = elf.PT_GNU_EH_FRAME,
2106 .type = @backingInt(elf.PT.GNU_EH_FRAME),
21082107 .flags = elf.PF_R,
21092108 })).toOptional();
21102109 }
21112110 if (self.phdr_indexes.gnu_stack == .none) {
21122111 self.phdr_indexes.gnu_stack = (try self.addPhdr(.{
2113 .type = elf.PT_GNU_STACK,
2112 .type = @backingInt(elf.PT.GNU_STACK),
21142113 .flags = elf.PF_W | elf.PF_R,
21152114 .memsz = self.base.stack_size,
21162115 .@"align" = 1,
......@@ -2122,7 +2121,7 @@ fn initSpecialPhdrs(self: *Elf) !void {
21222121 } else false;
21232122 if (has_tls and self.phdr_indexes.tls == .none) {
21242123 self.phdr_indexes.tls = (try self.addPhdr(.{
2125 .type = elf.PT_TLS,
2124 .type = @backingInt(elf.PT.TLS),
21262125 .flags = elf.PF_R,
21272126 .@"align" = 1,
21282127 })).toOptional();
......@@ -2173,7 +2172,7 @@ fn sortInitFini(self: *Elf) !void {
21732172 => is_init_fini = true,
21742173 else => {
21752174 const name = self.getShString(shdr.sh_name);
2176 is_ctor_dtor = mem.indexOf(u8, name, ".ctors") != null or mem.indexOf(u8, name, ".dtors") != null;
2175 is_ctor_dtor = mem.find(u8, name, ".ctors") != null or mem.find(u8, name, ".dtors") != null;
21772176 },
21782177 }
21792178 if (!is_init_fini and !is_ctor_dtor) continue;
......@@ -2260,15 +2259,15 @@ fn setHashSections(self: *Elf) !void {
22602259 }
22612260}
22622261
2263fn phdrRank(phdr: elf.Elf64_Phdr) u8 {
2264 return switch (phdr.p_type) {
2265 elf.PT_NULL => 0,
2266 elf.PT_PHDR => 1,
2267 elf.PT_INTERP => 2,
2268 elf.PT_LOAD => 3,
2269 elf.PT_DYNAMIC, elf.PT_TLS => 4,
2270 elf.PT_GNU_EH_FRAME => 5,
2271 elf.PT_GNU_STACK => 6,
2262fn phdrRank(phdr: elf.Elf64.Phdr) u8 {
2263 return switch (phdr.type) {
2264 .NULL => 0,
2265 .PHDR => 1,
2266 .INTERP => 2,
2267 .LOAD => 3,
2268 .DYNAMIC, .TLS => 4,
2269 .GNU_EH_FRAME => 5,
2270 .GNU_STACK => 6,
22722271 else => 7,
22732272 };
22742273}
......@@ -2282,12 +2281,12 @@ fn sortPhdrs(
22822281 const Entry = struct {
22832282 phndx: u16,
22842283
2285 pub fn lessThan(program_headers: []const elf.Elf64_Phdr, lhs: @This(), rhs: @This()) bool {
2284 pub fn lessThan(program_headers: []const elf.Elf64.Phdr, lhs: @This(), rhs: @This()) bool {
22862285 const lhs_phdr = program_headers[lhs.phndx];
22872286 const rhs_phdr = program_headers[rhs.phndx];
22882287 const lhs_rank = phdrRank(lhs_phdr);
22892288 const rhs_rank = phdrRank(rhs_phdr);
2290 if (lhs_rank == rhs_rank) return lhs_phdr.p_vaddr < rhs_phdr.p_vaddr;
2289 if (lhs_rank == rhs_rank) return lhs_phdr.vaddr < rhs_phdr.vaddr;
22912290 return lhs_rank < rhs_rank;
22922291 }
22932292 };
......@@ -2299,7 +2298,7 @@ fn sortPhdrs(
22992298 }
23002299
23012300 // The `@as` here works around a bug in the C backend.
2302 mem.sort(Entry, entries, @as([]const elf.Elf64_Phdr, phdrs.items), Entry.lessThan);
2301 mem.sort(Entry, entries, @as([]const elf.Elf64.Phdr, phdrs.items), Entry.lessThan);
23032302
23042303 const backlinks = try gpa.alloc(u16, entries.len);
23052304 defer gpa.free(backlinks);
......@@ -2655,8 +2654,8 @@ fn addLoadPhdrs(self: *Elf) error{OutOfMemory}!void {
26552654 if (shdr.sh_type == elf.SHT_NULL) continue;
26562655 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
26572656 const flags = shdrToPhdrFlags(shdr.sh_flags);
2658 if (self.getPhdr(.{ .flags = flags, .type = elf.PT_LOAD }) == .none) {
2659 _ = try self.addPhdr(.{ .flags = flags, .type = elf.PT_LOAD });
2657 if (self.getPhdr(.{ .flags = flags, .type = @backingInt(elf.PT.LOAD) }) == .none) {
2658 _ = try self.addPhdr(.{ .flags = flags, .type = @backingInt(elf.PT.LOAD) });
26602659 }
26612660 }
26622661}
......@@ -2672,11 +2671,11 @@ fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void {
26722671 .p64 => @sizeOf(elf.Elf64_Ehdr),
26732672 };
26742673 const phsize: u64 = switch (self.ptr_width) {
2675 .p32 => @sizeOf(elf.Elf32_Phdr),
2676 .p64 => @sizeOf(elf.Elf64_Phdr),
2674 .p32 => @sizeOf(elf.Elf32.Phdr),
2675 .p64 => @sizeOf(elf.Elf64.Phdr),
26772676 };
26782677 const needed_size = self.phdrs.items.len * phsize;
2679 const available_space = self.allocatedSize(phdr_table.p_offset);
2678 const available_space = self.allocatedSize(phdr_table.offset);
26802679
26812680 if (needed_size > available_space) {
26822681 // In this case, we have two options:
......@@ -2689,10 +2688,10 @@ fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void {
26892688 err.addNote("required 0x{x}, available 0x{x}", .{ needed_size, available_space });
26902689 }
26912690
2692 phdr_table_load.p_filesz = needed_size + ehsize;
2693 phdr_table_load.p_memsz = needed_size + ehsize;
2694 phdr_table.p_filesz = needed_size;
2695 phdr_table.p_memsz = needed_size;
2691 phdr_table_load.filesz = needed_size + ehsize;
2692 phdr_table_load.memsz = needed_size + ehsize;
2693 phdr_table.filesz = needed_size;
2694 phdr_table.memsz = needed_size;
26962695}
26972696
26982697/// Allocates alloc sections and creates load segments for sections
......@@ -2758,7 +2757,7 @@ pub fn allocateAllocSections(self: *Elf) !void {
27582757 // of any section that is contained in a cover and use it to align
27592758 // the start address of the segement (and first section).
27602759 const phdr_table = &self.phdrs.items[self.phdr_indexes.table_load.int().?];
2761 var addr = phdr_table.p_vaddr + phdr_table.p_memsz;
2760 var addr = phdr_table.vaddr + phdr_table.memsz;
27622761
27632762 for (covers) |cover| {
27642763 if (cover.items.len == 0) continue;
......@@ -2817,14 +2816,14 @@ pub fn allocateAllocSections(self: *Elf) !void {
28172816 }
28182817
28192818 const first = slice.items(.shdr)[cover.items[0]];
2820 const phndx = self.getPhdr(.{ .type = elf.PT_LOAD, .flags = shdrToPhdrFlags(first.sh_flags) }).unwrap().?;
2819 const phndx = self.getPhdr(.{ .type = @backingInt(elf.PT.LOAD), .flags = shdrToPhdrFlags(first.sh_flags) }).unwrap().?;
28212820 const phdr = &self.phdrs.items[phndx.int()];
2822 const allocated_size = self.allocatedSize(phdr.p_offset);
2821 const allocated_size = self.allocatedSize(phdr.offset);
28232822 if (filesz > allocated_size) {
2824 const old_offset = phdr.p_offset;
2825 phdr.p_offset = 0;
2823 const old_offset = phdr.offset;
2824 phdr.offset = 0;
28262825 var new_offset = try self.findFreeSpace(filesz, @"align");
2827 phdr.p_offset = new_offset;
2826 phdr.offset = new_offset;
28282827
28292828 log.debug("moving phdr({d}) from 0x{x} to 0x{x}", .{ phndx, old_offset, new_offset });
28302829
......@@ -2854,11 +2853,11 @@ pub fn allocateAllocSections(self: *Elf) !void {
28542853 }
28552854 }
28562855
2857 phdr.p_vaddr = first.sh_addr;
2858 phdr.p_paddr = first.sh_addr;
2859 phdr.p_memsz = memsz;
2860 phdr.p_filesz = filesz;
2861 phdr.p_align = @"align";
2856 phdr.vaddr = first.sh_addr;
2857 phdr.paddr = first.sh_addr;
2858 phdr.memsz = memsz;
2859 phdr.filesz = filesz;
2860 phdr.@"align" = @"align";
28622861
28632862 addr = mem.alignForward(u64, addr, self.page_size);
28642863 }
......@@ -2902,12 +2901,12 @@ fn allocateSpecialPhdrs(self: *Elf) void {
29022901 if (pair[0].int()) |index| {
29032902 const shdr = slice.items(.shdr)[pair[1].?];
29042903 const phdr = &self.phdrs.items[index];
2905 phdr.p_align = shdr.sh_addralign;
2906 phdr.p_offset = shdr.sh_offset;
2907 phdr.p_vaddr = shdr.sh_addr;
2908 phdr.p_paddr = shdr.sh_addr;
2909 phdr.p_filesz = shdr.sh_size;
2910 phdr.p_memsz = shdr.sh_size;
2904 phdr.@"align" = shdr.sh_addralign;
2905 phdr.offset = shdr.sh_offset;
2906 phdr.vaddr = shdr.sh_addr;
2907 phdr.paddr = shdr.sh_addr;
2908 phdr.filesz = shdr.sh_size;
2909 phdr.memsz = shdr.sh_size;
29112910 }
29122911 }
29132912
......@@ -2924,25 +2923,25 @@ fn allocateSpecialPhdrs(self: *Elf) void {
29242923 shndx += 1;
29252924 continue;
29262925 }
2927 phdr.p_offset = shdr.sh_offset;
2928 phdr.p_vaddr = shdr.sh_addr;
2929 phdr.p_paddr = shdr.sh_addr;
2930 phdr.p_align = shdr.sh_addralign;
2926 phdr.offset = shdr.sh_offset;
2927 phdr.vaddr = shdr.sh_addr;
2928 phdr.paddr = shdr.sh_addr;
2929 phdr.@"align" = shdr.sh_addralign;
29312930 shndx += 1;
2932 phdr.p_align = @max(phdr.p_align, shdr.sh_addralign);
2931 phdr.@"align" = @max(phdr.@"align", shdr.sh_addralign);
29332932 if (shdr.sh_type != elf.SHT_NOBITS) {
2934 phdr.p_filesz = shdr.sh_offset + shdr.sh_size - phdr.p_offset;
2933 phdr.filesz = shdr.sh_offset + shdr.sh_size - phdr.offset;
29352934 }
2936 phdr.p_memsz = shdr.sh_addr + shdr.sh_size - phdr.p_vaddr;
2935 phdr.memsz = shdr.sh_addr + shdr.sh_size - phdr.vaddr;
29372936
29382937 while (shndx < shdrs.len) : (shndx += 1) {
29392938 const next = shdrs[shndx];
29402939 if (next.sh_flags & elf.SHF_TLS == 0) break;
2941 phdr.p_align = @max(phdr.p_align, next.sh_addralign);
2940 phdr.@"align" = @max(phdr.@"align", next.sh_addralign);
29422941 if (next.sh_type != elf.SHT_NOBITS) {
2943 phdr.p_filesz = next.sh_offset + next.sh_size - phdr.p_offset;
2942 phdr.filesz = next.sh_offset + next.sh_size - phdr.offset;
29442943 }
2945 phdr.p_memsz = next.sh_addr + next.sh_size - phdr.p_vaddr;
2944 phdr.memsz = next.sh_addr + next.sh_size - phdr.vaddr;
29462945 }
29472946 }
29482947 }
......@@ -3347,16 +3346,16 @@ pub fn archPtrWidthBytes(self: Elf) u8 {
33473346 return @intCast(@divExact(self.getTarget().ptrBitWidth(), 8));
33483347}
33493348
3350fn phdrTo32(phdr: elf.Elf64_Phdr) elf.Elf32_Phdr {
3349fn phdrTo32(phdr: elf.Elf64.Phdr) elf.Elf32.Phdr {
33513350 return .{
3352 .p_type = phdr.p_type,
3353 .p_flags = phdr.p_flags,
3354 .p_offset = @as(u32, @intCast(phdr.p_offset)),
3355 .p_vaddr = @as(u32, @intCast(phdr.p_vaddr)),
3356 .p_paddr = @as(u32, @intCast(phdr.p_paddr)),
3357 .p_filesz = @as(u32, @intCast(phdr.p_filesz)),
3358 .p_memsz = @as(u32, @intCast(phdr.p_memsz)),
3359 .p_align = @as(u32, @intCast(phdr.p_align)),
3351 .type = phdr.type,
3352 .flags = phdr.flags,
3353 .offset = @intCast(phdr.offset),
3354 .vaddr = @intCast(phdr.vaddr),
3355 .paddr = @intCast(phdr.paddr),
3356 .filesz = @intCast(phdr.filesz),
3357 .memsz = @intCast(phdr.memsz),
3358 .@"align" = @intCast(phdr.@"align"),
33603359 };
33613360}
33623361
......@@ -3397,7 +3396,7 @@ fn getPhdr(self: *Elf, opts: struct {
33973396 if (self.phdr_indexes.table_load.int()) |index| {
33983397 if (phndx == index) continue;
33993398 }
3400 if (phdr.p_type == opts.type and phdr.p_flags == opts.flags)
3399 if (@backingInt(phdr.type) == opts.type and @backingInt(phdr.flags) == opts.flags)
34013400 return @fromBackingInt(@intCast(phndx));
34023401 }
34033402 return .none;
......@@ -3415,14 +3414,14 @@ fn addPhdr(self: *Elf, opts: struct {
34153414 const gpa = self.base.comp.gpa;
34163415 const index: ProgramHeaderIndex = @fromBackingInt(@intCast(self.phdrs.items.len));
34173416 try self.phdrs.append(gpa, .{
3418 .p_type = opts.type,
3419 .p_flags = opts.flags,
3420 .p_offset = opts.offset,
3421 .p_vaddr = opts.addr,
3422 .p_paddr = opts.addr,
3423 .p_filesz = opts.filesz,
3424 .p_memsz = opts.memsz,
3425 .p_align = opts.@"align",
3417 .type = @fromBackingInt(opts.type),
3418 .flags = @fromBackingInt(opts.flags),
3419 .offset = opts.offset,
3420 .vaddr = opts.addr,
3421 .paddr = opts.addr,
3422 .filesz = opts.filesz,
3423 .memsz = opts.memsz,
3424 .@"align" = opts.@"align",
34263425 });
34273426 return index;
34283427}
......@@ -3673,9 +3672,9 @@ pub fn tpAddress(self: *Elf) i64 {
36733672 const index = self.phdr_indexes.tls.int() orelse return 0;
36743673 const phdr = self.phdrs.items[index];
36753674 const addr = switch (self.getTarget().cpu.arch) {
3676 .x86_64 => mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, phdr.p_align),
3677 .aarch64, .aarch64_be => mem.alignBackward(u64, phdr.p_vaddr - 16, phdr.p_align),
3678 .riscv64, .riscv64be => phdr.p_vaddr,
3675 .x86_64 => mem.alignForward(u64, phdr.vaddr + phdr.memsz, phdr.@"align"),
3676 .aarch64, .aarch64_be => mem.alignBackward(u64, phdr.vaddr - 16, phdr.@"align"),
3677 .riscv64, .riscv64be => phdr.vaddr,
36793678 else => |arch| std.debug.panic("TODO implement getTpAddress for {s}", .{@tagName(arch)}),
36803679 };
36813680 return @intCast(addr);
......@@ -3684,13 +3683,13 @@ pub fn tpAddress(self: *Elf) i64 {
36843683pub fn dtpAddress(self: *Elf) i64 {
36853684 const index = self.phdr_indexes.tls.int() orelse return 0;
36863685 const phdr = self.phdrs.items[index];
3687 return @intCast(phdr.p_vaddr);
3686 return @intCast(phdr.vaddr);
36883687}
36893688
36903689pub fn tlsAddress(self: *Elf) i64 {
36913690 const index = self.phdr_indexes.tls.int() orelse return 0;
36923691 const phdr = self.phdrs.items[index];
3693 return @intCast(phdr.p_vaddr);
3692 return @intCast(phdr.vaddr);
36943693}
36953694
36963695pub fn getShString(self: Elf, off: u32) [:0]const u8 {
......@@ -3702,7 +3701,7 @@ fn shString(
37023701 off: u32,
37033702) [:0]const u8 {
37043703 const slice = shstrtab[off..];
3705 return slice[0..mem.indexOfScalar(u8, slice, 0).? :0];
3704 return slice[0..mem.findScalar(u8, slice, 0).? :0];
37063705}
37073706
37083707pub fn insertShString(self: *Elf, name: [:0]const u8) error{OutOfMemory}!u32 {
......@@ -3886,10 +3885,10 @@ fn formatShdrFlags(sh_flags: u64, writer: *std.Io.Writer) std.Io.Writer.Error!vo
38863885
38873886const FormatPhdr = struct {
38883887 elf_file: *Elf,
3889 phdr: elf.Elf64_Phdr,
3888 phdr: elf.Elf64.Phdr,
38903889};
38913890
3892fn fmtPhdr(self: *Elf, phdr: elf.Elf64_Phdr) std.fmt.Alt(FormatPhdr, formatPhdr) {
3891fn fmtPhdr(self: *Elf, phdr: elf.Elf64.Phdr) std.fmt.Alt(FormatPhdr, formatPhdr) {
38933892 return .{ .data = .{
38943893 .phdr = phdr,
38953894 .elf_file = self,
......@@ -3898,28 +3897,28 @@ fn fmtPhdr(self: *Elf, phdr: elf.Elf64_Phdr) std.fmt.Alt(FormatPhdr, formatPhdr)
38983897
38993898fn formatPhdr(ctx: FormatPhdr, writer: *std.Io.Writer) std.Io.Writer.Error!void {
39003899 const phdr = ctx.phdr;
3901 const write = phdr.p_flags & elf.PF_W != 0;
3902 const read = phdr.p_flags & elf.PF_R != 0;
3903 const exec = phdr.p_flags & elf.PF_X != 0;
3900 const write = phdr.flags.W;
3901 const read = phdr.flags.R;
3902 const exec = phdr.flags.X;
39043903 var flags: [3]u8 = @splat('_');
39053904 if (exec) flags[0] = 'X';
39063905 if (write) flags[1] = 'W';
39073906 if (read) flags[2] = 'R';
3908 const p_type = switch (phdr.p_type) {
3909 elf.PT_LOAD => "LOAD",
3910 elf.PT_TLS => "TLS",
3911 elf.PT_GNU_EH_FRAME => "GNU_EH_FRAME",
3912 elf.PT_GNU_STACK => "GNU_STACK",
3913 elf.PT_DYNAMIC => "DYNAMIC",
3914 elf.PT_INTERP => "INTERP",
3915 elf.PT_NULL => "NULL",
3916 elf.PT_PHDR => "PHDR",
3917 elf.PT_NOTE => "NOTE",
3907 const p_type = switch (phdr.type) {
3908 .LOAD => "LOAD",
3909 .TLS => "TLS",
3910 .GNU_EH_FRAME => "GNU_EH_FRAME",
3911 .GNU_STACK => "GNU_STACK",
3912 .DYNAMIC => "DYNAMIC",
3913 .INTERP => "INTERP",
3914 .NULL => "NULL",
3915 .PHDR => "PHDR",
3916 .NOTE => "NOTE",
39183917 else => "UNKNOWN",
39193918 };
39203919 try writer.print("{s} : {s} : @{x} ({x}) : align({x}) : filesz({x}) : memsz({x})", .{
3921 p_type, flags, phdr.p_offset, phdr.p_vaddr,
3922 phdr.p_align, phdr.p_filesz, phdr.p_memsz,
3920 p_type, flags, phdr.offset, phdr.vaddr,
3921 phdr.@"align", phdr.filesz, phdr.memsz,
39233922 });
39243923}
39253924
......@@ -4376,7 +4375,7 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {
43764375
43774376pub fn stringTableLookup(strtab: []const u8, off: u32) [:0]const u8 {
43784377 const slice = strtab[off..];
4379 return slice[0..mem.indexOfScalar(u8, slice, 0).? :0];
4378 return slice[0..mem.findScalar(u8, slice, 0).? :0];
43804379}
43814380
43824381pub fn pwriteAll(elf_file: *Elf, bytes: []const u8, offset: u64) error{AlreadyReported}!void {
src/link/Elf/Archive.zig+1-1
......@@ -118,7 +118,7 @@ pub fn parse(
118118
119119pub fn stringTableLookup(strtab: []const u8, off: u32) [:'\n']const u8 {
120120 const slice = strtab[off..];
121 return slice[0..mem.indexOfScalar(u8, slice, '\n').? :'\n'];
121 return slice[0..mem.findScalar(u8, slice, '\n').? :'\n'];
122122}
123123
124124pub fn setArHdr(opts: struct {
src/link/Elf/ZigObject.zig+4-4
......@@ -1299,7 +1299,7 @@ fn getNavShdrIndex(
12991299 }
13001300 if (nav_val.isUndef(zcu))
13011301 return switch (zcu.navFileScope(nav_index).mod.?.optimize_mode) {
1302 .Debug, .ReleaseSafe => {
1302 .debug, .safe => {
13031303 if (self.data_index) |symbol_index|
13041304 return self.symbol(symbol_index).outputShndx(elf_file).?;
13051305 const osec = try elf_file.addSection(.{
......@@ -1311,7 +1311,7 @@ fn getNavShdrIndex(
13111311 self.data_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".data"), osec);
13121312 return osec;
13131313 },
1314 .ReleaseFast, .ReleaseSmall => {
1314 .fast, .small => {
13151315 if (self.bss_index) |symbol_index|
13161316 return self.symbol(symbol_index).outputShndx(elf_file).?;
13171317 const osec = try elf_file.addSection(.{
......@@ -1374,8 +1374,8 @@ fn updateNavCode(
13741374 const target = &mod.resolved_target.result;
13751375 const required_alignment = switch (nav.resolved.?.@"align") {
13761376 .none => switch (mod.optimize_mode) {
1377 .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),
1378 .ReleaseSmall => target_util.minFunctionAlignment(target),
1377 .debug, .safe, .fast => target_util.defaultFunctionAlignment(target),
1378 .small => target_util.minFunctionAlignment(target),
13791379 }.maxStrict(Type.fromInterned(nav.resolved.?.type).abiAlignment(zcu)),
13801380 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
13811381 };
src/link/Elf2.zig+464-218
......@@ -126,8 +126,14 @@ needed: std.array_hash_map.Auto(String(.dynstr), void),
126126inputs: std.ArrayList(struct {
127127 path: std.Build.Cache.Path,
128128 member: ?[]const u8,
129 file_symbol: Symbol.LocalIndex,
129 extra: union {
130 /// Active for static libraries.
131 node: MappedFile.Node.Index,
132 /// Active otherwise.
133 file_symbol: Symbol.LocalIndex,
134 },
130135}),
136input_pending_index: u32,
131137input_sections: std.ArrayList(InputSection),
132138input_section_pending_index: u32,
133139navs: std.array_hash_map.Auto(InternPool.Nav.Index, struct {
......@@ -181,7 +187,10 @@ input_prog_node: std.Progress.Node,
181187const Error = link.Error || error{MappedFileIo};
182188
183189const Node = union(enum) {
184 file,
190 archive,
191 /// This includes the archive magic and long file member.
192 archive_header,
193 elf,
185194 ehdr,
186195 shdr,
187196 segment: u32,
......@@ -189,6 +198,8 @@ const Node = union(enum) {
189198 ///
190199 /// The section '.dynamic' may contain relocations via `elf.dynamic_first_symbol_reloc`.
191200 section: Section.Index,
201 /// Only valid for static libraries, represents one non-zcu archive member.
202 input_member: InputIndex,
192203 /// May contain relocations.
193204 input_section: InputSection.Index,
194205 /// 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) {
219230 return elf.inputs.items[@backingInt(ii)].member;
220231 }
221232
233 pub fn node(ii: InputIndex, elf: *const Elf) MappedFile.Node.Index {
234 return elf.inputs.items[@backingInt(ii)].extra.node;
235 }
236
222237 pub fn fileSymbol(ii: InputIndex, elf: *const Elf) Symbol.LocalIndex {
223 return elf.inputs.items[@backingInt(ii)].file_symbol;
238 return elf.inputs.items[@backingInt(ii)].extra.file_symbol;
224239 }
225240
226241 pub fn localSymbolRange(ii: InputIndex, elf: *Elf) [2]Symbol.LocalIndex {
227242 if (@backingInt(ii) + 1 < elf.inputs.items.len) {
228 const next_ii: InputIndex = @fromBackingInt(@intCast(@backingInt(ii) + 1));
243 const next_ii: InputIndex = @fromBackingInt(@backingInt(ii) + 1);
229244 return .{ ii.fileSymbol(elf), next_ii.fileSymbol(elf) };
230245 } else {
231246 const local_symbols_len = switch (elf.shdrPtr(.symtab)) {
232247 inline else => |shdr| elf.targetLoad(&shdr.info),
233248 };
234 return .{ ii.fileSymbol(elf), @fromBackingInt(@intCast(local_symbols_len)) };
249 return .{ ii.fileSymbol(elf), @fromBackingInt(local_symbols_len) };
235250 }
236251 }
237252 };
......@@ -315,15 +330,16 @@ const Node = union(enum) {
315330 };
316331
317332 pub const Known = struct {
318 comptime file: MappedFile.Node.Index = .root,
319 comptime ehdr: MappedFile.Node.Index = @fromBackingInt(@intCast(1)),
320 comptime shdr: MappedFile.Node.Index = @fromBackingInt(@intCast(2)),
321 comptime rodata: MappedFile.Node.Index = @fromBackingInt(@intCast(3)),
322 comptime phdr: MappedFile.Node.Index = @fromBackingInt(@intCast(4)),
323 comptime text: MappedFile.Node.Index = @fromBackingInt(@intCast(5)),
324 comptime data: MappedFile.Node.Index = @fromBackingInt(@intCast(6)),
325 comptime data_rel_ro: MappedFile.Node.Index = @fromBackingInt(@intCast(7)),
326
333 archive: MappedFile.Node.Index,
334 archive_header: MappedFile.Node.Index,
335 elf: MappedFile.Node.Index,
336 ehdr: MappedFile.Node.Index,
337 shdr: MappedFile.Node.Index,
338 rodata: MappedFile.Node.Index,
339 phdr: MappedFile.Node.Index,
340 text: MappedFile.Node.Index,
341 data: MappedFile.Node.Index,
342 data_rel_ro: MappedFile.Node.Index,
327343 tls: MappedFile.Node.Index,
328344 };
329345
......@@ -333,11 +349,11 @@ const Node = union(enum) {
333349
334350 /// In this linker implementation, `link.File.AtomId` is a type-erased `MappedFile.Node.Index`.
335351 fn toAtom(ni: MappedFile.Node.Index) link.File.AtomId {
336 return @fromBackingInt(@intCast(@backingInt(ni)));
352 return @fromBackingInt(@backingInt(ni));
337353 }
338354 /// In this linker implementation, `link.File.AtomId` is a type-erased `MappedFile.Node.Index`.
339355 fn fromAtom(atom: link.File.AtomId) MappedFile.Node.Index {
340 return @fromBackingInt(@intCast(@backingInt(atom)));
356 return @fromBackingInt(@backingInt(atom));
341357 }
342358};
343359
......@@ -424,13 +440,13 @@ const Section = struct {
424440 fn unwrap(opt: RelaIndex.Optional) ?RelaIndex {
425441 return switch (opt) {
426442 .none => null,
427 _ => @fromBackingInt(@intCast(@backingInt(opt))),
443 _ => @fromBackingInt(@backingInt(opt)),
428444 };
429445 }
430446 };
431447
432448 fn toOptional(i: RelaIndex) RelaIndex.Optional {
433 return @fromBackingInt(@intCast(@backingInt(i)));
449 return @fromBackingInt(@backingInt(i));
434450 }
435451 };
436452
......@@ -465,8 +481,8 @@ const Section = struct {
465481
466482 pub fn fromSection(sec: std.elf.Section) Index {
467483 return switch (sec) {
468 std.elf.SHN_UNDEF...std.elf.SHN_LORESERVE - 1 => @fromBackingInt(@intCast(sec)),
469 std.elf.SHN_LORESERVE...std.elf.SHN_HIRESERVE => @fromBackingInt(@intCast(reserve(sec))),
484 std.elf.SHN_UNDEF...std.elf.SHN_LORESERVE - 1 => @fromBackingInt(sec),
485 std.elf.SHN_LORESERVE...std.elf.SHN_HIRESERVE => @fromBackingInt(reserve(sec)),
470486 };
471487 }
472488 pub fn toSection(s: Index) ?std.elf.Section {
......@@ -485,7 +501,7 @@ const Section = struct {
485501
486502 fn name(s: Index, elf: *Elf) String(.shstrtab) {
487503 return switch (elf.shdrPtr(s)) {
488 inline else => |shdr| @fromBackingInt(@intCast(elf.targetLoad(&shdr.name))),
504 inline else => |shdr| @fromBackingInt(elf.targetLoad(&shdr.name)),
489505 };
490506 }
491507
......@@ -928,21 +944,7 @@ const GotReloc = struct {
928944 }
929945 }
930946 fn applyInner(reloc: *const GotReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void {
931 const node_vaddr: u64 = switch (elf.getNode(reloc.node)) {
932 .file => unreachable,
933 .ehdr => unreachable,
934 .shdr => unreachable,
935 .segment => unreachable,
936 .copied_global => unreachable,
937 .section => |shndx| shndx.vaddr(elf),
938 .input_section => |isi| isi.ptrConst(elf).vaddr,
939 inline .nav,
940 .uav,
941 .lazy_code,
942 .lazy_const_data,
943 => |i| Symbol.Id.local(i.symbol(elf)).value(elf),
944 };
945 const dest_vaddr = node_vaddr + reloc.offset;
947 const dest_vaddr = elf.getNodeVAddr(reloc.node) + reloc.offset;
946948 const dest_slice = reloc.node.slice(&elf.mf)[@intCast(reloc.offset)..];
947949
948950 const got_vaddr = elf.shndx.got.vaddr(elf);
......@@ -1131,12 +1133,12 @@ pub const MachineRelocType = union {
11311133
11321134 pub fn wrap(int: u32, elf: *const Elf) MachineRelocType {
11331135 return switch (elf.ehdrMachine()) {
1134 .AARCH64 => .{ .AARCH64 = @fromBackingInt(@intCast(int)) },
1135 .LOONGARCH => .{ .LARCH = @fromBackingInt(@intCast(int)) },
1136 .PPC64 => .{ .PPC64 = @fromBackingInt(@intCast(int)) },
1137 .RISCV => .{ .RISCV = @fromBackingInt(@intCast(int)) },
1138 .SPARCV9 => .{ .SPARC = @fromBackingInt(@intCast(int)) },
1139 .X86_64 => .{ .X86_64 = @fromBackingInt(@intCast(int)) },
1136 .AARCH64 => .{ .AARCH64 = @fromBackingInt(int) },
1137 .LOONGARCH => .{ .LARCH = @fromBackingInt(int) },
1138 .PPC64 => .{ .PPC64 = @fromBackingInt(int) },
1139 .RISCV => .{ .RISCV = @fromBackingInt(int) },
1140 .SPARCV9 => .{ .SPARC = @fromBackingInt(int) },
1141 .X86_64 => .{ .X86_64 = @fromBackingInt(int) },
11401142 };
11411143 }
11421144 pub fn unwrap(rt: MachineRelocType, elf: *const Elf) u32 {
......@@ -1646,21 +1648,7 @@ const SymbolReloc = struct {
16461648 }
16471649 }
16481650 fn applyInner(reloc: *const SymbolReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void {
1649 const node_vaddr: u64 = switch (elf.getNode(reloc.node)) {
1650 .file => unreachable,
1651 .ehdr => unreachable,
1652 .shdr => unreachable,
1653 .segment => unreachable,
1654 .copied_global => unreachable,
1655 .section => |shndx| shndx.vaddr(elf),
1656 .input_section => |isi| isi.ptrConst(elf).vaddr,
1657 inline .nav,
1658 .uav,
1659 .lazy_code,
1660 .lazy_const_data,
1661 => |i| Symbol.Id.local(i.symbol(elf)).value(elf),
1662 };
1663 const dest_vaddr = node_vaddr + reloc.offset;
1651 const dest_vaddr = elf.getNodeVAddr(reloc.node) + reloc.offset;
16641652 const dest_slice = reloc.node.slice(&elf.mf)[@intCast(reloc.offset)..];
16651653
16661654 const addend: u64 = @bitCast(reloc.addend);
......@@ -1875,7 +1863,7 @@ fn addLocalSymbolAssumeCapacity(elf: *Elf, opts: AddLocalSymbolOptions) Symbol.L
18751863
18761864 // `shdr.info` stores the index of the first global symbol. We will replace it with our
18771865 // new local symbol, and move the global symbol to a new index at the end of the symtab.
1878 const target_index: Symbol.Index = @fromBackingInt(@intCast(elf.targetLoad(&shdr.info)));
1866 const target_index: Symbol.Index = @fromBackingInt(elf.targetLoad(&shdr.info));
18791867
18801868 const old_size = elf.targetLoad(&shdr.size);
18811869 const new_size = old_size + ent_size;
......@@ -1897,7 +1885,7 @@ fn addLocalSymbolAssumeCapacity(elf: *Elf, opts: AddLocalSymbolOptions) Symbol.L
18971885 // ...then the `elf.symtab` metadata...
18981886 new_index.ptr(elf).* = target_index.ptr(elf).*;
18991887 // ...then update the `elf.globals` tracking.
1900 const global_name: String(.strtab) = @fromBackingInt(@intCast(elf.targetLoad(&new_sym.name)));
1888 const global_name: String(.strtab) = @fromBackingInt(elf.targetLoad(&new_sym.name));
19011889 elf.globalByName(global_name).?.symtab_index = new_index;
19021890
19031891 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
19231911 std.mem.byteSwapAllFields(class.ElfN().Sym, target_sym);
19241912 }
19251913
1926 return @fromBackingInt(@intCast(@backingInt(target_index)));
1914 return @fromBackingInt(@backingInt(target_index));
19271915 },
19281916 }
19291917}
......@@ -2371,7 +2359,7 @@ fn moveDemotedGlobal(elf: *Elf, global_ptr: *Symbol.Global) void {
23712359 inline else => |shdr, class| {
23722360 // `shdr.info` stores the index of the first global symbol. We are going to swap the
23732361 // demoted symbol with that first global symbol, then increment that start index.
2374 const dest_index: Symbol.Index = @fromBackingInt(@intCast(elf.targetLoad(&shdr.info)));
2362 const dest_index: Symbol.Index = @fromBackingInt(elf.targetLoad(&shdr.info));
23752363 const src_index = global_ptr.symtab_index;
23762364
23772365 // 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 {
23872375 const src_sym_ptr = @field(elf.symPtr(src_index), @tagName(class));
23882376 const dest_sym_ptr = @field(elf.symPtr(dest_index), @tagName(class));
23892377
2390 const this_name: String(.strtab) = @fromBackingInt(@intCast(elf.targetLoad(&src_sym_ptr.name)));
2378 const this_name: String(.strtab) = @fromBackingInt(elf.targetLoad(&src_sym_ptr.name));
23912379 assert(elf.globalByName(this_name).? == global_ptr);
23922380
2393 const other_name: String(.strtab) = @fromBackingInt(@intCast(elf.targetLoad(&dest_sym_ptr.name)));
2381 const other_name: String(.strtab) = @fromBackingInt(elf.targetLoad(&dest_sym_ptr.name));
23942382 const other_global_ptr = elf.globalByName(other_name).?;
23952383 assert(other_global_ptr.symtab_index == dest_index);
23962384
......@@ -2426,7 +2414,7 @@ fn moveDemotedGlobal(elf: *Elf, global_ptr: *Symbol.Global) void {
24262414 const src_dynsym_ptr = @field(elf.dynsymPtr(remove_dynsym_index), @tagName(class));
24272415 const dest_dynsym_ptr = @field(elf.dynsymPtr(free_dynsym_index), @tagName(class));
24282416
2429 const moved_name_dynstr: String(.dynstr) = @fromBackingInt(@intCast(elf.targetLoad(&src_dynsym_ptr.name)));
2417 const moved_name_dynstr: String(.dynstr) = @fromBackingInt(elf.targetLoad(&src_dynsym_ptr.name));
24302418 const moved_name = elf.stringExisting(.strtab, moved_name_dynstr.slice(elf));
24312419 const moved_global_ptr = elf.globalByName(moved_name).?;
24322420
......@@ -2505,7 +2493,7 @@ const Symbol = struct {
25052493 _,
25062494
25072495 fn index(li: LocalIndex) Index {
2508 return @fromBackingInt(@intCast(@backingInt(li)));
2496 return @fromBackingInt(@backingInt(li));
25092497 }
25102498 };
25112499
......@@ -2527,16 +2515,16 @@ const Symbol = struct {
25272515 global: String(.strtab),
25282516 } {
25292517 return switch (s.kind) {
2530 .local => .{ .local = @fromBackingInt(@intCast(s.raw)) },
2531 .global => .{ .global = @fromBackingInt(@intCast(s.raw)) },
2518 .local => .{ .local = @fromBackingInt(s.raw) },
2519 .global => .{ .global = @fromBackingInt(s.raw) },
25322520 };
25332521 }
25342522
25352523 fn toTypeErased(s: Symbol.Id) link.File.SymbolId {
2536 return @fromBackingInt(@intCast(@as(u32, @bitCast(s))));
2524 return @bitCast(s);
25372525 }
25382526 fn fromTypeErased(s: link.File.SymbolId) Symbol.Id {
2539 return @bitCast(@backingInt(s));
2527 return @bitCast(s);
25402528 }
25412529
25422530 fn index(s: Symbol.Id, elf: *const Elf) Symbol.Index {
......@@ -2648,24 +2636,10 @@ const Symbol = struct {
26482636 .yes_textrel => elf.textrel_count += 1,
26492637 .yes => {},
26502638 }
2651 const node_vaddr: u64 = switch (elf.getNode(reloc.node)) {
2652 .file => unreachable,
2653 .ehdr => unreachable,
2654 .shdr => unreachable,
2655 .segment => unreachable,
2656 .copied_global => unreachable,
2657 .section => |shndx| shndx.vaddr(elf),
2658 .input_section => |isi| isi.ptrConst(elf).vaddr,
2659 inline .nav,
2660 .uav,
2661 .lazy_code,
2662 .lazy_const_data,
2663 => |i| Symbol.Id.local(i.symbol(elf)).value(elf),
2664 };
26652639 // There is capacity for a relocation because we just deleted one earlier.
26662640 reloc.rela_index = elf.shndx.rela_dyn.relaAddOneAssumeCapacity(elf, .{
26672641 .type = .relative(elf),
2668 .offset = node_vaddr + reloc.offset,
2642 .offset = elf.getNodeVAddr(reloc.node) + reloc.offset,
26692643 .raw_sym_index = 0,
26702644 .addend = 0,
26712645 }).toOptional();
......@@ -2771,11 +2745,14 @@ fn classifySymbolValue(elf: *Elf, sym: Symbol.Id) enum {
27712745
27722746pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId {
27732747 const lsi: Symbol.LocalIndex = switch (elf.getNode(Node.fromAtom(atom))) {
2774 .file,
2748 .archive,
2749 .archive_header,
2750 .elf,
27752751 .ehdr,
27762752 .shdr,
27772753 .segment,
27782754 .section,
2755 .input_member,
27792756 .input_section,
27802757 .copied_global,
27812758 => unreachable,
......@@ -3001,12 +2978,12 @@ fn String(section: StringSection) type {
30012978}
30022979fn string(elf: *Elf, comptime section: StringSection, key: []const u8) Error!String(section) {
30032980 const st: *StringTable = &@field(elf, @tagName(section));
3004 return @fromBackingInt(@intCast(try st.get(elf, section.shndx(elf), key)));
2981 return @fromBackingInt(try st.get(elf, section.shndx(elf), key));
30052982}
30062983/// Like `string`, but asserts that the string is already in `section`.
30072984fn stringExisting(elf: *Elf, comptime section: StringSection, key: []const u8) String(section) {
30082985 const st: *StringTable = &@field(elf, @tagName(section));
3009 return @fromBackingInt(@intCast(st.getExisting(elf, section.shndx(elf), key)));
2986 return @fromBackingInt(st.getExisting(elf, section.shndx(elf), key));
30102987}
30112988
30122989const StringTable = struct {
......@@ -3033,7 +3010,7 @@ const StringTable = struct {
30333010 }
30343011
30353012 pub fn hash(_: Adapter, key: []const u8) u64 {
3036 assert(std.mem.indexOfScalar(u8, key, 0) == null);
3013 assert(std.mem.findScalar(u8, key, 0) == null);
30373014 return std.hash_map.hashString(key);
30383015 }
30393016 };
......@@ -3172,6 +3149,16 @@ fn create(
31723149 .options = options,
31733150 .mf = try .init(file, comp.gpa, io),
31743151 .ni = .{
3152 .archive = .root,
3153 .archive_header = .none,
3154 .elf = .root,
3155 .ehdr = .none,
3156 .shdr = .none,
3157 .rodata = .none,
3158 .phdr = .none,
3159 .text = .none,
3160 .data = .none,
3161 .data_rel_ro = .none,
31753162 .tls = .none,
31763163 },
31773164 .nodes = .empty,
......@@ -3218,6 +3205,7 @@ fn create(
32183205 .dynamic_first_symbol_reloc = .none,
32193206 .needed = .empty,
32203207 .inputs = .empty,
3208 .input_pending_index = 0,
32213209 .input_sections = .empty,
32223210 .input_section_pending_index = 0,
32233211 .navs = .empty,
......@@ -3293,6 +3281,7 @@ fn initHeaders(
32933281 const comp = elf.base.comp;
32943282 const gpa = comp.gpa;
32953283
3284 const is_archive = comp.config.output_mode == .Lib and comp.config.link_mode == .static;
32963285 const have_dynamic_section = switch (@"type") {
32973286 .REL => false,
32983287 .EXEC => comp.config.link_mode == .dynamic,
......@@ -3389,7 +3378,8 @@ fn initHeaders(
33893378 }, phnum };
33903379 };
33913380
3392 const expected_nodes_len = 3 + // `.file`, `.ehdr`, and `.shdr` nodes
3381 const expected_nodes_len = @as(usize, if (is_archive) 2 else 0) + // .archive, .archive_header
3382 3 + // `.file`, `.ehdr`, and `.shdr` nodes
33933383 (shnum - 1) + // -1 because the null shdr does not have a `.section` node
33943384 (phnum -| 1); // -1 because the GNU_STACK phdr does not have a `.segment` node
33953385
......@@ -3398,17 +3388,49 @@ fn initHeaders(
33983388 try elf.section_by_name.ensureUnusedCapacity(gpa, shnum);
33993389 try elf.phdrs.resize(gpa, phnum);
34003390 try elf.symtab.ensureTotalCapacity(gpa, 1);
3401 elf.nodes.appendAssumeCapacity(.file);
3391
3392 if (is_archive) {
3393 elf.nodes.appendAssumeCapacity(.archive);
3394 elf.ni.archive_header = try elf.mf.addOnlyChildNode(gpa, elf.ni.archive, .{
3395 .size = std.elf.ARMAG.len + @sizeOf(std.elf.ar_hdr) * 2,
3396 .alignment = .@"2",
3397 .fixed = true,
3398 .next_moved = true,
3399 .bubbles_moved = false,
3400 .enable_next_moved = true,
3401 });
3402 const archive_header_slice = elf.ni.archive_header.slice(&elf.mf);
3403 @memcpy(archive_header_slice[0..std.elf.ARMAG.len], std.elf.ARMAG);
3404 const strtab_ar_hdr: *std.elf.ar_hdr = @ptrCast(archive_header_slice[std.elf.ARMAG.len..]);
3405 strtab_ar_hdr.* = .{
3406 .ar_name = std.elf.STRNAME.*,
3407 .ar_date = @splat(' '),
3408 .ar_uid = @splat(' '),
3409 .ar_gid = @splat(' '),
3410 .ar_mode = @splat(' '),
3411 .ar_size = @splat(' '),
3412 .ar_fmag = std.elf.ARFMAG.*,
3413 };
3414
3415 elf.nodes.appendAssumeCapacity(.archive_header);
3416 elf.ni.elf = try elf.mf.addLastChildNode(gpa, elf.ni.archive, .{
3417 .alignment = elf.mf.flags.block_size.max(.@"2"),
3418 .next_moved = true,
3419 .bubbles_moved = false,
3420 .enable_next_moved = true,
3421 });
3422 }
3423 elf.nodes.appendAssumeCapacity(.elf);
34023424
34033425 const entsize: struct { ph: u32, sh: u32 } = switch (class) {
34043426 .NONE, _ => unreachable,
34053427 inline else => |ct_class| entsize: {
34063428 const ElfN = ct_class.ElfN();
3407 assert(elf.ni.ehdr == try elf.mf.addOnlyChildNode(gpa, elf.ni.file, .{
3429 elf.ni.ehdr = try elf.mf.addLastChildNode(gpa, elf.ni.elf, .{
34083430 .size = @sizeOf(ElfN.Ehdr),
34093431 .alignment = addr_align,
34103432 .fixed = true,
3411 }));
3433 });
34123434 elf.nodes.appendAssumeCapacity(.ehdr);
34133435
34143436 const ehdr: *ElfN.Ehdr = @ptrCast(@alignCast(elf.ni.ehdr.slice(&elf.mf)));
......@@ -3461,12 +3483,12 @@ fn initHeaders(
34613483 },
34623484 };
34633485
3464 assert(elf.ni.shdr == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{
3486 elf.ni.shdr = try elf.mf.addLastChildNode(gpa, elf.ni.elf, .{
34653487 .size = 1 * entsize.sh, // as above, only the null shdr initially
34663488 .alignment = elf.mf.flags.block_size,
34673489 .moved = true,
34683490 .resized = true,
3469 }));
3491 });
34703492 elf.nodes.appendAssumeCapacity(.shdr);
34713493
34723494 const page_align: std.mem.Alignment = .fromByteUnits(switch (machine) {
......@@ -3491,45 +3513,45 @@ fn initHeaders(
34913513 });
34923514
34933515 var ph_vaddr: u32 = if (@"type" != .REL) ph_vaddr: {
3494 assert(elf.ni.rodata == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{
3516 elf.ni.rodata = try elf.mf.addLastChildNode(gpa, elf.ni.elf, .{
34953517 .alignment = elf.mf.flags.block_size,
34963518 .moved = true,
34973519 .bubbles_moved = false,
3498 }));
3520 });
34993521 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.rodata });
35003522 elf.phdrs.items[phndx.rodata] = elf.ni.rodata;
35013523
3502 assert(elf.ni.phdr == try elf.mf.addOnlyChildNode(gpa, elf.ni.rodata, .{
3524 elf.ni.phdr = try elf.mf.addOnlyChildNode(gpa, elf.ni.rodata, .{
35033525 .size = @as(u64, phnum) * entsize.ph,
35043526 .alignment = addr_align,
35053527 .moved = true,
35063528 .resized = true,
35073529 .bubbles_moved = false,
3508 }));
3530 });
35093531 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.phdr });
35103532 elf.phdrs.items[phndx.phdr] = elf.ni.phdr;
35113533
3512 assert(elf.ni.text == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{
3534 elf.ni.text = try elf.mf.addLastChildNode(gpa, elf.ni.elf, .{
35133535 .alignment = elf.mf.flags.block_size,
35143536 .moved = true,
35153537 .bubbles_moved = false,
3516 }));
3538 });
35173539 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.text });
35183540 elf.phdrs.items[phndx.text] = elf.ni.text;
35193541
3520 assert(elf.ni.data == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{
3542 elf.ni.data = try elf.mf.addLastChildNode(gpa, elf.ni.elf, .{
35213543 .alignment = elf.mf.flags.block_size,
35223544 .moved = true,
35233545 .bubbles_moved = false,
3524 }));
3546 });
35253547 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.data });
35263548 elf.phdrs.items[phndx.data] = elf.ni.data;
35273549
3528 assert(elf.ni.data_rel_ro == try elf.mf.addOnlyChildNode(gpa, elf.ni.data, .{
3550 elf.ni.data_rel_ro = try elf.mf.addOnlyChildNode(gpa, elf.ni.data, .{
35293551 .alignment = elf.mf.flags.block_size,
35303552 .moved = true,
35313553 .bubbles_moved = false,
3532 }));
3554 });
35333555 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.relro });
35343556 elf.phdrs.items[phndx.relro] = elf.ni.data_rel_ro;
35353557
......@@ -3706,7 +3728,7 @@ fn initHeaders(
37063728 .node = .none,
37073729 .first_target_reloc = .none,
37083730 };
3709 assert(.symtab == try elf.addSection(elf.ni.file, .{
3731 assert(.symtab == try elf.addSection(elf.ni.elf, .{
37103732 .type = .SYMTAB,
37113733 .size = @sizeOf(ElfN.Sym) * 1,
37123734 .addralign = addr_align,
......@@ -3729,7 +3751,7 @@ fn initHeaders(
37293751 ehdr.shstrndx = ehdr.shnum;
37303752 },
37313753 }
3732 assert(.shstrtab == try elf.addSection(elf.ni.file, .{
3754 assert(.shstrtab == try elf.addSection(elf.ni.elf, .{
37333755 .type = .STRTAB,
37343756 .size = 1,
37353757 .entsize = 1,
......@@ -3740,7 +3762,7 @@ fn initHeaders(
37403762 try Section.Index.symtab.rename(elf, ".symtab");
37413763 try Section.Index.shstrtab.rename(elf, ".shstrtab");
37423764
3743 assert(.strtab == try elf.addSection(elf.ni.file, .{
3765 assert(.strtab == try elf.addSection(elf.ni.elf, .{
37443766 .name = ".strtab",
37453767 .type = .STRTAB,
37463768 .size = 1,
......@@ -4210,6 +4232,8 @@ fn initHeaders(
42104232 break :str try elf.string(.dynstr, slice);
42114233 },
42124234 };
4235
4236 try elf.ensureElfNodeSize();
42134237}
42144238
42154239pub 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 {
42214245 break :count count;
42224246 });
42234247 elf.mf.update_prog_node = prog_node.start("Relocations", elf.mf.updates.items.len);
4224 elf.input_prog_node = prog_node.start(
4225 "Inputs",
4226 elf.input_sections.items.len - elf.input_section_pending_index,
4227 );
4248 elf.input_prog_node = prog_node.start("Inputs", (elf.inputs.items.len - elf.input_pending_index) +
4249 (elf.input_sections.items.len - elf.input_section_pending_index));
42284250}
42294251
42304252pub fn endProgress(elf: *Elf) void {
......@@ -4244,13 +4266,15 @@ fn getNode(elf: *const Elf, ni: MappedFile.Node.Index) Node {
42444266/// Asserts that `ni` is a section, input section, copied global, NAV, UAV, or lazy code/data.
42454267fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {
42464268 return switch (elf.getNode(ni)) {
4247 .file => unreachable,
4248 .ehdr => unreachable,
4249 .shdr => unreachable,
4250 .segment => unreachable,
4251
4269 .archive,
4270 .archive_header,
4271 .elf,
4272 .ehdr,
4273 .shdr,
4274 .segment,
4275 .input_member,
4276 => unreachable,
42524277 .section => |shndx| shndx,
4253
42544278 .input_section,
42554279 .copied_global,
42564280 .nav,
......@@ -4260,21 +4284,44 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {
42604284 => elf.getNode(ni.parent(&elf.mf)).section,
42614285 };
42624286}
4287fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
4288 return switch (elf.getNode(ni)) {
4289 .archive,
4290 .archive_header,
4291 .elf,
4292 .ehdr,
4293 .shdr,
4294 .segment,
4295 .input_member,
4296 .copied_global,
4297 => unreachable,
4298 .section => |shndx| shndx.vaddr(elf),
4299 .input_section => |isi| isi.ptrConst(elf).vaddr,
4300 inline .nav,
4301 .uav,
4302 .lazy_code,
4303 .lazy_const_data,
4304 => |i| Symbol.Id.local(i.symbol(elf)).value(elf),
4305 };
4306}
42634307fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
42644308 const parent_vaddr = switch (elf.getNode(ni.parent(&elf.mf))) {
4265 .file => return 0,
4309 .archive, .archive_header => unreachable,
4310 .elf => return 0,
42664311 .ehdr, .shdr => unreachable,
42674312 .segment => |phndx| switch (elf.phdrSlice()) {
42684313 inline else => |phdr| elf.targetLoad(&phdr[phndx].vaddr),
42694314 },
42704315 .section => |shndx| if (shndx == elf.shndx.tdata) 0 else shndx.vaddr(elf),
4271 .input_section => unreachable,
4272 .copied_global => unreachable,
4316 .input_member, .input_section, .copied_global => unreachable,
42734317 inline .nav, .uav, .lazy_code, .lazy_const_data => |i| Symbol.Id.local(i.symbol(elf)).value(elf),
42744318 };
42754319 const offset, _ = ni.location(&elf.mf).resolve(&elf.mf);
42764320 return parent_vaddr + offset;
42774321}
4322fn getNodeElfOffset(elf: *Elf, ni: MappedFile.Node.Index) u64 {
4323 return ni.fileLocation(&elf.mf, false).offset - elf.ni.elf.fileLocation(&elf.mf, false).offset;
4324}
42784325
42794326/// Deletes any existing relocations in the given node, and marks the start of the node's contiguous
42804327/// 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 {
42834330/// the special-case sections '.plt' and '.dynamic'.
42844331fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
42854332 const symbol_relocs: *SymbolReloc.Index, const got_relocs: ?*GotReloc.Index = switch (elf.getNode(ni)) {
4286 .file => unreachable, // cannot contain relocs
4287 .ehdr => unreachable, // cannot contain relocs
4288 .shdr => unreachable, // cannot contain relocs
4289 .segment => unreachable, // cannot contain relocs
4333 .archive,
4334 .archive_header,
4335 .elf,
4336 .ehdr,
4337 .shdr,
4338 .segment,
4339 .input_member,
4340 .copied_global,
4341 => unreachable, // cannot contain relocs
42904342 .section => unreachable, // cannot contain relocs (.plt and .dynamic unsupported)
4291 .copied_global => unreachable, // cannot contain relocs
42924343 .input_section => |isi| .{
42934344 &elf.input_sections.items[@backingInt(isi)].first_symbol_reloc,
42944345 &elf.input_sections.items[@backingInt(isi)].first_got_reloc,
......@@ -4359,7 +4410,7 @@ fn flushMovedNodeRelocs(
43594410}
43604411
43614412fn identClass(elf: *const Elf) std.elf.CLASS {
4362 return @fromBackingInt(@intCast(elf.mf.memory_map.memory[std.elf.EI.CLASS]));
4413 return @fromBackingInt(elf.ni.elf.sliceConst(&elf.mf)[std.elf.EI.CLASS]);
43634414}
43644415
43654416/// 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 {
44154466 return elf.identClass().size();
44164467}
44174468fn targetEndian(elf: *const Elf) std.lang.Endian {
4418 const ident_data: std.elf.DATA = @fromBackingInt(@intCast(elf.mf.memory_map.memory[std.elf.EI.DATA]));
4469 const ident_data: std.elf.DATA = @fromBackingInt(elf.ni.elf.sliceConst(&elf.mf)[std.elf.EI.DATA]);
44194470 return ident_data.endian();
44204471}
44214472fn targetTlsVariant(elf: *const Elf) union(enum) {
......@@ -4487,7 +4538,7 @@ fn targetLoad(elf: *const Elf, ptr: anytype) @typeInfo(@TypeOf(ptr)).pointer.chi
44874538 return switch (@typeInfo(Child)) {
44884539 else => @compileError(@typeName(Child)),
44894540 .int => std.mem.toNative(Child, ptr.*, elf.targetEndian()),
4490 .@"enum" => |@"enum"| @fromBackingInt(@intCast(elf.targetLoad(@as(*align(alignment) const @"enum".tag_type, @ptrCast(ptr))))),
4541 .@"enum" => |@"enum"| @fromBackingInt(elf.targetLoad(@as(*align(alignment) const @"enum".tag_type, @ptrCast(ptr)))),
44914542 .@"struct" => |@"struct"| @bitCast(
44924543 elf.targetLoad(@as(*align(alignment) @"struct".backing_integer.?, @ptrCast(ptr))),
44934544 ),
......@@ -4563,6 +4614,16 @@ fn shdrPtr(elf: *Elf, shndx: Section.Index) ShdrPtr {
45634614 }
45644615}
45654616
4617fn arHdrPtr(elf: *Elf, ni: MappedFile.Node.Index) *align(2) std.elf.ar_hdr {
4618 assert(elf.ni.elf != MappedFile.Node.Index.root);
4619 const file_offset = ni.fileLocation(&elf.mf, false).offset;
4620 return @ptrCast(@alignCast(elf.mf.memory_map.memory[@intCast(switch (elf.getNode(ni)) {
4621 else => unreachable,
4622 .archive_header => file_offset + std.elf.ARMAG.len,
4623 .elf, .input_member => file_offset - @sizeOf(std.elf.ar_hdr),
4624 })..][0..@sizeOf(std.elf.ar_hdr)]));
4625}
4626
45664627const SymPtr = union(std.elf.CLASS) {
45674628 NONE: noreturn,
45684629 @"32": *std.elf.Elf32.Sym,
......@@ -4657,7 +4718,7 @@ fn mapInputSection(elf: *Elf, opts: struct {
46574718 }
46584719 errdefer assert(elf.section_by_name.pop().?.key == name_shstrtab);
46594720 const parent_node: MappedFile.Node.Index = parent: {
4660 if (!opts.flags.ALLOC) break :parent elf.ni.file;
4721 if (!opts.flags.ALLOC) break :parent elf.ni.elf;
46614722 if (opts.flags.EXECINSTR) break :parent elf.ni.text;
46624723 if (opts.flags.TLS) break :parent elf.ni.tls;
46634724 if (opts.flags.WRITE) break :parent elf.ni.data;
......@@ -4782,11 +4843,11 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node
47824843 break :a switch (nav.resolved.?.@"align") {
47834844 else => |a| a.maxStrict(min),
47844845 .none => switch (mod.optimize_mode) {
4785 .Debug,
4786 .ReleaseSafe,
4787 .ReleaseFast,
4846 .debug,
4847 .safe,
4848 .fast,
47884849 => target_util.defaultFunctionAlignment(target),
4789 .ReleaseSmall => min,
4850 .small => min,
47904851 }.maxStrict(Type.fromInterned(nav.resolved.?.type).abiAlignment(zcu)),
47914852 };
47924853 },
......@@ -4878,7 +4939,7 @@ const LoadParseInputError = Error || Io.File.SeekError || Io.Reader.Error;
48784939/// indicates to the frontend that the input could be a GNU ld script instead.
48794940pub fn loadInput(elf: *Elf, input: link.Input) (link.Error || error{BadMagic})!void {
48804941 const diags = &elf.base.comp.link_diags;
4881 return elf.loadInputInner(input) catch |err| switch (err) {
4942 elf.loadInputInner(input) catch |err| switch (err) {
48824943 else => |e| return e,
48834944 error.MappedFileIo => return diags.fail(
48844945 "failed to write output file: {t}",
......@@ -4986,6 +5047,9 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (Load
49865047 const r = &fr.interface;
49875048
49885049 log.debug("loadArchive({f})", .{path.fmtEscapeString()});
5050
5051 if (elf.ehdrType() == .REL) return; // this input does not affect the output artifact
5052
49895053 {
49905054 const magic = r.take(std.elf.ARMAG.len) catch |err| switch (err) {
49915055 error.ReadFailed => |e| return e,
......@@ -5071,21 +5135,40 @@ fn loadObject(
50715135 .{},
50725136 ),
50735137 };
5138
5139 const input = try elf.inputs.addOne(gpa);
5140 input.* = .{
5141 .path = path,
5142 .member = if (member) |m| try gpa.dupe(u8, m) else null,
5143 .extra = undefined,
5144 };
5145 if (elf.ni.elf != MappedFile.Node.Index.root) {
5146 try elf.nodes.ensureUnusedCapacity(gpa, 1);
5147 input.extra = .{ .node = try elf.mf.addLastChildNode(gpa, .root, .{
5148 .size = fl.size + @sizeOf(std.elf.ar_hdr),
5149 .alignment = .@"2",
5150 .next_moved = true,
5151 .bubbles_moved = false,
5152 .enable_next_moved = true,
5153 }) };
5154 elf.nodes.appendAssumeCapacity(.{ .input_member = input_index });
5155 elf.input_prog_node.increaseEstimatedTotalItems(1);
5156
5157 // Since we are not emitting the archive symbol table (yet?) we do not need to parse
5158 // the symbols in this input.
5159 return;
5160 }
5161
5162 elf.input_pending_index += 1;
50745163 try elf.ensureUnusedSymbolCapacity(1, .all_local);
5075 try elf.inputs.ensureUnusedCapacity(gpa, 1);
5076 const file_symbol = elf.addLocalSymbolAssumeCapacity(.{
5164 input.extra = .{ .file_symbol = elf.addLocalSymbolAssumeCapacity(.{
50775165 .node = .none,
50785166 .name = try elf.string(.strtab, std.fs.path.stem(member orelse path.sub_path)),
50795167 .value = 0,
50805168 .size = 0,
50815169 .type = .FILE,
50825170 .shndx = .ABS,
5083 });
5084 elf.inputs.addOneAssumeCapacity().* = .{
5085 .path = path,
5086 .member = if (member) |m| try gpa.dupe(u8, m) else null,
5087 .file_symbol = file_symbol,
5088 };
5171 }) };
50895172 const target_endian = elf.targetEndian();
50905173 switch (elf.identClass()) {
50915174 .NONE, _ => unreachable,
......@@ -5267,7 +5350,7 @@ fn loadObject(
52675350 .first_symbol_reloc = .none,
52685351 .first_got_reloc = .none,
52695352 };
5270 elf.synth_prog_node.increaseEstimatedTotalItems(1);
5353 elf.input_prog_node.increaseEstimatedTotalItems(1);
52715354 }
52725355 var symmap: std.ArrayList(Symbol.Id) = .empty;
52735356 defer symmap.deinit(gpa);
......@@ -5479,6 +5562,9 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (LoadPars
54795562
54805563 log.debug("loadDso({f})", .{path.fmtEscapeString()});
54815564 try elf.checkInputIdent(path, r);
5565
5566 if (elf.ehdrType() == .REL) return; // this input does not affect the output artifact
5567
54825568 const target_endian = elf.targetEndian();
54835569 switch (elf.identClass()) {
54845570 .NONE, _ => unreachable,
......@@ -5709,7 +5795,8 @@ fn checkInputIdent(
57095795 }
57105796
57115797 const ident = try r.peekStructPointer(std.elf.Ident);
5712 const target: *const std.elf.Ident = @ptrCast(elf.mf.memory_map.memory[0..@sizeOf(std.elf.Ident)]);
5798 const target: *const std.elf.Ident =
5799 @ptrCast(elf.ni.elf.sliceConst(&elf.mf)[0..@sizeOf(std.elf.Ident)]);
57135800
57145801 if (ident.class != target.class) return diags.failParse(
57155802 path,
......@@ -5812,7 +5899,9 @@ fn updateInitFiniArraySectionSize(
58125899}
58135900
58145901pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) link.Error!void {
5815 _ = prog_node;
5902 const sub_prog_node = prog_node.start("ELF Prelink", 0);
5903 defer sub_prog_node.end();
5904
58165905 const diags = &elf.base.comp.link_diags;
58175906 elf.prelinkInner() catch |err| switch (err) {
58185907 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
......@@ -5823,13 +5912,11 @@ fn prelinkInner(elf: *Elf) Error!void {
58235912 const comp = elf.base.comp;
58245913 const gpa = comp.gpa;
58255914
5826 if (comp.zcu != null and !comp.config.use_llvm) {
5827 // We're use self-hosted codegen---add an input representing the Zig "object".
5915 if (comp.zcu != null and !comp.config.use_llvm and elf.ni.elf == MappedFile.Node.Index.root) {
5916 // We're using self-hosted codegen---add an input representing the Zig "object".
58285917 try elf.ensureUnusedSymbolCapacity(1, .all_local);
58295918 try elf.inputs.ensureUnusedCapacity(gpa, 1);
5830 const zcu_name = try std.fmt.allocPrint(gpa, "{s}_zcu", .{
5831 std.fs.path.stem(elf.base.emit.sub_path),
5832 });
5919 const zcu_name = try std.fmt.allocPrint(gpa, "{s}_zcu", .{comp.root_name});
58335920 defer gpa.free(zcu_name);
58345921 const zcu_file_symbol = elf.addLocalSymbolAssumeCapacity(.{
58355922 .node = .none,
......@@ -5842,9 +5929,12 @@ fn prelinkInner(elf: *Elf) Error!void {
58425929 elf.inputs.addOneAssumeCapacity().* = .{
58435930 .path = elf.base.emit,
58445931 .member = null,
5845 .file_symbol = zcu_file_symbol,
5932 .extra = .{ .file_symbol = zcu_file_symbol },
58465933 };
5934 elf.input_pending_index += 1;
58475935 }
5936
5937 try elf.ensureElfNodeSize();
58485938}
58495939
58505940fn prepareDynamic(elf: *Elf) Error!void {
......@@ -6034,12 +6124,12 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
60346124 },
60356125 };
60366126 assert(shndx < @backingInt(Section.Index.LORESERVE));
6037 break :shndx .{ @fromBackingInt(@intCast(shndx)), @as(u64, elf.targetLoad(&ehdr.shentsize)) * @as(u64, shnum) };
6127 break :shndx .{ @fromBackingInt(shndx), @as(u64, elf.targetLoad(&ehdr.shentsize)) * @as(u64, shnum) };
60386128 },
60396129 };
60406130 try elf.ensureNodeSize(elf.ni.shdr, new_shdr_size);
60416131 const ni = try elf.mf.addLastChildNode(gpa, switch (elf.ehdrType()) {
6042 .REL => elf.ni.file,
6132 .REL => elf.ni.elf,
60436133 .EXEC, .DYN => segment_ni,
60446134 }, .{
60456135 .size = opts.size,
......@@ -6062,7 +6152,6 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
60626152 else => .{ .shndx = .UNDEF },
60636153 } });
60646154 elf.nodes.appendAssumeCapacity(.{ .section = shndx });
6065 const offset = ni.fileLocation(&elf.mf, false).offset;
60666155 switch (elf.shdrPtr(shndx)) {
60676156 inline else => |shdr, class| {
60686157 shdr.* = .{
......@@ -6070,7 +6159,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
60706159 .type = opts.type,
60716160 .flags = .{ .shf = opts.flags },
60726161 .addr = @intCast(addr),
6073 .offset = @intCast(offset),
6162 .offset = @intCast(elf.getNodeElfOffset(ni)),
60746163 .size = @intCast(opts.size),
60756164 .link = opts.link,
60766165 .info = opts.info,
......@@ -6504,20 +6593,7 @@ fn addSymbolRelocAssumeCapacity(
65046593
65056594 // If we emit a runtime relocation entry, its `offset` is a virtual address, so we need to
65066595 // determine the vaddr of `node`.
6507 const node_vaddr: u64 = switch (elf.getNode(node)) {
6508 .file => unreachable,
6509 .ehdr => unreachable,
6510 .shdr => unreachable,
6511 .segment => unreachable,
6512 .copied_global => unreachable,
6513 .section => |shndx| shndx.vaddr(elf),
6514 .input_section => |isi| isi.ptrConst(elf).vaddr,
6515 inline .nav,
6516 .uav,
6517 .lazy_code,
6518 .lazy_const_data,
6519 => |i| Symbol.Id.local(i.symbol(elf)).value(elf),
6520 };
6596 const node_vaddr = elf.getNodeVAddr(node);
65216597
65226598 // If this is `true`, we will try to create a copy relocation for the target symbol if it is
65236599 // not locally defined. If the relocation value is always computed from the target symbol's
......@@ -6656,20 +6732,23 @@ fn addGotRelocAssumeCapacity(
66566732) void {
66576733 assert(elf.ehdrType() != .REL);
66586734 switch (elf.getNode(node)) {
6735 .archive,
6736 .archive_header,
6737 .elf,
6738 .ehdr,
6739 .shdr,
6740 .segment,
6741 .input_member,
6742 .copied_global,
6743 => unreachable, // cannot contain relocs,
6744 .section,
6745 .uav,
6746 => unreachable, // cannot contain GOT relocs
66596747 .input_section,
66606748 .nav,
66616749 .lazy_code,
66626750 .lazy_const_data,
66636751 => {},
6664
6665 .section => unreachable, // cannot contain GOT relocs
6666 .uav => unreachable, // cannot contain GOT relocs
6667
6668 .file => unreachable, // cannot contain relocs
6669 .ehdr => unreachable, // cannot contain relocs
6670 .shdr => unreachable, // cannot contain relocs
6671 .segment => unreachable, // cannot contain relocs
6672 .copied_global => unreachable, // cannot contain relocs
66736752 }
66746753
66756754 const gop = elf.got.getOrPutAssumeCapacity(target);
......@@ -7053,11 +7132,24 @@ pub fn flush(
70537132 tid: Zcu.PerThread.Id,
70547133 prog_node: std.Progress.Node,
70557134) link.Error!void {
7135 elf.flushInner(arena, tid, prog_node) catch |err| switch (err) {
7136 error.MappedFileIo => return elf.base.comp.link_diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
7137 else => |e| return e,
7138 };
7139}
7140fn flushInner(
7141 elf: *Elf,
7142 arena: std.mem.Allocator,
7143 tid: Zcu.PerThread.Id,
7144 prog_node: std.Progress.Node,
7145) Error!void {
70567146 const comp = elf.base.comp;
70577147 const diags = &comp.link_diags;
7058 _ = prog_node;
70597148 _ = arena;
70607149
7150 const sub_prog_node = prog_node.start("ELF Flush", 0);
7151 defer sub_prog_node.end();
7152
70617153 if (comp.config.output_mode == .Exe) {
70627154 var any_undef = false;
70637155 for (elf.globals.strong_undef.keys()) |name| {
......@@ -7068,11 +7160,9 @@ pub fn flush(
70687160 if (any_undef) return error.AlreadyReported;
70697161 }
70707162
7071 elf.prepareDynamic() catch |err| switch (err) {
7072 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
7073 else => |e| return e,
7074 };
7163 try elf.prepareDynamic();
70757164
7165 try elf.ensureElfNodeSize();
70767166 while (try elf.idle(tid)) {}
70777167
70787168 // We've done the final `idle` loop, so everything is at its final place in the file. We have a
......@@ -7097,10 +7187,7 @@ pub fn flush(
70977187 .enabled => "_start",
70987188 .named => |named| named,
70997189 };
7100 const sym_name_strtab = elf.string(.strtab, sym_name_slice) catch |err| switch (err) {
7101 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
7102 else => |e| return e,
7103 };
7190 const sym_name_strtab = try elf.string(.strtab, sym_name_slice);
71047191 if (elf.globalByName(sym_name_strtab) == null) break :entry 0;
71057192 break :entry Symbol.Id.global(sym_name_strtab).value(elf);
71067193 };
......@@ -7108,10 +7195,11 @@ pub fn flush(
71087195 inline else => |ehdr| elf.targetStore(&ehdr.entry, @intCast(entry_addr)),
71097196 }
71107197
7111 elf.mf.flush() catch |err| switch (err) {
7112 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
7113 else => |e| return e,
7114 };
7198 try elf.mf.flush();
7199
7200 if (elf.options.enable_link_snapshots)
7201 elf.dumpStderr(tid) catch |err|
7202 return comp.link_diags.fail("dumping link snapshot failed: {t}", .{err});
71157203}
71167204
71177205pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {
......@@ -7124,8 +7212,19 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {
71247212 }
71257213
71267214 task: {
7215 if (elf.input_pending_index < elf.inputs.items.len) {
7216 const ii: Node.InputIndex = @fromBackingInt(elf.input_pending_index);
7217 elf.input_pending_index += 1;
7218 const sub_prog_node = elf.idleProgNode(tid, elf.input_prog_node, elf.getNode(ii.node(elf)));
7219 defer sub_prog_node.end();
7220 elf.flushInput(ii) catch |err| switch (err) {
7221 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
7222 else => |e| return e,
7223 };
7224 break :task;
7225 }
71277226 if (elf.input_section_pending_index < elf.input_sections.items.len) {
7128 const isi: InputSection.Index = @fromBackingInt(@intCast(elf.input_section_pending_index));
7227 const isi: InputSection.Index = @fromBackingInt(elf.input_section_pending_index);
71297228 elf.input_section_pending_index += 1;
71307229 const sub_prog_node = elf.idleProgNode(tid, elf.input_prog_node, elf.getNode(isi.node(elf)));
71317230 defer sub_prog_node.end();
......@@ -7213,11 +7312,13 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {
72137312 while (elf.mf.updates.pop()) |ni| {
72147313 const clean_moved = ni.cleanMoved(&elf.mf);
72157314 const clean_resized = ni.cleanResized(&elf.mf);
7216 if (clean_moved or clean_resized) {
7315 const clean_next_moved = ni.cleanNextMoved(&elf.mf);
7316 if (clean_moved or clean_resized or clean_next_moved) {
72177317 const sub_prog_node = elf.idleProgNode(tid, elf.mf.update_prog_node, elf.getNode(ni));
72187318 defer sub_prog_node.end();
72197319 if (clean_moved) try elf.flushMoved(ni);
72207320 if (clean_resized) try elf.flushResized(ni);
7321 if (clean_next_moved) try elf.flushNextMoved(ni);
72217322 break :task;
72227323 } else elf.mf.update_prog_node.completeOne();
72237324 }
......@@ -7238,6 +7339,10 @@ fn idleProgNode(
72387339 return prog_node.start(name: switch (node) {
72397340 else => |tag| @tagName(tag),
72407341 .section => |shndx| shndx.name(elf).slice(elf),
7342 .input_member => |ii| std.fmt.bufPrint(&name, "{f}{f}", .{
7343 ii.path(elf).fmtEscapeString(),
7344 fmtMemberString(ii.member(elf)),
7345 }) catch &name,
72417346 .input_section => |isi| {
72427347 const ii = isi.input(elf);
72437348 break :name std.fmt.bufPrint(&name, "{f}{f} {s}", .{
......@@ -7290,6 +7395,8 @@ fn genPending(elf: *Elf, pt: Zcu.PerThread) Error!void {
72907395 };
72917396 break;
72927397 }
7398
7399 try elf.ensureElfNodeSize();
72937400}
72947401
72957402fn genUav(
......@@ -7358,6 +7465,36 @@ fn genLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void {
73587465 }
73597466}
73607467
7468fn flushInput(elf: *Elf, ii: Node.InputIndex) Error!void {
7469 const comp = elf.base.comp;
7470 const io = comp.io;
7471 const gpa = comp.gpa;
7472 const diags = &comp.link_diags;
7473 const path = ii.path(elf);
7474 const file = path.root_dir.handle.openFile(io, path.sub_path, .{}) catch |err| switch (err) {
7475 error.Canceled => |e| return e,
7476 else => |e| return diags.fail("failed to open input file \"{f}\": {t}", .{ path.fmtEscapeString(), e }),
7477 };
7478 defer file.close(io);
7479 var fr = file.reader(io, &.{});
7480 var nw: MappedFile.Node.Writer = undefined;
7481 ii.node(elf).writer(&elf.mf, gpa, &nw);
7482 defer nw.deinit();
7483 const size = nw.interface.buffer.len - @sizeOf(std.elf.ar_hdr);
7484 const n_bytes = nw.interface.sendFileAll(&fr, .limited(size)) catch |err| switch (err) {
7485 error.ReadFailed => return diags.fail("failed to read input \"{f}{f}\": {t}", .{
7486 path.fmtEscapeString(),
7487 fmtMemberString(ii.member(elf)),
7488 fr.err orelse (fr.seek_err orelse fr.size_err.?),
7489 }),
7490 error.WriteFailed => return nw.err.?,
7491 };
7492 if (n_bytes + 1 < size) return diags.fail("failed to read input \"{f}{f}\": unexpected eof", .{
7493 path.fmtEscapeString(),
7494 fmtMemberString(ii.member(elf)),
7495 });
7496}
7497
73617498fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void {
73627499 const file_loc = isi.fileLocation(elf);
73637500 if (file_loc.size == 0) return;
......@@ -7404,33 +7541,29 @@ fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void {
74047541 assert(isi.node(elf).hasMoved(&elf.mf));
74057542}
74067543
7407fn flushFileOffset(elf: *Elf, ni: MappedFile.Node.Index) void {
7544fn flushElfOffset(elf: *Elf, ni: MappedFile.Node.Index) void {
7545 const elf_offset = elf.getNodeElfOffset(ni);
74087546 switch (elf.getNode(ni)) {
74097547 else => unreachable,
7410 .ehdr => assert(ni.fileLocation(&elf.mf, false).offset == 0),
7548 .ehdr => assert(elf_offset == 0),
74117549 .shdr => switch (elf.ehdrPtr()) {
7412 inline else => |ehdr| elf.targetStore(
7413 &ehdr.shoff,
7414 @intCast(ni.fileLocation(&elf.mf, false).offset),
7415 ),
7550 inline else => |ehdr| elf.targetStore(&ehdr.shoff, @intCast(elf_offset)),
74167551 },
74177552 .segment => |phndx| {
74187553 switch (elf.phdrSlice()) {
74197554 inline else => |phdr, class| {
74207555 const ph = &phdr[phndx];
7421 elf.targetStore(&ph.offset, @intCast(ni.fileLocation(&elf.mf, false).offset));
7556 elf.targetStore(&ph.offset, @intCast(elf_offset));
74227557 if (elf.targetLoad(&ph.type) == .PHDR) {
74237558 @field(elf.ehdrPtr(), @tagName(class)).phoff = ph.offset;
74247559 }
74257560 },
74267561 }
74277562 var child_it = ni.children(&elf.mf);
7428 while (child_it.next()) |child_ni| elf.flushFileOffset(child_ni);
7563 while (child_it.next()) |child_ni| elf.flushElfOffset(child_ni);
74297564 },
74307565 .section => |shndx| switch (elf.shdrPtr(shndx)) {
7431 inline else => |shdr| elf.targetStore(&shdr.offset, @intCast(
7432 ni.fileLocation(&elf.mf, false).offset,
7433 )),
7566 inline else => |shdr| elf.targetStore(&shdr.offset, @intCast(elf_offset)),
74347567 },
74357568 }
74367569}
......@@ -7443,10 +7576,11 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
74437576 defer elf.mf.nodes_lock.unlock();
74447577
74457578 switch (elf.getNode(ni)) {
7446 .file => unreachable,
7447 .ehdr, .shdr => elf.flushFileOffset(ni),
7579 .archive, .archive_header => unreachable,
7580 .elf => {},
7581 .ehdr, .shdr => elf.flushElfOffset(ni),
74487582 .segment => |phndx| {
7449 elf.flushFileOffset(ni);
7583 elf.flushElfOffset(ni);
74507584 switch (elf.phdrSlice()) {
74517585 inline else => |phdr| {
74527586 const ph = &phdr[phndx];
......@@ -7467,7 +7601,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
74677601 }
74687602 },
74697603 .section => |shndx| {
7470 elf.flushFileOffset(ni);
7604 elf.flushElfOffset(ni);
74717605 const addr = elf.computeNodeVAddr(ni);
74727606 const old_addr: u64, const flags: std.elf.SHF = switch (elf.shdrPtr(shndx)) {
74737607 inline else => |shdr| .{
......@@ -7518,6 +7652,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
75187652 elf.flushMovedNodeRelocs(ni, addr, elf.dynamic_first_symbol_reloc, .none);
75197653 }
75207654 },
7655 .input_member => {},
75217656 .input_section => |isi| {
75227657 const old_section_addr = isi.ptr(elf).vaddr;
75237658 const new_section_addr = elf.computeNodeVAddr(ni);
......@@ -7526,7 +7661,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
75267661 // Update local symbols
75277662 const ii = isi.input(elf);
75287663 var lsi, const end_lsi = ii.localSymbolRange(elf);
7529 while (lsi != end_lsi) : (lsi = @fromBackingInt(@intCast(@backingInt(lsi) + 1))) {
7664 while (lsi != end_lsi) : (lsi = @fromBackingInt(@backingInt(lsi) + 1)) {
75307665 if (lsi.index().ptr(elf).node != ni) continue;
75317666 const visibility: std.elf.STV = switch (elf.symPtr(lsi.index())) {
75327667 inline else => |sym| elf.targetLoad(&sym.other).visibility,
......@@ -7613,7 +7748,17 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo
76137748
76147749 _, const size = ni.location(&elf.mf).resolve(&elf.mf);
76157750 switch (elf.getNode(ni)) {
7616 .file => {},
7751 .archive => {
7752 var child_it = ni.reverseChildren(&elf.mf);
7753 if (child_it.next()) |last_ni| {
7754 if (child_it.next()) |prev_ni| if (prev_ni.hasNextMoved(&elf.mf)) return;
7755 const offset, _ = last_ni.location(&elf.mf).resolve(&elf.mf);
7756 _ = std.mem.print(&elf.arHdrPtr(last_ni).ar_size, "{d:<10}", .{
7757 size - offset,
7758 }) catch @panic("archive member too large");
7759 }
7760 },
7761 .archive_header, .elf => {},
76177762 .ehdr => unreachable,
76187763 .shdr => {},
76197764 .segment => |phndx| switch (elf.phdrSlice()) {
......@@ -7713,9 +7858,88 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo
77137858 }
77147859 },
77157860 },
7716 .copied_global, .input_section, .nav, .uav, .lazy_code, .lazy_const_data => {},
7861 .input_member, .input_section, .copied_global, .nav, .uav, .lazy_code, .lazy_const_data => {},
77177862 }
77187863}
7864
7865fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void {
7866 const trace = tracy.trace(@src());
7867 defer trace.end();
7868
7869 elf.mf.nodes_lock.lock();
7870 defer elf.mf.nodes_lock.unlock();
7871
7872 switch (elf.getNode(ni)) {
7873 .archive,
7874 .ehdr,
7875 .shdr,
7876 .segment,
7877 .section,
7878 .input_section,
7879 .copied_global,
7880 .nav,
7881 .uav,
7882 .lazy_code,
7883 .lazy_const_data,
7884 => unreachable,
7885 .archive_header, .elf, .input_member => |_, tag| {
7886 const member_offset, const update_size = member_offset: {
7887 const offset, _ = ni.location(&elf.mf).resolve(&elf.mf);
7888 break :member_offset switch (tag) {
7889 else => unreachable,
7890 .archive_header => .{ offset + std.elf.ARMAG.len + @sizeOf(std.elf.ar_hdr), true },
7891 .elf, .input_member => .{ offset, switch (ni.prev(&elf.mf)) {
7892 .none => unreachable,
7893 else => |prev_ni| !prev_ni.hasNextMoved(&elf.mf),
7894 } },
7895 };
7896 };
7897 const member_size = member_end: switch (ni.next(&elf.mf)) {
7898 else => |next_ni| {
7899 const next_offset, _ = next_ni.location(&elf.mf).resolve(&elf.mf);
7900 const next_member_size = next_member_end: switch (next_ni.next(&elf.mf)) {
7901 else => |next_next_ni| {
7902 const next_next_offset, _ = next_next_ni.location(&elf.mf).resolve(&elf.mf);
7903 break :next_member_end next_next_offset - @sizeOf(std.elf.ar_hdr);
7904 },
7905 .none => {
7906 _, const parent_size =
7907 ni.parent(&elf.mf).location(&elf.mf).resolve(&elf.mf);
7908 break :next_member_end parent_size;
7909 },
7910 } - next_offset;
7911 const ar_hdr = elf.arHdrPtr(next_ni);
7912 var name_buf: [16]u8 = undefined;
7913 _ = std.mem.print(&ar_hdr.ar_name, "{s:<16}", .{
7914 switch (elf.getNode(next_ni)) {
7915 else => unreachable,
7916 .elf => std.mem.print(&name_buf, "{s}_zcu.o/", .{elf.base.comp.root_name}),
7917 .input_member => |ii| std.mem.print(&name_buf, "{s}/", .{
7918 std.fs.path.basename(ii.path(elf).sub_path),
7919 }),
7920 } catch @panic("TODO: long archive member names"),
7921 }) catch @panic("TODO: long archive member names");
7922 ar_hdr.ar_date = "0 ".*;
7923 ar_hdr.ar_uid = "0 ".*;
7924 ar_hdr.ar_gid = "0 ".*;
7925 ar_hdr.ar_mode = "644 ".*;
7926 _ = std.mem.print(&ar_hdr.ar_size, "{d:<10}", .{next_member_size}) catch
7927 @panic("archive member too large");
7928 ar_hdr.ar_fmag = std.elf.ARFMAG.*;
7929 break :member_end next_offset - @sizeOf(std.elf.ar_hdr);
7930 },
7931 .none => {
7932 _, const parent_size = ni.parent(&elf.mf).location(&elf.mf).resolve(&elf.mf);
7933 break :member_end parent_size;
7934 },
7935 } - member_offset;
7936 if (update_size) _ = std.mem.print(&elf.arHdrPtr(ni).ar_size, "{d:<10}", .{
7937 member_size,
7938 }) catch @panic("archive member too large");
7939 },
7940 }
7941}
7942
77197943fn updateDynamicEntry(elf: *Elf, key: u32, new_val: u64) void {
77207944 switch (elf.shdrPtr(elf.shndx.dynamic)) {
77217945 inline else => |shdr, class| {
......@@ -7756,7 +7980,7 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void
77567980 };
77577981
77587982 // Now that we know the index, we can set the relocation's offset.
7759 elf.shndx.rela_plt.relaSetOffset(elf, @fromBackingInt(@intCast(plt_index)), got_plt_section.vaddr(elf) + got_plt_offset);
7983 elf.shndx.rela_plt.relaSetOffset(elf, @fromBackingInt(plt_index), got_plt_section.vaddr(elf) + got_plt_offset);
77607984
77617985 if (plt_index < elf.plt.count()) {
77627986 // We reused a free entry, so we're already done!
......@@ -8096,7 +8320,10 @@ fn updateExportsInner(
80968320 },
80978321 .uav => |uav| .{ (try elf.uavMapIndex(uav, .none)).symbol(elf), .OBJECT },
80988322 };
8323
8324 try elf.ensureElfNodeSize();
80998325 while (try elf.idle(pt.tid)) {}
8326
81008327 const value: u64 = Symbol.Id.local(exported_lsi).value(elf);
81018328 const size: u64, const shndx: Section.Index = switch (elf.symPtr(exported_lsi.index())) {
81028329 inline else => |exported_sym| .{
......@@ -8150,6 +8377,16 @@ pub fn deleteExport(elf: *Elf, exported: Zcu.Exported, name: InternPool.NullTerm
81508377 _ = name;
81518378}
81528379
8380fn dumpStderr(elf: *Elf, tid: Zcu.PerThread.Id) !void {
8381 const comp = elf.base.comp;
8382 const io = comp.io;
8383 var buffer: [512]u8 = undefined;
8384 const stderr = try io.lockStderr(&buffer, null);
8385 defer io.unlockStderr();
8386 const w = &stderr.file_writer.interface;
8387 _ = try elf.dump(w, tid);
8388}
8389
81538390pub fn dump(elf: *Elf, w: *Io.Writer, tid: Zcu.PerThread.Id) !link.File.DumpResult {
81548391 if (elf.options.enable_link_snapshots) {
81558392 try elf.printNode(tid, w, .root, 0);
......@@ -8227,13 +8464,14 @@ pub fn printNode(
82278464 {
82288465 const mf_node = &elf.mf.nodes.items[@backingInt(ni)];
82298466 const off, const size = mf_node.location().resolve(&elf.mf);
8230 try w.print(" index={d} offset=0x{x} size=0x{x} align=0x{x}{s}{s}{s}{s}\n", .{
8467 try w.print(" index={d} offset=0x{x} size=0x{x} align=0x{x}{s}{s}{s}{s}{s}\n", .{
82318468 @backingInt(ni),
82328469 off,
82338470 size,
82348471 mf_node.flags.alignment.toByteUnits(),
82358472 if (mf_node.flags.fixed) " fixed" else "",
82368473 if (mf_node.flags.moved) " moved" else "",
8474 if (mf_node.flags.next_moved) " next_moved" else "",
82378475 if (mf_node.flags.resized) " resized" else "",
82388476 if (mf_node.flags.has_content) " has_content" else "",
82398477 });
......@@ -8269,11 +8507,19 @@ pub fn printNode(
82698507 }
82708508}
82718509
8272fn ensureNodeSize(
8273 elf: *Elf,
8274 node: MappedFile.Node.Index,
8275 need_size: u64,
8276) Error!void {
8510/// Must be called deterministically after any call to `MappedFile.Node.Index.resize`
8511/// (of `elf.ni.elf` or one of its children) before any possible calls to `idle`.
8512fn ensureElfNodeSize(elf: *Elf) MappedFile.Error!void {
8513 if (elf.ni.elf == MappedFile.Node.Index.root) return;
8514 var child_it = elf.ni.elf.reverseChildren(&elf.mf);
8515 const last_end = if (child_it.next()) |last_ni| last_end: {
8516 const last_offset, const last_size = last_ni.location(&elf.mf).resolve(&elf.mf);
8517 break :last_end last_offset + last_size;
8518 } else 0;
8519 try elf.ensureNodeSize(elf.ni.elf, last_end + @sizeOf(std.elf.ar_hdr));
8520}
8521
8522fn ensureNodeSize(elf: *Elf, node: MappedFile.Node.Index, need_size: u64) MappedFile.Error!void {
82778523 _, const node_size = node.location(&elf.mf).resolve(&elf.mf);
82788524 if (need_size <= node_size) return;
82798525 const gpa = elf.base.comp.gpa;
src/link/Lld.zig+39-26
......@@ -99,8 +99,6 @@ pub const Elf = struct {
9999 bind_global_refs_locally: bool,
100100 pub const HashStyle = enum { sysv, gnu, both };
101101 pub const SortSection = enum { name, alignment };
102 /// Deprecated; use 'std.zig.CompressDebugSections' instead. To be removed after 0.16.0 is tagged.
103 pub const CompressDebugSections = std.zig.CompressDebugSections;
104102
105103 fn init(comp: *Compilation, options: link.File.OpenOptions) !Elf {
106104 const PtrWidth = enum { p32, p64 };
......@@ -208,8 +206,8 @@ pub fn createEmpty(
208206 const optimize_mode = comp.root_mod.optimize_mode;
209207
210208 const gc_sections: bool = options.gc_sections orelse switch (target.ofmt) {
211 .coff => optimize_mode != .Debug,
212 .elf => optimize_mode != .Debug and output_mode != .Obj,
209 .coff => optimize_mode != .debug,
210 .elf => optimize_mode != .debug and output_mode != .Obj,
213211 .wasm => output_mode != .Obj,
214212 else => unreachable,
215213 };
......@@ -271,12 +269,12 @@ pub fn flush(
271269 .wasm => wasmLink(lld, arena),
272270 };
273271 result catch |err| switch (err) {
274 error.OutOfMemory, error.AlreadyReported => |e| return e,
272 error.OutOfMemory, error.AlreadyReported, error.Canceled => |e| return e,
275273 else => |e| return lld.base.comp.link_diags.fail("failed to link with LLD: {t}", .{e}),
276274 };
277275}
278276
279fn linkAsArchive(lld: *Lld, arena: Allocator) !void {
277fn linkAsArchive(lld: *Lld, arena: Allocator) link.Error!void {
280278 const base = &lld.base;
281279 const comp = base.comp;
282280 const directory = base.emit.root_dir; // Just an alias to make it shorter to type.
......@@ -308,8 +306,8 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void {
308306
309307 try object_files.ensureUnusedCapacity(arena, comp.link_inputs.len);
310308 for (comp.link_inputs) |input| switch (input) {
311 .res, .dso, .dso_exact => {}, // shared libraries should not be included in static archives
312 .object, .archive => {
309 .dso, .dso_exact, .archive => {}, // static archives should not contain shared libraries or other static archives
310 .res, .object => {
313311 const path = try input.path().?.toStringZ(arena);
314312 object_files.appendAssumeCapacity(path);
315313 },
......@@ -340,7 +338,9 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void {
340338 const llvm = @import("../codegen/llvm.zig");
341339 const target = &comp.root_mod.resolved_target.result;
342340 llvm.initializeLLVMTarget(target.cpu.arch);
343 const bad = llvm_bindings.WriteArchive(
341 var err_file_index: usize = undefined;
342 var err_msg: [*:0]u8 = undefined;
343 if (llvm_bindings.WriteArchive(
344344 full_out_path_z,
345345 object_files.items.ptr,
346346 object_files.items.len,
......@@ -348,8 +348,19 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void {
348348 .windows => .COFF,
349349 else => if (target.os.tag.isDarwin()) .DARWIN else .GNU,
350350 },
351 );
352 if (bad) return error.UnableToWriteArchive;
351 &err_file_index,
352 &err_msg,
353 )) {
354 defer std.c.free(err_msg);
355 if (err_file_index < object_files.items.len) {
356 return comp.link_diags.fail("LLD failed to open input file '{s}': {s}", .{
357 object_files.items[err_file_index],
358 err_msg,
359 });
360 } else {
361 return comp.link_diags.fail("LLD failed to write archive: {s}", .{err_msg});
362 }
363 }
353364}
354365
355366fn addCommonArgs(argv: *std.array_list.Managed([]const u8), coff: bool) !void {
......@@ -383,7 +394,7 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {
383394 const target = &comp.root_mod.resolved_target.result;
384395 const optimize_mode = comp.root_mod.optimize_mode;
385396 const entry_name: ?[]const u8 = switch (coff.entry) {
386 // This logic isn't quite right for disabled or enabled. No point in fixing it
397 // This logic isn't quite right for default or enabled. No point in fixing it
387398 // when the goal is to eliminate dependency on LLD anyway.
388399 // https://github.com/ziglang/zig/issues/17751
389400 .disabled, .default, .enabled => null,
......@@ -456,9 +467,9 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {
456467
457468 if (comp.config.lto != .none) {
458469 switch (optimize_mode) {
459 .Debug => {},
460 .ReleaseSmall => try argv.append("-OPT:lldlto=2"),
461 .ReleaseFast, .ReleaseSafe => try argv.append("-OPT:lldlto=3"),
470 .debug => {},
471 .small => try argv.append("-OPT:lldlto=2"),
472 .fast, .safe => try argv.append("-OPT:lldlto=3"),
462473 }
463474 }
464475 if (comp.config.output_mode == .Exe) {
......@@ -492,6 +503,8 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {
492503
493504 if (entry_name) |name| {
494505 try argv.append(try arena.print("-ENTRY:{s}", .{name}));
506 } else if (coff.entry == .disabled) {
507 try argv.append("-NOENTRY");
495508 }
496509
497510 if (coff.repro) {
......@@ -865,15 +878,15 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {
865878
866879 if (comp.config.lto != .none) {
867880 switch (comp.root_mod.optimize_mode) {
868 .Debug => {},
869 .ReleaseSmall => try argv.append("--lto-O2"),
870 .ReleaseFast, .ReleaseSafe => try argv.append("--lto-O3"),
881 .debug => {},
882 .small => try argv.append("--lto-O2"),
883 .fast, .safe => try argv.append("--lto-O3"),
871884 }
872885 }
873886 switch (comp.root_mod.optimize_mode) {
874 .Debug => {},
875 .ReleaseSmall => try argv.append("-O2"),
876 .ReleaseFast, .ReleaseSafe => try argv.append("-O3"),
887 .debug => {},
888 .small => try argv.append("-O2"),
889 .fast, .safe => try argv.append("-O3"),
877890 }
878891
879892 if (elf.entry_name) |name| {
......@@ -1010,8 +1023,8 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {
10101023 }
10111024
10121025 if (is_exe_or_dyn_lib and target.os.tag == .netbsd) {
1013 // Add options to produce shared objects with only 2 PT_LOAD segments.
1014 // NetBSD expects 2 PT_LOAD segments in a shared object, otherwise
1026 // Add options to produce shared objects with only 2 PT.LOAD segments.
1027 // NetBSD expects 2 PT.LOAD segments in a shared object, otherwise
10151028 // ld.elf_so fails loading dynamic libraries with "not found" error.
10161029 // See https://github.com/ziglang/zig/issues/9109 .
10171030 try argv.append("--no-rosegment");
......@@ -1416,9 +1429,9 @@ fn wasmLink(lld: *Lld, arena: Allocator) !void {
14161429
14171430 if (comp.config.lto != .none) {
14181431 switch (comp.root_mod.optimize_mode) {
1419 .Debug => {},
1420 .ReleaseSmall => try argv.append("-O2"),
1421 .ReleaseFast, .ReleaseSafe => try argv.append("-O3"),
1432 .debug => {},
1433 .small => try argv.append("-O2"),
1434 .fast, .safe => try argv.append("-O3"),
14221435 }
14231436 }
14241437
src/link/MachO.zig+35-10
......@@ -24,6 +24,8 @@ dylibs: std.ArrayList(File.Index) = .empty,
2424
2525segments: std.ArrayList(macho.segment_command_64) = .empty,
2626sections: std.MultiArrayList(Section) = .{},
27/// Populated by `allocateSections`.
28header_size: ?u32 = null,
2729
2830resolver: SymbolResolver = .{},
2931/// This table will be populated after `scanRelocs` has run.
......@@ -181,7 +183,7 @@ pub fn createEmpty(
181183 .tag = .macho,
182184 .comp = comp,
183185 .emit = emit,
184 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug),
186 .gc_sections = options.gc_sections orelse (optimize_mode != .debug),
185187 .print_gc_sections = options.print_gc_sections,
186188 .stack_size = options.stack_size orelse 16777216,
187189 .allow_shlib_undefined = allow_shlib_undefined,
......@@ -990,6 +992,11 @@ fn addArchive(self: *MachO, lib: link.Input.Object, handle: File.HandleIndex, fa
990992 const tracy = trace(@src());
991993 defer tracy.end();
992994
995 if (self.base.isStaticLib()) {
996 // Ignore static library inputs when generating a static library.
997 return;
998 }
999
9931000 const gpa = self.base.comp.gpa;
9941001
9951002 var archive: Archive = .{};
......@@ -1068,7 +1075,7 @@ fn isHoisted(self: *MachO, install_name: []const u8) bool {
10681075 if (mem.startsWith(u8, dirname, "/usr/lib")) return true;
10691076 if (eatPrefix(dirname, "/System/Library/Frameworks/")) |path| {
10701077 const basename = fs.path.basename(install_name);
1071 if (mem.indexOfScalar(u8, path, '.')) |index| {
1078 if (mem.findScalar(u8, path, '.')) |index| {
10721079 if (mem.eql(u8, basename, path[0..index])) return true;
10731080 }
10741081 }
......@@ -1737,14 +1744,14 @@ fn initSyntheticSections(self: *MachO) !void {
17371744 });
17381745 }
17391746 } else if (eatPrefix(name, "section$start$")) |actual_name| {
1740 const sep = mem.indexOfScalar(u8, actual_name, '$').?; // TODO error rather than a panic
1747 const sep = mem.findScalar(u8, actual_name, '$').?; // TODO error rather than a panic
17411748 const segname = actual_name[0..sep]; // TODO check segname is valid
17421749 const sectname = actual_name[sep + 1 ..]; // TODO check sectname is valid
17431750 if (self.getSectionByName(segname, sectname) == null) {
17441751 _ = try self.addSection(segname, sectname, .{});
17451752 }
17461753 } else if (eatPrefix(name, "section$end$")) |actual_name| {
1747 const sep = mem.indexOfScalar(u8, actual_name, '$').?; // TODO error rather than a panic
1754 const sep = mem.findScalar(u8, actual_name, '$').?; // TODO error rather than a panic
17481755 const segname = actual_name[0..sep]; // TODO check segname is valid
17491756 const sectname = actual_name[sep + 1 ..]; // TODO check sectname is valid
17501757 if (self.getSectionByName(segname, sectname) == null) {
......@@ -1765,7 +1772,7 @@ fn getSegmentProt(segname: []const u8) macho.vm_prot_t {
17651772fn getSegmentRank(segname: []const u8) u8 {
17661773 if (mem.eql(u8, segname, "__PAGEZERO")) return 0x0;
17671774 if (mem.eql(u8, segname, "__LINKEDIT")) return 0xf;
1768 if (mem.indexOf(u8, segname, "ZIG")) |_| return 0xe;
1775 if (mem.find(u8, segname, "ZIG")) |_| return 0xe;
17691776 if (mem.startsWith(u8, segname, "__TEXT")) return 0x1;
17701777 if (mem.startsWith(u8, segname, "__DATA_CONST")) return 0x2;
17711778 if (mem.startsWith(u8, segname, "__DATA")) return 0x3;
......@@ -2209,13 +2216,14 @@ fn initSegments(self: *MachO) !void {
22092216}
22102217
22112218fn allocateSections(self: *MachO) !void {
2212 const headerpad = try load_commands.calcMinHeaderPadSize(self);
2219 const header_size = try load_commands.calcMinHeaderSize(self);
2220 self.header_size = header_size;
22132221 var vmaddr: u64 = if (self.pagezero_seg_index) |index|
22142222 self.segments.items[index].vmaddr + self.segments.items[index].vmsize
22152223 else
22162224 0;
2217 vmaddr += headerpad;
2218 var fileoff = headerpad;
2225 vmaddr += header_size;
2226 var fileoff = header_size;
22192227 var prev_seg_id: u8 = if (self.pagezero_seg_index) |index| index + 1 else 0;
22202228
22212229 const page_size = self.getPageSize();
......@@ -2339,7 +2347,7 @@ fn allocateSyntheticSymbols(self: *MachO) void {
23392347 }
23402348 } else if (mem.startsWith(u8, name, "section$start$")) {
23412349 const actual_name = name["section$start$".len..];
2342 const sep = mem.indexOfScalar(u8, actual_name, '$').?; // TODO error rather than a panic
2350 const sep = mem.findScalar(u8, actual_name, '$').?; // TODO error rather than a panic
23432351 const segname = actual_name[0..sep];
23442352 const sectname = actual_name[sep + 1 ..];
23452353 if (self.getSectionByName(segname, sectname)) |sect_id| {
......@@ -2349,7 +2357,7 @@ fn allocateSyntheticSymbols(self: *MachO) void {
23492357 }
23502358 } else if (mem.startsWith(u8, name, "section$end$")) {
23512359 const actual_name = name["section$end$".len..];
2352 const sep = mem.indexOfScalar(u8, actual_name, '$').?; // TODO error rather than a panic
2360 const sep = mem.findScalar(u8, actual_name, '$').?; // TODO error rather than a panic
23532361 const segname = actual_name[0..sep];
23542362 const sectname = actual_name[sep + 1 ..];
23552363 if (self.getSectionByName(segname, sectname)) |sect_id| {
......@@ -2895,6 +2903,11 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } {
28952903 ncmds += 1;
28962904 }
28972905
2906 if (self.needsEncryptionInfo()) {
2907 try load_commands.writeEncryptionInfoLC(self, &writer);
2908 ncmds += 1;
2909 }
2910
28982911 for (self.rpath_list) |rpath| {
28992912 try load_commands.writeRpathLC(rpath, &writer);
29002913 ncmds += 1;
......@@ -5410,6 +5423,18 @@ pub fn alignPow(macho_file: *MachO, x: u32) error{AlreadyReported}!u32 {
54105423 return result;
54115424}
54125425
5426pub fn needsEncryptionInfo(macho_file: *MachO) bool {
5427 const target = macho_file.getTarget();
5428 return switch (target.os.tag) {
5429 .ios,
5430 .tvos,
5431 .visionos,
5432 .watchos,
5433 => target.abi != .simulator,
5434 else => false,
5435 };
5436}
5437
54135438/// Branch instruction has 26 bits immediate but is 4 byte aligned.
54145439const jump_bits = @bitSizeOf(i28);
54155440const max_distance = (1 << (jump_bits - 1));
src/link/MachO/Archive.zig+2-2
......@@ -45,7 +45,7 @@ pub fn unpack(self: *Archive, macho_file: *MachO, path: Path, handle_index: File
4545 const amt = try handle.readPositionalAll(io, buf, pos);
4646 if (amt != len) return error.InputOutput;
4747 pos += len;
48 const actual_len = mem.indexOfScalar(u8, buf, @as(u8, 0)) orelse len;
48 const actual_len = mem.findScalar(u8, buf, @as(u8, 0)) orelse len;
4949 break :name buf[0..actual_len];
5050 }
5151 unreachable;
......@@ -161,7 +161,7 @@ pub const ar_hdr = extern struct {
161161 fn name(self: *const ar_hdr) ?[]const u8 {
162162 const value = &self.ar_name;
163163 if (mem.startsWith(u8, value, "#1/")) return null;
164 const sentinel = mem.indexOfScalar(u8, value, '/') orelse value.len;
164 const sentinel = mem.findScalar(u8, value, '/') orelse value.len;
165165 return value[0..sentinel];
166166 }
167167
src/link/MachO/Symbol.zig+1-1
......@@ -43,7 +43,7 @@ pub fn isSymbolStab(symbol: Symbol, macho_file: *MachO) bool {
4343
4444pub fn isTlvInit(symbol: Symbol, macho_file: *MachO) bool {
4545 const name = symbol.getName(macho_file);
46 return std.mem.indexOf(u8, name, "$tlv$init") != null;
46 return std.mem.find(u8, name, "$tlv$init") != null;
4747}
4848
4949pub fn weakRef(symbol: Symbol, macho_file: *MachO) bool {
src/link/MachO/ZigObject.zig+4-4
......@@ -946,8 +946,8 @@ fn updateNavCode(
946946 const target = &mod.resolved_target.result;
947947 const required_alignment = switch (nav.resolved.?.@"align") {
948948 .none => switch (mod.optimize_mode) {
949 .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),
950 .ReleaseSmall => target_util.minFunctionAlignment(target),
949 .debug, .safe, .fast => target_util.defaultFunctionAlignment(target),
950 .small => target_util.minFunctionAlignment(target),
951951 },
952952 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
953953 };
......@@ -1172,8 +1172,8 @@ fn getNavOutputSection(
11721172 if (nav.resolved.?.@"const") return macho_file.zig_const_sect_index.?;
11731173 if (nav_val.isUndef(zcu))
11741174 return switch (zcu.navFileScope(nav_index).mod.?.optimize_mode) {
1175 .Debug, .ReleaseSafe => macho_file.zig_data_sect_index.?,
1176 .ReleaseFast, .ReleaseSmall => macho_file.zig_bss_sect_index.?,
1175 .debug, .safe => macho_file.zig_data_sect_index.?,
1176 .fast, .small => macho_file.zig_bss_sect_index.?,
11771177 };
11781178 for (code) |byte| {
11791179 if (byte != 0) break;
src/link/MachO/dyld_info/Trie.zig+2-2
......@@ -54,7 +54,7 @@ fn putNode(self: *Trie, node_index: Node.Index, allocator: Allocator, label: []c
5454 // Check for match with edges from this node.
5555 for (self.nodes.items(.edges)[node_index].items) |edge_index| {
5656 const edge = &self.edges.items[edge_index];
57 const match = mem.indexOfDiff(u8, edge.label, label) orelse return edge.node;
57 const match = mem.findDiff(u8, edge.label, label) orelse return edge.node;
5858 if (match == 0) continue;
5959 if (match == edge.label.len) return self.putNode(edge.node, allocator, label[match..]);
6060
......@@ -351,7 +351,7 @@ fn expectEqualHexStrings(expected: []const u8, given: []const u8) !void {
351351 defer testing.allocator.free(expected_fmt);
352352 const given_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{given});
353353 defer testing.allocator.free(given_fmt);
354 const idx = mem.indexOfDiff(u8, expected_fmt, given_fmt).?;
354 const idx = mem.findDiff(u8, expected_fmt, given_fmt).?;
355355 const padding = try testing.allocator.alloc(u8, idx + 5);
356356 defer testing.allocator.free(padding);
357357 @memset(padding, ' ');
src/link/MachO/load_commands.zig+22-5
......@@ -62,6 +62,10 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) !u32
6262 assume_max_path_len,
6363 );
6464 }
65 // LC_ENCRYPTION_INFO_64
66 if (macho_file.needsEncryptionInfo()) {
67 sizeofcmds += @sizeOf(macho.encryption_info_command_64);
68 }
6569 // LC_RPATH
6670 {
6771 for (macho_file.rpath_list) |rpath| {
......@@ -163,23 +167,29 @@ pub fn calcLoadCommandsSizeObject(macho_file: *MachO) u32 {
163167 return @as(u32, @intCast(sizeofcmds));
164168}
165169
166pub fn calcMinHeaderPadSize(macho_file: *MachO) !u32 {
170pub fn calcMinHeaderSize(macho_file: *MachO) !u32 {
167171 var padding: u32 = (try calcLoadCommandsSize(macho_file, false)) +
168172 (macho_file.headerpad_size orelse MachO.default_headerpad_size);
169 log.debug("minimum requested headerpad size 0x{x}", .{padding + @sizeOf(macho.mach_header_64)});
173 log.debug("minimum requested header + padding size 0x{x}", .{padding + @sizeOf(macho.mach_header_64)});
170174
171175 if (macho_file.headerpad_max_install_names) {
172176 const min_headerpad_size: u32 = try calcLoadCommandsSize(macho_file, true);
173 log.debug("headerpad_max_install_names minimum headerpad size 0x{x}", .{
177 log.debug("headerpad_max_install_names minimum header + padding size 0x{x}", .{
174178 min_headerpad_size + @sizeOf(macho.mach_header_64),
175179 });
176180 padding = @max(padding, min_headerpad_size);
177181 }
178182
179183 const offset = @sizeOf(macho.mach_header_64) + padding;
180 log.debug("actual headerpad size 0x{x}", .{offset});
184 log.debug("actual header + padding size 0x{x}", .{offset});
181185
182 return offset;
186 // Encryption is done at page granularity, so if the output needs a load
187 // command for encryption info, ensure that the header + load commands have
188 // at least one full, unencrypted page.
189 return if (macho_file.needsEncryptionInfo())
190 mem.alignForward(u32, offset, macho_file.getPageSize())
191 else
192 offset;
183193}
184194
185195pub fn writeDylinkerLC(writer: *Writer) !void {
......@@ -260,6 +270,13 @@ pub fn writeDylibIdLC(macho_file: *MachO, writer: *Writer) !void {
260270 }, writer);
261271}
262272
273pub fn writeEncryptionInfoLC(macho_file: *MachO, writer: *Writer) !void {
274 try writer.writeAll(mem.asBytes(&macho.encryption_info_command_64{
275 .cryptoff = macho_file.header_size.?,
276 .cryptsize = @as(u32, @intCast(macho_file.getTextSegment().filesize)) - macho_file.header_size.?,
277 }));
278}
279
263280pub fn writeRpathLC(rpath: []const u8, writer: *Writer) !void {
264281 const rpath_len = rpath.len + 1;
265282 const cmdsize = @as(u32, @intCast(mem.alignForward(
src/link/MappedFile.zig+93-41
......@@ -23,6 +23,7 @@ nodes: std.ArrayList(Node),
2323free_ni: Node.Index,
2424large: std.ArrayList(u64),
2525updates: std.ArrayList(Node.Index),
26/// This progress node's estimated total items is increased once for each node appended to `updates`.
2627update_prog_node: std.Progress.Node,
2728writers: std.SinglyLinkedList,
2829io_err: ?IoError,
......@@ -61,7 +62,7 @@ pub const Error = Allocator.Error || Io.Cancelable || error{
6162 MappedFileIo,
6263};
6364
64pub fn init(file: Io.File, gpa: std.mem.Allocator, io: Io) (Allocator.Error || Io.Cancelable || IoError)!MappedFile {
65pub fn init(file: Io.File, gpa: Allocator, io: Io) (Allocator.Error || Io.Cancelable || IoError)!MappedFile {
6566 var mf: MappedFile = .{
6667 .io = io,
6768 .flags = undefined,
......@@ -105,7 +106,7 @@ pub fn init(file: Io.File, gpa: std.mem.Allocator, io: Io) (Allocator.Error || I
105106 return mf;
106107}
107108
108pub fn deinit(mf: *MappedFile, gpa: std.mem.Allocator) void {
109pub fn deinit(mf: *MappedFile, gpa: Allocator) void {
109110 mf.unmap();
110111 mf.nodes.deinit(gpa);
111112 mf.large.deinit(gpa);
......@@ -133,11 +134,15 @@ pub const Node = extern struct {
133134 moved: bool,
134135 /// Whether this node has been resized.
135136 resized: bool,
137 /// Whether the next sibling has moved or is a different node.
138 next_moved: bool,
136139 /// Whether this node might contain non-zero bytes.
137140 has_content: bool,
138 /// Whether a moved event on this node bubbles down to children.
141 /// Whether `moved` events on this node bubble down to children.
139142 bubbles_moved: bool,
140 unused: @Int(.unsigned, 32 - @bitSizeOf(std.mem.Alignment) - 6) = 0,
143 /// Whether `next_moved` events are reported in `updates`.
144 enable_next_moved: bool,
145 unused: @Int(.unsigned, 32 - @bitSizeOf(std.mem.Alignment) - 8) = 0,
141146 };
142147
143148 pub const Location = union(enum(u1)) {
......@@ -191,6 +196,22 @@ pub const Node = extern struct {
191196 pub fn next(ni: Node.Index, mf: *const MappedFile) Node.Index {
192197 return ni.get(mf).next;
193198 }
199 fn setNext(
200 prev_ni: Node.Index,
201 gpa: Allocator,
202 next_ni: Node.Index,
203 mf: *MappedFile,
204 ) Allocator.Error!void {
205 assert(prev_ni != .none);
206 const prev_next = &prev_ni.get(mf).next;
207 if (prev_next.* == next_ni) return;
208 prev_next.* = next_ni;
209 try prev_ni.nextMoved(gpa, mf);
210 }
211
212 pub fn prev(ni: Node.Index, mf: *const MappedFile) Node.Index {
213 return ni.get(mf).prev;
214 }
194215
195216 pub fn ChildIterator(comptime direction: enum { prev, next }) type {
196217 return struct {
......@@ -211,7 +232,7 @@ pub const Node = extern struct {
211232 return .{ .mf = mf, .ni = ni.get(mf).last };
212233 }
213234
214 pub fn childrenMoved(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) Allocator.Error!void {
235 pub fn childrenMoved(ni: Node.Index, gpa: Allocator, mf: *MappedFile) Allocator.Error!void {
215236 var child_ni = ni.get(mf).last;
216237 while (child_ni != .none) {
217238 try child_ni.moved(gpa, mf);
......@@ -229,11 +250,11 @@ pub const Node = extern struct {
229250 }
230251 return false;
231252 }
232 pub fn moved(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) Allocator.Error!void {
233 try mf.updates.ensureUnusedCapacity(gpa, 1);
253 pub fn moved(ni: Node.Index, gpa: Allocator, mf: *MappedFile) Allocator.Error!void {
254 try mf.updates.ensureUnusedCapacity(gpa, 2);
234255 ni.movedAssumeCapacity(mf);
235256 }
236 pub fn cleanMoved(ni: Node.Index, mf: *const MappedFile) bool {
257 pub fn cleanMoved(ni: Node.Index, mf: *MappedFile) bool {
237258 const node_moved = &ni.get(mf).flags.moved;
238259 defer node_moved.* = false;
239260 return node_moved.*;
......@@ -242,7 +263,11 @@ pub const Node = extern struct {
242263 if (ni.hasMoved(mf)) return;
243264 const node = ni.get(mf);
244265 node.flags.moved = true;
245 if (node.flags.resized) return;
266 switch (node.prev) {
267 .none => {},
268 else => |prev_ni| prev_ni.nextMovedAssumeCapacity(mf),
269 }
270 if (node.flags.resized or node.flags.next_moved) return;
246271 mf.updates.appendAssumeCapacity(ni);
247272 mf.update_prog_node.increaseEstimatedTotalItems(1);
248273 }
......@@ -250,11 +275,11 @@ pub const Node = extern struct {
250275 pub fn hasResized(ni: Node.Index, mf: *const MappedFile) bool {
251276 return ni.get(mf).flags.resized;
252277 }
253 pub fn resized(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) Allocator.Error!void {
278 pub fn resized(ni: Node.Index, gpa: Allocator, mf: *MappedFile) Allocator.Error!void {
254279 try mf.updates.ensureUnusedCapacity(gpa, 1);
255280 ni.resizedAssumeCapacity(mf);
256281 }
257 pub fn cleanResized(ni: Node.Index, mf: *const MappedFile) bool {
282 pub fn cleanResized(ni: Node.Index, mf: *MappedFile) bool {
258283 const node_resized = &ni.get(mf).flags.resized;
259284 defer node_resized.* = false;
260285 return node_resized.*;
......@@ -263,7 +288,28 @@ pub const Node = extern struct {
263288 const node = ni.get(mf);
264289 if (node.flags.resized) return;
265290 node.flags.resized = true;
266 if (node.flags.moved) return;
291 if (node.flags.moved or node.flags.next_moved) return;
292 mf.updates.appendAssumeCapacity(ni);
293 mf.update_prog_node.increaseEstimatedTotalItems(1);
294 }
295
296 pub fn hasNextMoved(ni: Node.Index, mf: *const MappedFile) bool {
297 return ni.get(mf).flags.next_moved;
298 }
299 pub fn nextMoved(ni: Node.Index, gpa: Allocator, mf: *MappedFile) Allocator.Error!void {
300 try mf.updates.ensureUnusedCapacity(gpa, 1);
301 ni.nextMovedAssumeCapacity(mf);
302 }
303 pub fn cleanNextMoved(ni: Node.Index, mf: *MappedFile) bool {
304 const node_next_moved = &ni.get(mf).flags.next_moved;
305 defer node_next_moved.* = false;
306 return node_next_moved.*;
307 }
308 pub fn nextMovedAssumeCapacity(ni: Node.Index, mf: *MappedFile) void {
309 const node = ni.get(mf);
310 if (!node.flags.enable_next_moved or node.flags.next_moved) return;
311 node.flags.next_moved = true;
312 if (node.flags.moved or node.flags.resized) return;
267313 mf.updates.appendAssumeCapacity(ni);
268314 mf.update_prog_node.increaseEstimatedTotalItems(1);
269315 }
......@@ -333,7 +379,7 @@ pub const Node = extern struct {
333379 return mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)];
334380 }
335381
336 pub fn resize(ni: Node.Index, mf: *MappedFile, gpa: std.mem.Allocator, size: u64) Error!void {
382 pub fn resize(ni: Node.Index, mf: *MappedFile, gpa: Allocator, size: u64) Error!void {
337383 mf.resizeNode(gpa, ni, size) catch |err| switch (err) {
338384 error.OutOfMemory,
339385 error.Canceled,
......@@ -360,7 +406,7 @@ pub const Node = extern struct {
360406 pub fn realign(
361407 ni: Node.Index,
362408 mf: *MappedFile,
363 gpa: std.mem.Allocator,
409 gpa: Allocator,
364410 new_alignment: std.mem.Alignment,
365411 opts: RealignNodeOptions,
366412 ) Error!void {
......@@ -384,7 +430,7 @@ pub const Node = extern struct {
384430 pub fn shrink(
385431 ni: Node.Index,
386432 mf: *MappedFile,
387 gpa: std.mem.Allocator,
433 gpa: Allocator,
388434 size: u64,
389435 shift_next: bool,
390436 ) Error!void {
......@@ -392,7 +438,7 @@ pub const Node = extern struct {
392438 mf.updateWriters();
393439 }
394440
395 pub fn writer(ni: Node.Index, mf: *MappedFile, gpa: std.mem.Allocator, w: *Writer) void {
441 pub fn writer(ni: Node.Index, mf: *MappedFile, gpa: Allocator, w: *Writer) void {
396442 w.* = .{
397443 .gpa = gpa,
398444 .mf = mf,
......@@ -419,7 +465,7 @@ pub const Node = extern struct {
419465 }
420466
421467 pub const Writer = struct {
422 gpa: std.mem.Allocator,
468 gpa: Allocator,
423469 mf: *MappedFile,
424470 writer_node: std.SinglyLinkedList.Node,
425471 ni: Node.Index,
......@@ -543,14 +589,13 @@ pub const Node = extern struct {
543589 }
544590};
545591
546fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {
592fn addNode(mf: *MappedFile, gpa: Allocator, opts: struct {
547593 parent: Node.Index = .none,
548594 prev: Node.Index = .none,
549595 next: Node.Index = .none,
550596 offset: u64 = 0,
551597 add_node: AddNodeOptions,
552598}) (Allocator.Error || Io.Cancelable || IoError)!Node.Index {
553 if (opts.add_node.moved or opts.add_node.resized) try mf.updates.ensureUnusedCapacity(gpa, 1);
554599 mf.nodes_lock.assertUnlocked();
555600 const location_tag: Node.Location.Tag, const location_payload: Node.Location.Payload = location: {
556601 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 {
570615 };
571616 switch (opts.prev) {
572617 .none => opts.parent.get(mf).first = free_ni,
573 else => |prev_ni| prev_ni.get(mf).next = free_ni,
618 else => |prev_ni| try prev_ni.setNext(gpa, free_ni, mf),
574619 }
575620 switch (opts.next) {
576621 .none => opts.parent.get(mf).last = free_ni,
......@@ -588,22 +633,27 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {
588633 .fixed = opts.add_node.fixed,
589634 .moved = true,
590635 .resized = true,
636 .next_moved = true,
591637 .has_content = false,
592638 .bubbles_moved = opts.add_node.bubbles_moved,
639 .enable_next_moved = opts.add_node.enable_next_moved,
593640 },
594641 .location_payload = location_payload,
595642 };
596643
597644 {
645 defer {
646 free_node.flags.moved = false;
647 free_node.flags.resized = false;
648 free_node.flags.next_moved = false;
649 }
598650 try mf.realignNode(gpa, free_ni, opts.add_node.alignment, .{});
599651 try mf.resizeNode(gpa, free_ni, opts.add_node.size);
600 if (opts.add_node.moved or opts.add_node.resized) try mf.updates.ensureUnusedCapacity(gpa, 1);
601 free_node.flags.moved = false;
602 free_node.flags.resized = false;
603652 }
604 if (opts.add_node.moved) free_ni.movedAssumeCapacity(mf);
605 if (opts.add_node.resized) free_ni.resizedAssumeCapacity(mf);
606653 mf.updateWriters();
654 if (opts.add_node.moved) try free_ni.moved(gpa, mf);
655 if (opts.add_node.resized) try free_ni.resized(gpa, mf);
656 if (opts.add_node.next_moved) try free_ni.nextMoved(gpa, mf);
607657 return free_ni;
608658}
609659
......@@ -613,12 +663,14 @@ pub const AddNodeOptions = struct {
613663 fixed: bool = false,
614664 moved: bool = false,
615665 resized: bool = false,
666 next_moved: bool = false,
616667 bubbles_moved: bool = true,
668 enable_next_moved: bool = false,
617669};
618670
619671pub fn addOnlyChildNode(
620672 mf: *MappedFile,
621 gpa: std.mem.Allocator,
673 gpa: Allocator,
622674 parent_ni: Node.Index,
623675 opts: AddNodeOptions,
624676) Error!Node.Index {
......@@ -641,7 +693,7 @@ pub fn addOnlyChildNode(
641693
642694pub fn addFirstChildNode(
643695 mf: *MappedFile,
644 gpa: std.mem.Allocator,
696 gpa: Allocator,
645697 parent_ni: Node.Index,
646698 opts: AddNodeOptions,
647699) Error!Node.Index {
......@@ -664,7 +716,7 @@ pub fn addFirstChildNode(
664716
665717pub fn addLastChildNode(
666718 mf: *MappedFile,
667 gpa: std.mem.Allocator,
719 gpa: Allocator,
668720 parent_ni: Node.Index,
669721 opts: AddNodeOptions,
670722) Error!Node.Index {
......@@ -694,7 +746,7 @@ pub fn addLastChildNode(
694746
695747pub fn addNodeAfter(
696748 mf: *MappedFile,
697 gpa: std.mem.Allocator,
749 gpa: Allocator,
698750 prev_ni: Node.Index,
699751 opts: AddNodeOptions,
700752) Error!Node.Index {
......@@ -721,7 +773,7 @@ pub fn addNodeAfter(
721773
722774fn shrinkNode(
723775 mf: *MappedFile,
724 gpa: std.mem.Allocator,
776 gpa: Allocator,
725777 ni: Node.Index,
726778 size: u64,
727779 shift_next: bool,
......@@ -740,7 +792,7 @@ fn shrinkNode(
740792 }
741793
742794 try mf.large.ensureUnusedCapacity(gpa, 4);
743 try mf.updates.ensureUnusedCapacity(gpa, 2);
795 try mf.updates.ensureUnusedCapacity(gpa, 4);
744796
745797 ni.setLocationAssumeCapacity(mf, old_offset, size);
746798 if (!shift_next or node.next == .none) return;
......@@ -765,7 +817,7 @@ fn shrinkNode(
765817
766818fn resizeNode(
767819 mf: *MappedFile,
768 gpa: std.mem.Allocator,
820 gpa: Allocator,
769821 ni: Node.Index,
770822 requested_size: u64,
771823) (Allocator.Error || Io.Cancelable || IoError)!void {
......@@ -904,11 +956,11 @@ fn resizeNode(
904956 next_ni.get(mf).prev = node.prev;
905957 switch (node.prev) {
906958 .none => parent.first = next_ni,
907 else => |prev_ni| prev_ni.get(mf).next = next_ni,
959 else => |prev_ni| try prev_ni.setNext(gpa, next_ni, mf),
908960 }
909 last.next = ni;
961 try parent.last.setNext(gpa, ni, mf);
910962 node.prev = parent.last;
911 node.next = .none;
963 try ni.setNext(gpa, .none, mf);
912964 parent.last = ni;
913965 if (node.flags.has_content) {
914966 const parent_file_offset = node.parent.fileLocation(mf, false).offset;
......@@ -972,13 +1024,13 @@ fn resizeNode(
9721024 if (parent.last != first_floating_ni) {
9731025 first_floating.prev = parent.last;
9741026 parent.last = first_floating_ni;
975 last.next = first_floating_ni;
976 last_fixed.next = first_floating.next;
1027 try parent.last.setNext(gpa, first_floating_ni, mf);
1028 try last_fixed_ni.setNext(gpa, first_floating.next, mf);
9771029 switch (first_floating.next) {
9781030 .none => {},
9791031 else => |next_ni| next_ni.get(mf).prev = last_fixed_ni,
9801032 }
981 first_floating.next = .none;
1033 try first_floating_ni.setNext(gpa, .none, mf);
9821034 }
9831035 if (first_floating.flags.has_content) {
9841036 const parent_file_offset =
......@@ -1040,7 +1092,7 @@ fn resizeNode(
10401092
10411093fn realignNode(
10421094 mf: *MappedFile,
1043 gpa: std.mem.Allocator,
1095 gpa: Allocator,
10441096 ni: Node.Index,
10451097 new_alignment: std.mem.Alignment,
10461098 opts: Node.Index.RealignNodeOptions,
......@@ -1241,9 +1293,9 @@ fn copyFileRange(
12411293 return size - remaining_size;
12421294}
12431295
1244fn ensureCapacityForSetLocation(mf: *MappedFile, gpa: std.mem.Allocator) Allocator.Error!void {
1296fn ensureCapacityForSetLocation(mf: *MappedFile, gpa: Allocator) Allocator.Error!void {
12451297 try mf.large.ensureUnusedCapacity(gpa, 2);
1246 try mf.updates.ensureUnusedCapacity(gpa, 1);
1298 try mf.updates.ensureUnusedCapacity(gpa, 2);
12471299}
12481300
12491301pub fn ensureTotalCapacity(mf: *MappedFile, new_capacity: usize) Error!void {
src/link/SpirV.zig+13-13
......@@ -25,10 +25,10 @@ const Mir = @import("../codegen/spirv/Mir.zig");
2525const Linker = @This();
2626
2727base: link.File,
28fragments: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, Mir) = .empty,
29pending_navs: std.ArrayListUnmanaged(InternPool.Nav.Index) = .empty,
30entry_points: std.ArrayListUnmanaged(EntryPointDecl) = .empty,
31external_objects: std.ArrayListUnmanaged(ExternalObject) = .empty,
28fragments: std.array_hash_map.Auto(InternPool.Nav.Index, Mir) = .empty,
29pending_navs: std.ArrayList(InternPool.Nav.Index) = .empty,
30entry_points: std.ArrayList(EntryPointDecl) = .empty,
31external_objects: std.ArrayList(ExternalObject) = .empty,
3232
3333const EntryPointDecl = struct {
3434 nav: InternPool.Nav.Index,
......@@ -363,16 +363,16 @@ fn mergeFragments(linker: *Linker, gpa: Allocator, arena: Allocator) error{OutOf
363363 }
364364
365365 // Resolve Zig extern navs against external objects.
366 var ext_id_offsets: std.ArrayListUnmanaged(Word) = .empty;
366 var ext_id_offsets: std.ArrayList(Word) = .empty;
367367 defer ext_id_offsets.deinit(gpa);
368368 try ext_id_offsets.ensureTotalCapacity(gpa, linker.external_objects.items.len);
369369
370370 var unresolved_extern_count: u32 = 0;
371 var resolved_ids: std.AutoArrayHashMapUnmanaged(Id, void) = .empty;
371 var resolved_ids: std.array_hash_map.Auto(Id, void) = .empty;
372372 defer resolved_ids.deinit(gpa);
373373
374374 if (maybe_ip) |ip| {
375 var extern_name_map: std.StringArrayHashMapUnmanaged(InternPool.Nav.Index) = .empty;
375 var extern_name_map: std.array_hash_map.String(InternPool.Nav.Index) = .empty;
376376 defer extern_name_map.deinit(gpa);
377377
378378 var nav_it = nav_final_ids.iterator();
......@@ -518,14 +518,14 @@ fn mergeZigFragments(
518518 frag_infos: []const FragmentInfo,
519519 nav_final_ids: *const std.AutoHashMapUnmanaged(InternPool.Nav.Index, Id),
520520 uav_final_ids: *const std.AutoHashMapUnmanaged(struct { InternPool.Index, spec.StorageClass }, Id),
521 resolved_ids: *const std.AutoArrayHashMapUnmanaged(Id, void),
521 resolved_ids: *const std.array_hash_map.Auto(Id, void),
522522 maybe_ip: ?*InternPool,
523523) error{OutOfMemory}!void {
524524 for (linker.fragments.values(), frag_infos) |*mir, frag_info| {
525525 var id_remap: std.AutoHashMapUnmanaged(Id, Id) = .empty;
526526 defer id_remap.deinit(gpa);
527527
528 var resolved_local_ids: std.AutoArrayHashMapUnmanaged(Id, void) = .empty;
528 var resolved_local_ids: std.array_hash_map.Auto(Id, void) = .empty;
529529 defer resolved_local_ids.deinit(gpa);
530530
531531 for (mir.nav_refs) |ref| {
......@@ -569,7 +569,7 @@ fn remapFilteredInsts(
569569 id_offset: Word,
570570 id_remap: *const std.AutoHashMapUnmanaged(Id, Id),
571571 parser: *BinaryModule.Parser,
572 skip_ids: *const std.AutoArrayHashMapUnmanaged(Id, void),
572 skip_ids: *const std.array_hash_map.Auto(Id, void),
573573 mode: FilterMode,
574574) error{OutOfMemory}!void {
575575 if (words.len == 0) return;
......@@ -887,9 +887,9 @@ fn appendExternalObjects(
887887 has_linkage: *bool,
888888 keep_entry_points: bool,
889889 is_obj: bool,
890 resolved_ids: *const std.AutoArrayHashMapUnmanaged(Id, void),
890 resolved_ids: *const std.array_hash_map.Auto(Id, void),
891891) error{OutOfMemory}!void {
892 var export_map: std.StringArrayHashMapUnmanaged(Id) = .empty;
892 var export_map: std.array_hash_map.String(Id) = .empty;
893893 defer export_map.deinit(gpa);
894894
895895 for (linker.external_objects.items, ext_id_offsets) |ext_obj, id_offset| {
......@@ -908,7 +908,7 @@ fn appendExternalObjects(
908908 }
909909 for (per_obj_remaps) |*m| m.* = .empty;
910910
911 var resolved_linkage_ids: std.AutoArrayHashMapUnmanaged(Id, void) = .empty;
911 var resolved_linkage_ids: std.array_hash_map.Auto(Id, void) = .empty;
912912 defer resolved_linkage_ids.deinit(gpa);
913913
914914 for (resolved_ids.keys()) |id| {
src/link/SpirV/dedup_types.zig+2-2
......@@ -85,7 +85,7 @@ pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule) !void {
8585
8686 for (inst.operands, 0..) |word, i| {
8787 if (i == result_id_index) continue;
88 if (std.mem.indexOfScalar(u16, id_offsets.items, @intCast(i)) != null) {
88 if (std.mem.findScalar(u16, id_offsets.items, @intCast(i)) != null) {
8989 const canonical = id_remap.get(@fromBackingInt(@intCast(word))) orelse @as(Id, @fromBackingInt(@intCast(word)));
9090 try key_words.append(gpa, @backingInt(canonical));
9191 } else {
......@@ -182,7 +182,7 @@ pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule) !void {
182182 } else null;
183183
184184 for (inst_slice, 0..) |*word, i| {
185 if (std.mem.indexOfScalar(u16, id_offsets.items, @intCast(i)) == null) continue;
185 if (std.mem.findScalar(u16, id_offsets.items, @intCast(i)) == null) continue;
186186 max_id = @max(max_id, word.*);
187187 if (maybe_result_id_index != null and i == maybe_result_id_index.?) continue;
188188
src/link/SpirV/prune_unused.zig+1-1
......@@ -187,7 +187,7 @@ fn markAlive(
187187 parser: *BinaryModule.Parser,
188188 binary: BinaryModule,
189189 inst: BinaryModule.Instruction,
190 alive: *std.DynamicBitSetUnmanaged,
190 alive: *std.bit_set.Dynamic,
191191 id_to_index: *const std.AutoHashMapUnmanaged(ResultId, u32),
192192 code_offsets: *const std.ArrayList(usize),
193193 id_offset_buf: *std.ArrayList(u16),
src/link/Wasm.zig+953-206
......@@ -133,25 +133,21 @@ object_total_sections: u32 = 0,
133133/// All comdat symbols from all objects concatenated.
134134object_comdat_symbols: std.MultiArrayList(Comdat.Symbol) = .empty,
135135
136/// Relocations to be emitted into an object file. Remains empty when not
137/// emitting an object file.
138out_relocs: std.MultiArrayList(OutReloc) = .empty,
136/// Relocations produced by Zig code and data lowering. These retain semantic
137/// targets until `flush`, where final output indexes are known.
138zcu_relocations: std.MultiArrayList(ZcuRelocation) = .empty,
139139/// List of locations within `string_bytes` that must be patched with the virtual
140140/// memory address of a Uav during `flush`.
141/// When emitting an object file, `out_relocs` is used instead.
141/// When emitting an object file, `zcu_relocations` is used instead.
142142uav_fixups: std.ArrayList(UavFixup) = .empty,
143143/// List of locations within `string_bytes` that must be patched with the virtual
144144/// memory address of a Nav during `flush`.
145/// When emitting an object file, `out_relocs` is used instead.
145/// When emitting an object file, `zcu_relocations` is used instead.
146146/// No functions here only global variables.
147147nav_fixups: std.ArrayList(NavFixup) = .empty,
148148/// When a nav reference is a function pointer, this tracks the required function
149149/// table entry index that needs to overwrite the code in the final output.
150150func_table_fixups: std.ArrayList(FuncTableFixup) = .empty,
151/// Symbols to be emitted into an object file. Remains empty when not emitting
152/// an object file.
153symbol_table: std.array_hash_map.Auto(String, void) = .empty,
154
155151/// When importing objects from the host environment, a name must be supplied.
156152/// LLVM uses "env" by default when none is given.
157153/// 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,
244240/// remove elements from the table, and the remainder are either undefined
245241/// symbol errors, or symbol table entries depending on the output mode.
246242data_imports: std.array_hash_map.Auto(String, DataImportId) = .empty,
247/// Set of data symbols that will appear in the final binary. Used to populate
243/// Set of data symbols that will appear in the final binary when outputting an object file.
244datas: std.array_hash_map.Auto(ObjectDataImport.Resolution, void) = .empty,
245/// Set of data segment symbols that will appear in the final binary. Used to populate
248246/// `Flush.data_segments` before sorting.
249247data_segments: std.array_hash_map.Auto(DataSegmentId, void) = .empty,
250248
......@@ -302,11 +300,6 @@ pub const TagNameOff = extern struct {
302300 len: u32,
303301};
304302
305/// Index into `Wasm.zcu_indirect_function_set`.
306pub const ZcuIndirectFunctionSetIndex = enum(u32) {
307 _,
308};
309
310303pub const UavFixup = extern struct {
311304 uavs_exe_index: UavsExeIndex,
312305 /// Index into `string_bytes`.
......@@ -315,14 +308,14 @@ pub const UavFixup = extern struct {
315308};
316309
317310pub const NavFixup = extern struct {
318 navs_exe_index: NavsExeIndex,
311 nav_index: InternPool.Nav.Index,
319312 /// Index into `string_bytes`.
320313 offset: u32,
321314 addend: u32,
322315};
323316
324317pub const FuncTableFixup = extern struct {
325 table_index: ZcuIndirectFunctionSetIndex,
318 nav_index: InternPool.Nav.Index,
326319 /// Index into `string_bytes`.
327320 offset: u32,
328321};
......@@ -355,7 +348,9 @@ pub const FunctionIndex = enum(u32) {
355348
356349 pub fn fromSymbolName(wasm: *const Wasm, name: String) ?FunctionIndex {
357350 if (wasm.object_function_imports.getPtr(name)) |import| {
358 return fromResolution(wasm, import.resolution);
351 if (import.resolution != .unresolved) {
352 return fromResolution(wasm, import.resolution);
353 }
359354 }
360355 if (wasm.function_exports.get(name)) |index| return index;
361356 if (wasm.hidden_function_exports.get(name)) |index| return index;
......@@ -374,7 +369,8 @@ pub const GlobalExport = extern struct {
374369};
375370
376371/// 0. Index into `Flush.function_imports`
377/// 1. Index into `functions`.
372/// 1. Index into `Flush.intrinsic_function_imports`
373/// 2. Index into `functions`.
378374///
379375/// Note that function_imports indexes are subject to swap removals during
380376/// `flush`.
......@@ -386,7 +382,11 @@ pub const OutputFunctionIndex = enum(u32) {
386382 }
387383
388384 pub fn fromFunctionIndex(wasm: *const Wasm, index: FunctionIndex) OutputFunctionIndex {
389 return @fromBackingInt(@intCast(wasm.flush_buffer.function_imports.entries.len + @backingInt(index)));
385 return @fromBackingInt(@intCast(
386 wasm.flush_buffer.function_imports.entries.len +
387 wasm.flush_buffer.intrinsic_function_imports.entries.len +
388 @backingInt(index),
389 ));
390390 }
391391
392392 pub fn fromObjectFunction(wasm: *const Wasm, index: ObjectFunctionIndex) OutputFunctionIndex {
......@@ -429,6 +429,9 @@ pub const OutputFunctionIndex = enum(u32) {
429429
430430 pub fn fromSymbolName(wasm: *const Wasm, name: String) OutputFunctionIndex {
431431 if (wasm.flush_buffer.function_imports.getIndex(name)) |i| return @fromBackingInt(@intCast(i));
432 if (wasm.flush_buffer.intrinsic_function_imports.getIndex(name)) |i| return @fromBackingInt(@intCast(
433 wasm.flush_buffer.function_imports.entries.len + i,
434 ));
432435 return fromFunctionIndex(wasm, FunctionIndex.fromSymbolName(wasm, name) orelse {
433436 if (std.debug.runtime_safety) {
434437 std.debug.panic("function index for symbol not found: {s}", .{name.slice(wasm)});
......@@ -437,6 +440,56 @@ pub const OutputFunctionIndex = enum(u32) {
437440 }
438441};
439442
443// Order
444// 0. Flush.data_imports
445// 1. Wasm.datas
446pub const OutputDataIndex = enum(u32) {
447 _,
448
449 pub fn fromSymbolName(wasm: *const Wasm, name: String) OutputDataIndex {
450 if (wasm.flush_buffer.data_imports.getIndex(name)) |i| return @fromBackingInt(@intCast(i));
451 if (wasm.object_data_imports.getPtr(name)) |import| {
452 if (import.resolution != .unresolved) return fromResolution(wasm, import.resolution).?;
453 }
454 if (wasm.flush_buffer.data_exports.get(name)) |symbol| return fromResolution(wasm, symbol.resolution).?;
455 if (std.debug.runtime_safety) {
456 std.debug.panic("data index for symbol not found: {s}", .{name.slice(wasm)});
457 } else unreachable;
458 }
459
460 pub fn fromObjectData(wasm: *const Wasm, index: ObjectData.Index) OutputDataIndex {
461 return fromResolution(wasm, .fromObjectDataIndex(wasm, index)).?;
462 }
463
464 pub fn fromResolution(wasm: *const Wasm, resolution: ObjectDataImport.Resolution) ?OutputDataIndex {
465 const i = wasm.datas.getIndex(resolution) orelse return null;
466 return @fromBackingInt(@intCast(wasm.flush_buffer.data_imports.entries.len + i));
467 }
468
469 pub fn fromUav(wasm: *const Wasm, ip_index: InternPool.Index) OutputDataIndex {
470 const comp = wasm.base.comp;
471 const resolution: ObjectDataImport.Resolution = if (comp.config.output_mode == .Obj)
472 .pack(wasm, .{ .uav_obj = @fromBackingInt(@intCast(wasm.uavs_obj.getIndex(ip_index).?)) })
473 else
474 .pack(wasm, .{ .uav_exe = @fromBackingInt(@intCast(wasm.uavs_exe.getIndex(ip_index).?)) });
475 return fromResolution(wasm, resolution).?;
476 }
477
478 pub fn fromNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) OutputDataIndex {
479 const zcu = wasm.base.comp.zcu.?;
480 const ip = &zcu.intern_pool;
481 const nav = ip.getNav(nav_index);
482 if (nav.getExtern(ip)) |ext| {
483 return fromSymbolName(wasm, wasm.getExistingString(ext.name.toSlice(ip)).?);
484 }
485 const resolution: ObjectDataImport.Resolution = if (wasm.base.comp.config.output_mode == .Obj)
486 .pack(wasm, .{ .nav_obj = @fromBackingInt(@intCast(wasm.navs_obj.getIndex(nav_index).?)) })
487 else
488 .pack(wasm, .{ .nav_exe = @fromBackingInt(@intCast(wasm.navs_exe.getIndex(nav_index).?)) });
489 return fromResolution(wasm, resolution).?;
490 }
491};
492
440493/// Index into `Wasm.globals`.
441494pub const GlobalIndex = enum(u32) {
442495 _,
......@@ -452,17 +505,17 @@ pub const GlobalIndex = enum(u32) {
452505 return .stack_pointer;
453506 }
454507
455 pub fn ptr(index: GlobalIndex, f: *const Flush) *Wasm.GlobalImport.Resolution {
456 return &f.globals.items[@backingInt(index)];
508 pub fn fromResolution(wasm: *const Wasm, resolution: GlobalImport.Resolution) ?GlobalIndex {
509 const i = wasm.globals.getIndex(resolution) orelse return null;
510 return @fromBackingInt(@intCast(wasm.flush_buffer.global_imports.entries.len + i));
457511 }
458512
459513 pub fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) ?GlobalIndex {
460 const i = wasm.globals.getIndex(.fromIpNav(wasm, nav_index)) orelse return null;
461 return @fromBackingInt(@intCast(i));
514 return fromResolution(wasm, .fromIpNav(wasm, nav_index));
462515 }
463516
464517 pub fn fromObjectGlobal(wasm: *const Wasm, i: ObjectGlobalIndex) GlobalIndex {
465 return @fromBackingInt(@intCast(wasm.globals.getIndex(.fromObjectGlobal(wasm, i)).?));
518 return fromResolution(wasm, .fromObjectGlobal(wasm, i)).?;
466519 }
467520
468521 pub fn fromObjectGlobalHandlingWeak(wasm: *const Wasm, index: ObjectGlobalIndex) GlobalIndex {
......@@ -474,8 +527,9 @@ pub const GlobalIndex = enum(u32) {
474527 }
475528
476529 pub fn fromSymbolName(wasm: *const Wasm, name: String) GlobalIndex {
530 if (wasm.flush_buffer.global_imports.getIndex(name)) |i| return @fromBackingInt(@intCast(i));
477531 const import = wasm.object_global_imports.getPtr(name).?;
478 return @fromBackingInt(@intCast(wasm.globals.getIndex(import.resolution).?));
532 return fromResolution(wasm, import.resolution).?;
479533 }
480534};
481535
......@@ -483,10 +537,6 @@ pub const GlobalIndex = enum(u32) {
483537pub const TableIndex = enum(u32) {
484538 _,
485539
486 pub fn ptr(index: TableIndex, f: *const Flush) *Wasm.TableImport.Resolution {
487 return &f.tables.items[@backingInt(index)];
488 }
489
490540 pub fn fromObjectTable(wasm: *const Wasm, i: ObjectTableIndex) TableIndex {
491541 return @fromBackingInt(@intCast(wasm.tables.getIndex(.fromObjectTable(i)).?));
492542 }
......@@ -668,9 +718,10 @@ pub const SymbolFlags = packed struct(u32) {
668718 flags.ref_type = .funcref;
669719 }
670720
671 pub fn isIncluded(flags: SymbolFlags, is_dynamic: bool) bool {
721 pub fn isIncluded(flags: SymbolFlags, is_dynamic: bool, is_obj: bool) bool {
672722 return flags.exported or
673723 (is_dynamic and !flags.visibility_hidden) or
724 (is_obj and flags.binding != .local) or
674725 (flags.no_strip and flags.must_link);
675726 }
676727
......@@ -696,8 +747,8 @@ pub const SymbolFlags = packed struct(u32) {
696747 /// Masks off the Zig-specific stuff.
697748 pub fn toAbiInteger(flags: SymbolFlags) u32 {
698749 var copy = flags;
699 copy.initZigSpecific(false, false);
700 return @bitCast(copy);
750 copy.initZigSpecific(false, flags.no_strip);
751 return @backingInt(copy);
701752 }
702753};
703754
......@@ -812,7 +863,7 @@ pub const UavsExeIndex = enum(u32) {
812863/// Used when emitting a relocatable object.
813864pub const ZcuDataObj = extern struct {
814865 code: DataPayload,
815 relocs: OutReloc.Slice,
866 relocs: ZcuRelocation.Slice,
816867};
817868
818869/// Used when not emitting a relocatable object.
......@@ -855,7 +906,9 @@ const ZcuDataStarts = struct {
855906 var uavs_i = zds.uavs_i;
856907 while (uavs_i < wasm.uavs_obj.entries.len) : (uavs_i += 1) {
857908 // Call to `lowerZcuData` here possibly creates more entries in these tables.
858 wasm.uavs_obj.values()[uavs_i] = try lowerZcuData(wasm, pt, wasm.uavs_obj.keys()[uavs_i]);
909 const uav = wasm.uavs_obj.keys()[uavs_i];
910 const zcu_data = try lowerZcuData(wasm, pt, uav);
911 wasm.uavs_obj.values()[uavs_i] = zcu_data;
859912 }
860913 }
861914
......@@ -906,6 +959,51 @@ pub const ZcuFunc = union {
906959 return &wasm.zcu_funcs.values()[@backingInt(i)];
907960 }
908961
962 pub fn flags(i: @This(), wasm: *const Wasm) SymbolFlags {
963 const zcu = wasm.base.comp.zcu.?;
964 const ip = &zcu.intern_pool;
965 const ip_index = i.key(wasm).*;
966 switch (ip.indexToKey(ip_index)) {
967 .func => |func| {
968 const nav = ip.getNav(func.owner_nav);
969 if (nav.getExtern(ip)) |ext| {
970 const name_slice = ext.name.toSlice(ip);
971 const name_string = wasm.getExistingString(name_slice).?;
972 return .{
973 .binding = switch (ext.linkage) {
974 .internal => .local,
975 .strong => .strong,
976 .weak => .weak,
977 .link_once => @panic("TODO: COMDAT"),
978 },
979 .visibility_hidden = switch (ext.visibility) {
980 .default => false,
981 .hidden => true,
982 .protected => false,
983 },
984 .undefined = false,
985 .exported = wasm.missing_exports.contains(name_string),
986 .explicit_name = false,
987 .no_strip = false,
988 .tls = ext.is_threadlocal,
989 .absolute = false,
990 };
991 } else {
992 return .{
993 .binding = .local,
994 .tls = nav.resolved.?.@"threadlocal",
995 };
996 }
997 },
998 .enum_type => {
999 return .{
1000 .binding = .local,
1001 };
1002 },
1003 else => unreachable,
1004 }
1005 }
1006
9091007 pub fn name(i: @This(), wasm: *const Wasm) [:0]const u8 {
9101008 const zcu = wasm.base.comp.zcu.?;
9111009 const ip = &zcu.intern_pool;
......@@ -1034,6 +1132,15 @@ pub const FunctionImport = extern struct {
10341132 return pack(wasm, .{ .object_function = object_function });
10351133 }
10361134
1135 pub fn flags(r: Resolution, wasm: *Wasm) SymbolFlags {
1136 return switch (unpack(r, wasm)) {
1137 .unresolved => unreachable,
1138 .__wasm_apply_global_tls_relocs, .__wasm_call_ctors, .__wasm_init_memory, .__wasm_init_tls => unreachable,
1139 .object_function => |i| i.ptr(wasm).flags,
1140 .zcu_func => |i| i.flags(wasm),
1141 };
1142 }
1143
10371144 pub fn isNavOrUnresolved(r: Resolution, wasm: *const Wasm) bool {
10381145 return switch (r.unpack(wasm)) {
10391146 .unresolved, .zcu_func => true,
......@@ -1136,6 +1243,7 @@ pub const GlobalImport = extern struct {
11361243 __tls_base,
11371244 __tls_size,
11381245 // Next, index into `object_globals`.
1246 // Next, index into `uavs_obj` or `uavs_exe` depending on whether emitting an object.
11391247 // Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object.
11401248 _,
11411249
......@@ -1150,6 +1258,8 @@ pub const GlobalImport = extern struct {
11501258 __tls_base,
11511259 __tls_size,
11521260 object_global: ObjectGlobalIndex,
1261 uav_exe: UavsExeIndex,
1262 uav_obj: UavsObjIndex,
11531263 nav_exe: NavsExeIndex,
11541264 nav_obj: NavsObjIndex,
11551265 };
......@@ -1170,12 +1280,22 @@ pub const GlobalImport = extern struct {
11701280 return .{ .object_global = @fromBackingInt(@intCast(object_global_index)) };
11711281 const comp = wasm.base.comp;
11721282 const is_obj = comp.config.output_mode == .Obj;
1173 const nav_index = object_global_index - wasm.object_globals.items.len;
1174 return if (is_obj) .{
1175 .nav_obj = @fromBackingInt(@intCast(nav_index)),
1176 } else .{
1177 .nav_exe = @fromBackingInt(@intCast(nav_index)),
1178 };
1283 const uav_index = object_global_index - wasm.object_globals.items.len;
1284 if (is_obj) {
1285 if (uav_index < wasm.uavs_obj.entries.len) {
1286 return .{ .uav_obj = @fromBackingInt(@intCast(uav_index)) };
1287 }
1288 return .{ .nav_obj = @fromBackingInt(
1289 @intCast(uav_index - wasm.uavs_obj.entries.len),
1290 ) };
1291 } else {
1292 if (uav_index < wasm.uavs_exe.entries.len) {
1293 return .{ .uav_exe = @fromBackingInt(@intCast(uav_index)) };
1294 }
1295 return .{ .nav_exe = @fromBackingInt(
1296 @intCast(uav_index - wasm.uavs_exe.entries.len),
1297 ) };
1298 }
11791299 },
11801300 };
11811301 }
......@@ -1190,11 +1310,29 @@ pub const GlobalImport = extern struct {
11901310 .__tls_base => .__tls_base,
11911311 .__tls_size => .__tls_size,
11921312 .object_global => |i| @fromBackingInt(@intCast(first_object_global + @backingInt(i))),
1193 .nav_obj => |i| @fromBackingInt(@intCast(first_object_global + wasm.object_globals.items.len + @backingInt(i))),
1194 .nav_exe => |i| @fromBackingInt(@intCast(first_object_global + wasm.object_globals.items.len + @backingInt(i))),
1313 inline .uav_obj, .uav_exe => |i| @fromBackingInt(@intCast(
1314 first_object_global + wasm.object_globals.items.len + @backingInt(i),
1315 )),
1316 .nav_obj => |i| @fromBackingInt(@intCast(
1317 first_object_global + wasm.object_globals.items.len +
1318 wasm.uavs_obj.entries.len + @backingInt(i),
1319 )),
1320 .nav_exe => |i| @fromBackingInt(@intCast(
1321 first_object_global + wasm.object_globals.items.len +
1322 wasm.uavs_exe.entries.len + @backingInt(i),
1323 )),
11951324 };
11961325 }
11971326
1327 pub fn fromIpIndex(wasm: *const Wasm, ip_index: InternPool.Index) Resolution {
1328 const is_obj = wasm.base.comp.config.output_mode == .Obj;
1329 return pack(wasm, if (is_obj) .{
1330 .uav_obj = @fromBackingInt(@intCast(wasm.uavs_obj.getIndex(ip_index).?)),
1331 } else .{
1332 .uav_exe = @fromBackingInt(@intCast(wasm.uavs_exe.getIndex(ip_index).?)),
1333 });
1334 }
1335
11981336 pub fn fromIpNav(wasm: *const Wasm, ip_nav: InternPool.Nav.Index) Resolution {
11991337 const comp = wasm.base.comp;
12001338 const is_obj = comp.config.output_mode == .Obj;
......@@ -1209,7 +1347,22 @@ pub const GlobalImport = extern struct {
12091347 return pack(wasm, .{ .object_global = object_global });
12101348 }
12111349
1212 pub fn name(r: Resolution, wasm: *const Wasm) ?[]const u8 {
1350 pub fn flags(r: Resolution, wasm: *const Wasm) SymbolFlags {
1351 return switch (unpack(r, wasm)) {
1352 .unresolved,
1353 .__heap_base,
1354 .__heap_end,
1355 .__stack_pointer,
1356 .__tls_align,
1357 .__tls_base,
1358 .__tls_size,
1359 => unreachable,
1360 .object_global => |i| i.ptr(wasm).flags,
1361 .uav_obj, .uav_exe, .nav_obj, .nav_exe => unreachable,
1362 };
1363 }
1364
1365 pub fn name(r: Resolution, wasm: *const Wasm, buf: []u8) ?[]const u8 {
12131366 return switch (unpack(r, wasm)) {
12141367 .unresolved => unreachable,
12151368 .__heap_base => @tagName(Unpacked.__heap_base),
......@@ -1219,6 +1372,11 @@ pub const GlobalImport = extern struct {
12191372 .__tls_base => @tagName(Unpacked.__tls_base),
12201373 .__tls_size => @tagName(Unpacked.__tls_size),
12211374 .object_global => |i| i.name(wasm).slice(wasm),
1375 inline .uav_obj, .uav_exe => |i| std.fmt.bufPrint(
1376 buf,
1377 "__anon_{d}",
1378 .{@backingInt(i.key(wasm).*)},
1379 ) catch unreachable,
12221380 .nav_obj => |i| i.name(wasm),
12231381 .nav_exe => |i| i.name(wasm),
12241382 };
......@@ -1349,6 +1507,22 @@ pub const TableImport = extern struct {
13491507 return pack(.{ .object_table = object_table });
13501508 }
13511509
1510 pub fn name(r: Resolution, wasm: *const Wasm) ?[]const u8 {
1511 return switch (unpack(r)) {
1512 .unresolved => unreachable,
1513 .__indirect_function_table => @tagName(Unpacked.__indirect_function_table),
1514 .object_table => |i| i.ptr(wasm).name.slice(wasm),
1515 };
1516 }
1517
1518 pub fn flags(r: Resolution, wasm: *const Wasm) SymbolFlags {
1519 return switch (unpack(r)) {
1520 .unresolved => unreachable,
1521 .__indirect_function_table => unreachable,
1522 .object_table => |i| i.ptr(wasm).flags,
1523 };
1524 }
1525
13521526 pub fn refType(r: Resolution, wasm: *const Wasm) std.wasm.RefType {
13531527 return switch (unpack(r)) {
13541528 .unresolved => unreachable,
......@@ -1602,6 +1776,8 @@ pub const ObjectDataImport = extern struct {
16021776 unresolved,
16031777 __zig_error_names,
16041778 __zig_error_name_table,
1779 __zig_tag_names,
1780 __zig_tag_name_table,
16051781 __heap_base,
16061782 __heap_end,
16071783 /// Next, an `ObjectData.Index`.
......@@ -1615,6 +1791,8 @@ pub const ObjectDataImport = extern struct {
16151791 unresolved,
16161792 __zig_error_names,
16171793 __zig_error_name_table,
1794 __zig_tag_names,
1795 __zig_tag_name_table,
16181796 __heap_base,
16191797 __heap_end,
16201798 object: ObjectData.Index,
......@@ -1629,6 +1807,8 @@ pub const ObjectDataImport = extern struct {
16291807 .unresolved => .unresolved,
16301808 .__zig_error_names => .__zig_error_names,
16311809 .__zig_error_name_table => .__zig_error_name_table,
1810 .__zig_tag_names => .__zig_tag_names,
1811 .__zig_tag_name_table => .__zig_tag_name_table,
16321812 .__heap_base => .__heap_base,
16331813 .__heap_end => .__heap_end,
16341814 _ => {
......@@ -1665,6 +1845,8 @@ pub const ObjectDataImport = extern struct {
16651845 .unresolved => .unresolved,
16661846 .__zig_error_names => .__zig_error_names,
16671847 .__zig_error_name_table => .__zig_error_name_table,
1848 .__zig_tag_names => .__zig_tag_names,
1849 .__zig_tag_name_table => .__zig_tag_name_table,
16681850 .__heap_base => .__heap_base,
16691851 .__heap_end => .__heap_end,
16701852 .object => |i| @fromBackingInt(@intCast(first_object + @backingInt(i))),
......@@ -1678,12 +1860,32 @@ pub const ObjectDataImport = extern struct {
16781860 return pack(wasm, .{ .object = object_data_index });
16791861 }
16801862
1863 pub fn fromIpIndex(wasm: *const Wasm, ip_index: InternPool.Index) Resolution {
1864 const is_obj = wasm.base.comp.config.output_mode == .Obj;
1865 return pack(wasm, if (is_obj) .{
1866 .uav_obj = @fromBackingInt(@intCast(wasm.uavs_obj.getIndex(ip_index).?)),
1867 } else .{
1868 .uav_exe = @fromBackingInt(@intCast(wasm.uavs_exe.getIndex(ip_index).?)),
1869 });
1870 }
1871
1872 pub fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) Resolution {
1873 const is_obj = wasm.base.comp.config.output_mode == .Obj;
1874 return pack(wasm, if (is_obj) .{
1875 .nav_obj = @fromBackingInt(@intCast(wasm.navs_obj.getIndex(nav_index).?)),
1876 } else .{
1877 .nav_exe = @fromBackingInt(@intCast(wasm.navs_exe.getIndex(nav_index).?)),
1878 });
1879 }
1880
16811881 pub fn objectDataSegment(r: Resolution, wasm: *const Wasm) ?ObjectDataSegment.Index {
16821882 return switch (unpack(r, wasm)) {
16831883 .unresolved => unreachable,
16841884 .object => |i| i.ptr(wasm).segment,
16851885 .__zig_error_names,
16861886 .__zig_error_name_table,
1887 .__zig_tag_names,
1888 .__zig_tag_name_table,
16871889 .__heap_base,
16881890 .__heap_end,
16891891 .uav_exe,
......@@ -1706,12 +1908,107 @@ pub const ObjectDataImport = extern struct {
17061908 },
17071909 .__zig_error_names => .{ .segment = .__zig_error_names, .offset = 0 },
17081910 .__zig_error_name_table => .{ .segment = .__zig_error_name_table, .offset = 0 },
1911 .__zig_tag_names => .{ .segment = .__zig_tag_names, .offset = 0 },
1912 .__zig_tag_name_table => .{ .segment = .__zig_tag_name_table, .offset = 0 },
17091913 .__heap_base => .{ .segment = .__heap_base, .offset = 0 },
17101914 .__heap_end => .{ .segment = .__heap_end, .offset = 0 },
1711 .uav_exe => @panic("TODO"),
1712 .uav_obj => @panic("TODO"),
1713 .nav_exe => @panic("TODO"),
1714 .nav_obj => @panic("TODO"),
1915 .uav_exe => |i| .{ .segment = .pack(wasm, .{ .uav_exe = i }), .offset = 0 },
1916 .uav_obj => |i| .{ .segment = .pack(wasm, .{ .uav_obj = i }), .offset = 0 },
1917 .nav_exe => |i| .{ .segment = .pack(wasm, .{ .nav_exe = i }), .offset = 0 },
1918 .nav_obj => |i| .{ .segment = .pack(wasm, .{ .nav_obj = i }), .offset = 0 },
1919 };
1920 }
1921
1922 pub fn flags(r: Resolution, wasm: *const Wasm) SymbolFlags {
1923 return switch (unpack(r, wasm)) {
1924 .unresolved => unreachable,
1925 .__zig_error_names,
1926 .__zig_error_name_table,
1927 .__zig_tag_names,
1928 .__zig_tag_name_table,
1929 => .{ .binding = .local },
1930 .__heap_base,
1931 .__heap_end,
1932 => unreachable,
1933 .object => |i| i.ptr(wasm).flags,
1934 inline .nav_exe, .nav_obj => |i| {
1935 const zcu = wasm.base.comp.zcu.?;
1936 const ip = &zcu.intern_pool;
1937 const nav = ip.getNav(i.key(wasm).*);
1938 if (nav.getExtern(ip)) |ext| {
1939 const name_slice = ext.name.toSlice(ip);
1940 const name_string = wasm.getExistingString(name_slice).?;
1941 return .{
1942 .binding = switch (ext.linkage) {
1943 .internal => .local,
1944 .strong => .strong,
1945 .weak => .weak,
1946 .link_once => @panic("TODO: COMDAT"),
1947 },
1948 .visibility_hidden = switch (ext.visibility) {
1949 .default => false,
1950 .hidden => true,
1951 .protected => false,
1952 },
1953 .undefined = false,
1954 .exported = wasm.missing_exports.contains(name_string),
1955 .explicit_name = false,
1956 .no_strip = false,
1957 .tls = ext.is_threadlocal,
1958 .absolute = false,
1959 };
1960 } else {
1961 return .{
1962 .binding = .local,
1963 .tls = nav.resolved.?.@"threadlocal",
1964 };
1965 }
1966 },
1967 .uav_exe, .uav_obj => .{ .binding = .local },
1968 };
1969 }
1970
1971 pub fn name(r: Resolution, wasm: *const Wasm, buf: []u8) []const u8 {
1972 return switch (unpack(r, wasm)) {
1973 .unresolved => unreachable,
1974 .object => |i| i.ptr(wasm).name.slice(wasm),
1975 .__zig_error_names => @tagName(.__zig_error_names),
1976 .__zig_error_name_table => @tagName(.__zig_error_name_table),
1977 .__zig_tag_names => @tagName(.__zig_tag_names),
1978 .__zig_tag_name_table => @tagName(.__zig_tag_name_table),
1979 .__heap_base => @tagName(.__heap_base),
1980 .__heap_end => @tagName(.__heap_end),
1981 inline .uav_exe, .uav_obj => |i| std.fmt.bufPrint(
1982 buf,
1983 "__anon_{d}",
1984 .{@backingInt(i.key(wasm).*)},
1985 ) catch unreachable,
1986 inline .nav_exe, .nav_obj => |i| i.name(wasm),
1987 };
1988 }
1989
1990 pub fn size(r: Resolution, wasm: *const Wasm) u32 {
1991 return switch (unpack(r, wasm)) {
1992 .unresolved => unreachable,
1993 .__zig_error_names => @intCast(wasm.error_name_bytes.items.len),
1994 .__zig_error_name_table => {
1995 const comp = wasm.base.comp;
1996 const zcu = comp.zcu.?;
1997 const errors_len = wasm.error_name_offs.items.len;
1998 const elem_size = Zcu.Type.slice_const_u8_sentinel_0.abiSize(zcu);
1999 return @intCast(errors_len * elem_size);
2000 },
2001 .__zig_tag_names => @intCast(wasm.tag_name_bytes.items.len),
2002 .__zig_tag_name_table => {
2003 const comp = wasm.base.comp;
2004 const zcu = comp.zcu.?;
2005 const table_len = wasm.tag_name_offs.items.len;
2006 const elem_size = Zcu.Type.slice_const_u8_sentinel_0.abiSize(zcu);
2007 return @intCast(table_len * elem_size);
2008 },
2009 .__heap_base, .__heap_end => wasm.pointerSize(),
2010 .object => |i| i.ptr(wasm).size,
2011 inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.len,
17152012 };
17162013 }
17172014 };
......@@ -1910,6 +2207,38 @@ pub const DataSegmentId = enum(u32) {
19102207 };
19112208 }
19122209
2210 pub fn isStrings(id: DataSegmentId, wasm: *const Wasm) bool {
2211 return switch (unpack(id, wasm)) {
2212 .__zig_error_names, .__zig_tag_names => true,
2213
2214 .__zig_error_name_table,
2215 .__zig_tag_name_table,
2216 .__heap_base,
2217 .__heap_end,
2218 => false,
2219
2220 .object => |i| i.ptr(wasm).flags.strings,
2221 .uav_exe, .uav_obj => false,
2222 .nav_exe, .nav_obj => false,
2223 };
2224 }
2225
2226 pub fn isRetain(id: DataSegmentId, wasm: *const Wasm) bool {
2227 return switch (unpack(id, wasm)) {
2228 .__zig_error_names,
2229 .__zig_error_name_table,
2230 .__zig_tag_names,
2231 .__zig_tag_name_table,
2232 .__heap_base,
2233 .__heap_end,
2234 => false,
2235
2236 .object => |i| i.ptr(wasm).flags.retain,
2237 .uav_exe, .uav_obj => false,
2238 .nav_exe, .nav_obj => false,
2239 };
2240 }
2241
19132242 pub fn isBss(id: DataSegmentId, wasm: *const Wasm) bool {
19142243 return id.category(wasm) == .zero;
19152244 }
......@@ -2181,6 +2510,7 @@ const PreloadedStrings = struct {
21812510 _initialize: String,
21822511 _start: String,
21832512 memory: String,
2513 env: String,
21842514};
21852515
21862516/// Index into string_bytes
......@@ -2209,14 +2539,14 @@ pub const String = enum(u32) {
22092539 }
22102540
22112541 pub fn hash(_: @This(), adapted_key: []const u8) u64 {
2212 assert(mem.indexOfScalar(u8, adapted_key, 0) == null);
2542 assert(mem.findScalar(u8, adapted_key, 0) == null);
22132543 return std.hash_map.hashString(adapted_key);
22142544 }
22152545 };
22162546
22172547 pub fn slice(index: String, wasm: *const Wasm) [:0]const u8 {
22182548 const start_slice = wasm.string_bytes.items[@backingInt(index)..];
2219 return start_slice[0..mem.indexOfScalar(u8, start_slice, 0).? :0];
2549 return start_slice[0..mem.findScalar(u8, start_slice, 0).? :0];
22202550 }
22212551
22222552 pub fn toOptional(i: String) OptionalString {
......@@ -2262,6 +2592,34 @@ pub const ZcuImportIndex = enum(u32) {
22622592 return &wasm.imports.keys()[@backingInt(index)];
22632593 }
22642594
2595 pub fn flags(index: ZcuImportIndex, wasm: *const Wasm) SymbolFlags {
2596 const zcu = wasm.base.comp.zcu.?;
2597 const ip = &zcu.intern_pool;
2598 const nav_index = index.ptr(wasm).*;
2599 const ext = ip.indexToKey(ip.getNav(nav_index).resolved.?.value).@"extern";
2600 const name_slice = ext.name.toSlice(ip);
2601 const name_string = wasm.getExistingString(name_slice).?;
2602 return .{
2603 .binding = switch (ext.linkage) {
2604 .internal => .local,
2605 .strong => .strong,
2606 .weak => .weak,
2607 .link_once => @panic("TODO: COMDAT"),
2608 },
2609 .visibility_hidden = switch (ext.visibility) {
2610 .default => false,
2611 .hidden => true,
2612 .protected => false,
2613 },
2614 .undefined = true,
2615 .exported = wasm.missing_exports.contains(name_string),
2616 .explicit_name = false,
2617 .no_strip = false,
2618 .tls = ext.is_threadlocal,
2619 .absolute = false,
2620 };
2621 }
2622
22652623 pub fn importName(index: ZcuImportIndex, wasm: *const Wasm) String {
22662624 const zcu = wasm.base.comp.zcu.?;
22672625 const ip = &zcu.intern_pool;
......@@ -2348,6 +2706,13 @@ pub const FunctionImportId = enum(u32) {
23482706 }
23492707 }
23502708
2709 pub fn flags(id: FunctionImportId, wasm: *const Wasm) SymbolFlags {
2710 return switch (id.unpack(wasm)) {
2711 .object_function_import => |i| i.value(wasm).flags,
2712 .zcu_import => |i| i.flags(wasm),
2713 };
2714 }
2715
23512716 pub fn importName(id: FunctionImportId, wasm: *const Wasm) String {
23522717 return switch (unpack(id, wasm)) {
23532718 inline .object_function_import, .zcu_import => |i| i.importName(wasm),
......@@ -2385,38 +2750,61 @@ pub const FunctionImportId = enum(u32) {
23852750 }
23862751};
23872752
2388/// 0. Index into `object_global_imports`.
2389/// 1. Index into `imports`.
2753/// 0. `__stack_pointer`.
2754/// 1. Index into `object_global_imports`.
2755/// 2. Index into `imports`.
23902756pub const GlobalImportId = enum(u32) {
2757 __stack_pointer,
23912758 _,
23922759
23932760 pub const Unpacked = union(enum) {
2761 __stack_pointer,
23942762 object_global_import: GlobalImport.Index,
23952763 zcu_import: ZcuImportIndex,
23962764 };
23972765
23982766 pub fn pack(unpacked: Unpacked, wasm: *const Wasm) GlobalImportId {
23992767 return switch (unpacked) {
2400 .object_global_import => |i| @fromBackingInt(@intCast(@backingInt(i))),
2401 .zcu_import => |i| @fromBackingInt(@intCast(@backingInt(i) + wasm.object_global_imports.entries.len)),
2768 .__stack_pointer => .__stack_pointer,
2769 .object_global_import => |i| @fromBackingInt(@intCast(@backingInt(i) + 1)),
2770 .zcu_import => |i| @fromBackingInt(@intCast(@backingInt(i) + wasm.object_global_imports.entries.len + 1)),
24022771 };
24032772 }
24042773
24052774 pub fn unpack(id: GlobalImportId, wasm: *const Wasm) Unpacked {
2406 const i = @backingInt(id);
2407 if (i < wasm.object_global_imports.entries.len) return .{ .object_global_import = @fromBackingInt(@intCast(i)) };
2408 const zcu_import_i = i - wasm.object_global_imports.entries.len;
2409 return .{ .zcu_import = @fromBackingInt(@intCast(zcu_import_i)) };
2775 return switch (id) {
2776 .__stack_pointer => .__stack_pointer,
2777 _ => {
2778 const i = @backingInt(id) - 1;
2779 if (i < wasm.object_global_imports.entries.len) {
2780 return .{ .object_global_import = @fromBackingInt(@intCast(i)) };
2781 }
2782 const zcu_import_i = i - wasm.object_global_imports.entries.len;
2783 return .{ .zcu_import = @fromBackingInt(@intCast(zcu_import_i)) };
2784 },
2785 };
24102786 }
24112787
24122788 pub fn fromObject(object_global_import: GlobalImport.Index, wasm: *const Wasm) GlobalImportId {
24132789 return pack(.{ .object_global_import = object_global_import }, wasm);
24142790 }
24152791
2792 pub fn flags(id: GlobalImportId, wasm: *const Wasm) SymbolFlags {
2793 return switch (id.unpack(wasm)) {
2794 .__stack_pointer => .{
2795 .binding = .strong,
2796 .undefined = true,
2797 },
2798 .object_global_import => |i| i.value(wasm).flags,
2799 .zcu_import => |i| i.flags(wasm),
2800 };
2801 }
2802
24162803 /// This function is allowed O(N) lookup because it is only called during
24172804 /// diagnostic generation.
24182805 pub fn sourceLocation(id: GlobalImportId, wasm: *const Wasm) SourceLocation {
24192806 switch (id.unpack(wasm)) {
2807 .__stack_pointer => return .zig_object_nofile,
24202808 .object_global_import => |obj_global_index| {
24212809 // TODO binary search
24222810 for (wasm.objects.items, 0..) |o, i| {
......@@ -2433,18 +2821,28 @@ pub const GlobalImportId = enum(u32) {
24332821
24342822 pub fn importName(id: GlobalImportId, wasm: *const Wasm) String {
24352823 return switch (unpack(id, wasm)) {
2824 .__stack_pointer => wasm.preloaded_strings.__stack_pointer,
24362825 inline .object_global_import, .zcu_import => |i| i.importName(wasm),
24372826 };
24382827 }
24392828
24402829 pub fn moduleName(id: GlobalImportId, wasm: *const Wasm) OptionalString {
24412830 return switch (unpack(id, wasm)) {
2831 .__stack_pointer => wasm.preloaded_strings.env.toOptional(),
24422832 inline .object_global_import, .zcu_import => |i| i.moduleName(wasm),
24432833 };
24442834 }
24452835
24462836 pub fn globalType(id: GlobalImportId, wasm: *Wasm) ObjectGlobal.Type {
24472837 return switch (unpack(id, wasm)) {
2838 .__stack_pointer => .{
2839 .valtype = switch (wasm.pointerSize()) {
2840 4 => .i32,
2841 8 => .i64,
2842 else => unreachable,
2843 },
2844 .mutable = true,
2845 },
24482846 inline .object_global_import, .zcu_import => |i| i.globalType(wasm),
24492847 };
24502848 }
......@@ -2482,6 +2880,13 @@ pub const DataImportId = enum(u32) {
24822880 return pack(.{ .object_data_import = object_data_import }, wasm);
24832881 }
24842882
2883 pub fn flags(id: DataImportId, wasm: *const Wasm) SymbolFlags {
2884 return switch (id.unpack(wasm)) {
2885 .object_data_import => |i| i.value(wasm).flags,
2886 .zcu_import => |i| i.flags(wasm),
2887 };
2888 }
2889
24852890 pub fn sourceLocation(id: DataImportId, wasm: *const Wasm) SourceLocation {
24862891 switch (id.unpack(wasm)) {
24872892 .object_data_import => |obj_data_index| {
......@@ -2499,33 +2904,42 @@ pub const DataImportId = enum(u32) {
24992904 }
25002905};
25012906
2502/// Index into `Wasm.symbol_table`.
2503pub const SymbolTableIndex = enum(u32) {
2504 _,
2505
2506 pub fn key(i: @This(), wasm: *const Wasm) *String {
2507 return &wasm.symbol_table.keys()[@backingInt(i)];
2508 }
2509};
2510
2511pub const OutReloc = struct {
2907pub const ZcuRelocation = struct {
25122908 tag: Object.RelocationType,
25132909 offset: u32,
25142910 pointee: Pointee,
25152911 addend: i32,
25162912
2517 pub const Pointee = union {
2518 symbol_index: SymbolTableIndex,
2913 pub const Pointee = union(enum) {
2914 function_nav: InternPool.Nav.Index,
2915 function_name: String,
2916 tag_function: InternPool.Index,
2917 data_uav: InternPool.Index,
2918 data_nav: InternPool.Nav.Index,
2919 data_resolution: ObjectDataImport.Resolution,
2920 stack_pointer,
25192921 type_index: FunctionType.Index,
25202922 };
25212923
25222924 pub const Slice = extern struct {
2523 /// Index into `out_relocs`.
2925 /// Index into `zcu_relocations`.
25242926 off: u32,
25252927 len: u32,
25262928
2527 pub fn slice(s: Slice, wasm: *const Wasm) []OutReloc {
2528 return wasm.relocations.items[s.off..][0..s.len];
2929 pub fn tags(s: Slice, wasm: *const Wasm) []const Object.RelocationType {
2930 return wasm.zcu_relocations.items(.tag)[s.off..][0..s.len];
2931 }
2932
2933 pub fn offsets(s: Slice, wasm: *const Wasm) []const u32 {
2934 return wasm.zcu_relocations.items(.offset)[s.off..][0..s.len];
2935 }
2936
2937 pub fn pointees(s: Slice, wasm: *const Wasm) []const Pointee {
2938 return wasm.zcu_relocations.items(.pointee)[s.off..][0..s.len];
2939 }
2940
2941 pub fn addends(s: Slice, wasm: *const Wasm) []const i32 {
2942 return wasm.zcu_relocations.items(.addend)[s.off..][0..s.len];
25292943 }
25302944 };
25312945};
......@@ -3137,9 +3551,9 @@ pub fn deinit(wasm: *Wasm) void {
31373551 wasm.table_imports.deinit(gpa);
31383552 wasm.tables.deinit(gpa);
31393553 wasm.data_imports.deinit(gpa);
3554 wasm.datas.deinit(gpa);
31403555 wasm.data_segments.deinit(gpa);
3141 wasm.symbol_table.deinit(gpa);
3142 wasm.out_relocs.deinit(gpa);
3556 wasm.zcu_relocations.deinit(gpa);
31433557 wasm.uav_fixups.deinit(gpa);
31443558 wasm.nav_fixups.deinit(gpa);
31453559 wasm.func_table_fixups.deinit(gpa);
......@@ -3351,6 +3765,25 @@ pub fn updateExports(
33513765 const zcu = pt.zcu;
33523766 const gpa = zcu.gpa;
33533767 const ip = &zcu.intern_pool;
3768 const is_obj = wasm.base.comp.config.output_mode == .Obj;
3769 switch (exported) {
3770 .nav => {}, // handled in updateNav
3771 .uav => |uav_index| { // export may be the only reference
3772 const zds: ZcuDataStarts = .init(wasm);
3773 if (is_obj) {
3774 const gop = try wasm.uavs_obj.getOrPut(gpa, uav_index);
3775 if (!gop.found_existing) gop.value_ptr.* = undefined;
3776 } else {
3777 const gop = try wasm.uavs_exe.getOrPut(gpa, uav_index);
3778 if (!gop.found_existing) gop.value_ptr.* = .{
3779 .code = undefined,
3780 .count = 0,
3781 };
3782 gop.value_ptr.count += 1;
3783 }
3784 try zds.finish(wasm, pt);
3785 },
3786 }
33543787 for (export_indices) |export_idx| {
33553788 const exp = export_idx.ptr(zcu);
33563789 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 {
34433876 // Zig always depends on a stack pointer global.
34443877 // If emitting an object, it's an import. Otherwise, the linker synthesizes it.
34453878 if (is_obj) {
3446 @panic("TODO");
3879 try wasm.global_imports.putNoClobber(
3880 gpa,
3881 wasm.preloaded_strings.__stack_pointer,
3882 .__stack_pointer,
3883 );
34473884 } else {
34483885 try wasm.globals.put(gpa, .__stack_pointer, {});
34493886 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 {
34533890 // These loops do both recursive marking of alive symbols well as checking for undefined symbols.
34543891 // At the end, output functions and globals will be populated.
34553892 for (wasm.object_function_imports.keys(), wasm.object_function_imports.values(), 0..) |name, *import, i| {
3456 if (import.flags.isIncluded(rdynamic)) {
3893 if (import.flags.isIncluded(rdynamic, is_obj)) {
34573894 try markFunctionImport(wasm, name, import, @fromBackingInt(@intCast(i)));
34583895 }
34593896 }
......@@ -3467,7 +3904,7 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void {
34673904 wasm.functions_end_prelink = @intCast(wasm.functions.entries.len);
34683905
34693906 for (wasm.object_global_imports.keys(), wasm.object_global_imports.values(), 0..) |name, *import, i| {
3470 if (import.flags.isIncluded(rdynamic)) {
3907 if (import.flags.isIncluded(rdynamic, is_obj)) {
34713908 try markGlobalImport(wasm, name, import, @fromBackingInt(@intCast(i)));
34723909 }
34733910 }
......@@ -3475,13 +3912,13 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void {
34753912 wasm.global_exports_len = @intCast(wasm.global_exports.items.len);
34763913
34773914 for (wasm.object_table_imports.keys(), wasm.object_table_imports.values(), 0..) |name, *import, i| {
3478 if (import.flags.isIncluded(rdynamic)) {
3915 if (import.flags.isIncluded(rdynamic, is_obj)) {
34793916 try markTableImport(wasm, name, import, @fromBackingInt(@intCast(i)));
34803917 }
34813918 }
34823919
34833920 for (wasm.object_data_imports.keys(), wasm.object_data_imports.values(), 0..) |name, *import, i| {
3484 if (import.flags.isIncluded(rdynamic)) {
3921 if (import.flags.isIncluded(rdynamic, is_obj)) {
34853922 try markDataImport(wasm, name, import, @fromBackingInt(@intCast(i)));
34863923 }
34873924 }
......@@ -3512,18 +3949,23 @@ pub fn markFunctionImport(
35123949
35133950 const comp = wasm.base.comp;
35143951 const gpa = comp.gpa;
3952 const is_obj = comp.config.output_mode == .Obj;
35153953
35163954 try wasm.functions.ensureUnusedCapacity(gpa, 1);
35173955
35183956 if (import.resolution == .unresolved) {
3519 if (name == wasm.preloaded_strings.__wasm_init_memory) {
3520 try wasm.resolveFunctionSynthetic(import, .__wasm_init_memory, &.{}, &.{});
3521 } else if (name == wasm.preloaded_strings.__wasm_apply_global_tls_relocs) {
3522 try wasm.resolveFunctionSynthetic(import, .__wasm_apply_global_tls_relocs, &.{}, &.{});
3523 } else if (name == wasm.preloaded_strings.__wasm_call_ctors) {
3524 try wasm.resolveFunctionSynthetic(import, .__wasm_call_ctors, &.{}, &.{});
3525 } else if (name == wasm.preloaded_strings.__wasm_init_tls) {
3526 try wasm.resolveFunctionSynthetic(import, .__wasm_init_tls, &.{.i32}, &.{});
3957 if (!is_obj) {
3958 if (name == wasm.preloaded_strings.__wasm_init_memory) {
3959 try wasm.resolveFunctionSynthetic(import, .__wasm_init_memory, &.{}, &.{});
3960 } else if (name == wasm.preloaded_strings.__wasm_apply_global_tls_relocs) {
3961 try wasm.resolveFunctionSynthetic(import, .__wasm_apply_global_tls_relocs, &.{}, &.{});
3962 } else if (name == wasm.preloaded_strings.__wasm_call_ctors) {
3963 try wasm.resolveFunctionSynthetic(import, .__wasm_call_ctors, &.{}, &.{});
3964 } else if (name == wasm.preloaded_strings.__wasm_init_tls) {
3965 try wasm.resolveFunctionSynthetic(import, .__wasm_init_tls, &.{.i32}, &.{});
3966 } else {
3967 try wasm.function_imports.put(gpa, name, .fromObject(func_index, wasm));
3968 }
35273969 } else {
35283970 try wasm.function_imports.put(gpa, name, .fromObject(func_index, wasm));
35293971 }
......@@ -3576,28 +4018,33 @@ fn markGlobalImport(
35764018
35774019 const comp = wasm.base.comp;
35784020 const gpa = comp.gpa;
4021 const is_obj = comp.config.output_mode == .Obj;
35794022
35804023 try wasm.globals.ensureUnusedCapacity(gpa, 1);
35814024
35824025 if (import.resolution == .unresolved) {
3583 if (name == wasm.preloaded_strings.__heap_base) {
3584 import.resolution = .__heap_base;
3585 wasm.globals.putAssumeCapacity(.__heap_base, {});
3586 } else if (name == wasm.preloaded_strings.__heap_end) {
3587 import.resolution = .__heap_end;
3588 wasm.globals.putAssumeCapacity(.__heap_end, {});
3589 } else if (name == wasm.preloaded_strings.__stack_pointer) {
3590 import.resolution = .__stack_pointer;
3591 wasm.globals.putAssumeCapacity(.__stack_pointer, {});
3592 } else if (name == wasm.preloaded_strings.__tls_align) {
3593 import.resolution = .__tls_align;
3594 wasm.globals.putAssumeCapacity(.__tls_align, {});
3595 } else if (name == wasm.preloaded_strings.__tls_base) {
3596 import.resolution = .__tls_base;
3597 wasm.globals.putAssumeCapacity(.__tls_base, {});
3598 } else if (name == wasm.preloaded_strings.__tls_size) {
3599 import.resolution = .__tls_size;
3600 wasm.globals.putAssumeCapacity(.__tls_size, {});
4026 if (!is_obj) {
4027 if (name == wasm.preloaded_strings.__heap_base) {
4028 import.resolution = .__heap_base;
4029 wasm.globals.putAssumeCapacity(.__heap_base, {});
4030 } else if (name == wasm.preloaded_strings.__heap_end) {
4031 import.resolution = .__heap_end;
4032 wasm.globals.putAssumeCapacity(.__heap_end, {});
4033 } else if (name == wasm.preloaded_strings.__stack_pointer) {
4034 import.resolution = .__stack_pointer;
4035 wasm.globals.putAssumeCapacity(.__stack_pointer, {});
4036 } else if (name == wasm.preloaded_strings.__tls_align) {
4037 import.resolution = .__tls_align;
4038 wasm.globals.putAssumeCapacity(.__tls_align, {});
4039 } else if (name == wasm.preloaded_strings.__tls_base) {
4040 import.resolution = .__tls_base;
4041 wasm.globals.putAssumeCapacity(.__tls_base, {});
4042 } else if (name == wasm.preloaded_strings.__tls_size) {
4043 import.resolution = .__tls_size;
4044 wasm.globals.putAssumeCapacity(.__tls_size, {});
4045 } else {
4046 try wasm.global_imports.put(gpa, name, .fromObject(global_index, wasm));
4047 }
36014048 } else {
36024049 try wasm.global_imports.put(gpa, name, .fromObject(global_index, wasm));
36034050 }
......@@ -3625,7 +4072,7 @@ fn markGlobal(wasm: *Wasm, i: ObjectGlobalIndex, override_export: bool) link.Err
36254072 try wasm.markRelocations(global.relocations(wasm));
36264073}
36274074
3628fn markTableImport(
4075pub fn markTableImport(
36294076 wasm: *Wasm,
36304077 name: String,
36314078 import: *TableImport,
......@@ -3636,13 +4083,18 @@ fn markTableImport(
36364083
36374084 const comp = wasm.base.comp;
36384085 const gpa = comp.gpa;
4086 const is_obj = comp.config.output_mode == .Obj;
36394087
36404088 try wasm.tables.ensureUnusedCapacity(gpa, 1);
36414089
36424090 if (import.resolution == .unresolved) {
3643 if (name == wasm.preloaded_strings.__indirect_function_table) {
3644 import.resolution = .__indirect_function_table;
3645 wasm.tables.putAssumeCapacity(.__indirect_function_table, {});
4091 if (!is_obj) {
4092 if (name == wasm.preloaded_strings.__indirect_function_table) {
4093 import.resolution = .__indirect_function_table;
4094 wasm.tables.putAssumeCapacity(.__indirect_function_table, {});
4095 } else {
4096 try wasm.table_imports.put(gpa, name, table_index);
4097 }
36464098 } else {
36474099 try wasm.table_imports.put(gpa, name, table_index);
36484100 }
......@@ -3676,22 +4128,38 @@ pub fn markDataImport(
36764128
36774129 const comp = wasm.base.comp;
36784130 const gpa = comp.gpa;
4131 const is_obj = comp.config.output_mode == .Obj;
4132
4133 try wasm.data_segments.ensureUnusedCapacity(gpa, 1);
36794134
36804135 if (import.resolution == .unresolved) {
3681 if (name == wasm.preloaded_strings.__heap_base) {
3682 import.resolution = .__heap_base;
3683 wasm.data_segments.putAssumeCapacity(.__heap_base, {});
3684 } else if (name == wasm.preloaded_strings.__heap_end) {
3685 import.resolution = .__heap_end;
3686 wasm.data_segments.putAssumeCapacity(.__heap_end, {});
4136 if (!is_obj) {
4137 if (name == wasm.preloaded_strings.__heap_base) {
4138 import.resolution = .__heap_base;
4139 wasm.data_segments.putAssumeCapacity(.__heap_base, {});
4140 } else if (name == wasm.preloaded_strings.__heap_end) {
4141 import.resolution = .__heap_end;
4142 wasm.data_segments.putAssumeCapacity(.__heap_end, {});
4143 } else {
4144 try wasm.data_imports.put(gpa, name, .fromObject(data_index, wasm));
4145 }
36874146 } else {
36884147 try wasm.data_imports.put(gpa, name, .fromObject(data_index, wasm));
36894148 }
3690 } else if (import.resolution.objectDataSegment(wasm)) |segment_index| {
3691 try markDataSegment(wasm, segment_index);
4149 } else switch (import.resolution.unpack(wasm)) {
4150 .object => |object_data_index| try markData(wasm, object_data_index),
4151 else => {},
36924152 }
36934153}
36944154
4155fn markData(wasm: *Wasm, i: ObjectData.Index) link.Error!void {
4156 const gpa = wasm.base.comp.gpa;
4157 const gop = try wasm.datas.getOrPut(gpa, .fromObjectDataIndex(wasm, i));
4158 if (gop.found_existing) return;
4159
4160 try markDataSegment(wasm, i.ptr(wasm).segment);
4161}
4162
36954163fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Error!void {
36964164 const gpa = wasm.base.comp.gpa;
36974165 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
37824250 .memory_addr_tls_sleb,
37834251 .memory_addr_locrel_i32,
37844252 .memory_addr_tls_sleb64,
3785 => try markDataSegment(wasm, pointee.data.ptr(wasm).segment),
4253 => try markData(wasm, pointee.data),
37864254
37874255 .type_index_leb => continue,
37884256 }
......@@ -3829,7 +4297,13 @@ pub fn flush(
38294297 const hidden_function_exports_end_zcu: u32 = @intCast(wasm.hidden_function_exports.entries.len);
38304298 defer wasm.hidden_function_exports.shrinkRetainingCapacity(hidden_function_exports_end_zcu);
38314299
4300 const global_exports_end_zcu: u32 = @intCast(wasm.global_exports.items.len);
4301 defer wasm.global_exports.shrinkRetainingCapacity(global_exports_end_zcu);
4302
38324303 wasm.flush_buffer.clear();
4304 wasm.tag_name_bytes.clearRetainingCapacity();
4305 wasm.tag_name_offs.clearRetainingCapacity();
4306 wasm.tag_name_table_ref_count = 0;
38334307 try wasm.flush_buffer.missing_exports.reinit(gpa, wasm.missing_exports.keys(), &.{});
38344308 try wasm.flush_buffer.function_imports.reinit(gpa, wasm.function_imports.keys(), wasm.function_imports.values());
38354309 try wasm.flush_buffer.global_imports.reinit(gpa, wasm.global_imports.keys(), wasm.global_imports.values());
......@@ -3858,7 +4332,7 @@ pub fn internOptionalString(wasm: *Wasm, optional_bytes: ?[]const u8) Allocator.
38584332}
38594333
38604334pub fn internString(wasm: *Wasm, bytes: []const u8) Allocator.Error!String {
3861 assert(mem.indexOfScalar(u8, bytes, 0) == null);
4335 assert(mem.findScalar(u8, bytes, 0) == null);
38624336 wasm.string_bytes_lock.lock();
38634337 defer wasm.string_bytes_lock.unlock();
38644338 const gpa = wasm.base.comp.gpa;
......@@ -3889,7 +4363,7 @@ pub fn internStringFmt(wasm: *Wasm, comptime format: []const u8, args: anytype)
38894363}
38904364
38914365pub fn getExistingString(wasm: *const Wasm, bytes: []const u8) ?String {
3892 assert(mem.indexOfScalar(u8, bytes, 0) == null);
4366 assert(mem.findScalar(u8, bytes, 0) == null);
38934367 return wasm.string_table.getKeyAdapted(bytes, @as(String.TableIndexAdapter, .{
38944368 .bytes = wasm.string_bytes.items,
38954369 }));
......@@ -3953,6 +4427,255 @@ pub fn getExistingFunctionType(
39534427 });
39544428}
39554429
4430fn internIntrinsicType(
4431 wasm: *Wasm,
4432 params: []const InternPool.Index,
4433 return_type: Zcu.Type,
4434) Allocator.Error!FunctionType.Index {
4435 const target = &wasm.base.comp.root_mod.resolved_target.result;
4436 return wasm.internFunctionType(.{ .wasm_mvp = .{} }, params, return_type, false, target);
4437}
4438
4439pub fn intrinsicFunctionType(wasm: *Wasm, intrinsic: Mir.Intrinsic) Allocator.Error!FunctionType.Index {
4440 return switch (intrinsic) {
4441 .__addhf3 => internIntrinsicType(wasm, &.{ .f16_type, .f16_type }, .f16),
4442 .__addtf3 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128),
4443 .__addxf3 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .f80),
4444 .__ashlti3 => internIntrinsicType(wasm, &.{ .i128_type, .i32_type }, .i128),
4445 .__ashrti3 => internIntrinsicType(wasm, &.{ .i128_type, .i32_type }, .i128),
4446 .__bitreversedi2 => internIntrinsicType(wasm, &.{.u64_type}, .u64),
4447 .__bitreversesi2 => internIntrinsicType(wasm, &.{.u32_type}, .u32),
4448 .__bswapdi2 => internIntrinsicType(wasm, &.{.u64_type}, .u64),
4449 .__bswapsi2 => internIntrinsicType(wasm, &.{.u32_type}, .u32),
4450 .__ceilh => internIntrinsicType(wasm, &.{.f16_type}, .f16),
4451 .__ceilx => internIntrinsicType(wasm, &.{.f80_type}, .f80),
4452 .__cosh => internIntrinsicType(wasm, &.{.f16_type}, .f16),
4453 .__cosx => internIntrinsicType(wasm, &.{.f80_type}, .f80),
4454 .__divei5 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .usize_type, .usize_type }, .void),
4455 .__divhf3 => internIntrinsicType(wasm, &.{ .f16_type, .f16_type }, .f16),
4456 .__divtf3 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128),
4457 .__divti3 => internIntrinsicType(wasm, &.{ .i128_type, .i128_type }, .i128),
4458 .__divxf3 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .f80),
4459 .__eqtf2 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .bool),
4460 .__eqxf2 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .bool),
4461 .__exp2h => internIntrinsicType(wasm, &.{.f16_type}, .f16),
4462 .__exp2x => internIntrinsicType(wasm, &.{.f80_type}, .f80),
4463 .__exph => internIntrinsicType(wasm, &.{.f16_type}, .f16),
4464 .__expx => internIntrinsicType(wasm, &.{.f80_type}, .f80),
4465 .__extenddftf2 => internIntrinsicType(wasm, &.{.f64_type}, .f128),
4466 .__extenddfxf2 => internIntrinsicType(wasm, &.{.f64_type}, .f80),
4467 .__extendhfsf2 => internIntrinsicType(wasm, &.{.f16_type}, .f32),
4468 .__extendhftf2 => internIntrinsicType(wasm, &.{.f16_type}, .f128),
4469 .__extendhfxf2 => internIntrinsicType(wasm, &.{.f16_type}, .f80),
4470 .__extendsftf2 => internIntrinsicType(wasm, &.{.f32_type}, .f128),
4471 .__extendsfxf2 => internIntrinsicType(wasm, &.{.f32_type}, .f80),
4472 .__extendxftf2 => internIntrinsicType(wasm, &.{.f80_type}, .f128),
4473 .__fabsh => internIntrinsicType(wasm, &.{.f16_type}, .f16),
4474 .__fabsx => internIntrinsicType(wasm, &.{.f80_type}, .f80),
4475 .__fixdfdi => internIntrinsicType(wasm, &.{.f64_type}, .i64),
4476 .__fixdfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f64_type }, .void),
4477 .__fixdfsi => internIntrinsicType(wasm, &.{.f64_type}, .i32),
4478 .__fixdfti => internIntrinsicType(wasm, &.{.f64_type}, .i128),
4479 .__fixhfdi => internIntrinsicType(wasm, &.{.f16_type}, .i64),
4480 .__fixhfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f16_type }, .void),
4481 .__fixhfsi => internIntrinsicType(wasm, &.{.f16_type}, .i32),
4482 .__fixhfti => internIntrinsicType(wasm, &.{.f16_type}, .i128),
4483 .__fixsfdi => internIntrinsicType(wasm, &.{.f32_type}, .i64),
4484 .__fixsfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f32_type }, .void),
4485 .__fixsfsi => internIntrinsicType(wasm, &.{.f32_type}, .i32),
4486 .__fixsfti => internIntrinsicType(wasm, &.{.f32_type}, .i128),
4487 .__fixtfdi => internIntrinsicType(wasm, &.{.f128_type}, .i64),
4488 .__fixtfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f128_type }, .void),
4489 .__fixtfsi => internIntrinsicType(wasm, &.{.f128_type}, .i32),
4490 .__fixtfti => internIntrinsicType(wasm, &.{.f128_type}, .i128),
4491 .__fixunsdfdi => internIntrinsicType(wasm, &.{.f64_type}, .u64),
4492 .__fixunsdfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f64_type }, .void),
4493 .__fixunsdfsi => internIntrinsicType(wasm, &.{.f64_type}, .u32),
4494 .__fixunsdfti => internIntrinsicType(wasm, &.{.f64_type}, .u128),
4495 .__fixunshfdi => internIntrinsicType(wasm, &.{.f16_type}, .u64),
4496 .__fixunshfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f16_type }, .void),
4497 .__fixunshfsi => internIntrinsicType(wasm, &.{.f16_type}, .u32),
4498 .__fixunshfti => internIntrinsicType(wasm, &.{.f16_type}, .u128),
4499 .__fixunssfdi => internIntrinsicType(wasm, &.{.f32_type}, .u64),
4500 .__fixunssfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f32_type }, .void),
4501 .__fixunssfsi => internIntrinsicType(wasm, &.{.f32_type}, .u32),
4502 .__fixunssfti => internIntrinsicType(wasm, &.{.f32_type}, .u128),
4503 .__fixunstfdi => internIntrinsicType(wasm, &.{.f128_type}, .u64),
4504 .__fixunstfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f128_type }, .void),
4505 .__fixunstfsi => internIntrinsicType(wasm, &.{.f128_type}, .u32),
4506 .__fixunstfti => internIntrinsicType(wasm, &.{.f128_type}, .u128),
4507 .__fixunsxfdi => internIntrinsicType(wasm, &.{.f80_type}, .u64),
4508 .__fixunsxfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f80_type }, .void),
4509 .__fixunsxfsi => internIntrinsicType(wasm, &.{.f80_type}, .u32),
4510 .__fixunsxfti => internIntrinsicType(wasm, &.{.f80_type}, .u128),
4511 .__fixxfdi => internIntrinsicType(wasm, &.{.f80_type}, .i64),
4512 .__fixxfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f80_type }, .void),
4513 .__fixxfsi => internIntrinsicType(wasm, &.{.f80_type}, .i32),
4514 .__fixxfti => internIntrinsicType(wasm, &.{.f80_type}, .i128),
4515 .__floatdidf => internIntrinsicType(wasm, &.{.i64_type}, .f64),
4516 .__floatdihf => internIntrinsicType(wasm, &.{.i64_type}, .f16),
4517 .__floatdisf => internIntrinsicType(wasm, &.{.i64_type}, .f32),
4518 .__floatditf => internIntrinsicType(wasm, &.{.i64_type}, .f128),
4519 .__floatdixf => internIntrinsicType(wasm, &.{.i64_type}, .f80),
4520 .__floateidf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f64),
4521 .__floateihf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f16),
4522 .__floateisf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f32),
4523 .__floateitf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f128),
4524 .__floateixf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f80),
4525 .__floatsidf => internIntrinsicType(wasm, &.{.i32_type}, .f64),
4526 .__floatsihf => internIntrinsicType(wasm, &.{.i32_type}, .f16),
4527 .__floatsisf => internIntrinsicType(wasm, &.{.i32_type}, .f32),
4528 .__floatsitf => internIntrinsicType(wasm, &.{.i32_type}, .f128),
4529 .__floatsixf => internIntrinsicType(wasm, &.{.i32_type}, .f80),
4530 .__floattidf => internIntrinsicType(wasm, &.{.i128_type}, .f64),
4531 .__floattihf => internIntrinsicType(wasm, &.{.i128_type}, .f16),
4532 .__floattisf => internIntrinsicType(wasm, &.{.i128_type}, .f32),
4533 .__floattitf => internIntrinsicType(wasm, &.{.i128_type}, .f128),
4534 .__floattixf => internIntrinsicType(wasm, &.{.i128_type}, .f80),
4535 .__floatundidf => internIntrinsicType(wasm, &.{.u64_type}, .f64),
4536 .__floatundihf => internIntrinsicType(wasm, &.{.u64_type}, .f16),
4537 .__floatundisf => internIntrinsicType(wasm, &.{.u64_type}, .f32),
4538 .__floatunditf => internIntrinsicType(wasm, &.{.u64_type}, .f128),
4539 .__floatundixf => internIntrinsicType(wasm, &.{.u64_type}, .f80),
4540 .__floatuneidf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f64),
4541 .__floatuneihf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f16),
4542 .__floatuneisf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f32),
4543 .__floatuneitf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f128),
4544 .__floatuneixf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f80),
4545 .__floatunsidf => internIntrinsicType(wasm, &.{.u32_type}, .f64),
4546 .__floatunsihf => internIntrinsicType(wasm, &.{.u32_type}, .f16),
4547 .__floatunsisf => internIntrinsicType(wasm, &.{.u32_type}, .f32),
4548 .__floatunsitf => internIntrinsicType(wasm, &.{.u32_type}, .f128),
4549 .__floatunsixf => internIntrinsicType(wasm, &.{.u32_type}, .f80),
4550 .__floatuntidf => internIntrinsicType(wasm, &.{.u128_type}, .f64),
4551 .__floatuntihf => internIntrinsicType(wasm, &.{.u128_type}, .f16),
4552 .__floatuntisf => internIntrinsicType(wasm, &.{.u128_type}, .f32),
4553 .__floatuntitf => internIntrinsicType(wasm, &.{.u128_type}, .f128),
4554 .__floatuntixf => internIntrinsicType(wasm, &.{.u128_type}, .f80),
4555 .__floorh => internIntrinsicType(wasm, &.{.f16_type}, .f16),
4556 .__floorx => internIntrinsicType(wasm, &.{.f80_type}, .f80),
4557 .__fmah => internIntrinsicType(wasm, &.{ .f16_type, .f16_type, .f16_type }, .f16),
4558 .__fmax => internIntrinsicType(wasm, &.{ .f80_type, .f80_type, .f80_type }, .f80),
4559 .__fmaxh => internIntrinsicType(wasm, &.{ .f16_type, .f16_type }, .f16),
4560 .__fmaxx => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .f80),
4561 .__fminh => internIntrinsicType(wasm, &.{ .f16_type, .f16_type }, .f16),
4562 .__fminx => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .f80),
4563 .__fmodh => internIntrinsicType(wasm, &.{ .f16_type, .f16_type }, .f16),
4564 .__fmodx => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .f80),
4565 .__getf2 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .bool),
4566 .__gexf2 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .bool),
4567 .__gttf2 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .bool),
4568 .__gtxf2 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .bool),
4569 .__letf2 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .bool),
4570 .__lexf2 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .bool),
4571 .__log10h => internIntrinsicType(wasm, &.{.f16_type}, .f16),
4572 .__log10x => internIntrinsicType(wasm, &.{.f80_type}, .f80),
4573 .__log2h => internIntrinsicType(wasm, &.{.f16_type}, .f16),
4574 .__log2x => internIntrinsicType(wasm, &.{.f80_type}, .f80),
4575 .__logh => internIntrinsicType(wasm, &.{.f16_type}, .f16),
4576 .__logx => internIntrinsicType(wasm, &.{.f80_type}, .f80),
4577 .__lshrti3 => internIntrinsicType(wasm, &.{ .i128_type, .i32_type }, .i128),
4578 .__lttf2 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .bool),
4579 .__ltxf2 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .bool),
4580 .__modei5 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .usize_type, .usize_type }, .void),
4581 .__modti3 => internIntrinsicType(wasm, &.{ .i128_type, .i128_type }, .i128),
4582 .__mulhf3 => internIntrinsicType(wasm, &.{ .f16_type, .f16_type }, .f16),
4583 .__mulodi4 => internIntrinsicType(wasm, &.{ .i64_type, .i64_type, .usize_type }, .i64),
4584 .__muloti4 => internIntrinsicType(wasm, &.{ .i128_type, .i128_type, .usize_type }, .i128),
4585 .__multf3 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128),
4586 .__multi3 => internIntrinsicType(wasm, &.{ .i128_type, .i128_type }, .i128),
4587 .__mulxf3 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .f80),
4588 .__netf2 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .bool),
4589 .__nexf2 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .bool),
4590 .__roundh => internIntrinsicType(wasm, &.{.f16_type}, .f16),
4591 .__roundx => internIntrinsicType(wasm, &.{.f80_type}, .f80),
4592 .__sinh => internIntrinsicType(wasm, &.{.f16_type}, .f16),
4593 .__sinx => internIntrinsicType(wasm, &.{.f80_type}, .f80),
4594 .__sqrth => internIntrinsicType(wasm, &.{.f16_type}, .f16),
4595 .__sqrtx => internIntrinsicType(wasm, &.{.f80_type}, .f80),
4596 .__subhf3 => internIntrinsicType(wasm, &.{ .f16_type, .f16_type }, .f16),
4597 .__subtf3 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128),
4598 .__subxf3 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .f80),
4599 .__tanh => internIntrinsicType(wasm, &.{.f16_type}, .f16),
4600 .__tanx => internIntrinsicType(wasm, &.{.f80_type}, .f80),
4601 .__trunch => internIntrinsicType(wasm, &.{.f16_type}, .f16),
4602 .__truncsfhf2 => internIntrinsicType(wasm, &.{.f32_type}, .f16),
4603 .__trunctfdf2 => internIntrinsicType(wasm, &.{.f128_type}, .f64),
4604 .__trunctfhf2 => internIntrinsicType(wasm, &.{.f128_type}, .f16),
4605 .__trunctfsf2 => internIntrinsicType(wasm, &.{.f128_type}, .f32),
4606 .__trunctfxf2 => internIntrinsicType(wasm, &.{.f128_type}, .f80),
4607 .__truncx => internIntrinsicType(wasm, &.{.f80_type}, .f80),
4608 .__truncxfdf2 => internIntrinsicType(wasm, &.{.f80_type}, .f64),
4609 .__truncxfhf2 => internIntrinsicType(wasm, &.{.f80_type}, .f16),
4610 .__truncxfsf2 => internIntrinsicType(wasm, &.{.f80_type}, .f32),
4611 .__udivei5 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .usize_type, .usize_type }, .void),
4612 .__udivti3 => internIntrinsicType(wasm, &.{ .u128_type, .u128_type }, .u128),
4613 .__umodei5 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .usize_type, .usize_type }, .void),
4614 .__umodti3 => internIntrinsicType(wasm, &.{ .u128_type, .u128_type }, .u128),
4615 .ceilf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128),
4616 .cos => internIntrinsicType(wasm, &.{.f64_type}, .f64),
4617 .cosf => internIntrinsicType(wasm, &.{.f32_type}, .f32),
4618 .cosf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128),
4619 .exp => internIntrinsicType(wasm, &.{.f64_type}, .f64),
4620 .exp2 => internIntrinsicType(wasm, &.{.f64_type}, .f64),
4621 .exp2f => internIntrinsicType(wasm, &.{.f32_type}, .f32),
4622 .exp2f128 => internIntrinsicType(wasm, &.{.f128_type}, .f128),
4623 .expf => internIntrinsicType(wasm, &.{.f32_type}, .f32),
4624 .expf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128),
4625 .fabsf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128),
4626 .floorf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128),
4627 .fma => internIntrinsicType(wasm, &.{ .f64_type, .f64_type, .f64_type }, .f64),
4628 .fmaf => internIntrinsicType(wasm, &.{ .f32_type, .f32_type, .f32_type }, .f32),
4629 .fmaf128 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type, .f128_type }, .f128),
4630 .fmax => internIntrinsicType(wasm, &.{ .f64_type, .f64_type }, .f64),
4631 .fmaxf => internIntrinsicType(wasm, &.{ .f32_type, .f32_type }, .f32),
4632 .fmaxf128 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128),
4633 .fmin => internIntrinsicType(wasm, &.{ .f64_type, .f64_type }, .f64),
4634 .fminf => internIntrinsicType(wasm, &.{ .f32_type, .f32_type }, .f32),
4635 .fminf128 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128),
4636 .fmod => internIntrinsicType(wasm, &.{ .f64_type, .f64_type }, .f64),
4637 .fmodf => internIntrinsicType(wasm, &.{ .f32_type, .f32_type }, .f32),
4638 .fmodf128 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128),
4639 .log => internIntrinsicType(wasm, &.{.f64_type}, .f64),
4640 .log10 => internIntrinsicType(wasm, &.{.f64_type}, .f64),
4641 .log10f => internIntrinsicType(wasm, &.{.f32_type}, .f32),
4642 .log10f128 => internIntrinsicType(wasm, &.{.f128_type}, .f128),
4643 .log2 => internIntrinsicType(wasm, &.{.f64_type}, .f64),
4644 .log2f => internIntrinsicType(wasm, &.{.f32_type}, .f32),
4645 .log2f128 => internIntrinsicType(wasm, &.{.f128_type}, .f128),
4646 .logf => internIntrinsicType(wasm, &.{.f32_type}, .f32),
4647 .logf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128),
4648 .roundf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128),
4649 .sin => internIntrinsicType(wasm, &.{.f64_type}, .f64),
4650 .sinf => internIntrinsicType(wasm, &.{.f32_type}, .f32),
4651 .sinf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128),
4652 .sqrtf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128),
4653 .tan => internIntrinsicType(wasm, &.{.f64_type}, .f64),
4654 .tanf => internIntrinsicType(wasm, &.{.f32_type}, .f32),
4655 .tanf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128),
4656 .truncf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128),
4657 .memcpy => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type }, .usize),
4658 .memmove => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type }, .usize),
4659 .memset => internIntrinsicType(wasm, &.{ .usize_type, .i32_type, .usize_type }, .usize),
4660 .__addo_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .bool_type, .u16_type }, .bool),
4661 .__subo_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .bool_type, .u16_type }, .bool),
4662 .__cmp_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .bool_type, .u16_type }, .i8),
4663 .__and_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .u16_type }, .void),
4664 .__or_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .u16_type }, .void),
4665 .__xor_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .u16_type }, .void),
4666 .__not_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .bool_type, .u16_type }, .void),
4667 .__shlo_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .u16_type, .bool_type, .u16_type }, .bool),
4668 .__shr_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .u16_type, .bool_type, .u16_type }, .void),
4669 .__clz_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .u16_type }, .u16),
4670 .__ctz_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .u16_type }, .u16),
4671 .__popcount_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .u16_type }, .u16),
4672 .__bitreverse_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .bool_type, .u16_type }, .void),
4673 .__byteswap_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .bool_type, .u16_type }, .void),
4674 .__mulo_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .bool_type, .u16_type }, .bool),
4675 .__abs_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .u16_type }, .void),
4676 };
4677}
4678
39564679pub fn addExpr(wasm: *Wasm, bytes: []const u8) Allocator.Error!Expr {
39574680 const gpa = wasm.base.comp.gpa;
39584681 // 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
39724695 };
39734696}
39744697
3975pub fn uavSymbolIndex(wasm: *Wasm, ip_index: InternPool.Index) Allocator.Error!SymbolTableIndex {
3976 const comp = wasm.base.comp;
3977 assert(comp.config.output_mode == .Obj);
3978 const gpa = comp.gpa;
3979 const name = try wasm.internStringFmt("__anon_{d}", .{@backingInt(ip_index)});
3980 const gop = try wasm.symbol_table.getOrPut(gpa, name);
3981 gop.value_ptr.* = {};
3982 return @fromBackingInt(@intCast(gop.index));
3983}
3984
3985pub fn navSymbolIndex(wasm: *Wasm, nav_index: InternPool.Nav.Index) Allocator.Error!SymbolTableIndex {
4698pub fn addNavReloc(
4699 wasm: *Wasm,
4700 reloc_offset: usize,
4701 nav_index: InternPool.Nav.Index,
4702 nav_ty: Zcu.Type,
4703 addend: u32,
4704) !void {
39864705 const comp = wasm.base.comp;
3987 assert(comp.config.output_mode == .Obj);
39884706 const zcu = comp.zcu.?;
39894707 const ip = &zcu.intern_pool;
39904708 const gpa = comp.gpa;
3991 const nav = ip.getNav(nav_index);
3992 const name = try wasm.internString(nav.fqn.toSlice(ip));
3993 const gop = try wasm.symbol_table.getOrPut(gpa, name);
3994 gop.value_ptr.* = {};
3995 return @fromBackingInt(@intCast(gop.index));
3996}
3997
3998pub fn errorNameTableSymbolIndex(wasm: *Wasm) Allocator.Error!SymbolTableIndex {
3999 const comp = wasm.base.comp;
4000 assert(comp.config.output_mode == .Obj);
4001 const gpa = comp.gpa;
4002 const gop = try wasm.symbol_table.getOrPut(gpa, wasm.preloaded_strings.__zig_error_name_table);
4003 gop.value_ptr.* = {};
4004 return @fromBackingInt(@intCast(gop.index));
4005}
4006
4007pub fn stackPointerSymbolIndex(wasm: *Wasm) Allocator.Error!SymbolTableIndex {
4008 const comp = wasm.base.comp;
4009 assert(comp.config.output_mode == .Obj);
4010 const gpa = comp.gpa;
4011 const gop = try wasm.symbol_table.getOrPut(gpa, wasm.preloaded_strings.__stack_pointer);
4012 gop.value_ptr.* = {};
4013 return @fromBackingInt(@intCast(gop.index));
4014}
40154709
4016pub fn tagTableIndexSymbolIndex(wasm: *Wasm, ip_index: InternPool.Index) Allocator.Error!SymbolTableIndex {
4017 const comp = wasm.base.comp;
4018 assert(comp.config.output_mode == .Obj);
4019 const gpa = comp.gpa;
4020 const name = try wasm.internStringFmt("__zig_tag_name_{d}", .{ip_index});
4021 const gop = try wasm.symbol_table.getOrPut(gpa, name);
4022 gop.value_ptr.* = {};
4023 return @fromBackingInt(@intCast(gop.index));
4024}
4710 const is_obj = comp.config.output_mode == .Obj;
40254711
4026pub fn symbolNameIndex(wasm: *Wasm, name: String) Allocator.Error!SymbolTableIndex {
4027 const comp = wasm.base.comp;
4028 assert(comp.config.output_mode == .Obj);
4029 const gpa = comp.gpa;
4030 const gop = try wasm.symbol_table.getOrPut(gpa, name);
4031 gop.value_ptr.* = {};
4032 return @fromBackingInt(@intCast(gop.index));
4712 if (nav_ty.zigTypeTag(zcu) == .@"fn") {
4713 const gop = try wasm.zcu_indirect_function_set.getOrPut(gpa, nav_index);
4714 if (!gop.found_existing) gop.value_ptr.* = {};
4715 if (is_obj) {
4716 assert(addend == 0);
4717 try wasm.zcu_relocations.append(gpa, .{
4718 .offset = @intCast(reloc_offset),
4719 .pointee = .{ .function_nav = nav_index },
4720 .tag = switch (wasm.pointerSize()) {
4721 4 => .table_index_i32,
4722 8 => .table_index_i64,
4723 else => unreachable,
4724 },
4725 .addend = 0,
4726 });
4727 } else {
4728 try wasm.func_table_fixups.append(gpa, .{
4729 .nav_index = nav_index,
4730 .offset = @intCast(reloc_offset),
4731 });
4732 }
4733 } else {
4734 if (is_obj) {
4735 if (ip.getNav(nav_index).getExtern(ip) == null) _ = try wasm.refNavObj(nav_index);
4736 try wasm.zcu_relocations.append(gpa, .{
4737 .offset = @intCast(reloc_offset),
4738 .pointee = .{ .data_nav = nav_index },
4739 .tag = switch (wasm.pointerSize()) {
4740 4 => .memory_addr_i32,
4741 8 => .memory_addr_i64,
4742 else => unreachable,
4743 },
4744 .addend = @intCast(addend),
4745 });
4746 } else {
4747 try wasm.nav_fixups.ensureUnusedCapacity(gpa, 1);
4748 wasm.nav_fixups.appendAssumeCapacity(.{
4749 .nav_index = nav_index,
4750 .offset = @intCast(reloc_offset),
4751 .addend = addend,
4752 });
4753 }
4754 }
40334755}
40344756
40354757pub fn addUavReloc(
......@@ -4057,12 +4779,12 @@ pub fn addUavReloc(
40574779 if (comp.config.output_mode == .Obj) {
40584780 const gop = try wasm.uavs_obj.getOrPut(gpa, uav_val);
40594781 if (!gop.found_existing) gop.value_ptr.* = undefined; // to avoid recursion, `ZcuDataStarts` will lower the value later
4060 try wasm.out_relocs.append(gpa, .{
4782 try wasm.zcu_relocations.append(gpa, .{
40614783 .offset = @intCast(reloc_offset),
4062 .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(uav_val) },
4784 .pointee = .{ .data_uav = uav_val },
40634785 .tag = switch (wasm.pointerSize()) {
4064 32 => .memory_addr_i32,
4065 64 => .memory_addr_i64,
4786 4 => .memory_addr_i32,
4787 8 => .memory_addr_i64,
40664788 else => unreachable,
40674789 },
40684790 .addend = @intCast(addend),
......@@ -4085,7 +4807,7 @@ pub fn addUavReloc(
40854807pub fn refNavObj(wasm: *Wasm, nav_index: InternPool.Nav.Index) !NavsObjIndex {
40864808 const comp = wasm.base.comp;
40874809 const gpa = comp.gpa;
4088 assert(comp.config.output_mode != .Obj);
4810 assert(comp.config.output_mode == .Obj);
40894811 const gop = try wasm.navs_obj.getOrPut(gpa, nav_index);
40904812 if (!gop.found_existing) gop.value_ptr.* = .{
40914813 // Lowering the value is delayed to avoid recursion.
......@@ -4113,7 +4835,7 @@ pub fn refNavExe(wasm: *Wasm, nav_index: InternPool.Nav.Index) !NavsExeIndex {
41134835}
41144836
41154837/// Asserts it is called after `Flush.data_segments` is fully populated and sorted.
4116pub fn uavAddr(wasm: *Wasm, ip_index: InternPool.Index) u32 {
4838pub fn uavAddr(wasm: *const Wasm, ip_index: InternPool.Index) u32 {
41174839 assert(wasm.flush_buffer.memory_layout_finished);
41184840 const comp = wasm.base.comp;
41194841 assert(comp.config.output_mode != .Obj);
......@@ -4123,7 +4845,7 @@ pub fn uavAddr(wasm: *Wasm, ip_index: InternPool.Index) u32 {
41234845}
41244846
41254847/// Asserts it is called after `Flush.data_segments` is fully populated and sorted.
4126pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 {
4848pub fn navAddr(wasm: *const Wasm, nav_index: InternPool.Nav.Index) u32 {
41274849 assert(wasm.flush_buffer.memory_layout_finished);
41284850 const comp = wasm.base.comp;
41294851 assert(comp.config.output_mode != .Obj);
......@@ -4139,23 +4861,34 @@ pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 {
41394861 .@"extern" => |ext| if (wasm.getExistingString(ext.name.toSlice(ip))) |symbol_name| {
41404862 if (wasm.object_data_imports.getPtr(symbol_name)) |import| {
41414863 switch (import.resolution.unpack(wasm)) {
4142 .unresolved => unreachable,
4864 .unresolved => {},
41434865 .object => |object_data_index| {
41444866 const object_data = object_data_index.ptr(wasm);
41454867 const ds_id: DataSegmentId = .fromObjectDataSegment(wasm, object_data.segment);
41464868 const segment_base_addr = wasm.flush_buffer.data_segments.get(ds_id).?;
41474869 return segment_base_addr + object_data.offset;
41484870 },
4149 .__zig_error_names => @panic("TODO"),
4150 .__zig_error_name_table => @panic("TODO"),
4151 .__heap_base => @panic("TODO"),
4152 .__heap_end => @panic("TODO"),
4153 .uav_exe => @panic("TODO"),
4154 .uav_obj => @panic("TODO"),
4155 .nav_exe => @panic("TODO"),
4156 .nav_obj => @panic("TODO"),
4871 .__heap_base,
4872 .__heap_end,
4873 .uav_exe,
4874 .nav_exe,
4875 => {
4876 const data_loc = import.resolution.dataLoc(wasm);
4877 return wasm.flush_buffer.data_segments.get(data_loc.segment).? + data_loc.offset;
4878 },
4879 .__zig_error_names,
4880 .__zig_error_name_table,
4881 .__zig_tag_names,
4882 .__zig_tag_name_table,
4883 .uav_obj,
4884 .nav_obj,
4885 => unreachable,
41574886 }
41584887 }
4888 if (wasm.flush_buffer.data_exports.get(symbol_name)) |symbol| {
4889 const data_loc = symbol.resolution.dataLoc(wasm);
4890 return wasm.flush_buffer.data_segments.get(data_loc.segment).? + data_loc.offset;
4891 }
41594892 },
41604893 else => {},
41614894 }
......@@ -4177,8 +4910,12 @@ pub fn tagIndexTableAddr(wasm: *Wasm, ip_index: InternPool.Index) u32 {
41774910 assert(comp.config.output_mode != .Obj);
41784911 const f = &wasm.flush_buffer;
41794912 const table_base_addr = f.data_segments.get(.__zig_tag_name_table).?;
4180 const table_index = f.enum_tag_name_table.get(ip_index).?;
4181 return table_base_addr + table_index * 8;
4913 return table_base_addr + wasm.tagIndexTableOffset(ip_index);
4914}
4915
4916pub fn tagIndexTableOffset(wasm: *const Wasm, ip_index: InternPool.Index) u32 {
4917 const table_index = wasm.flush_buffer.enum_tag_name_table.get(ip_index).?;
4918 return table_index * wasm.pointerSize() * 2;
41824919}
41834920
41844921fn convertZcuFnType(
......@@ -4201,12 +4938,15 @@ fn convertZcuFnType(
42014938 try params_buffer.append(gpa, .i32); // memory address is always a 32-bit handle
42024939 } else if (return_type.hasRuntimeBits(zcu)) {
42034940 if (cc == .wasm_mvp) {
4204 switch (abi.classifyType(return_type, zcu)) {
4205 .direct => |scalar_ty| {
4206 assert(!abi.lowerAsDoubleI64(scalar_ty, zcu));
4207 try returns_buffer.append(gpa, CodeGen.typeToValtype(scalar_ty, zcu, target));
4941 switch (abi.classifyType(return_type, zcu, target)) {
4942 .direct => |scalar_type| {
4943 try returns_buffer.append(gpa, CodeGen.typeToValtype(scalar_type, zcu, target));
4944 },
4945 .double_i64, .indirect => unreachable,
4946 .unrolled => |vector| {
4947 assert(vector.len == 1);
4948 try returns_buffer.append(gpa, CodeGen.typeToValtype(vector.elem_type, zcu, target));
42084949 },
4209 .indirect => unreachable,
42104950 }
42114951 } else {
42124952 try returns_buffer.append(gpa, CodeGen.typeToValtype(return_type, zcu, target));
......@@ -4222,16 +4962,22 @@ fn convertZcuFnType(
42224962
42234963 switch (cc) {
42244964 .wasm_mvp => {
4225 switch (abi.classifyType(param_type, zcu)) {
4226 .direct => |scalar_ty| {
4227 if (!abi.lowerAsDoubleI64(scalar_ty, zcu)) {
4228 try params_buffer.append(gpa, CodeGen.typeToValtype(scalar_ty, zcu, target));
4229 } else {
4230 try params_buffer.append(gpa, .i64);
4231 try params_buffer.append(gpa, .i64);
4965 switch (abi.classifyType(param_type, zcu, target)) {
4966 .direct => |scalar_type| {
4967 try params_buffer.append(gpa, CodeGen.typeToValtype(scalar_type, zcu, target));
4968 },
4969 .double_i64 => {
4970 try params_buffer.append(gpa, .i64);
4971 try params_buffer.append(gpa, .i64);
4972 },
4973 .indirect => {
4974 try params_buffer.append(gpa, CodeGen.typeToValtype(param_type, zcu, target));
4975 },
4976 .unrolled => |vector| {
4977 for (0..vector.len) |_| {
4978 try params_buffer.append(gpa, CodeGen.typeToValtype(vector.elem_type, zcu, target));
42324979 }
42334980 },
4234 .indirect => try params_buffer.append(gpa, CodeGen.typeToValtype(param_type, zcu, target)),
42354981 }
42364982 },
42374983 else => try params_buffer.append(gpa, CodeGen.typeToValtype(param_type, zcu, target)),
......@@ -4255,7 +5001,7 @@ pub fn isBss(wasm: *const Wasm, optional_name: OptionalString) bool {
42555001/// those entries.
42565002fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !ZcuDataObj {
42575003 const code_start: u32 = @intCast(wasm.string_bytes.items.len);
4258 const relocs_start: u32 = @intCast(wasm.out_relocs.len);
5004 const relocs_start: u32 = @intCast(wasm.zcu_relocations.len);
42595005 const uav_fixups_start: u32 = @intCast(wasm.uav_fixups.items.len);
42605006 const nav_fixups_start: u32 = @intCast(wasm.nav_fixups.items.len);
42615007 const func_table_fixups_start: u32 = @intCast(wasm.func_table_fixups.items.len);
......@@ -4271,8 +5017,9 @@ fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !Zcu
42715017 }
42725018
42735019 const code_len: u32 = @intCast(wasm.string_bytes.items.len - code_start);
4274 const relocs_len: u32 = @intCast(wasm.out_relocs.len - relocs_start);
5020 const relocs_len: u32 = @intCast(wasm.zcu_relocations.len - relocs_start);
42755021 const any_fixups =
5022 relocs_len != 0 or
42765023 uav_fixups_start != wasm.uav_fixups.items.len or
42775024 nav_fixups_start != wasm.nav_fixups.items.len or
42785025 func_table_fixups_start != wasm.func_table_fixups.items.len;
src/link/Wasm/Archive.zig+1-1
......@@ -45,7 +45,7 @@ const Header = extern struct {
4545
4646 fn nameOrIndex(archive: Header) !NameOrIndex {
4747 const value = getValue(&archive.name);
48 const slash_index = mem.indexOfScalar(u8, value, '/') orelse return error.MalformedArchive;
48 const slash_index = mem.findScalar(u8, value, '/') orelse return error.MalformedArchive;
4949 const len = value.len;
5050 if (slash_index == len - 1) {
5151 // Name stored directly
src/link/Wasm/Flush.zig+1148-137
......@@ -7,7 +7,6 @@ const Object = @import("Object.zig");
77const Zcu = @import("../../Zcu.zig");
88const Alignment = Wasm.Alignment;
99const String = Wasm.String;
10const Relocation = Wasm.Relocation;
1110const InternPool = @import("../../InternPool.zig");
1211const Mir = @import("../../codegen/wasm/Mir.zig");
1312
......@@ -33,8 +32,13 @@ data_segment_groups: ArrayList(DataSegmentGroup) = .empty,
3332binary_bytes: ArrayList(u8) = .empty,
3433missing_exports: std.array_hash_map.Auto(String, void) = .empty,
3534function_imports: std.array_hash_map.Auto(String, Wasm.FunctionImportId) = .empty,
35intrinsic_function_imports: std.array_hash_map.Auto(String, Wasm.FunctionType.Index) = .empty,
36/// Function aliases emitted after function symbols.
37function_export_symbols: std.array_hash_map.Auto(String, FunctionExportSymbol) = .empty,
3638global_imports: std.array_hash_map.Auto(String, Wasm.GlobalImportId) = .empty,
3739data_imports: std.array_hash_map.Auto(String, Wasm.DataImportId) = .empty,
40/// Data aliases emitted after data symbols.
41data_exports: std.array_hash_map.Auto(String, DataExportSymbol) = .empty,
3842
3943indirect_function_table: std.array_hash_map.Auto(Wasm.OutputFunctionIndex, void) = .empty,
4044
......@@ -43,6 +47,9 @@ func_types: std.array_hash_map.Auto(Wasm.FunctionType.Index, void) = .empty,
4347
4448enum_tag_name_table: std.array_hash_map.Auto(InternPool.Index, u32) = .empty,
4549
50code_relocs: std.ArrayList(Relocation) = .empty,
51data_relocs: std.ArrayList(Relocation) = .empty,
52
4653/// For debug purposes only.
4754memory_layout_finished: bool = false,
4855
......@@ -55,6 +62,74 @@ pub const FuncTypeIndex = enum(u32) {
5562 }
5663};
5764
65/// Index into SYMTAB_FUNCTION.
66const FunctionSymbolIndex = enum(u32) {
67 _,
68
69 fn fromOutputFunctionIndex(i: Wasm.OutputFunctionIndex) FunctionSymbolIndex {
70 return @fromBackingInt(@backingInt(i));
71 }
72
73 fn fromObjectFunctionHandlingWeak(wasm: *const Wasm, index: Wasm.ObjectFunctionIndex) FunctionSymbolIndex {
74 return fromOutputFunctionIndex(.fromObjectFunctionHandlingWeak(wasm, index));
75 }
76
77 fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) FunctionSymbolIndex {
78 return fromOutputFunctionIndex(.fromIpNav(wasm, nav_index));
79 }
80
81 fn fromTagIndexType(wasm: *const Wasm, ip_index: InternPool.Index) FunctionSymbolIndex {
82 return fromOutputFunctionIndex(.fromTagIndexType(wasm, ip_index));
83 }
84
85 fn fromSymbolName(wasm: *const Wasm, name: String) FunctionSymbolIndex {
86 const f = &wasm.flush_buffer;
87 if (f.function_imports.getIndex(name)) |i| return @fromBackingInt(@intCast(i));
88 if (f.intrinsic_function_imports.getIndex(name)) |i| return @fromBackingInt(@intCast(
89 f.function_imports.entries.len + i,
90 ));
91 if (f.function_export_symbols.getIndex(name)) |i| return @fromBackingInt(@intCast(
92 f.function_imports.entries.len + f.intrinsic_function_imports.entries.len +
93 wasm.functions.entries.len + i,
94 ));
95 return fromOutputFunctionIndex(.fromSymbolName(wasm, name));
96 }
97};
98
99/// Index into SYMTAB_DATA.
100const DataSymbolIndex = enum(u32) {
101 _,
102
103 fn fromOutputDataIndex(i: Wasm.OutputDataIndex) DataSymbolIndex {
104 return @fromBackingInt(@backingInt(i));
105 }
106
107 fn fromResolution(wasm: *const Wasm, resolution: Wasm.ObjectDataImport.Resolution) DataSymbolIndex {
108 return fromOutputDataIndex(Wasm.OutputDataIndex.fromResolution(wasm, resolution).?);
109 }
110
111 fn fromObjectData(wasm: *const Wasm, index: Wasm.ObjectData.Index) DataSymbolIndex {
112 return fromOutputDataIndex(.fromObjectData(wasm, index));
113 }
114
115 fn fromUav(wasm: *const Wasm, ip_index: InternPool.Index) DataSymbolIndex {
116 return fromOutputDataIndex(.fromUav(wasm, ip_index));
117 }
118
119 fn fromNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) DataSymbolIndex {
120 return fromOutputDataIndex(.fromNav(wasm, nav_index));
121 }
122
123 fn fromSymbolName(wasm: *const Wasm, name: String) DataSymbolIndex {
124 const f = &wasm.flush_buffer;
125 if (f.data_imports.getIndex(name)) |i| return @fromBackingInt(@intCast(i));
126 if (f.data_exports.getIndex(name)) |i| return @fromBackingInt(@intCast(
127 f.data_imports.entries.len + wasm.datas.entries.len + i,
128 ));
129 return fromOutputDataIndex(.fromSymbolName(wasm, name));
130 }
131};
132
58133/// Index into `indirect_function_table`.
59134const IndirectFunctionTableIndex = enum(u32) {
60135 _,
......@@ -71,9 +146,8 @@ const IndirectFunctionTableIndex = enum(u32) {
71146 return @fromBackingInt(@intCast(f.indirect_function_table.getIndex(i).?));
72147 }
73148
74 fn fromZcuIndirectFunctionSetIndex(i: Wasm.ZcuIndirectFunctionSetIndex) IndirectFunctionTableIndex {
75 // These are the same since those are added to the table first.
76 return @fromBackingInt(@intCast(@backingInt(i)));
149 fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) IndirectFunctionTableIndex {
150 return fromOutputFunctionIndex(&wasm.flush_buffer, .fromIpNav(wasm, nav_index));
77151 }
78152
79153 fn toAbi(i: IndirectFunctionTableIndex) u32 {
......@@ -81,6 +155,39 @@ const IndirectFunctionTableIndex = enum(u32) {
81155 }
82156};
83157
158const SymbolTableOffsets = struct {
159 function: u32,
160 data: u32,
161 global: u32,
162 table: u32,
163};
164
165const FunctionExportSymbol = struct {
166 function_index: Wasm.FunctionIndex,
167 flags: Wasm.SymbolFlags,
168};
169
170const DataExportSymbol = struct {
171 resolution: Wasm.ObjectDataImport.Resolution,
172 flags: Wasm.SymbolFlags,
173};
174
175const Relocation = struct {
176 tag: Object.RelocationType,
177 offset: u32,
178 pointee: Pointee,
179 addend: i32,
180
181 const Pointee = union {
182 data: DataSymbolIndex,
183 type_index: FuncTypeIndex,
184 section: Wasm.ObjectSectionIndex,
185 function: FunctionSymbolIndex,
186 global: Wasm.GlobalIndex,
187 table: Wasm.TableIndex,
188 };
189};
190
84191const DataSegmentGroup = struct {
85192 first_segment: Wasm.DataSegmentId,
86193 end_addr: u32,
......@@ -90,9 +197,14 @@ pub fn clear(f: *Flush) void {
90197 f.data_segments.clearRetainingCapacity();
91198 f.data_segment_groups.clearRetainingCapacity();
92199 f.binary_bytes.clearRetainingCapacity();
200 f.intrinsic_function_imports.clearRetainingCapacity();
201 f.function_export_symbols.clearRetainingCapacity();
202 f.data_exports.clearRetainingCapacity();
93203 f.indirect_function_table.clearRetainingCapacity();
94204 f.func_types.clearRetainingCapacity();
95205 f.enum_tag_name_table.clearRetainingCapacity();
206 f.code_relocs.clearRetainingCapacity();
207 f.data_relocs.clearRetainingCapacity();
96208 f.memory_layout_finished = false;
97209}
98210
......@@ -102,11 +214,16 @@ pub fn deinit(f: *Flush, gpa: Allocator) void {
102214 f.binary_bytes.deinit(gpa);
103215 f.missing_exports.deinit(gpa);
104216 f.function_imports.deinit(gpa);
217 f.intrinsic_function_imports.deinit(gpa);
218 f.function_export_symbols.deinit(gpa);
105219 f.global_imports.deinit(gpa);
106220 f.data_imports.deinit(gpa);
221 f.data_exports.deinit(gpa);
107222 f.indirect_function_table.deinit(gpa);
108223 f.func_types.deinit(gpa);
109224 f.enum_tag_name_table.deinit(gpa);
225 f.code_relocs.deinit(gpa);
226 f.data_relocs.deinit(gpa);
110227 f.* = undefined;
111228}
112229
......@@ -131,51 +248,12 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
131248
132249 if (comp.zcu) |zcu| {
133250 const ip: *const InternPool = &zcu.intern_pool; // No mutations allowed!
251 const function_imports_start = wasm.function_imports.entries.len;
252 const global_imports_start = wasm.global_imports.entries.len;
253 const data_imports_start = wasm.data_imports.entries.len;
134254
135255 log.debug("total MIR instructions: {d}", .{wasm.mir_instructions.len});
136256
137 // Detect any intrinsics that were called; they need to have dependencies on the symbols marked.
138 // Likewise detect `@tagName` calls so those functions can be included in the output and synthesized.
139 for (wasm.mir_instructions.items(.tag), wasm.mir_instructions.items(.data)) |tag, *data| switch (tag) {
140 .call_intrinsic => {
141 const symbol_name = try wasm.internString(@tagName(data.intrinsic));
142 const i: Wasm.FunctionImport.Index = @fromBackingInt(@intCast(wasm.object_function_imports.getIndex(symbol_name) orelse {
143 return diags.fail("missing compiler runtime intrinsic '{t}' (undefined linker symbol)", .{
144 data.intrinsic,
145 });
146 }));
147 try wasm.markFunctionImport(symbol_name, i.value(wasm), i);
148 log.debug("markFunctionImport intrinsic {d}={t}", .{ i, data.intrinsic });
149 },
150 .call_tag_index => {
151 assert(ip.indexToKey(data.ip_index) == .enum_type);
152 const gop = try wasm.zcu_funcs.getOrPut(gpa, data.ip_index);
153 if (!gop.found_existing) {
154 const int_tag_ty = Zcu.Type.fromInterned(data.ip_index).backingIntType(zcu);
155 gop.value_ptr.* = .{ .tag_name = .{
156 .symbol_name = try wasm.internStringFmt("__zig_tag_index_{d}", .{data.ip_index}),
157 .type_index = try wasm.internFunctionType(.auto, &.{int_tag_ty.ip_index}, .u32, false, target),
158 } };
159 }
160 try wasm.functions.put(gpa, .fromZcuFunc(wasm, @fromBackingInt(@intCast(gop.index))), {});
161 },
162 .enum_tag_name_table_ref => {
163 assert(ip.indexToKey(data.ip_index) == .enum_type);
164 const gop = try f.enum_tag_name_table.getOrPut(gpa, data.ip_index);
165 if (!gop.found_existing) {
166 wasm.tag_name_table_ref_count += 1;
167 gop.value_ptr.* = @intCast(wasm.tag_name_offs.items.len);
168 const tag_names = ip.loadEnumType(data.ip_index).field_names;
169 for (tag_names.get(ip)) |tag_name| {
170 const slice = tag_name.toSlice(ip);
171 try wasm.tag_name_offs.append(gpa, @intCast(wasm.tag_name_bytes.items.len));
172 try wasm.tag_name_bytes.appendSlice(gpa, slice[0 .. slice.len + 1]);
173 }
174 }
175 },
176 else => continue,
177 };
178
179257 {
180258 var i = wasm.function_imports_len_prelink;
181259 while (i < f.function_imports.entries.len) {
......@@ -225,10 +303,24 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
225303 log.debug("flush export '{s}' nav={d}", .{ nav_export.name.slice(wasm), nav_export.nav_index });
226304 const function_index = Wasm.FunctionIndex.fromIpNav(wasm, nav_export.nav_index).?;
227305 const explicit = f.missing_exports.swapRemove(nav_export.name);
228 const is_hidden = !explicit and switch (export_index.ptr(zcu).opts.visibility) {
306 const opts = export_index.ptr(zcu).opts;
307 const is_hidden = !explicit and switch (opts.visibility) {
229308 .hidden => true,
230309 .default, .protected => false,
231310 };
311 if (is_obj) try f.function_export_symbols.put(gpa, nav_export.name, .{
312 .function_index = function_index,
313 .flags = .{
314 .binding = switch (opts.linkage) {
315 .internal => .local,
316 .strong => .strong,
317 .weak => .weak,
318 .link_once => @panic("TODO: COMDAT"),
319 },
320 .visibility_hidden = is_hidden,
321 .exported = !is_hidden,
322 },
323 });
232324 if (is_hidden) {
233325 try wasm.hidden_function_exports.put(gpa, nav_export.name, function_index);
234326 } else {
......@@ -239,17 +331,170 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
239331 if (nav_export.name.toOptional() == entry_name)
240332 wasm.entry_resolution = .fromIpNav(wasm, nav_export.nav_index);
241333 } else {
242 // This is a data export because Zcu currently has no way to
243 // export wasm globals.
244 _ = f.missing_exports.swapRemove(nav_export.name);
334 // data exports are linker symbols
335 // explicit exports become address globals
336 const explicit = f.missing_exports.swapRemove(nav_export.name);
337 const opts = export_index.ptr(zcu).opts;
338 try f.data_exports.put(gpa, nav_export.name, .{
339 .resolution = .fromIpNav(wasm, nav_export.nav_index),
340 .flags = if (is_obj) .{
341 .binding = switch (opts.linkage) {
342 .internal => .local,
343 .strong => .strong,
344 .weak => .weak,
345 .link_once => @panic("TODO: COMDAT"),
346 },
347 .visibility_hidden = !explicit and switch (opts.visibility) {
348 .default => false,
349 .hidden => true,
350 .protected => false,
351 },
352 .exported = explicit,
353 .tls = ip.getNav(nav_export.nav_index).resolved.?.@"threadlocal",
354 } else .{},
355 });
245356 _ = f.data_imports.swapRemove(nav_export.name);
246 if (!is_obj) {
247 diags.addError("unable to export data symbol '{s}'; not emitting a relocatable", .{
248 nav_export.name.slice(wasm),
357 if (explicit and !is_obj) {
358 const global_resolution: Wasm.GlobalImport.Resolution = .fromIpNav(
359 wasm,
360 nav_export.nav_index,
361 );
362 try wasm.globals.put(gpa, global_resolution, {});
363 try wasm.global_exports.append(gpa, .{
364 .name = nav_export.name,
365 .global_index = Wasm.GlobalIndex.fromResolution(wasm, global_resolution).?,
249366 });
250367 }
251368 }
252369 }
370 // handle exported values without navs
371 for (wasm.uav_exports.keys(), wasm.uav_exports.values()) |uav_export, export_index| {
372 assert(!ip.isFunctionType(ip.typeOf(uav_export.uav_index)));
373 const explicit = f.missing_exports.swapRemove(uav_export.name);
374 const opts = export_index.ptr(zcu).opts;
375 try f.data_exports.put(gpa, uav_export.name, .{
376 .resolution = .fromIpIndex(wasm, uav_export.uav_index),
377 .flags = if (is_obj) .{
378 .binding = switch (opts.linkage) {
379 .internal => .local,
380 .strong => .strong,
381 .weak => .weak,
382 .link_once => @panic("TODO: COMDAT"),
383 },
384 .visibility_hidden = !explicit and switch (opts.visibility) {
385 .default => false,
386 .hidden => true,
387 .protected => false,
388 },
389 .exported = explicit,
390 } else .{},
391 });
392 _ = f.data_imports.swapRemove(uav_export.name);
393 if (explicit and !is_obj) {
394 const global_resolution: Wasm.GlobalImport.Resolution = .fromIpIndex(
395 wasm,
396 uav_export.uav_index,
397 );
398 try wasm.globals.put(gpa, global_resolution, {});
399 try wasm.global_exports.append(gpa, .{
400 .name = uav_export.name,
401 .global_index = Wasm.GlobalIndex.fromResolution(wasm, global_resolution).?,
402 });
403 }
404 }
405
406 // Detect any intrinsics that were called; they need to have dependencies on the symbols marked.
407 // Likewise detect `@tagName` calls so those functions can be included in the output and synthesized.
408 for (wasm.mir_instructions.items(.tag), wasm.mir_instructions.items(.data)) |tag, *data| switch (tag) {
409 .call_intrinsic => {
410 const symbol_name = try wasm.internString(@tagName(data.intrinsic));
411 if (Wasm.FunctionIndex.fromSymbolName(wasm, symbol_name) == null and
412 !f.function_imports.contains(symbol_name))
413 {
414 if (wasm.object_function_imports.getIndex(symbol_name)) |object_import_index| {
415 const i: Wasm.FunctionImport.Index = @fromBackingInt(@intCast(object_import_index));
416 try wasm.markFunctionImport(symbol_name, i.value(wasm), i);
417 if (Wasm.FunctionIndex.fromSymbolName(wasm, symbol_name) == null) {
418 try f.function_imports.put(gpa, symbol_name, .fromObject(i, wasm));
419 }
420 } else if (is_obj) {
421 const gop = try f.intrinsic_function_imports.getOrPut(gpa, symbol_name);
422 if (!gop.found_existing) gop.value_ptr.* = try wasm.intrinsicFunctionType(data.intrinsic);
423 } else {
424 return diags.fail("missing compiler runtime intrinsic '{t}' (undefined linker symbol)", .{
425 data.intrinsic,
426 });
427 }
428 }
429 },
430 .call_indirect => {
431 const fn_info = zcu.typeToFunc(.fromInterned(data.ip_index)).?;
432 const type_index = wasm.getExistingFunctionType(
433 fn_info.cc,
434 fn_info.param_types.get(ip),
435 .fromInterned(fn_info.return_type),
436 fn_info.is_var_args,
437 target,
438 ).?;
439 try f.func_types.put(gpa, type_index, {});
440 },
441 .call_tag_index => {
442 assert(ip.indexToKey(data.ip_index) == .enum_type);
443 const gop = try wasm.zcu_funcs.getOrPut(gpa, data.ip_index);
444 if (!gop.found_existing) {
445 const int_tag_ty = Zcu.Type.fromInterned(data.ip_index).backingIntType(zcu);
446 gop.value_ptr.* = .{ .tag_name = .{
447 .symbol_name = try wasm.internStringFmt("__zig_tag_index_{d}", .{data.ip_index}),
448 .type_index = try wasm.internFunctionType(.auto, &.{int_tag_ty.ip_index}, .u32, false, target),
449 } };
450 }
451 try wasm.functions.put(gpa, .fromZcuFunc(wasm, @fromBackingInt(@intCast(gop.index))), {});
452 },
453 .enum_tag_name_table_ref => {
454 assert(ip.indexToKey(data.ip_index) == .enum_type);
455 const gop = try f.enum_tag_name_table.getOrPut(gpa, data.ip_index);
456 if (!gop.found_existing) {
457 wasm.tag_name_table_ref_count += 1;
458 gop.value_ptr.* = @intCast(wasm.tag_name_offs.items.len);
459 const tag_names = ip.loadEnumType(data.ip_index).field_names;
460 for (tag_names.get(ip)) |tag_name| {
461 const slice = tag_name.toSlice(ip);
462 try wasm.tag_name_offs.append(gpa, @intCast(wasm.tag_name_bytes.items.len));
463 try wasm.tag_name_bytes.appendSlice(gpa, slice[0 .. slice.len + 1]);
464 }
465 }
466 },
467 else => continue,
468 };
469
470 // marking above may discover additional imports
471 try f.function_imports.ensureUnusedCapacity(gpa, wasm.function_imports.entries.len - function_imports_start);
472 for (
473 wasm.function_imports.keys()[function_imports_start..],
474 wasm.function_imports.values()[function_imports_start..],
475 ) |name, id| {
476 if (!f.function_imports.contains(name) and Wasm.FunctionIndex.fromSymbolName(wasm, name) == null) {
477 f.function_imports.putAssumeCapacity(name, id);
478 }
479 }
480
481 try f.global_imports.ensureUnusedCapacity(gpa, wasm.global_imports.entries.len - global_imports_start);
482 for (
483 wasm.global_imports.keys()[global_imports_start..],
484 wasm.global_imports.values()[global_imports_start..],
485 ) |name, id| {
486 if (!f.global_imports.contains(name)) f.global_imports.putAssumeCapacity(name, id);
487 }
488
489 try f.data_imports.ensureUnusedCapacity(gpa, wasm.data_imports.entries.len - data_imports_start);
490 for (
491 wasm.data_imports.keys()[data_imports_start..],
492 wasm.data_imports.values()[data_imports_start..],
493 ) |name, id| {
494 if (!f.data_imports.contains(name) and !f.data_exports.contains(name)) {
495 f.data_imports.putAssumeCapacity(name, id);
496 }
497 }
253498
254499 for (f.missing_exports.keys()) |exp_name| {
255500 diags.addError("manually specified export name '{s}' undefined", .{exp_name.slice(wasm)});
......@@ -300,7 +545,27 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
300545 if (wasm.object_init_funcs.items.len > 0) {
301546 // Zig has no constructors so these are only for object file inputs.
302547 mem.sortUnstable(Wasm.InitFunc, wasm.object_init_funcs.items, {}, Wasm.InitFunc.lessThan);
303 try wasm.functions.put(gpa, .__wasm_call_ctors, {});
548 if (!is_obj) try wasm.functions.put(gpa, .__wasm_call_ctors, {});
549 }
550
551 if (is_obj) {
552 try wasm.datas.ensureUnusedCapacity(gpa, wasm.uavs_obj.entries.len + wasm.navs_obj.entries.len + 4);
553 for (0..wasm.uavs_obj.entries.len) |i| wasm.datas.putAssumeCapacity(
554 .pack(wasm, .{ .uav_obj = @fromBackingInt(@intCast(i)) }),
555 {},
556 );
557 for (0..wasm.navs_obj.entries.len) |i| wasm.datas.putAssumeCapacity(
558 .pack(wasm, .{ .nav_obj = @fromBackingInt(@intCast(i)) }),
559 {},
560 );
561 if (wasm.error_name_table_ref_count > 0) {
562 wasm.datas.putAssumeCapacity(.__zig_error_names, {});
563 wasm.datas.putAssumeCapacity(.__zig_error_name_table, {});
564 }
565 if (wasm.tag_name_table_ref_count > 0) {
566 wasm.datas.putAssumeCapacity(.__zig_tag_names, {});
567 wasm.datas.putAssumeCapacity(.__zig_tag_name_table, {});
568 }
304569 }
305570
306571 // Merge and order the data segments. Depends on garbage collection so that
......@@ -341,14 +606,33 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
341606 // dropped in __wasm_init_memory, which is registered as the start function
342607 // We also initialize bss segments (using memory.fill) as part of this
343608 // function.
344 if (wasm.any_passive_inits) {
609 if (!is_obj and wasm.any_passive_inits) {
345610 try wasm.addFunction(.__wasm_init_memory, &.{}, &.{});
346611 }
347612
348613 try wasm.tables.ensureUnusedCapacity(gpa, 1);
349614
350615 if (f.indirect_function_table.entries.len > 0) {
351 wasm.tables.putAssumeCapacity(.__indirect_function_table, {});
616 if (is_obj) {
617 const name = wasm.preloaded_strings.__indirect_function_table;
618 const gop = try wasm.object_table_imports.getOrPut(gpa, name);
619 if (!gop.found_existing) gop.value_ptr.* = .{
620 .flags = .{
621 .undefined = true,
622 .no_strip = true,
623 },
624 .module_name = wasm.preloaded_strings.env,
625 .name = name,
626 .source_location = .zig_object_nofile,
627 .resolution = .unresolved,
628 .limits_min = 1,
629 .limits_max = 0,
630 };
631 const import_index: Wasm.TableImport.Index = @fromBackingInt(@intCast(gop.index));
632 try wasm.markTableImport(name, gop.value_ptr, import_index);
633 } else {
634 wasm.tables.putAssumeCapacity(.__indirect_function_table, {});
635 }
352636 }
353637
354638 // Sort order:
......@@ -449,7 +733,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
449733 const start_addr = alignment.forward(memory_ptr);
450734
451735 const want_new_segment = b: {
452 if (is_obj) break :b false;
736 if (is_obj) break :b i != 0;
453737 switch (seen_tls) {
454738 .before => switch (category) {
455739 .tls => {
......@@ -489,7 +773,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
489773 log.debug("0x{x} {d} {s}", .{ start_addr, @backingInt(segment_id), segment_id.name(wasm) });
490774 memory_ptr = start_addr + size;
491775 }
492 if (category != .zero) try f.data_segment_groups.append(gpa, .{
776 if (is_obj or category != .zero) try f.data_segment_groups.append(gpa, .{
493777 .first_segment = first_segment,
494778 .end_addr = @intCast(memory_ptr),
495779 });
......@@ -555,7 +839,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
555839
556840 // When we have TLS GOT entries and shared memory is enabled, we must
557841 // perform runtime relocations or else we don't create the function.
558 if (shared_memory and virtual_addrs.tls_base != null) {
842 if (!is_obj and shared_memory and virtual_addrs.tls_base != null) {
559843 // This logic that checks `any_tls_relocs` is missing the part where it
560844 // also notices threadlocal globals from Zcu code.
561845 if (wasm.any_tls_relocs) try wasm.addFunction(.__wasm_apply_global_tls_relocs, &.{}, &.{});
......@@ -582,6 +866,9 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
582866 for (f.function_imports.values()) |id| {
583867 try f.func_types.put(gpa, id.functionType(wasm), {});
584868 }
869 for (f.intrinsic_function_imports.values()) |type_index| {
870 try f.func_types.put(gpa, type_index, {});
871 }
585872 for (wasm.functions.keys()) |function| {
586873 try f.func_types.put(gpa, function.typeIndex(wasm), {});
587874 }
......@@ -617,7 +904,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
617904 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
618905
619906 for (f.function_imports.values()) |id| {
620 const module_name = id.moduleName(wasm).slice(wasm).?;
907 const module_name = (id.moduleName(wasm).unwrap() orelse wasm.preloaded_strings.env).slice(wasm);
621908 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(module_name.len)));
622909 try binary_bytes.appendSlice(gpa, module_name);
623910
......@@ -631,6 +918,20 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
631918 }
632919 total_imports += f.function_imports.entries.len;
633920
921 for (f.intrinsic_function_imports.keys(), f.intrinsic_function_imports.values()) |name_string, type_index| {
922 const module_name = wasm.preloaded_strings.env.slice(wasm);
923 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(module_name.len)));
924 try binary_bytes.appendSlice(gpa, module_name);
925
926 const name = name_string.slice(wasm);
927 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));
928 try binary_bytes.appendSlice(gpa, name);
929
930 try binary_bytes.append(gpa, @backingInt(std.wasm.ExternalKind.function));
931 try appendLeb128(gpa, binary_bytes, @backingInt(FuncTypeIndex.fromTypeIndex(type_index, f)));
932 }
933 total_imports += f.intrinsic_function_imports.entries.len;
934
634935 for (wasm.table_imports.values()) |id| {
635936 const table_import = id.value(wasm);
636937 const module_name = table_import.module_name.slice(wasm);
......@@ -662,7 +963,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
662963 }
663964
664965 for (f.global_imports.values()) |id| {
665 const module_name = id.moduleName(wasm).slice(wasm).?;
966 const module_name = (id.moduleName(wasm).unwrap() orelse wasm.preloaded_strings.env).slice(wasm);
666967 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(module_name.len)));
667968 try binary_bytes.appendSlice(gpa, module_name);
668969
......@@ -726,12 +1027,12 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
7261027 for (wasm.globals.keys()) |global_resolution| {
7271028 switch (global_resolution.unpack(wasm)) {
7281029 .unresolved => unreachable,
729 .__heap_base => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_base),
730 .__heap_end => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_end),
731 .__stack_pointer => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.stack_pointer),
732 .__tls_align => try appendGlobal(gpa, binary_bytes, 0, @intCast(virtual_addrs.tls_align.toByteUnits().?)),
733 .__tls_base => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.tls_base.?),
734 .__tls_size => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.tls_size.?),
1030 .__heap_base => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_base, is64),
1031 .__heap_end => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_end, is64),
1032 .__stack_pointer => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.stack_pointer, is64),
1033 .__tls_align => try appendGlobal(gpa, binary_bytes, 0, @intCast(virtual_addrs.tls_align.toByteUnits().?), is64),
1034 .__tls_base => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.tls_base.?, is64),
1035 .__tls_size => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.tls_size.?, is64),
7351036 .object_global => |i| {
7361037 const global = i.ptr(wasm);
7371038 try binary_bytes.appendSlice(gpa, &.{
......@@ -740,8 +1041,9 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
7401041 });
7411042 try emitExpr(wasm, binary_bytes, global.expr);
7421043 },
743 .nav_exe => unreachable, // Zig source code currently cannot represent this.
744 .nav_obj => unreachable, // Zig source code currently cannot represent this.
1044 .uav_exe => |i| try appendGlobal(gpa, binary_bytes, 0, wasm.uavAddr(i.key(wasm).*), is64),
1045 .nav_exe => |i| try appendGlobal(gpa, binary_bytes, 0, wasm.navAddr(i.key(wasm).*), is64),
1046 .uav_obj, .nav_obj => unreachable,
7451047 }
7461048 }
7471049
......@@ -766,7 +1068,8 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
7661068
7671069 if (wasm.export_table and f.indirect_function_table.entries.len > 0) {
7681070 const name = "__indirect_function_table";
769 const index: u32 = @intCast(wasm.tables.getIndex(.__indirect_function_table).?);
1071 const index: u32 = @intCast(wasm.table_imports.entries.len +
1072 wasm.tables.getIndex(.__indirect_function_table).?);
7701073 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));
7711074 try binary_bytes.appendSlice(gpa, name);
7721075 try binary_bytes.append(gpa, @backingInt(std.wasm.ExternalKind.table));
......@@ -803,16 +1106,18 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
8031106 // start section
8041107 if (wasm.functions.getIndex(.__wasm_init_memory)) |func_index| {
8051108 try emitStartSection(gpa, binary_bytes, .fromFunctionIndex(wasm, @fromBackingInt(@intCast(func_index))));
806 } else if (Wasm.OutputFunctionIndex.fromResolution(wasm, wasm.entry_resolution)) |func_index| {
807 try emitStartSection(gpa, binary_bytes, func_index);
1109 section_index += 1;
8081110 }
8091111
8101112 // element section
811 if (f.indirect_function_table.entries.len > 0) {
1113 if (!is_obj and f.indirect_function_table.entries.len > 0) {
8121114 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
8131115
8141116 // indirect function table elements
815 const table_index: u32 = @intCast(wasm.tables.getIndex(.__indirect_function_table).?);
1117 const table_index: u32 = @intCast(
1118 wasm.table_imports.getIndex(wasm.preloaded_strings.__indirect_function_table) orelse
1119 wasm.table_imports.entries.len + wasm.tables.getIndex(.__indirect_function_table).?,
1120 );
8161121 // passive with implicit 0-index table or set table index manually
8171122 const flags: u32 = if (table_index == 0) 0x0 else 0x02;
8181123 try appendLeb128(gpa, binary_bytes, flags);
......@@ -841,11 +1146,13 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
8411146 if (f.data_segment_groups.items.len > 0) {
8421147 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
8431148 replaceVecSectionHeader(binary_bytes, header_offset, .data_count, @intCast(f.data_segment_groups.items.len));
1149 section_index += 1;
8441150 }
8451151
8461152 // Code section.
8471153 if (wasm.functions.count() != 0) {
8481154 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
1155 const section_offset = binary_bytes.items.len - uleb128size(@intCast(wasm.functions.count()));
8491156
8501157 for (wasm.functions.keys()) |resolution| switch (resolution.unpack(wasm)) {
8511158 .unresolved => unreachable,
......@@ -870,10 +1177,22 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
8701177 const code = ptr.code.slice(wasm);
8711178 try appendLeb128(gpa, binary_bytes, code.len);
8721179 const code_start = binary_bytes.items.len;
1180 const output_offset: u32 = @intCast(binary_bytes.items.len - section_offset);
8731181 try binary_bytes.appendSlice(gpa, code);
874 if (!is_obj) applyRelocs(binary_bytes.items[code_start..], ptr.offset, ptr.relocations(wasm), wasm);
1182 if (is_obj) {
1183 try processRelocs(
1184 wasm,
1185 &f.code_relocs,
1186 output_offset,
1187 ptr.offset,
1188 ptr.relocations(wasm),
1189 );
1190 } else {
1191 applyRelocs(binary_bytes.items[code_start..], ptr.offset, ptr.relocations(wasm), wasm);
1192 }
8751193 },
8761194 .zcu_func => |i| {
1195 const function_offset: u32 = @intCast(binary_bytes.items.len - section_offset);
8771196 const code_start = try reserveSize(gpa, binary_bytes);
8781197 defer replaceSize(binary_bytes, code_start);
8791198
......@@ -899,7 +1218,22 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
8991218 .func_tys = undefined,
9001219 .error_name_table_ref_count = undefined,
9011220 };
1221 const body_start: u32 = @intCast(binary_bytes.items.len);
1222 const relocs_start: u32 = @intCast(wasm.zcu_relocations.len);
1223 defer wasm.zcu_relocations.shrinkRetainingCapacity(relocs_start);
9021224 try mir.lower(wasm, binary_bytes);
1225 const relocs_len: u32 = @intCast(wasm.zcu_relocations.len - relocs_start);
1226 if (is_obj) {
1227 const body_len: u32 = @intCast(binary_bytes.items.len - @as(usize, body_start));
1228 const output_offset = function_offset + uleb128size(body_len);
1229 try processZcuRelocs(
1230 wasm,
1231 &f.code_relocs,
1232 output_offset,
1233 body_start,
1234 .{ .off = relocs_start, .len = relocs_len },
1235 );
1236 }
9031237 },
9041238 }
9051239 },
......@@ -921,8 +1255,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
9211255 }
9221256 }
9231257 for (wasm.nav_fixups.items) |nav_fixup| {
924 const ds_id: Wasm.DataSegmentId = .pack(wasm, .{ .nav_exe = nav_fixup.navs_exe_index });
925 const vaddr = f.data_segments.get(ds_id).? + nav_fixup.addend;
1258 const vaddr = wasm.navAddr(nav_fixup.nav_index) + nav_fixup.addend;
9261259 if (!is64) {
9271260 mem.writeInt(u32, wasm.string_bytes.items[nav_fixup.offset..][0..4], vaddr, .little);
9281261 } else {
......@@ -930,7 +1263,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
9301263 }
9311264 }
9321265 for (wasm.func_table_fixups.items) |fixup| {
933 const table_index: IndirectFunctionTableIndex = .fromZcuIndirectFunctionSetIndex(fixup.table_index);
1266 const table_index: IndirectFunctionTableIndex = .fromIpNav(wasm, fixup.nav_index);
9341267 if (!is64) {
9351268 mem.writeInt(u32, wasm.string_bytes.items[fixup.offset..][0..4], table_index.toAbi(), .little);
9361269 } else {
......@@ -942,6 +1275,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
9421275 // Data section.
9431276 if (f.data_segment_groups.items.len != 0) {
9441277 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
1278 const section_offset = binary_bytes.items.len - uleb128size(@intCast(f.data_segment_groups.items.len));
9451279
9461280 var group_index: u32 = 0;
9471281 var segment_offset: u32 = 0;
......@@ -976,7 +1310,11 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
9761310 try appendLeb128(gpa, binary_bytes, group_size);
9771311 }
9781312 if (segment_id.isEmpty(wasm)) {
979 // It counted for virtual memory but it does not go into the binary.
1313 if (is_obj) {
1314 const group_size = group_end_addr - group_start_addr;
1315 try binary_bytes.appendNTimes(gpa, 0, group_size - segment_offset);
1316 segment_offset = group_size;
1317 }
9801318 continue;
9811319 }
9821320
......@@ -986,6 +1324,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
9861324 segment_offset = needed_offset;
9871325
9881326 const code_start = binary_bytes.items.len;
1327 const output_offset: u32 = @intCast(binary_bytes.items.len - section_offset);
9891328 append: {
9901329 const code = switch (segment_id.unpack(wasm)) {
9911330 .__heap_base => {
......@@ -1001,12 +1340,19 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
10011340 break :append;
10021341 },
10031342 .__zig_error_name_table => {
1004 if (is_obj) @panic("TODO error name table reloc");
1005 const base = f.data_segments.get(.__zig_error_names).?;
1006 if (!is64) {
1007 try emitTagNameTable(gpa, binary_bytes, wasm.error_name_offs.items, wasm.error_name_bytes.items, base, u32);
1343 if (is_obj) {
1344 try emitRelocatableNameTable(
1345 wasm,
1346 binary_bytes,
1347 &f.data_relocs,
1348 output_offset,
1349 wasm.error_name_offs.items,
1350 wasm.error_name_bytes.items,
1351 .__zig_error_names,
1352 );
10081353 } else {
1009 try emitTagNameTable(gpa, binary_bytes, wasm.error_name_offs.items, wasm.error_name_bytes.items, base, u64);
1354 const base = f.data_segments.get(.__zig_error_names).?;
1355 try emitTagNameTable(wasm, binary_bytes, wasm.error_name_offs.items, wasm.error_name_bytes.items, base, is64);
10101356 }
10111357 break :append;
10121358 },
......@@ -1015,22 +1361,51 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
10151361 break :append;
10161362 },
10171363 .__zig_tag_name_table => {
1018 if (is_obj) @panic("TODO tag name table reloc");
1019 const base = f.data_segments.get(.__zig_tag_names).?;
1020 if (!is64) {
1021 try emitTagNameTable(gpa, binary_bytes, wasm.tag_name_offs.items, wasm.tag_name_bytes.items, base, u32);
1364 if (is_obj) {
1365 try emitRelocatableNameTable(
1366 wasm,
1367 binary_bytes,
1368 &f.data_relocs,
1369 output_offset,
1370 wasm.tag_name_offs.items,
1371 wasm.tag_name_bytes.items,
1372 .__zig_tag_names,
1373 );
10221374 } else {
1023 try emitTagNameTable(gpa, binary_bytes, wasm.tag_name_offs.items, wasm.tag_name_bytes.items, base, u64);
1375 const base = f.data_segments.get(.__zig_tag_names).?;
1376 try emitTagNameTable(wasm, binary_bytes, wasm.tag_name_offs.items, wasm.tag_name_bytes.items, base, is64);
10241377 }
10251378 break :append;
10261379 },
10271380 .object => |i| {
10281381 const ptr = i.ptr(wasm);
10291382 try binary_bytes.appendSlice(gpa, ptr.payload.slice(wasm));
1030 if (!is_obj) applyRelocs(binary_bytes.items[code_start..], ptr.offset, ptr.relocations(wasm), wasm);
1383 if (is_obj) {
1384 try processRelocs(
1385 wasm,
1386 &f.data_relocs,
1387 output_offset,
1388 ptr.offset,
1389 ptr.relocations(wasm),
1390 );
1391 } else {
1392 applyRelocs(binary_bytes.items[code_start..], ptr.offset, ptr.relocations(wasm), wasm);
1393 }
10311394 break :append;
10321395 },
1033 inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code,
1396 inline .uav_obj, .nav_obj => |i| {
1397 const zcu_data = i.value(wasm);
1398 try binary_bytes.appendSlice(gpa, zcu_data.code.slice(wasm));
1399 try processZcuRelocs(
1400 wasm,
1401 &f.data_relocs,
1402 output_offset,
1403 zcu_data.code.off.unwrap().?,
1404 zcu_data.relocs,
1405 );
1406 break :append;
1407 },
1408 inline .uav_exe, .nav_exe => |i| i.value(wasm).code,
10341409 };
10351410 try binary_bytes.appendSlice(gpa, code.slice(wasm));
10361411 }
......@@ -1043,7 +1418,274 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
10431418 }
10441419
10451420 if (is_obj) {
1046 @panic("TODO emit link section for object file and emit modified relocations");
1421 var symbol_table_offsets: SymbolTableOffsets = undefined;
1422 {
1423 const header_offset = try reserveCustomSectionHeader(gpa, binary_bytes);
1424 defer writeCustomSectionHeader(binary_bytes, header_offset);
1425
1426 const linking_name = "linking";
1427 try appendLeb128(gpa, binary_bytes, @as(u32, linking_name.len));
1428 try binary_bytes.appendSlice(gpa, linking_name);
1429
1430 try appendLeb128(gpa, binary_bytes, @as(u32, 2));
1431
1432 // WASM_SEGMENT_INFO
1433 {
1434 const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes);
1435 defer replaceHeader(binary_bytes, sub_offset, @backingInt(Object.SubsectionType.segment_info));
1436
1437 const total_data_segments: u32 = @intCast(f.data_segment_groups.items.len);
1438 try appendLeb128(gpa, binary_bytes, total_data_segments);
1439
1440 for (f.data_segment_groups.items) |group| {
1441 const segment = group.first_segment;
1442 const name, _ = splitSegmentName(segment.name(wasm));
1443 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));
1444 try binary_bytes.appendSlice(gpa, name);
1445
1446 try appendLeb128(gpa, binary_bytes, @as(u32, segment.alignment(wasm).toLog2Units()));
1447
1448 var flags: u32 = 0;
1449 if (segment.isStrings(wasm)) flags |= 1;
1450 if (segment.isTls(wasm)) flags |= 2;
1451 if (segment.isRetain(wasm)) flags |= 4;
1452 try appendLeb128(gpa, binary_bytes, flags);
1453 }
1454 }
1455
1456 // WASM_SYMBOL_TABLE
1457 {
1458 const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes);
1459 defer replaceHeader(binary_bytes, sub_offset, @backingInt(Object.SubsectionType.symbol_table));
1460
1461 const total_symbols: u32 = @intCast(
1462 f.function_imports.entries.len + f.intrinsic_function_imports.entries.len +
1463 wasm.functions.entries.len +
1464 f.function_export_symbols.entries.len +
1465 f.data_imports.entries.len + wasm.datas.entries.len + f.data_exports.entries.len +
1466 f.global_imports.entries.len + wasm.globals.entries.len +
1467 wasm.table_imports.entries.len + wasm.tables.entries.len,
1468 );
1469 try appendLeb128(gpa, binary_bytes, total_symbols);
1470 var symbol_count: u32 = 0;
1471
1472 // SYMTAB_FUNCTION
1473 {
1474 symbol_table_offsets.function = symbol_count;
1475 for (f.function_imports.values(), 0..) |i, function_index| {
1476 try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.function));
1477 const flags = i.flags(wasm);
1478 assert(flags.undefined);
1479 try appendLeb128(gpa, binary_bytes, flags.toAbiInteger());
1480 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(function_index)));
1481 if (flags.explicit_name) {
1482 unreachable; // never set
1483 }
1484 symbol_count += 1;
1485 }
1486 const intrinsic_flags: Wasm.SymbolFlags = .{ .undefined = true };
1487 for (f.intrinsic_function_imports.keys(), f.function_imports.entries.len..) |_, function_index| {
1488 try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.function));
1489 try appendLeb128(gpa, binary_bytes, intrinsic_flags.toAbiInteger());
1490 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(function_index)));
1491 symbol_count += 1;
1492 }
1493 for (
1494 wasm.functions.keys(),
1495 f.function_imports.entries.len + f.intrinsic_function_imports.entries.len..,
1496 ) |resolution, function_index| {
1497 const name = resolution.name(wasm).?;
1498 const flags = resolution.flags(wasm);
1499 try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.function));
1500 assert(!flags.undefined);
1501 try appendLeb128(gpa, binary_bytes, flags.toAbiInteger());
1502 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(function_index)));
1503 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));
1504 try binary_bytes.appendSlice(gpa, name);
1505 symbol_count += 1;
1506 }
1507 for (
1508 f.function_export_symbols.keys(),
1509 f.function_export_symbols.values(),
1510 ) |name_string, symbol| {
1511 const name = name_string.slice(wasm);
1512 const function_index: Wasm.OutputFunctionIndex = .fromFunctionIndex(
1513 wasm,
1514 symbol.function_index,
1515 );
1516 try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.function));
1517 try appendLeb128(gpa, binary_bytes, symbol.flags.toAbiInteger());
1518 try appendLeb128(gpa, binary_bytes, @backingInt(function_index));
1519 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));
1520 try binary_bytes.appendSlice(gpa, name);
1521 symbol_count += 1;
1522 }
1523 }
1524
1525 // SYMTAB_DATA
1526 {
1527 symbol_table_offsets.data = symbol_count;
1528 for (f.data_imports.keys(), f.data_imports.values()) |name_string, data_index| {
1529 const name = name_string.slice(wasm);
1530 try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.data));
1531 const flags = data_index.flags(wasm);
1532 assert(flags.undefined);
1533 try appendLeb128(gpa, binary_bytes, flags.toAbiInteger());
1534 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));
1535 try binary_bytes.appendSlice(gpa, name);
1536 symbol_count += 1;
1537 }
1538 for (wasm.datas.keys()) |resolution| {
1539 var buf: [32]u8 = undefined;
1540 const name = resolution.name(wasm, &buf);
1541 try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.data));
1542 const flags = resolution.flags(wasm);
1543 assert(!flags.undefined);
1544 try appendLeb128(gpa, binary_bytes, flags.toAbiInteger());
1545
1546 const data_loc = resolution.dataLoc(wasm);
1547 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));
1548 try binary_bytes.appendSlice(gpa, name);
1549
1550 const segment_index = f.data_segments.getIndex(data_loc.segment).?;
1551 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(segment_index)));
1552 try appendLeb128(gpa, binary_bytes, data_loc.offset);
1553 try appendLeb128(gpa, binary_bytes, resolution.size(wasm));
1554 symbol_count += 1;
1555 }
1556 for (f.data_exports.keys(), f.data_exports.values()) |name_string, symbol| {
1557 const name = name_string.slice(wasm);
1558 try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.data));
1559 try appendLeb128(gpa, binary_bytes, symbol.flags.toAbiInteger());
1560 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));
1561 try binary_bytes.appendSlice(gpa, name);
1562
1563 const data_loc = symbol.resolution.dataLoc(wasm);
1564 const segment_index = f.data_segments.getIndex(data_loc.segment).?;
1565 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(segment_index)));
1566 try appendLeb128(gpa, binary_bytes, data_loc.offset);
1567 try appendLeb128(gpa, binary_bytes, symbol.resolution.size(wasm));
1568 symbol_count += 1;
1569 }
1570 }
1571
1572 // SYMTAB_GLOBAL
1573 {
1574 symbol_table_offsets.global = symbol_count;
1575 for (f.global_imports.values(), 0..) |i, global_index| {
1576 try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.global));
1577 const flags = i.flags(wasm);
1578 assert(flags.undefined);
1579 try appendLeb128(gpa, binary_bytes, flags.toAbiInteger());
1580 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(global_index)));
1581 if (flags.explicit_name) {
1582 unreachable; // never set
1583 }
1584 symbol_count += 1;
1585 }
1586 for (wasm.globals.keys(), f.global_imports.entries.len..) |resolution, global_index| {
1587 var buf: [32]u8 = undefined;
1588 const name = resolution.name(wasm, &buf).?;
1589 try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.global));
1590 const flags = resolution.flags(wasm);
1591 assert(!flags.undefined);
1592 try appendLeb128(gpa, binary_bytes, flags.toAbiInteger());
1593 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(global_index)));
1594 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));
1595 try binary_bytes.appendSlice(gpa, name);
1596 symbol_count += 1;
1597 }
1598 }
1599
1600 // SYMTAB_EVENT
1601 {
1602 // TODO not parsed yet
1603 }
1604
1605 // SYMTAB_SECTION
1606 {
1607 // TODO not parsed correctly yet
1608 }
1609
1610 // SYMTAB_TABLE
1611 {
1612 symbol_table_offsets.table = symbol_count;
1613 for (wasm.table_imports.values(), 0..) |i, table_index| {
1614 try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.table));
1615 const flags = i.value(wasm).flags;
1616 assert(flags.undefined);
1617 try appendLeb128(gpa, binary_bytes, flags.toAbiInteger());
1618 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(table_index)));
1619 if (flags.explicit_name) {
1620 unreachable; // never set
1621 }
1622 symbol_count += 1;
1623 }
1624 for (wasm.tables.keys(), wasm.table_imports.entries.len..) |resolution, table_index| {
1625 const name = resolution.name(wasm).?;
1626 try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.table));
1627 const flags = resolution.flags(wasm);
1628 assert(!flags.undefined);
1629 try appendLeb128(gpa, binary_bytes, flags.toAbiInteger());
1630 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(table_index)));
1631 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));
1632 try binary_bytes.appendSlice(gpa, name);
1633 symbol_count += 1;
1634 }
1635 }
1636 assert(symbol_count == total_symbols);
1637 }
1638
1639 // WASM_INIT_FUNCS
1640 {
1641 const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes);
1642 defer replaceHeader(binary_bytes, sub_offset, @backingInt(Object.SubsectionType.init_funcs));
1643
1644 const init_funcs = wasm.object_init_funcs.items;
1645 const total_functions: u32 = b: {
1646 var cnt: u32 = 0;
1647 for (init_funcs) |init_func| {
1648 const func = init_func.function_index.ptr(wasm);
1649 if (!func.object_index.ptr(wasm).is_included) continue;
1650 cnt += 1;
1651 }
1652 break :b cnt;
1653 };
1654 try appendLeb128(gpa, binary_bytes, total_functions);
1655
1656 for (init_funcs) |init_func| {
1657 const func = init_func.function_index.ptr(wasm);
1658 if (!func.object_index.ptr(wasm).is_included) continue;
1659
1660 try appendLeb128(gpa, binary_bytes, init_func.priority);
1661 const out_index: Wasm.OutputFunctionIndex = .fromObjectFunction(wasm, init_func.function_index);
1662 const symbol_index: u32 = symbol_table_offsets.function + @backingInt(out_index);
1663 try appendLeb128(gpa, binary_bytes, symbol_index);
1664 }
1665 }
1666
1667 // WASM_COMDAT_INFO
1668 {
1669 // TODO
1670 }
1671 }
1672
1673 if (f.code_relocs.items.len != 0) try emitRelocSection(
1674 wasm,
1675 binary_bytes,
1676 code_section_index.?,
1677 "reloc.CODE",
1678 f.code_relocs.items,
1679 symbol_table_offsets,
1680 );
1681 if (f.data_relocs.items.len != 0) try emitRelocSection(
1682 wasm,
1683 binary_bytes,
1684 data_section_index.?,
1685 "reloc.DATA",
1686 f.data_relocs.items,
1687 symbol_table_offsets,
1688 );
10471689 } else if (comp.config.debug_format != .strip) {
10481690 try emitNameSection(wasm, f.data_segment_groups.items, binary_bytes);
10491691 }
......@@ -1121,7 +1763,10 @@ fn emitNameSection(
11211763 const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes);
11221764 defer replaceHeader(binary_bytes, sub_offset, @backingInt(std.wasm.NameSubsection.function));
11231765
1124 const total_functions: u32 = @intCast(f.function_imports.entries.len + wasm.functions.entries.len);
1766 const total_functions: u32 = @intCast(
1767 f.function_imports.entries.len + f.intrinsic_function_imports.entries.len +
1768 wasm.functions.entries.len,
1769 );
11251770 try appendLeb128(gpa, binary_bytes, total_functions);
11261771
11271772 for (f.function_imports.keys(), 0..) |name_index, function_index| {
......@@ -1130,7 +1775,16 @@ fn emitNameSection(
11301775 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));
11311776 try binary_bytes.appendSlice(gpa, name);
11321777 }
1133 for (wasm.functions.keys(), f.function_imports.entries.len..) |resolution, function_index| {
1778 for (f.intrinsic_function_imports.keys(), f.function_imports.entries.len..) |name_index, function_index| {
1779 const name = name_index.slice(wasm);
1780 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(function_index)));
1781 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));
1782 try binary_bytes.appendSlice(gpa, name);
1783 }
1784 for (
1785 wasm.functions.keys(),
1786 f.function_imports.entries.len + f.intrinsic_function_imports.entries.len..,
1787 ) |resolution, function_index| {
11341788 const name = resolution.name(wasm).?;
11351789 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(function_index)));
11361790 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));
......@@ -1152,7 +1806,8 @@ fn emitNameSection(
11521806 try binary_bytes.appendSlice(gpa, name);
11531807 }
11541808 for (wasm.globals.keys(), f.global_imports.entries.len..) |resolution, global_index| {
1155 const name = resolution.name(wasm).?;
1809 var buf: [32]u8 = undefined;
1810 const name = resolution.name(wasm, &buf).?;
11561811 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(global_index)));
11571812 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));
11581813 try binary_bytes.appendSlice(gpa, name);
......@@ -1270,7 +1925,7 @@ fn emitProducerSection(gpa: Allocator, binary_bytes: *ArrayList(u8)) !void {
12701925
12711926fn splitSegmentName(name: []const u8) struct { []const u8, []const u8 } {
12721927 const start = @intFromBool(name.len >= 1 and name[0] == '.');
1273 const pivot = mem.indexOfScalarPos(u8, name, start, '.') orelse name.len;
1928 const pivot = mem.findScalarPos(u8, name, start, '.') orelse name.len;
12741929 return .{ name[0..pivot], name[pivot..] };
12751930}
12761931
......@@ -1418,29 +2073,6 @@ pub fn emitExpr(wasm: *const Wasm, binary_bytes: *ArrayList(u8), expr: Wasm.Expr
14182073 try binary_bytes.appendSlice(gpa, slice[0 .. slice.len + 1]); // +1 to include end opcode
14192074}
14202075
1421fn emitSegmentInfo(wasm: *Wasm, binary_bytes: *std.array_list.Managed(u8)) !void {
1422 const gpa = wasm.base.comp.gpa;
1423 try appendLeb128(gpa, binary_bytes, @backingInt(Wasm.SubsectionType.segment_info));
1424 const segment_offset = binary_bytes.items.len;
1425
1426 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(wasm.segment_info.count())));
1427 for (wasm.segment_info.values()) |segment_info| {
1428 log.debug("Emit segment: {s} align({d}) flags({b})", .{
1429 segment_info.name,
1430 segment_info.alignment,
1431 segment_info.flags,
1432 });
1433 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(segment_info.name.len)));
1434 try binary_bytes.appendSlice(gpa, segment_info.name);
1435 try appendLeb128(gpa, binary_bytes, segment_info.alignment.toLog2Units());
1436 try appendLeb128(gpa, binary_bytes, segment_info.flags);
1437 }
1438
1439 var buf: [5]u8 = undefined;
1440 leb.writeUnsignedFixed(5, &buf, @as(u32, @intCast(binary_bytes.items.len - segment_offset)));
1441 try binary_bytes.insertSlice(segment_offset, &buf);
1442}
1443
14442076fn uleb128size(x: u32) u32 {
14452077 var value = x;
14462078 var size: u32 = 0;
......@@ -1449,22 +2081,395 @@ fn uleb128size(x: u32) u32 {
14492081}
14502082
14512083fn emitTagNameTable(
1452 gpa: Allocator,
2084 wasm: *const Wasm,
14532085 code: *ArrayList(u8),
14542086 tag_name_offs: []const u32,
14552087 tag_name_bytes: []const u8,
14562088 base: u32,
1457 comptime Int: type,
2089 is64: bool,
14582090) error{OutOfMemory}!void {
1459 const ptr_size_bytes = @divExact(@bitSizeOf(Int), 8);
2091 const gpa = wasm.base.comp.gpa;
2092 const ptr_size_bytes: usize = if (is64) 8 else 4;
14602093 try code.ensureUnusedCapacity(gpa, ptr_size_bytes * 2 * tag_name_offs.len);
14612094 for (tag_name_offs) |off| {
1462 const name_len: u32 = @intCast(mem.indexOfScalar(u8, tag_name_bytes[off..], 0).?);
1463 mem.writeInt(Int, code.addManyAsArrayAssumeCapacity(ptr_size_bytes), base + off, .little);
1464 mem.writeInt(Int, code.addManyAsArrayAssumeCapacity(ptr_size_bytes), name_len, .little);
2095 const name_len: u32 = @intCast(mem.findScalar(u8, tag_name_bytes[off..], 0).?);
2096 if (is64) {
2097 mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), base + off, .little);
2098 mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), name_len, .little);
2099 } else {
2100 mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), base + off, .little);
2101 mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), name_len, .little);
2102 }
2103 }
2104}
2105
2106fn emitRelocatableNameTable(
2107 wasm: *const Wasm,
2108 code: *ArrayList(u8),
2109 relocs: *ArrayList(Relocation),
2110 output_offset: u32,
2111 name_offs: []const u32,
2112 name_bytes: []const u8,
2113 names_resolution: Wasm.ObjectDataImport.Resolution,
2114) error{OutOfMemory}!void {
2115 const gpa = wasm.base.comp.gpa;
2116 const ptr_size = @divExact(wasm.base.comp.root_mod.resolved_target.result.ptrBitWidth(), 8);
2117 const table_start = code.items.len;
2118 const data_index: DataSymbolIndex = .fromResolution(wasm, names_resolution);
2119 try code.ensureUnusedCapacity(gpa, @as(usize, ptr_size) * 2 * name_offs.len);
2120 try relocs.ensureUnusedCapacity(gpa, name_offs.len);
2121 for (name_offs) |off| {
2122 const name_len: u32 = @intCast(mem.findScalar(u8, name_bytes[off..], 0).?);
2123 const reloc_offset = output_offset + @as(u32, @intCast(code.items.len - table_start));
2124 switch (ptr_size) {
2125 4 => {
2126 @memset(code.addManyAsArrayAssumeCapacity(4), 0);
2127 mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), name_len, .little);
2128 },
2129 8 => {
2130 @memset(code.addManyAsArrayAssumeCapacity(8), 0);
2131 mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), @intCast(name_len), .little);
2132 },
2133 else => unreachable,
2134 }
2135 relocs.appendAssumeCapacity(.{
2136 .tag = if (ptr_size == 4) .memory_addr_i32 else .memory_addr_i64,
2137 .offset = reloc_offset,
2138 .pointee = .{ .data = data_index },
2139 .addend = @intCast(off),
2140 });
2141 }
2142}
2143
2144fn emitRelocSection(
2145 wasm: *const Wasm,
2146 binary_bytes: *ArrayList(u8),
2147 section_index: u32,
2148 reloc_name: []const u8,
2149 relocs: []const Relocation,
2150 symbol_table_offsets: SymbolTableOffsets,
2151) !void {
2152 const comp = wasm.base.comp;
2153 const gpa = comp.gpa;
2154
2155 const header_offset = try reserveCustomSectionHeader(gpa, binary_bytes);
2156 defer writeCustomSectionHeader(binary_bytes, header_offset);
2157
2158 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(reloc_name.len)));
2159 try binary_bytes.appendSlice(gpa, reloc_name);
2160
2161 try appendLeb128(gpa, binary_bytes, section_index);
2162 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(relocs.len)));
2163
2164 for (relocs) |r| {
2165 try binary_bytes.append(gpa, @backingInt(r.tag));
2166 try appendLeb128(gpa, binary_bytes, r.offset);
2167 switch (r.tag) {
2168 .memory_addr_leb,
2169 .memory_addr_sleb,
2170 .memory_addr_i32,
2171 .memory_addr_rel_sleb,
2172 .memory_addr_leb64,
2173 .memory_addr_sleb64,
2174 .memory_addr_i64,
2175 .memory_addr_rel_sleb64,
2176 .memory_addr_tls_sleb,
2177 .memory_addr_locrel_i32,
2178 .memory_addr_tls_sleb64,
2179 => {
2180 const symbol_index: u32 = symbol_table_offsets.data + @backingInt(r.pointee.data);
2181 try appendLeb128(gpa, binary_bytes, symbol_index);
2182 },
2183 .section_offset_i32 => {
2184 @panic("TODO");
2185 },
2186 .type_index_leb => {
2187 try appendLeb128(gpa, binary_bytes, @backingInt(r.pointee.type_index));
2188 },
2189 .function_offset_i32,
2190 .function_offset_i64,
2191 .function_index_leb,
2192 .function_index_i32,
2193 .table_index_sleb,
2194 .table_index_i32,
2195 .table_index_sleb64,
2196 .table_index_i64,
2197 .table_index_rel_sleb,
2198 .table_index_rel_sleb64,
2199 => {
2200 const symbol_index: u32 = symbol_table_offsets.function + @backingInt(r.pointee.function);
2201 try appendLeb128(gpa, binary_bytes, symbol_index);
2202 },
2203 .global_index_leb, .global_index_i32 => {
2204 const symbol_index: u32 = symbol_table_offsets.global + @backingInt(r.pointee.global);
2205 try appendLeb128(gpa, binary_bytes, symbol_index);
2206 },
2207 .table_number_leb => {
2208 const symbol_index: u32 = symbol_table_offsets.table + @backingInt(r.pointee.table);
2209 try appendLeb128(gpa, binary_bytes, symbol_index);
2210 },
2211 .event_index_leb => @panic("TODO"),
2212 }
2213 switch (r.tag) {
2214 .memory_addr_leb,
2215 .memory_addr_sleb,
2216 .memory_addr_i32,
2217 .memory_addr_rel_sleb,
2218 .memory_addr_leb64,
2219 .memory_addr_sleb64,
2220 .memory_addr_i64,
2221 .memory_addr_rel_sleb64,
2222 .memory_addr_tls_sleb,
2223 .memory_addr_locrel_i32,
2224 .memory_addr_tls_sleb64,
2225 .function_offset_i32,
2226 .function_offset_i64,
2227 .section_offset_i32,
2228 => {
2229 try appendLeb128(gpa, binary_bytes, r.addend);
2230 },
2231 else => {},
2232 }
2233 }
2234}
2235
2236fn processZcuRelocs(
2237 wasm: *const Wasm,
2238 out: *ArrayList(Relocation),
2239 output_offset: u32,
2240 input_offset: u32,
2241 relocs: Wasm.ZcuRelocation.Slice,
2242) !void {
2243 const gpa = wasm.base.comp.gpa;
2244 for (
2245 relocs.tags(wasm),
2246 relocs.pointees(wasm),
2247 relocs.offsets(wasm),
2248 relocs.addends(wasm),
2249 ) |tag, pointee, offset, addend| {
2250 const output_pointee: Relocation.Pointee = switch (pointee) {
2251 .function_nav => |nav_index| .{ .function = .fromIpNav(wasm, nav_index) },
2252 .function_name => |name| .{ .function = .fromSymbolName(wasm, name) },
2253 .tag_function => |ip_index| .{ .function = .fromTagIndexType(wasm, ip_index) },
2254 .data_uav => |ip_index| .{ .data = .fromUav(wasm, ip_index) },
2255 .data_nav => |nav_index| .{ .data = .fromNav(wasm, nav_index) },
2256 .data_resolution => |resolution| .{ .data = .fromResolution(wasm, resolution) },
2257 .stack_pointer => .{ .global = .fromSymbolName(wasm, wasm.preloaded_strings.__stack_pointer) },
2258 .type_index => |type_index| .{ .type_index = .fromTypeIndex(type_index, &wasm.flush_buffer) },
2259 };
2260 try out.append(gpa, .{
2261 .tag = tag,
2262 .offset = output_offset + (offset - input_offset),
2263 .pointee = output_pointee,
2264 .addend = addend,
2265 });
14652266 }
14662267}
14672268
2269fn processRelocs(
2270 wasm: *const Wasm,
2271 out: *ArrayList(Relocation),
2272 output_offset: u32,
2273 input_offset: u32,
2274 relocs: Wasm.ObjectRelocation.IterableSlice,
2275) !void {
2276 const gpa = wasm.base.comp.gpa;
2277 for (
2278 relocs.slice.tags(wasm),
2279 relocs.slice.pointees(wasm),
2280 relocs.slice.offsets(wasm),
2281 relocs.slice.addends(wasm),
2282 ) |tag, pointee, offset, addend| {
2283 if (offset >= relocs.end) break;
2284 const rebased_offset = output_offset + (offset - input_offset);
2285 try out.ensureUnusedCapacity(gpa, 1);
2286 switch (tag) {
2287 .function_index_i32 => out.appendAssumeCapacity(.{
2288 .tag = .function_index_i32,
2289 .offset = rebased_offset,
2290 .pointee = .{ .function = .fromObjectFunctionHandlingWeak(wasm, pointee.function) },
2291 .addend = addend,
2292 }),
2293 .function_index_leb => out.appendAssumeCapacity(.{
2294 .tag = .function_index_leb,
2295 .offset = rebased_offset,
2296 .pointee = .{ .function = .fromObjectFunctionHandlingWeak(wasm, pointee.function) },
2297 .addend = addend,
2298 }),
2299 .function_offset_i32 => @panic("TODO this value is not known yet"),
2300 .function_offset_i64 => @panic("TODO this value is not known yet"),
2301 .table_index_i32 => out.appendAssumeCapacity(.{
2302 .tag = .table_index_i32,
2303 .offset = rebased_offset,
2304 .pointee = .{ .function = .fromObjectFunctionHandlingWeak(wasm, pointee.function) },
2305 .addend = addend,
2306 }),
2307 .table_index_i64 => out.appendAssumeCapacity(.{
2308 .tag = .table_index_i64,
2309 .offset = rebased_offset,
2310 .pointee = .{ .function = .fromObjectFunctionHandlingWeak(wasm, pointee.function) },
2311 .addend = addend,
2312 }),
2313 .table_index_rel_sleb => @panic("TODO what does this reloc tag mean?"),
2314 .table_index_rel_sleb64 => @panic("TODO what does this reloc tag mean?"),
2315 .table_index_sleb => out.appendAssumeCapacity(.{
2316 .tag = .table_index_sleb,
2317 .offset = rebased_offset,
2318 .pointee = .{ .function = .fromObjectFunctionHandlingWeak(wasm, pointee.function) },
2319 .addend = addend,
2320 }),
2321 .table_index_sleb64 => out.appendAssumeCapacity(.{
2322 .tag = .table_index_sleb64,
2323 .offset = rebased_offset,
2324 .pointee = .{ .function = .fromObjectFunctionHandlingWeak(wasm, pointee.function) },
2325 .addend = addend,
2326 }),
2327
2328 .function_import_index_i32 => out.appendAssumeCapacity(.{
2329 .tag = .function_index_i32,
2330 .offset = rebased_offset,
2331 .pointee = .{ .function = .fromSymbolName(wasm, pointee.symbol_name) },
2332 .addend = addend,
2333 }),
2334 .function_import_index_leb => out.appendAssumeCapacity(.{
2335 .tag = .function_index_leb,
2336 .offset = rebased_offset,
2337 .pointee = .{ .function = .fromSymbolName(wasm, pointee.symbol_name) },
2338 .addend = addend,
2339 }),
2340 .function_import_offset_i32 => @panic("TODO this value is not known yet"),
2341 .function_import_offset_i64 => @panic("TODO this value is not known yet"),
2342 .table_import_index_i32 => out.appendAssumeCapacity(.{
2343 .tag = .table_index_i32,
2344 .offset = rebased_offset,
2345 .pointee = .{ .function = .fromSymbolName(wasm, pointee.symbol_name) },
2346 .addend = addend,
2347 }),
2348 .table_import_index_i64 => out.appendAssumeCapacity(.{
2349 .tag = .table_index_i64,
2350 .offset = rebased_offset,
2351 .pointee = .{ .function = .fromSymbolName(wasm, pointee.symbol_name) },
2352 .addend = addend,
2353 }),
2354 .table_import_index_rel_sleb => @panic("TODO what does this reloc tag mean?"),
2355 .table_import_index_rel_sleb64 => @panic("TODO what does this reloc tag mean?"),
2356 .table_import_index_sleb => out.appendAssumeCapacity(.{
2357 .tag = .table_index_sleb,
2358 .offset = rebased_offset,
2359 .pointee = .{ .function = .fromSymbolName(wasm, pointee.symbol_name) },
2360 .addend = addend,
2361 }),
2362 .table_import_index_sleb64 => out.appendAssumeCapacity(.{
2363 .tag = .table_index_sleb64,
2364 .offset = rebased_offset,
2365 .pointee = .{ .function = .fromSymbolName(wasm, pointee.symbol_name) },
2366 .addend = addend,
2367 }),
2368
2369 .global_index_i32 => out.appendAssumeCapacity(.{
2370 .tag = .global_index_i32,
2371 .offset = rebased_offset,
2372 .pointee = .{ .global = .fromObjectGlobalHandlingWeak(wasm, pointee.global) },
2373 .addend = addend,
2374 }),
2375 .global_index_leb => out.appendAssumeCapacity(.{
2376 .tag = .global_index_leb,
2377 .offset = rebased_offset,
2378 .pointee = .{ .global = .fromObjectGlobalHandlingWeak(wasm, pointee.global) },
2379 .addend = addend,
2380 }),
2381
2382 .global_import_index_i32 => out.appendAssumeCapacity(.{
2383 .tag = .global_index_i32,
2384 .offset = rebased_offset,
2385 .pointee = .{ .global = .fromSymbolName(wasm, pointee.symbol_name) },
2386 .addend = addend,
2387 }),
2388 .global_import_index_leb => out.appendAssumeCapacity(.{
2389 .tag = .global_index_leb,
2390 .offset = rebased_offset,
2391 .pointee = .{ .global = .fromSymbolName(wasm, pointee.symbol_name) },
2392 .addend = addend,
2393 }),
2394
2395 .memory_addr_i32,
2396 .memory_addr_i64,
2397 .memory_addr_leb,
2398 .memory_addr_leb64,
2399 .memory_addr_sleb,
2400 .memory_addr_sleb64,
2401 .memory_addr_tls_sleb,
2402 .memory_addr_tls_sleb64,
2403 => out.appendAssumeCapacity(.{
2404 .tag = memoryRelocationType(tag),
2405 .offset = rebased_offset,
2406 .pointee = .{ .data = .fromObjectData(wasm, pointee.data) },
2407 .addend = addend,
2408 }),
2409 .memory_addr_locrel_i32 => @panic("TODO implement relocation memory_addr_locrel_i32"),
2410 .memory_addr_rel_sleb => @panic("TODO implement relocation memory_addr_rel_sleb"),
2411 .memory_addr_rel_sleb64 => @panic("TODO implement relocation memory_addr_rel_sleb64"),
2412
2413 .memory_addr_import_i32,
2414 .memory_addr_import_i64,
2415 .memory_addr_import_leb,
2416 .memory_addr_import_leb64,
2417 .memory_addr_import_sleb,
2418 .memory_addr_import_sleb64,
2419 => out.appendAssumeCapacity(.{
2420 .tag = memoryRelocationType(tag),
2421 .offset = rebased_offset,
2422 .pointee = .{ .data = .fromSymbolName(wasm, pointee.symbol_name) },
2423 .addend = addend,
2424 }),
2425 .memory_addr_import_locrel_i32 => @panic("TODO implement relocation memory_addr_import_locrel_i32"),
2426 .memory_addr_import_rel_sleb => @panic("TODO implement relocation memory_addr_import_rel_sleb"),
2427 .memory_addr_import_rel_sleb64 => @panic("TODO implement memory_addr_import_rel_sleb64"),
2428 .memory_addr_import_tls_sleb => @panic("TODO"),
2429 .memory_addr_import_tls_sleb64 => @panic("TODO"),
2430
2431 .section_offset_i32 => @panic("TODO this value is not known yet"),
2432
2433 .table_number_leb => out.appendAssumeCapacity(.{
2434 .tag = .table_number_leb,
2435 .offset = rebased_offset,
2436 .pointee = .{ .table = .fromObjectTable(wasm, pointee.table) },
2437 .addend = addend,
2438 }),
2439 .table_import_number_leb => out.appendAssumeCapacity(.{
2440 .tag = .table_number_leb,
2441 .offset = rebased_offset,
2442 .pointee = .{ .table = .fromSymbolName(wasm, pointee.symbol_name) },
2443 .addend = addend,
2444 }),
2445
2446 .type_index_leb => out.appendAssumeCapacity(.{
2447 .tag = .type_index_leb,
2448 .offset = rebased_offset,
2449 .pointee = .{ .type_index = .fromTypeIndex(pointee.type_index, &wasm.flush_buffer) },
2450 .addend = addend,
2451 }),
2452 }
2453 }
2454}
2455
2456fn memoryRelocationType(tag: Wasm.ObjectRelocation.Tag) Object.RelocationType {
2457 return switch (tag) {
2458 .memory_addr_i32, .memory_addr_import_i32 => .memory_addr_i32,
2459 .memory_addr_i64, .memory_addr_import_i64 => .memory_addr_i64,
2460 .memory_addr_leb, .memory_addr_import_leb => .memory_addr_leb,
2461 .memory_addr_leb64, .memory_addr_import_leb64 => .memory_addr_leb64,
2462 .memory_addr_locrel_i32, .memory_addr_import_locrel_i32 => .memory_addr_locrel_i32,
2463 .memory_addr_rel_sleb, .memory_addr_import_rel_sleb => .memory_addr_rel_sleb,
2464 .memory_addr_rel_sleb64, .memory_addr_import_rel_sleb64 => .memory_addr_rel_sleb64,
2465 .memory_addr_sleb, .memory_addr_import_sleb => .memory_addr_sleb,
2466 .memory_addr_sleb64, .memory_addr_import_sleb64 => .memory_addr_sleb64,
2467 .memory_addr_tls_sleb, .memory_addr_import_tls_sleb => .memory_addr_tls_sleb,
2468 .memory_addr_tls_sleb64, .memory_addr_import_tls_sleb64 => .memory_addr_tls_sleb64,
2469 else => unreachable,
2470 };
2471}
2472
14682473fn applyRelocs(code: []u8, code_offset: u32, relocs: Wasm.ObjectRelocation.IterableSlice, wasm: *const Wasm) void {
14692474 for (
14702475 relocs.slice.tags(wasm),
......@@ -1579,12 +2584,17 @@ const RelocAddr = struct {
15792584 fn fromSymbolName(wasm: *const Wasm, name: String, addend: i32) RelocAddr {
15802585 const flush = &wasm.flush_buffer;
15812586 if (wasm.object_data_imports.getPtr(name)) |import| {
1582 return fromDataLoc(flush, import.resolution.dataLoc(wasm), addend);
1583 } else if (wasm.data_imports.get(name)) |id| {
2587 if (import.resolution != .unresolved) {
2588 return fromDataLoc(flush, import.resolution.dataLoc(wasm), addend);
2589 }
2590 }
2591 if (flush.data_exports.get(name)) |symbol| {
2592 return fromDataLoc(flush, symbol.resolution.dataLoc(wasm), addend);
2593 }
2594 if (wasm.data_imports.get(name)) |id| {
15842595 return fromDataLoc(flush, .fromDataImportId(wasm, id), addend);
1585 } else {
1586 unreachable;
15872596 }
2597 unreachable;
15882598 }
15892599
15902600 fn fromDataLoc(flush: *const Flush, data_loc: Wasm.DataLoc, addend: i32) RelocAddr {
......@@ -1702,13 +2712,11 @@ fn emitInitMemoryFunction(
17022712 }
17032713
17042714 const segment_groups = wasm.flush_buffer.data_segment_groups.items;
1705 var prev_end: u32 = 0;
17062715 for (segment_groups, 0..) |group, segment_index| {
1707 defer prev_end = group.end_addr;
17082716 const segment = group.first_segment;
17092717 if (!segment.isPassive(wasm)) continue;
17102718
1711 const start_addr: u32 = @intCast(segment.alignment(wasm).forward(prev_end));
2719 const start_addr = wasm.flush_buffer.data_segments.get(segment).?;
17122720 const segment_size: u32 = group.end_addr - start_addr;
17132721
17142722 try binary_bytes.ensureUnusedCapacity(gpa, 6 + 6 + 1 + 5 + 6 + 6 + 1 + 6 * 2 + 1 + 1);
......@@ -2028,12 +3036,15 @@ fn appendReservedUleb32(bytes: *ArrayList(u8), val: u32) void {
20283036 };
20293037}
20303038
2031fn appendGlobal(gpa: Allocator, bytes: *ArrayList(u8), mutable: u8, val: u32) Allocator.Error!void {
2032 try bytes.ensureUnusedCapacity(gpa, 9);
2033 bytes.appendAssumeCapacity(@backingInt(std.wasm.Valtype.i32));
3039fn appendGlobal(gpa: Allocator, bytes: *ArrayList(u8), mutable: u8, val: u64, is64: bool) Allocator.Error!void {
3040 try bytes.ensureUnusedCapacity(gpa, if (is64) 14 else 9);
3041 bytes.appendAssumeCapacity(@backingInt(@as(std.wasm.Valtype, if (is64) .i64 else .i32)));
20343042 bytes.appendAssumeCapacity(mutable);
2035 bytes.appendAssumeCapacity(@backingInt(std.wasm.Opcode.i32_const));
2036 appendReservedUleb32(bytes, val);
3043 if (is64) {
3044 appendReservedI64Const(bytes, val);
3045 } else {
3046 appendReservedI32Const(bytes, @intCast(val));
3047 }
20373048 bytes.appendAssumeCapacity(@backingInt(std.wasm.Opcode.end));
20383049}
20393050
src/link/Wasm/Object.zig+2-2
......@@ -146,7 +146,7 @@ pub const Symbol = struct {
146146 pointee: Pointee,
147147
148148 /// https://github.com/WebAssembly/tool-conventions/blob/df8d737539eb8a8f446ba5eab9dc670c40dfb81e/Linking.md#symbol-table-subsection
149 const Tag = enum(u8) {
149 pub const Tag = enum(u8) {
150150 function,
151151 data,
152152 global,
......@@ -856,7 +856,7 @@ pub fn parse(
856856 start_function = @fromBackingInt(@intCast(functions_start + index));
857857 },
858858 .element => {
859 log.warn("unimplemented: element section in {f} {?s}", .{ path, archive_member_name });
859 // element section is not needed for linking, validating it serves no purpose
860860 pos = section_end;
861861 },
862862 .code => {
src/main.zig+40-54
......@@ -44,9 +44,9 @@ pub const std_options: std.Options = .{
4444 .logFn = log,
4545
4646 .log_level = switch (builtin.mode) {
47 .Debug => .debug,
48 .ReleaseSafe, .ReleaseFast => .info,
49 .ReleaseSmall => .err,
47 .debug => .debug,
48 .safe, .fast => .info,
49 .small => .err,
5050 },
5151};
5252pub const std_options_cwd = if (native_os == .wasi) wasi_cwd else null;
......@@ -158,8 +158,8 @@ pub fn log(
158158
159159const use_safe_allocator = build_options.debug_gpa or
160160 (native_os != .wasi and !builtin.link_libc and switch (builtin.mode) {
161 .Debug, .ReleaseSafe => true,
162 .ReleaseFast, .ReleaseSmall => false,
161 .debug, .safe => true,
162 .fast, .small => false,
163163 });
164164
165165var safe_allocator: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{
......@@ -359,8 +359,7 @@ fn mainArgs(
359359 .prepend_global_cache_path = true,
360360 .prepend_zig_exe_path = true,
361361 .prepend_seed = true,
362 .debug_env_var = .ZIG_DEBUG_MAKER,
363 .release_mode = .ReleaseSafe,
362 .release_mode = .safe,
364363 });
365364 },
366365 .clang, .@"-cc1", .@"-cc1as" => {
......@@ -557,10 +556,6 @@ const usage_build_generic =
557556 \\ -fno-function-sections All functions go into same section
558557 \\ -fdata-sections Places each data in a separate section
559558 \\ -fno-data-sections All data go into same section
560 \\ -fformatted-panics Enable formatted safety panics
561 \\ -fno-formatted-panics Disable formatted safety panics
562 \\ -fstructured-cfg (SPIR-V) force SPIR-V kernels to use structured control flow
563 \\ -fno-structured-cfg (SPIR-V) force SPIR-V kernels to not use structured control flow
564559 \\ -mexec-model=[value] (WASI) Execution model
565560 \\ -municode (Windows) Use wmain/wWinMain as entry point
566561 \\ --time-report Send timing diagnostics to '--listen' clients
......@@ -568,10 +563,10 @@ const usage_build_generic =
568563 \\Per-Module Compile Options:
569564 \\ -target [name] <arch><sub>-<os>-<abi> see the targets command
570565 \\ -O [mode] Choose what to optimize for
571 \\ Debug (default) Optimizations off, safety on
572 \\ ReleaseFast Optimize for performance, safety off
573 \\ ReleaseSafe Optimize for performance, safety on
574 \\ ReleaseSmall Optimize for small binary, safety off
566 \\ debug (default) Prioritize bug detection, accurate debug info, compilation speed
567 \\ fast Prioritize runtime performance. Safety checks off.
568 \\ safe Enable both safety checks and machine code optimizations
569 \\ small Prioritize small binary size. Safety checks off.
575570 \\ -ofmt=[fmt] Override target object format
576571 \\ elf Executable and Linking Format
577572 \\ c C source code
......@@ -994,7 +989,7 @@ fn buildOutputType(
994989 var minor_subsystem_version: ?u16 = null;
995990 var mingw_unicode_entry_point: bool = false;
996991 var enable_link_snapshots: bool = false;
997 var debug_compiler_runtime_libs: ?std.lang.OptimizeMode = null;
992 var debug_compiler_runtime_libs: ?std.lang.Optimize = null;
998993 var install_name: ?[]const u8 = null;
999994 var hash_style: link.File.Lld.Elf.HashStyle = .both;
1000995 var entitlements: ?[]const u8 = null;
......@@ -1200,10 +1195,6 @@ fn buildOutputType(
12001195 if (mem.eql(u8, next_arg, "--")) break;
12011196 try extra_rcflags.append(arena, next_arg);
12021197 }
1203 } else if (mem.eql(u8, arg, "-fstructured-cfg")) {
1204 mod_opts.structured_cfg = true;
1205 } else if (mem.eql(u8, arg, "-fno-structured-cfg")) {
1206 mod_opts.structured_cfg = false;
12071198 } else if (mem.eql(u8, arg, "--color")) {
12081199 const next_arg = args_iter.next() orelse {
12091200 fatal("expected [auto|on|off] after --color", .{});
......@@ -1433,7 +1424,7 @@ fn buildOutputType(
14331424 enable_link_snapshots = true;
14341425 }
14351426 } else if (mem.eql(u8, arg, "--debug-rt")) {
1436 debug_compiler_runtime_libs = .Debug;
1427 debug_compiler_runtime_libs = .debug;
14371428 } else if (mem.cutPrefix(u8, arg, "--debug-rt=")) |rest| {
14381429 debug_compiler_runtime_libs = parseOptimizeMode(rest);
14391430 } else if (mem.eql(u8, arg, "--debug-incremental")) {
......@@ -1650,12 +1641,6 @@ fn buildOutputType(
16501641 create_module.opts.debug_format = .{ .dwarf = .@"32" };
16511642 } else if (mem.eql(u8, arg, "-gdwarf64")) {
16521643 create_module.opts.debug_format = .{ .dwarf = .@"64" };
1653 } else if (mem.eql(u8, arg, "-fformatted-panics")) {
1654 // Remove this after 0.15.0 is tagged.
1655 warn("-fformatted-panics is deprecated and does nothing", .{});
1656 } else if (mem.eql(u8, arg, "-fno-formatted-panics")) {
1657 // Remove this after 0.15.0 is tagged.
1658 warn("-fno-formatted-panics is deprecated and does nothing", .{});
16591644 } else if (mem.eql(u8, arg, "-fsingle-threaded")) {
16601645 mod_opts.single_threaded = true;
16611646 } else if (mem.eql(u8, arg, "-fno-single-threaded")) {
......@@ -2162,7 +2147,7 @@ fn buildOutputType(
21622147 preprocessor_arg[0] == '-' and
21632148 preprocessor_arg[2] != '-')
21642149 {
2165 if (mem.indexOfScalar(u8, preprocessor_arg, '=')) |equals_pos| {
2150 if (mem.findScalar(u8, preprocessor_arg, '=')) |equals_pos| {
21662151 const key = preprocessor_arg[0..equals_pos];
21672152 const value = preprocessor_arg[equals_pos + 1 ..];
21682153 try preprocessor_args.append(key);
......@@ -2184,7 +2169,7 @@ fn buildOutputType(
21842169 linker_arg[0] == '-' and
21852170 linker_arg[2] != '-')
21862171 {
2187 if (mem.indexOfScalar(u8, linker_arg, '=')) |equals_pos| {
2172 if (mem.findScalar(u8, linker_arg, '=')) |equals_pos| {
21882173 const key = linker_arg[0..equals_pos];
21892174 const value = linker_arg[equals_pos + 1 ..];
21902175
......@@ -2271,18 +2256,18 @@ fn buildOutputType(
22712256 if (mem.eql(u8, level, "s") or
22722257 mem.eql(u8, level, "z"))
22732258 {
2274 mod_opts.optimize_mode = .ReleaseSmall;
2259 mod_opts.optimize_mode = .small;
22752260 } else if (mem.eql(u8, level, "1") or
22762261 mem.eql(u8, level, "2") or
22772262 mem.eql(u8, level, "3") or
22782263 mem.eql(u8, level, "4") or
22792264 mem.eql(u8, level, "fast"))
22802265 {
2281 mod_opts.optimize_mode = .ReleaseFast;
2266 mod_opts.optimize_mode = .fast;
22822267 } else if (mem.eql(u8, level, "g") or
22832268 mem.eql(u8, level, "0"))
22842269 {
2285 mod_opts.optimize_mode = .Debug;
2270 mod_opts.optimize_mode = .debug;
22862271 } else {
22872272 try cc_argv.appendSlice(arena, it.other_args);
22882273 }
......@@ -2356,9 +2341,9 @@ fn buildOutputType(
23562341 // `sanitize_c` will resolve to! So we either have to pick `off` or `full`.
23572342 //
23582343 // `full` has the potential to be problematic if `optimize_mode` turns out to
2359 // be `ReleaseFast`/`ReleaseSmall` because the user will get a slower and larger
2344 // be `fast`/`small` because the user will get a slower and larger
23602345 // binary than expected. On the other hand, if `optimize_mode` turns out to be
2361 // `Debug`/`ReleaseSafe`, `off` would mean UBSan would unexpectedly be disabled.
2346 // `debug`/`safe`, `off` would mean UBSan would unexpectedly be disabled.
23622347 //
23632348 // `off` seems very slightly less bad, so let's go with that.
23642349 mod_opts.sanitize_c = .off;
......@@ -2392,7 +2377,7 @@ fn buildOutputType(
23922377 // Handle joined args like `--dependency-file=foo.d`.
23932378 // Must be prefixed with 1 or 2 dashes.
23942379 if (it.only_arg.len >= 3 and it.only_arg[0] == '-' and it.only_arg[2] != '-') {
2395 if (mem.indexOfScalar(u8, it.only_arg, '=')) |equals_pos| {
2380 if (mem.findScalar(u8, it.only_arg, '=')) |equals_pos| {
23962381 const key = it.only_arg[0..equals_pos];
23972382 const value = it.only_arg[equals_pos + 1 ..];
23982383
......@@ -2972,8 +2957,8 @@ fn buildOutputType(
29722957 }
29732958
29742959 if (mod_opts.sanitize_c) |wsc| {
2975 if (wsc != .off and mod_opts.optimize_mode == .ReleaseFast) {
2976 mod_opts.optimize_mode = .ReleaseSafe;
2960 if (wsc != .off and mod_opts.optimize_mode == .fast) {
2961 mod_opts.optimize_mode = .safe;
29772962 }
29782963 }
29792964
......@@ -3835,11 +3820,17 @@ fn buildOutputType(
38353820
38363821 var prev_has_cflags = false;
38373822 var prev_has_rcflags = false;
3838 if (dirs.zig_lib.path) |zig_lib_path| {
3839 try test_exec_args.appendSlice(arena, &.{ "-cflags", "-I", zig_lib_path, "--" });
3840 prev_has_cflags = true;
3823 {
3824 if (dirs.zig_lib.path) |zig_lib_path| {
3825 try test_exec_args.appendSlice(arena, &.{ "-cflags", "-I", zig_lib_path, "--" });
3826 prev_has_cflags = true;
3827 }
3828 const emit_ext: Compilation.FileExt = .c;
3829 const need_lang = if (comp.emit_bin) |comp_emit_bin| Compilation.classifyFileExt(comp_emit_bin) != emit_ext else true;
3830 if (need_lang) try test_exec_args.appendSlice(arena, &.{ "-x", emit_ext.toLang() });
3831 try test_exec_args.append(arena, null);
3832 if (need_lang) try test_exec_args.appendSlice(arena, &.{ "-x", "none" });
38413833 }
3842 try test_exec_args.append(arena, null);
38433834 for (create_module.modules.keys(), create_module.modules.values()) |mod_name, mod| {
38443835 for (create_module.c_source_files.items[mod.c_source_files_start..mod.c_source_files_end]) |c_source_file| {
38453836 const cflags_len = c_source_file.extra_flags.len + c_source_file.cache_exempt_flags.len;
......@@ -4305,11 +4296,8 @@ fn serve(
43054296 const gpa = comp.gpa;
43064297 const io = comp.io;
43074298
4308 var server = try Server.init(.{
4309 .in = in,
4310 .out = out,
4311 .zig_version = build_options.version,
4312 });
4299 var server: Server = .{ .in = in, .out = out };
4300 try server.serveStringMessage(.zig_version, build_options.version);
43134301
43144302 var child_pid: ?std.process.Child.Id = null;
43154303
......@@ -4874,8 +4862,7 @@ const JitCmdOptions = struct {
48744862 capture: ?*[]u8 = null,
48754863 /// Send error bundles via std.zig.Server over stdout
48764864 server: bool = false,
4877 debug_env_var: EnvVar = .ZIG_DEBUG_CMD,
4878 release_mode: std.lang.OptimizeMode = .ReleaseFast,
4865 release_mode: std.lang.Optimize = .fast,
48794866};
48804867
48814868fn jitCmd(
......@@ -4926,11 +4913,11 @@ fn jitCmdInner(
49264913 const self_exe_path = process.executablePathAlloc(io, arena) catch |err|
49274914 fatal("unable to find self exe path: {t}", .{err});
49284915
4929 const optimize_mode: std.lang.OptimizeMode = if (options.debug_env_var.isSet(environ_map))
4930 .Debug
4916 const optimize_mode: std.lang.Optimize = if (EnvVar.ZIG_DEBUG_CMD.isSet(environ_map))
4917 .debug
49314918 else
49324919 options.release_mode;
4933 const strip = optimize_mode != .Debug;
4920 const strip = optimize_mode != .debug;
49344921 var override_lib_dir: ?[]const u8 = EnvVar.ZIG_LIB_DIR.get(environ_map);
49354922 const override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map);
49364923
......@@ -6008,9 +5995,8 @@ fn parseRcIncludes(arg: []const u8) std.zig.RcIncludes {
60085995 fatal("unsupported rc includes type: {q}", .{arg});
60095996}
60105997
6011fn parseOptimizeMode(s: []const u8) std.lang.OptimizeMode {
6012 return stringToEnum(std.lang.OptimizeMode, s) orelse
6013 fatal("unrecognized optimization mode: {q}", .{s});
5998fn parseOptimizeMode(s: []const u8) std.lang.Optimize {
5999 return std.lang.Optimize.fromString(s) orelse fatal("unrecognized optimization mode: {q}", .{s});
60146000}
60156001
60166002fn parseWasiExecModel(s: []const u8) std.lang.WasiExecModel {
src/print_targets.zig+3-3
......@@ -43,9 +43,9 @@ pub fn cmdTargets(
4343 {
4444 var root_obj = try serializer.beginStruct(.{});
4545
46 try root_obj.field("arch", meta.fieldNames(Target.Cpu.Arch), .{});
47 try root_obj.field("os", meta.fieldNames(Target.Os.Tag), .{});
48 try root_obj.field("abi", meta.fieldNames(Target.Abi), .{});
46 try root_obj.field("arch", @typeInfo(Target.Cpu.Arch).@"enum".field_names, .{});
47 try root_obj.field("os", @typeInfo(Target.Os.Tag).@"enum".field_names, .{});
48 try root_obj.field("abi", @typeInfo(Target.Abi).@"enum".field_names, .{});
4949
5050 {
5151 var libc_obj = try root_obj.beginTupleField("libc", .{});
src/target.zig+12-17
......@@ -12,7 +12,6 @@ pub const default_stack_protector_buffer_size = 4;
1212
1313pub fn canDynamicLink(target: *const std.Target) bool {
1414 return switch (target.cpu.arch) {
15 .amdgcn,
1615 .bpfeb,
1716 .bpfel,
1817 .nvptx,
......@@ -119,10 +118,6 @@ pub fn defaultSingleThreaded(target: *const std.Target) bool {
119118 .wasm32, .wasm64 => return true,
120119 else => {},
121120 }
122 switch (target.os.tag) {
123 .haiku => return true,
124 else => {},
125 }
126121 return false;
127122}
128123
......@@ -357,12 +352,12 @@ pub fn libcProvidesStackProtector(target: *const std.Target) bool {
357352
358353/// Returns true if `@returnAddress()` is supported by the target and has a
359354/// reasonably performant implementation for the requested optimization mode.
360pub fn supportsReturnAddress(target: *const std.Target, optimize: std.lang.OptimizeMode) bool {
355pub fn supportsReturnAddress(target: *const std.Target, optimize: std.lang.Optimize) bool {
361356 return switch (target.cpu.arch) {
362357 // Emscripten currently implements `emscripten_return_address()` by calling
363358 // out into JavaScript and parsing a stack trace, which introduces significant
364359 // overhead that we would prefer to avoid in release builds.
365 .wasm32, .wasm64 => target.os.tag == .emscripten and optimize == .Debug,
360 .wasm32, .wasm64 => target.os.tag == .emscripten and optimize == .debug,
366361 .bpfel, .bpfeb => false,
367362 .spirv32, .spirv64 => false,
368363 else => true,
......@@ -417,11 +412,11 @@ pub fn hasDebugInfo(target: *const std.Target) bool {
417412 };
418413}
419414
420pub fn defaultCompilerRtOptimizeMode(target: *const std.Target) std.lang.OptimizeMode {
415pub fn defaultCompilerRtOptimizeMode(target: *const std.Target) std.lang.Optimize {
421416 if (target.cpu.arch.isWasm() and target.os.tag == .freestanding) {
422 return .ReleaseSmall;
417 return .small;
423418 } else {
424 return .ReleaseFast;
419 return .fast;
425420 }
426421}
427422
......@@ -437,7 +432,7 @@ pub fn canBuildLibCompilerRt(target: *const std.Target) enum { no, yes, llvm_onl
437432 else => {},
438433 }
439434 return switch (zigBackend(target, false)) {
440 .stage2_aarch64, .stage2_x86_64 => .yes,
435 .stage2_aarch64, .stage2_wasm, .stage2_x86_64 => .yes,
441436 else => .llvm_only,
442437 };
443438}
......@@ -450,7 +445,7 @@ pub fn canBuildLibUbsanRt(target: *const std.Target) enum { no, yes, llvm_only,
450445 else => {},
451446 }
452447 return switch (zigBackend(target, false)) {
453 .stage2_wasm => .llvm_lld_only,
448 .stage2_wasm => .yes,
454449 .stage2_x86_64 => .yes,
455450 else => .llvm_only,
456451 };
......@@ -681,14 +676,14 @@ pub fn isDynamicAMDGCNFeature(target: *const std.Target, feature: std.Target.Cpu
681676 const feature_tag: std.Target.amdgcn.Feature = @fromBackingInt(@intCast(feature.index));
682677
683678 if (feature_tag == .sramecc) {
684 if (std.mem.indexOfScalar(
679 if (std.mem.findScalar(
685680 *const std.Target.Cpu.Model,
686681 sramecc_only ++ xnack_or_sramecc,
687682 target.cpu.model,
688683 )) |_| return true;
689684 }
690685 if (feature_tag == .xnack) {
691 if (std.mem.indexOfScalar(
686 if (std.mem.findScalar(
692687 *const std.Target.Cpu.Model,
693688 xnack_or_sramecc,
694689 target.cpu.model,
......@@ -876,18 +871,18 @@ pub fn libcFloatSuffix(float_bits: u16) []const u8 {
876871 32 => "f",
877872 64 => "",
878873 80 => "x", // Non-standard
879 128 => "q", // Non-standard (mimics convention in GCC libquadmath)
874 128 => "f128",
880875 else => unreachable,
881876 };
882877}
883878
884pub fn compilerRtFloatAbbrev(float_bits: u16) []const u8 {
879pub fn compilerRtFloatAbbrev(target: *const std.Target, float_bits: u16) []const u8 {
885880 return switch (float_bits) {
886881 16 => "h",
887882 32 => "s",
888883 64 => "d",
889884 80 => "x",
890 128 => "t",
885 128 => if (target.cpu.arch.isPowerPC()) "k" else "t",
891886 else => unreachable,
892887 };
893888}
src/zig_llvm.cpp+16-3
......@@ -473,19 +473,32 @@ void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) {
473473}
474474
475475bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count,
476 ZigLLVMArchiveKind archive_kind)
476 ZigLLVMArchiveKind archive_kind, size_t *err_file_index_out, char **err_msg_out)
477477{
478478 SmallVector<NewArchiveMember, 4> new_members;
479479 for (size_t i = 0; i < file_name_count; i += 1) {
480480 Expected<NewArchiveMember> new_member = NewArchiveMember::getFile(file_names[i], true);
481481 Error err = new_member.takeError();
482 if (err) return true;
482 if (err) {
483 *err_file_index_out = i;
484 const std::string msg = toString(std::move(err));
485 *err_msg_out = (char *)malloc(msg.length() + 1);
486 strcpy(*err_msg_out, msg.c_str());
487 return true;
488 }
483489 new_members.push_back(std::move(*new_member));
484490 }
485491 Error err = writeArchive(archive_name, new_members,
486492 SymtabWritingMode::NormalSymtab, static_cast<object::Archive::Kind>(archive_kind), true, false, nullptr);
487493
488 if (err) return true;
494 if (err) {
495 *err_file_index_out = file_name_count;
496 const std::string msg = toString(std::move(err));
497 *err_msg_out = (char *)malloc(msg.length() + 1);
498 strcpy(*err_msg_out, msg.c_str());
499 return true;
500 }
501
489502 return false;
490503}
491504
src/zig_llvm.h+6-1
......@@ -121,7 +121,12 @@ ZIG_EXTERN_C bool ZigLLDLinkCOFF(int argc, const char **argv, bool can_exit_earl
121121ZIG_EXTERN_C bool ZigLLDLinkELF(int argc, const char **argv, bool can_exit_early, bool disable_output);
122122ZIG_EXTERN_C bool ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early, bool disable_output);
123123
124// On error, populates `*err_file_index_out` and `*err_msg_out` and returns `true`. The caller is
125// responsible for freeing `*err_msg_out` using `free`.
126//
127// If an error occurs reading an input file, `*err_file_index_out` is set to the index of that input
128// file in `file_names`. Otherwise, `*err_file_index_out` is set to `file_name_count`.
124129ZIG_EXTERN_C bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count,
125 ZigLLVMArchiveKind archive_kind);
130 ZigLLVMArchiveKind archive_kind, size_t *err_file_index_out, char **err_msg_out);
126131
127132#endif
stage1/FuncGen.h+3-3
......@@ -52,17 +52,17 @@ static void FuncGen_free(struct FuncGen *self) {
5252}
5353
5454static void FuncGen_outdent(struct FuncGen *self, FILE *out) {
55 for (uint32_t i = 0; i < self->block_i; i += 1) fputs(" ", out);
55 for (uint32_t i = 0; i < self->block_i; i += 1) fputs(" ", out);
5656}
5757
5858static void FuncGen_indent(struct FuncGen *self, FILE *out) {
5959 FuncGen_outdent(self, out);
60 fputs(" ", out);
60 fputs(" ", out);
6161}
6262
6363static void FuncGen_cont(struct FuncGen *self, FILE *out) {
6464 FuncGen_indent(self, out);
65 fputs(" ", out);
65 fputs(" ", out);
6666}
6767
6868static uint32_t FuncGen_localAlloc(struct FuncGen *self, int8_t type) {
stage1/wasm2c.c+9-9
......@@ -518,8 +518,8 @@ int main(int argc, char **argv) {
518518 }
519519 fprintf(out,
520520 ") {\n"
521 " init();\n"
522 " %sf%" PRIu32 "(",
521 " init();\n"
522 " %sf%" PRIu32 "(",
523523 func_type->result->len > 0 ? "return " : "", idx - imports_len);
524524 for (uint32_t param_i = 0; param_i < func_type->param->len; param_i += 1) {
525525 if (param_i > 0) fputs(", ", out);
......@@ -552,7 +552,7 @@ int main(int argc, char **argv) {
552552 uint32_t segment_len = InputStream_readLeb128_u32(&in);
553553 for (uint32_t i = 0; i < segment_len; i += 1) {
554554 uint32_t func_id = InputStream_readLeb128_u32(&in);
555 fprintf(out, " t%" PRIu32 "[UINT32_C(%" PRIu32 ")] = (void (*)(void))&",
555 fprintf(out, " t%" PRIu32 "[UINT32_C(%" PRIu32 ")] = (void (*)(void))&",
556556 table_idx, offset + i);
557557 if (func_id < imports_len)
558558 fprintf(out, "%s_%s", imports[func_id].mod, imports[func_id].name);
......@@ -2260,9 +2260,9 @@ int main(int argc, char **argv) {
22602260 uint32_t len = InputStream_readLeb128_u32(&in);
22612261 fputs("static void init_data(void) {\n", out);
22622262 for (uint32_t i = 0; i < mems_len; i += 1)
2263 fprintf(out, " p%" PRIu32 " = UINT32_C(%" PRIu32 ");\n"
2264 " c%" PRIu32 " = p%" PRIu32 ";\n"
2265 " m%" PRIu32 " = calloc(c%" PRIu32 ", UINT32_C(1) << 16);\n",
2263 fprintf(out, " p%" PRIu32 " = UINT32_C(%" PRIu32 ");\n"
2264 " c%" PRIu32 " = p%" PRIu32 ";\n"
2265 " m%" PRIu32 " = calloc(c%" PRIu32 ", UINT32_C(1) << 16);\n",
22662266 i, mems[i].limits.min, i, i, i, i);
22672267 for (uint32_t segment_i = 0; segment_i < len; segment_i += 1) {
22682268 uint32_t mem_idx;
......@@ -2280,15 +2280,15 @@ int main(int argc, char **argv) {
22802280 uint32_t offset = evalExpr(&in);
22812281 uint32_t segment_len = InputStream_readLeb128_u32(&in);
22822282 fputc('\n', out);
2283 fprintf(out, " static const uint8_t s%" PRIu32 "[UINT32_C(%" PRIu32 ")] = {",
2283 fprintf(out, " static const uint8_t s%" PRIu32 "[UINT32_C(%" PRIu32 ")] = {",
22842284 segment_i, segment_len);
22852285 for (uint32_t i = 0; i < segment_len; i += 1) {
22862286 if (i % 32 == 0) fputs("\n ", out);
22872287 fprintf(out, " 0x%02hhX,", InputStream_readByte(&in));
22882288 }
22892289 fprintf(out, "\n"
2290 " };\n"
2291 " memcpy(&m%" PRIu32 "[UINT32_C(0x%" PRIX32 ")], s%" PRIu32 ", UINT32_C(%" PRIu32 "));\n",
2290 " };\n"
2291 " memcpy(&m%" PRIu32 "[UINT32_C(0x%" PRIX32 ")], s%" PRIu32 ", UINT32_C(%" PRIu32 "));\n",
22922292 mem_idx, offset, segment_i, segment_len);
22932293 }
22942294 fputs("}\n", out);
stage1/zig.h+3079-991
......@@ -166,6 +166,12 @@
166166#endif
167167#define zig_expand_has_builtin(b) zig_has_builtin(b)
168168
169#if defined(__has_feature)
170#define zig_has_feature(feature) __has_feature(feature)
171#else
172#define zig_has_feature(feature) 0
173#endif
174
169175#if defined(__has_attribute)
170176#define zig_has_attribute(attribute) __has_attribute(attribute)
171177#else
......@@ -175,9 +181,9 @@
175181#if __STDC_VERSION__ >= 201112L
176182#define zig_static_assert(cond, msg) _Static_assert(cond, msg)
177183#elif zig_has_attribute(unused)
178#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] __attribute__((unused))
184#define zig_static_assert(cond, msg) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[(cond) ? 1 : -1] __attribute__((unused))
179185#else
180#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)]
186#define zig_static_assert(cond, msg) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[(cond) ? 1 : -1]
181187#endif
182188
183189#if __STDC_VERSION__ >= 202311L
......@@ -193,10 +199,8 @@
193199#endif
194200
195201#if defined(zig_msvc)
196#define zig_const_arr
197202#define zig_callconv(c) __##c
198203#else
199#define zig_const_arr static const
200204#define zig_callconv(c) __attribute__((c))
201205#endif
202206
......@@ -267,12 +271,20 @@
267271
268272#if __STDC_VERSION__ >= 202311L
269273#define zig_align(alignment) alignas(alignment)
270#elif __STDC_VERSION__ >= 201112L
274#elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignas)
271275#define zig_align(alignment) _Alignas(alignment)
272276#else
273277#define zig_align(alignment) zig_under_align(alignment)
274278#endif
275279
280#if __STDC_VERSION__ >= 202311L
281#define zig_alignOf(Type) alignof(Type)
282#elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignof)
283#define zig_alignOf(Type) _Alignof(Type)
284#else
285#define zig_alignOf(Type) (sizeof(struct { char c; Type t; }) - sizeof(Type))
286#endif
287
276288#if zig_has_attribute(aligned) || defined(zig_tinyc)
277289#define zig_align_fn(alignment) __attribute__((aligned(alignment)))
278290#elif defined(zig_msvc)
......@@ -350,11 +362,9 @@
350362#define zig_export(symbol, name) __attribute__((alias(symbol)))
351363#else
352364#define zig_export(symbol, name) ; \
353 __asm(zig_mangle_c(name) " = " zig_mangle_c(symbol))
365 __asm("\t.globl\t" zig_mangle_c(name) "\n" zig_mangle_c(name) " = " zig_mangle_c(symbol))
354366#endif
355367
356#define zig_mangled_tentative zig_mangled
357#define zig_mangled_final zig_mangled
358368#if defined(zig_msvc)
359369#define zig_mangled(mangled, unmangled) ; \
360370 zig_export(#mangled, unmangled)
......@@ -364,7 +374,7 @@
364374#else /* zig_msvc */
365375#define zig_mangled(mangled, unmangled) __asm(zig_mangle_c(unmangled))
366376#define zig_mangled_export(mangled, unmangled, symbol) \
367 zig_mangled_final(mangled, unmangled) \
377 zig_mangled(mangled, unmangled) \
368378 zig_export(symbol, unmangled)
369379#endif /* zig_msvc */
370380
......@@ -550,6 +560,9 @@
550560#define zig_noreturn
551561#endif
552562
563#define zig_has_always 1
564#define zig_has_never 0
565
553566#define zig_compiler_rt_abbrev_uint32_t si
554567#define zig_compiler_rt_abbrev_int32_t si
555568#define zig_compiler_rt_abbrev_uint64_t di
......@@ -560,7 +573,11 @@
560573#define zig_compiler_rt_abbrev_zig_f32 sf
561574#define zig_compiler_rt_abbrev_zig_f64 df
562575#define zig_compiler_rt_abbrev_zig_f80 xf
576#ifdef zig_powerpc
577#define zig_compiler_rt_abbrev_zig_f128 kf
578#else
563579#define zig_compiler_rt_abbrev_zig_f128 tf
580#endif
564581
565582zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t);
566583zig_extern void *memset (void *, int, size_t);
......@@ -645,16 +662,6 @@ typedef signed long long int16_t;
645662#define INT16_MAX ( INT16_C(0x7FFF))
646663#define UINT16_MAX ( INT16_C(0xFFFF))
647664
648#if defined(zig_ez80)
649typedef unsigned int uint24_t;
650typedef signed int int24_t;
651#define INT24_C(c) c
652#define UINT24_C(c) c##U
653#endif
654#define INT24_MIN (~INT24_C(0x7FFF))
655#define INT24_MAX ( INT24_C(0x7FFF))
656#define UINT24_MAX ( INT24_C(0xFFFF))
657
658665#if SCHAR_MIN == ~0x7FFFFFFF && SCHAR_MAX == 0x7FFFFFFF && UCHAR_MAX == 0xFFFFFFFF
659666typedef unsigned char uint32_t;
660667typedef signed char int32_t;
......@@ -685,17 +692,6 @@ typedef signed long long int32_t;
685692#define INT32_MAX ( INT32_C(0x7FFFFFFF))
686693#define UINT32_MAX ( INT32_C(0xFFFFFFFF))
687694
688#if defined(zig_ez80)
689typedef unsigned __int48 uint48_t;
690typedef signed __int48 int48_t;
691#define INT48_C(c) c
692/* no suffix */
693#define UINT48_C(c) ((uint48_t)(c))
694#endif
695#define INT48_MIN (~INT48_C(0x7FFFFFFFFFFF))
696#define INT48_MAX ( INT48_C(0x7FFFFFFFFFFF))
697#define UINT48_MAX ( INT48_C(0xFFFFFFFFFFFF))
698
699695#if SCHAR_MIN == ~0x7FFFFFFFFFFFFFFF && SCHAR_MAX == 0x7FFFFFFFFFFFFFFF && UCHAR_MAX == 0xFFFFFFFFFFFFFFFF
700696typedef unsigned char uint64_t;
701697typedef signed char int64_t;
......@@ -726,6 +722,27 @@ typedef signed long long int64_t;
726722#define INT64_MAX ( INT64_C(0x7FFFFFFFFFFFFFFF))
727723#define UINT64_MAX ( INT64_C(0xFFFFFFFFFFFFFFFF))
728724
725#if defined(zig_ez80)
726
727typedef unsigned int uint24_t;
728typedef signed int int24_t;
729#define INT24_C(c) c
730#define UINT24_C(c) c##U
731#define INT24_MIN (~INT24_C(0x7FFF))
732#define INT24_MAX ( INT24_C(0x7FFF))
733#define UINT24_MAX ( INT24_C(0xFFFF))
734
735typedef unsigned __int48 uint48_t;
736typedef signed __int48 int48_t;
737#define INT48_C(c) c
738/* no suffix */
739#define UINT48_C(c) ((uint48_t)(c))
740#define INT48_MIN (~INT48_C(0x7FFFFFFFFFFF))
741#define INT48_MAX ( INT48_C(0x7FFFFFFFFFFF))
742#define UINT48_MAX ( INT48_C(0xFFFFFFFFFFFF))
743
744#endif
745
729746typedef size_t uintptr_t;
730747typedef ptrdiff_t intptr_t;
731748
......@@ -739,23 +756,145 @@ typedef ptrdiff_t intptr_t;
739756#define zig_maxInt_i16 INT16_MAX
740757#define zig_minInt_u16 UINT16_C(0)
741758#define zig_maxInt_u16 UINT16_MAX
742#define zig_minInt_i24 INT24_MIN
743#define zig_maxInt_i24 INT24_MAX
744#define zig_minInt_u24 UINT24_C(0)
745#define zig_maxInt_u24 UINT24_MAX
746759#define zig_minInt_i32 INT32_MIN
747760#define zig_maxInt_i32 INT32_MAX
748761#define zig_minInt_u32 UINT32_C(0)
749762#define zig_maxInt_u32 UINT32_MAX
750#define zig_minInt_i48 INT48_MIN
751#define zig_maxInt_i48 INT48_MAX
752#define zig_minInt_u48 UINT48_C(0)
753#define zig_maxInt_u48 UINT48_MAX
754763#define zig_minInt_i64 INT64_MIN
755764#define zig_maxInt_i64 INT64_MAX
756765#define zig_minInt_u64 UINT64_C(0)
757766#define zig_maxInt_u64 UINT64_MAX
758767
768// zig_promoted_T implements C integral promotions except with signedness preserved, which
769// allows wrapping operations to avoid the ub that would be caused by the normal promotion.
770
771#if INT8_MAX <= INT_MAX
772typedef unsigned int zig_promoted_i8;
773#elif INT8_MAX <= LONG_MAX
774typedef unsigned long zig_promoted_i8;
775#elif INT8_MAX <= LLONG_MAX
776typedef unsigned long long zig_promoted_i8;
777#else
778typedef int8_t zig_promoted_i8;
779#endif
780#if UINT8_MAX <= UINT_MAX
781typedef unsigned int zig_promoted_u8;
782#elif UINT8_MAX <= ULONG_MAX
783typedef unsigned long zig_promoted_u8;
784#elif UINT8_MAX <= ULLONG_MAX
785typedef unsigned long long zig_promoted_u8;
786#else
787typedef uint8_t zig_promoted_u8;
788#endif
789
790#if INT16_MAX <= INT_MAX
791typedef unsigned int zig_promoted_i16;
792#elif INT16_MAX <= LONG_MAX
793typedef unsigned long zig_promoted_i16;
794#elif INT16_MAX <= LLONG_MAX
795typedef unsigned long long zig_promoted_i16;
796#else
797typedef int16_t zig_promoted_i16;
798#endif
799#if UINT16_MAX <= UINT_MAX
800typedef unsigned int zig_promoted_u16;
801#elif UINT16_MAX <= ULONG_MAX
802typedef unsigned long zig_promoted_u16;
803#elif UINT16_MAX <= ULLONG_MAX
804typedef unsigned long long zig_promoted_u16;
805#else
806typedef uint16_t zig_promoted_u16;
807#endif
808
809#if INT32_MAX <= INT_MAX
810typedef unsigned int zig_promoted_i32;
811#elif INT32_MAX <= LONG_MAX
812typedef unsigned long zig_promoted_i32;
813#elif INT32_MAX <= LLONG_MAX
814typedef unsigned long long zig_promoted_i32;
815#else
816typedef int32_t zig_promoted_i32;
817#endif
818#if UINT32_MAX <= UINT_MAX
819typedef unsigned int zig_promoted_u32;
820#elif UINT32_MAX <= ULONG_MAX
821typedef unsigned long zig_promoted_u32;
822#elif UINT32_MAX <= ULLONG_MAX
823typedef unsigned long long zig_promoted_u32;
824#else
825typedef uint32_t zig_promoted_u32;
826#endif
827
828#if INT64_MAX <= INT_MAX
829typedef unsigned int zig_promoted_i64;
830#elif INT64_MAX <= LONG_MAX
831typedef unsigned long zig_promoted_i64;
832#elif INT64_MAX <= LLONG_MAX
833typedef unsigned long long zig_promoted_i64;
834#else
835typedef int64_t zig_promoted_i64;
836#endif
837#if UINT64_MAX <= UINT_MAX
838typedef unsigned int zig_promoted_u64;
839#elif UINT64_MAX <= ULONG_MAX
840typedef unsigned long zig_promoted_u64;
841#elif UINT64_MAX <= ULLONG_MAX
842typedef unsigned long long zig_promoted_u64;
843#else
844typedef uint64_t zig_promoted_u64;
845#endif
846
847#ifdef zig_ez80
848
849#define zig_minInt_i24 INT24_MIN
850#define zig_maxInt_i24 INT24_MAX
851#define zig_minInt_u24 UINT24_C(0)
852#define zig_maxInt_u24 UINT24_MAX
853#define zig_minInt_i48 INT48_MIN
854#define zig_maxInt_i48 INT48_MAX
855#define zig_minInt_u48 UINT48_C(0)
856#define zig_maxInt_u48 UINT48_MAX
857
858#if INT24_MAX <= INT_MAX
859typedef unsigned int zig_promoted_i24;
860#elif INT24_MAX <= LONG_MAX
861typedef unsigned long zig_promoted_i24;
862#elif INT24_MAX <= LLONG_MAX
863typedef unsigned long long zig_promoted_i24;
864#else
865typedef int24_t zig_promoted_i24;
866#endif
867#if UINT24_MAX <= UINT_MAX
868typedef unsigned int zig_promoted_u24;
869#elif UINT24_MAX <= ULONG_MAX
870typedef unsigned long zig_promoted_u24;
871#elif UINT24_MAX <= ULLONG_MAX
872typedef unsigned long long zig_promoted_u24;
873#else
874typedef uint24_t zig_promoted_u24;
875#endif
876
877#if INT48_MAX <= INT_MAX
878typedef unsigned int zig_promoted_i48;
879#elif INT48_MAX <= LONG_MAX
880typedef unsigned long zig_promoted_i48;
881#elif INT48_MAX <= LLONG_MAX
882typedef unsigned long long zig_promoted_i48;
883#else
884typedef int48_t zig_promoted_i48;
885#endif
886#if UINT48_MAX <= UINT_MAX
887typedef unsigned int zig_promoted_u48;
888#elif UINT48_MAX <= ULONG_MAX
889typedef unsigned long zig_promoted_u48;
890#elif UINT48_MAX <= ULLONG_MAX
891typedef unsigned long long zig_promoted_u48;
892#else
893typedef uint48_t zig_promoted_u48;
894#endif
895
896#endif
897
759898#define zig_intLimit(s, w, limit, bits) zig_shr_##s##w(zig_##limit##Int_##s##w, w - (bits))
760899#define zig_minInt_i(w, bits) zig_intLimit(i, w, min, bits)
761900#define zig_maxInt_i(w, bits) zig_intLimit(i, w, max, bits)
......@@ -770,7 +909,33 @@ typedef ptrdiff_t intptr_t;
770909 zig_operator(Type, Type, operation, operator)
771910#define zig_shift_operator(Type, operation, operator) \
772911 zig_operator(Type, uint8_t, operation, operator)
773#define zig_int_helpers(w, PromotedUnsigned) \
912
913#define zig_int_casts_common(bw, sw) \
914 static inline uint##bw##_t zig_u##bw##_intCast_u##sw(uint##sw##_t arg) { \
915 return arg; \
916 } \
917\
918 static inline uint##bw##_t zig_u##bw##_intCast_i##sw(int##sw##_t arg) { \
919 return (uint##bw##_t)arg; \
920 } \
921\
922 static inline int##bw##_t zig_i##bw##_intCast_u##sw(uint##sw##_t arg) { \
923 return arg; \
924 } \
925\
926 static inline int##bw##_t zig_i##bw##_intCast_i##sw(int##sw##_t arg) { \
927 return arg; \
928 } \
929\
930 static inline uint##sw##_t zig_u##sw##_truncate_u##bw(uint##bw##_t arg, uint8_t bits) { \
931 return (uint##sw##_t)arg & zig_maxInt_u(sw, bits); \
932 } \
933\
934 static inline int##sw##_t zig_i##sw##_truncate_i##bw(int##bw##_t arg, uint8_t bits) { \
935 return ((uint##sw##_t)arg & UINT##sw##_C(1) << (bits - UINT8_C(1))) != UINT##sw##_C(0) \
936 ? (int##sw##_t)arg | zig_minInt_i(sw, bits) : (int##sw##_t)arg & zig_maxInt_i(sw, bits); \
937 }
938#define zig_int_operators(w) \
774939 zig_basic_operator(uint##w##_t, and_u##w, &) \
775940 zig_basic_operator( int##w##_t, and_i##w, &) \
776941 zig_basic_operator(uint##w##_t, or_u##w, |) \
......@@ -786,44 +951,48 @@ typedef ptrdiff_t intptr_t;
786951 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \
787952 } \
788953\
789 static inline uint##w##_t zig_not_u##w(uint##w##_t val, uint8_t bits) { \
790 return val ^ zig_maxInt_u(w, bits); \
954 static inline uint##w##_t zig_not_u##w(uint##w##_t arg, uint8_t bits) { \
955 return arg ^ zig_maxInt_u(w, bits); \
791956 } \
792957\
793 static inline int##w##_t zig_not_i##w(int##w##_t val, uint8_t bits) { \
958 static inline int##w##_t zig_not_i##w(int##w##_t arg, uint8_t bits) { \
794959 (void)bits; \
795 return ~val; \
960 return ~arg; \
796961 } \
797962\
798 static inline uint##w##_t zig_wrap_u##w(uint##w##_t val, uint8_t bits) { \
799 return val & zig_maxInt_u(w, bits); \
963 zig_basic_operator(uint##w##_t, divFloor_u##w, /) \
964\
965 static inline int##w##_t zig_divFloor_i##w(int##w##_t lhs, int##w##_t rhs) { \
966 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)); \
800967 } \
801968\
802 static inline int##w##_t zig_wrap_i##w(int##w##_t val, uint8_t bits) { \
803 return (val & UINT##w##_C(1) << (bits - UINT8_C(1))) != 0 \
804 ? val | zig_minInt_i(w, bits) : val & zig_maxInt_i(w, bits); \
969 static inline uint##w##_t zig_divCeil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \
970 return lhs / rhs + (lhs % rhs != UINT##w##_C(0) ? UINT##w##_C(1) : UINT##w##_C(0)); \
805971 } \
806972\
807 static inline uint##w##_t zig_abs_i##w(int##w##_t val) { \
808 return (val < 0) ? -(uint##w##_t)val : (uint##w##_t)val; \
973 static inline int##w##_t zig_divCeil_i##w(int##w##_t lhs, int##w##_t rhs) { \
974 return lhs / rhs + (lhs % rhs != INT##w##_C(0) \
975 ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) + INT##w##_C(1) : INT##w##_C(0)); \
809976 } \
810977\
811 zig_basic_operator(uint##w##_t, div_floor_u##w, /) \
978 zig_basic_operator(uint##w##_t, mod_u##w, %) \
979 zig_int_casts_common(w, w) \
812980\
813 static inline int##w##_t zig_div_floor_i##w(int##w##_t lhs, int##w##_t rhs) { \
814 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)); \
981 static inline uint##w##_t zig_u##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \
982 return zig_u##w##_truncate_u##w(arg, bits); \
815983 } \
816984\
817 static inline uint##w##_t zig_div_ceil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \
818 return lhs / rhs + (lhs % rhs != UINT##w##_C(0) ? UINT##w##_C(1) : UINT##w##_C(0)); \
985 static inline uint##w##_t zig_u##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \
986 return zig_u##w##_bitCast_u##w((uint##w##_t)arg, bits); \
819987 } \
820988\
821 static inline int##w##_t zig_div_ceil_i##w(int##w##_t lhs, int##w##_t rhs) { \
822 return lhs / rhs + (lhs % rhs != INT##w##_C(0) \
823 ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) + INT##w##_C(1) : INT##w##_C(0)); \
989 static inline int##w##_t zig_i##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \
990 return zig_i##w##_truncate_i##w(arg, bits); \
824991 } \
825992\
826 zig_basic_operator(uint##w##_t, mod_u##w, %) \
993 static inline int##w##_t zig_i##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \
994 return zig_i##w##_bitCast_i##w((int##w##_t)arg, bits); \
995 } \
827996\
828997 static inline int##w##_t zig_mod_i##w(int##w##_t lhs, int##w##_t rhs) { \
829998 int##w##_t rem = lhs % rhs; \
......@@ -831,100 +1000,102 @@ typedef ptrdiff_t intptr_t;
8311000 } \
8321001\
8331002 static inline uint##w##_t zig_shlw_u##w(uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \
834 return zig_wrap_u##w(zig_shl_u##w(lhs, rhs), bits); \
1003 return zig_u##w##_truncate_u##w(zig_shl_u##w(lhs, rhs), bits); \
8351004 } \
8361005\
8371006 static inline int##w##_t zig_shlw_i##w(int##w##_t lhs, uint8_t rhs, uint8_t bits) { \
838 return zig_wrap_i##w((int##w##_t)zig_shl_u##w((uint##w##_t)lhs, rhs), bits); \
1007 return zig_i##w##_bitCast_u##w(zig_shl_u##w(zig_u##w##_bitCast_i##w(lhs, bits), rhs), bits); \
8391008 } \
8401009\
8411010 static inline uint##w##_t zig_addw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
842 return zig_wrap_u##w(lhs + rhs, bits); \
1011 return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs + rhs, bits); \
8431012 } \
8441013\
8451014 static inline int##w##_t zig_addw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
846 return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs + (uint##w##_t)rhs), bits); \
1015 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); \
8471016 } \
8481017\
8491018 static inline uint##w##_t zig_subw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
850 return zig_wrap_u##w(lhs - rhs, bits); \
1019 return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs - rhs, bits); \
8511020 } \
8521021\
8531022 static inline int##w##_t zig_subw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
854 return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs - (uint##w##_t)rhs), bits); \
1023 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); \
8551024 } \
8561025\
8571026 static inline uint##w##_t zig_mulw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
858 return zig_wrap_u##w((PromotedUnsigned)lhs * rhs, bits); \
1027 return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs * rhs, bits); \
8591028 } \
8601029\
8611030 static inline int##w##_t zig_mulw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
862 return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs * (uint##w##_t)rhs), bits); \
1031 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); \
1032 } \
1033\
1034 static inline uint##w##_t zig_abs_i##w(int##w##_t arg) { \
1035 int##w##_t tmp = zig_shr_i##w(arg, UINT8_C(w) - UINT8_C(1)); \
1036 return zig_u##w##_bitCast_i##w(zig_subw_i##w(zig_xor_i##w(arg, tmp), tmp, UINT8_C(w)), UINT8_C(w)); \
1037 } \
1038\
1039 static inline uint##w##_t zig_min_u##w(uint##w##_t lhs, uint##w##_t rhs) { \
1040 return lhs < rhs ? lhs : rhs; \
1041 } \
1042\
1043 static inline int##w##_t zig_min_i##w(int##w##_t lhs, int##w##_t rhs) { \
1044 return lhs < rhs ? lhs : rhs; \
1045 } \
1046\
1047 static inline uint##w##_t zig_max_u##w(uint##w##_t lhs, uint##w##_t rhs) { \
1048 return lhs >= rhs ? lhs : rhs; \
1049 } \
1050\
1051 static inline int##w##_t zig_max_i##w(int##w##_t lhs, int##w##_t rhs) { \
1052 return lhs >= rhs ? lhs : rhs; \
8631053 }
864#if UINT8_MAX <= UINT_MAX
865zig_int_helpers(8, unsigned int)
866#elif UINT8_MAX <= ULONG_MAX
867zig_int_helpers(8, unsigned long)
868#elif UINT8_MAX <= ULLONG_MAX
869zig_int_helpers(8, unsigned long long)
870#else
871zig_int_helpers(8, uint8_t)
872#endif
873#if UINT16_MAX <= UINT_MAX
874zig_int_helpers(16, unsigned int)
875#elif UINT16_MAX <= ULONG_MAX
876zig_int_helpers(16, unsigned long)
877#elif UINT16_MAX <= ULLONG_MAX
878zig_int_helpers(16, unsigned long long)
879#else
880zig_int_helpers(16, uint16_t)
881#endif
882#if defined(zig_ez80)
883#if UINT24_MAX <= UINT_MAX
884zig_int_helpers(24, unsigned int)
885#elif UINT24_MAX <= ULONG_MAX
886zig_int_helpers(24, unsigned long)
887#elif UINT24_MAX <= ULLONG_MAX
888zig_int_helpers(24, unsigned long long)
889#else
890zig_int_helpers(24, uint24_t)
891#endif
892#endif
893#if UINT32_MAX <= UINT_MAX
894zig_int_helpers(32, unsigned int)
895#elif UINT32_MAX <= ULONG_MAX
896zig_int_helpers(32, unsigned long)
897#elif UINT32_MAX <= ULLONG_MAX
898zig_int_helpers(32, unsigned long long)
899#else
900zig_int_helpers(32, uint32_t)
901#endif
902#if defined(zig_ez80)
903#if UINT24_MAX <= UINT_MAX
904zig_int_helpers(48, unsigned int)
905#elif UINT24_MAX <= ULONG_MAX
906zig_int_helpers(48, unsigned long)
907#elif UINT24_MAX <= ULLONG_MAX
908zig_int_helpers(48, unsigned long long)
909#else
910zig_int_helpers(48, uint48_t)
911#endif
912#endif
913#if UINT64_MAX <= UINT_MAX
914zig_int_helpers(64, unsigned int)
915#elif UINT64_MAX <= ULONG_MAX
916zig_int_helpers(64, unsigned long)
917#elif UINT64_MAX <= ULLONG_MAX
918zig_int_helpers(64, unsigned long long)
919#else
920zig_int_helpers(64, uint64_t)
1054zig_int_operators(8)
1055zig_int_operators(16)
1056zig_int_operators(32)
1057zig_int_operators(64)
1058#ifdef zig_ez80
1059zig_int_operators(24)
1060zig_int_operators(48)
1061#endif
1062
1063#define zig_int_casts(bw, sw) \
1064 static inline uint##sw##_t zig_u##sw##_intCast_u##bw(uint##bw##_t arg) { \
1065 return (uint##sw##_t)arg; \
1066 } \
1067\
1068 static inline uint##sw##_t zig_u##sw##_intCast_i##bw(int##bw##_t arg) { \
1069 return (uint##sw##_t)arg; \
1070 } \
1071\
1072 static inline int##sw##_t zig_i##sw##_intCast_u##bw(uint##bw##_t arg) { \
1073 return (int##sw##_t)arg; \
1074 } \
1075\
1076 static inline int##sw##_t zig_i##sw##_intCast_i##bw(int##bw##_t arg) { \
1077 return (int##sw##_t)arg; \
1078 } \
1079\
1080 zig_int_casts_common(bw, sw)
1081zig_int_casts(16, 8)
1082zig_int_casts(32, 8)
1083zig_int_casts(64, 8)
1084zig_int_casts(32, 16)
1085zig_int_casts(64, 16)
1086zig_int_casts(64, 32)
1087#ifdef zig_ez80
1088zig_int_casts(32, 24)
1089zig_int_casts(48, 24)
1090zig_int_casts(64, 24)
1091zig_int_casts(64, 48)
9211092#endif
9221093
9231094static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
9241095#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9251096 uint32_t full_res;
9261097 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
927 *res = zig_wrap_u32(full_res, bits);
1098 *res = zig_u32_truncate_u32(full_res, bits);
9281099 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
9291100#else
9301101 *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
9361107#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9371108 int32_t full_res;
9381109 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1110 *res = zig_i32_truncate_i32(full_res, bits);
1111 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
9391112#else
940 int32_t full_res = (int32_t)((uint32_t)lhs + (uint32_t)rhs);
941 bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0;
1113 *res = zig_addw_i32(lhs, rhs, bits);
1114 return ((*res ^ lhs) & (*res ^ rhs)) < INT32_C(0);
9421115#endif
943 *res = zig_wrap_i32(full_res, bits);
944 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
9451116}
9461117
9471118static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
9481119#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9491120 uint64_t full_res;
9501121 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
951 *res = zig_wrap_u64(full_res, bits);
1122 *res = zig_u64_truncate_u64(full_res, bits);
9521123 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
9531124#else
9541125 *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
9601131#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9611132 int64_t full_res;
9621133 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1134 *res = zig_i64_truncate_i64(full_res, bits);
1135 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
9631136#else
964 int64_t full_res = (int64_t)((uint64_t)lhs + (uint64_t)rhs);
965 bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0;
1137 *res = zig_addw_i64(lhs, rhs, bits);
1138 return ((*res ^ lhs) & (*res ^ rhs)) < INT64_C(0);
9661139#endif
967 *res = zig_wrap_i64(full_res, bits);
968 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
9691140}
9701141
9711142static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
9721143#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9731144 uint8_t full_res;
9741145 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
975 *res = zig_wrap_u8(full_res, bits);
1146 *res = zig_u8_truncate_u8(full_res, bits);
9761147 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
9771148#else
9781149 uint32_t full_res;
9791150 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
980 *res = (uint8_t)full_res;
1151 *res = zig_u8_intCast_u32(full_res);
9811152 return overflow;
9821153#endif
9831154}
......@@ -986,12 +1157,12 @@ static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
9861157#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9871158 int8_t full_res;
9881159 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
989 *res = zig_wrap_i8(full_res, bits);
1160 *res = zig_i8_truncate_i8(full_res, bits);
9901161 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
9911162#else
9921163 int32_t full_res;
9931164 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
994 *res = (int8_t)full_res;
1165 *res = zig_i8_intCast_i32(full_res);
9951166 return overflow;
9961167#endif
9971168}
......@@ -1000,12 +1171,12 @@ static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
10001171#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10011172 uint16_t full_res;
10021173 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1003 *res = zig_wrap_u16(full_res, bits);
1174 *res = zig_u16_truncate_u16(full_res, bits);
10041175 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
10051176#else
10061177 uint32_t full_res;
10071178 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
1008 *res = (uint16_t)full_res;
1179 *res = zig_u16_intCast_u32(full_res);
10091180 return overflow;
10101181#endif
10111182}
......@@ -1014,27 +1185,28 @@ static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
10141185#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10151186 int16_t full_res;
10161187 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1017 *res = zig_wrap_i16(full_res, bits);
1188 *res = zig_i16_truncate_i16(full_res, bits);
10181189 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
10191190#else
10201191 int32_t full_res;
10211192 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
1022 *res = (int16_t)full_res;
1193 *res = zig_i16_intCast_i32(full_res);
10231194 return overflow;
10241195#endif
10251196}
10261197
10271198#if defined(zig_ez80)
1199
10281200static inline bool zig_addo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {
10291201#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10301202 uint24_t full_res;
10311203 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1032 *res = zig_wrap_u24(full_res, bits);
1204 *res = zig_u24_truncate_u24(full_res, bits);
10331205 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);
10341206#else
10351207 uint32_t full_res;
10361208 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
1037 *res = (uint24_t)full_res;
1209 *res = zig_u24_intCast_u32(full_res);
10381210 return overflow;
10391211#endif
10401212}
......@@ -1043,28 +1215,26 @@ static inline bool zig_addo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t
10431215#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10441216 int24_t full_res;
10451217 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1046 *res = zig_wrap_i24(full_res, bits);
1218 *res = zig_i24_truncate_i24(full_res, bits);
10471219 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);
10481220#else
10491221 int32_t full_res;
10501222 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
1051 *res = (int24_t)full_res;
1223 *res = zig_i24_intCast_i32(full_res);
10521224 return overflow;
10531225#endif
10541226}
1055#endif
10561227
1057#if defined(zig_ez80)
10581228static inline bool zig_addo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {
10591229#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10601230 uint48_t full_res;
10611231 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1062 *res = zig_wrap_u48(full_res, bits);
1232 *res = zig_u48_truncate_u48(full_res, bits);
10631233 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);
10641234#else
10651235 uint64_t full_res;
10661236 bool overflow = zig_addo_u64(&full_res, lhs, rhs, bits);
1067 *res = (uint48_t)full_res;
1237 *res = zig_u48_intCast_u64(full_res);
10681238 return overflow;
10691239#endif
10701240}
......@@ -1073,22 +1243,23 @@ static inline bool zig_addo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
10731243#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10741244 int48_t full_res;
10751245 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1076 *res = zig_wrap_i48(full_res, bits);
1246 *res = zig_i48_truncate_i48(full_res, bits);
10771247 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);
10781248#else
10791249 int64_t full_res;
10801250 bool overflow = zig_addo_i64(&full_res, lhs, rhs, bits);
1081 *res = (int48_t)full_res;
1251 *res = zig_i48_intCast_i64(full_res);
10821252 return overflow;
10831253#endif
10841254}
1255
10851256#endif
10861257
10871258static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
10881259#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
10891260 uint32_t full_res;
10901261 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1091 *res = zig_wrap_u32(full_res, bits);
1262 *res = zig_u32_truncate_u32(full_res, bits);
10921263 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
10931264#else
10941265 *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
11001271#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11011272 int32_t full_res;
11021273 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1274 *res = zig_i32_truncate_i32(full_res, bits);
1275 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
11031276#else
1104 int32_t full_res = (int32_t)((uint32_t)lhs - (uint32_t)rhs);
1105 bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0;
1277 *res = zig_subw_i32(lhs, rhs, bits);
1278 return ((lhs ^ rhs) & (*res ^ lhs)) < INT32_C(0);
11061279#endif
1107 *res = zig_wrap_i32(full_res, bits);
1108 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
11091280}
11101281
1111
11121282static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
11131283#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11141284 uint64_t full_res;
11151285 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1116 *res = zig_wrap_u64(full_res, bits);
1286 *res = zig_u64_truncate_u64(full_res, bits);
11171287 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
11181288#else
11191289 *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
11251295#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11261296 int64_t full_res;
11271297 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1298 *res = zig_i64_truncate_i64(full_res, bits);
1299 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
11281300#else
1129 int64_t full_res = (int64_t)((uint64_t)lhs - (uint64_t)rhs);
1130 bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0;
1301 *res = zig_subw_i64(lhs, rhs, bits);
1302 return ((lhs ^ rhs) & (*res ^ lhs)) < INT64_C(0);
11311303#endif
1132 *res = zig_wrap_i64(full_res, bits);
1133 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
11341304}
11351305
11361306static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
11371307#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11381308 uint8_t full_res;
11391309 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1140 *res = zig_wrap_u8(full_res, bits);
1310 *res = zig_u8_truncate_u8(full_res, bits);
11411311 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
11421312#else
11431313 uint32_t full_res;
11441314 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
1145 *res = (uint8_t)full_res;
1315 *res = zig_u8_intCast_u32(full_res);
11461316 return overflow;
11471317#endif
11481318}
......@@ -1151,12 +1321,12 @@ static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
11511321#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11521322 int8_t full_res;
11531323 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1154 *res = zig_wrap_i8(full_res, bits);
1324 *res = zig_i8_truncate_i8(full_res, bits);
11551325 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
11561326#else
11571327 int32_t full_res;
11581328 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
1159 *res = (int8_t)full_res;
1329 *res = zig_i8_intCast_i32(full_res);
11601330 return overflow;
11611331#endif
11621332}
......@@ -1165,12 +1335,12 @@ static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
11651335#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11661336 uint16_t full_res;
11671337 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1168 *res = zig_wrap_u16(full_res, bits);
1338 *res = zig_u16_truncate_u16(full_res, bits);
11691339 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
11701340#else
11711341 uint32_t full_res;
11721342 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
1173 *res = (uint16_t)full_res;
1343 *res = zig_u16_intCast_u32(full_res);
11741344 return overflow;
11751345#endif
11761346}
......@@ -1179,27 +1349,28 @@ static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
11791349#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11801350 int16_t full_res;
11811351 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1182 *res = zig_wrap_i16(full_res, bits);
1352 *res = zig_i16_truncate_i16(full_res, bits);
11831353 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
11841354#else
11851355 int32_t full_res;
11861356 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
1187 *res = (int16_t)full_res;
1357 *res = zig_i16_intCast_i32(full_res);
11881358 return overflow;
11891359#endif
11901360}
11911361
11921362#if defined(zig_ez80)
1363
11931364static inline bool zig_subo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {
11941365#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11951366 uint24_t full_res;
11961367 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1197 *res = zig_wrap_u24(full_res, bits);
1368 *res = zig_u24_truncate_u24(full_res, bits);
11981369 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);
11991370#else
12001371 uint32_t full_res;
12011372 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
1202 *res = (uint24_t)full_res;
1373 *res = zig_u24_intCast_u32(full_res);
12031374 return overflow;
12041375#endif
12051376}
......@@ -1208,28 +1379,26 @@ static inline bool zig_subo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t
12081379#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
12091380 int24_t full_res;
12101381 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1211 *res = zig_wrap_i24(full_res, bits);
1382 *res = zig_i24_truncate_i24(full_res, bits);
12121383 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);
12131384#else
12141385 int32_t full_res;
12151386 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
1216 *res = (int24_t)full_res;
1387 *res = zig_i24_intCast_i32(full_res);
12171388 return overflow;
12181389#endif
12191390}
1220#endif
12211391
1222#if defined(zig_ez80)
12231392static inline bool zig_subo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {
12241393#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
12251394 uint48_t full_res;
12261395 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1227 *res = zig_wrap_u48(full_res, bits);
1396 *res = zig_u48_truncate_u48(full_res, bits);
12281397 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);
12291398#else
12301399 uint64_t full_res;
12311400 bool overflow = zig_subo_u64(&full_res, lhs, rhs, bits);
1232 *res = (uint48_t)full_res;
1401 *res = zig_u48_intCast_u64(full_res);
12331402 return overflow;
12341403#endif
12351404}
......@@ -1238,22 +1407,23 @@ static inline bool zig_subo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
12381407#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
12391408 int48_t full_res;
12401409 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1241 *res = zig_wrap_i48(full_res, bits);
1410 *res = zig_i48_truncate_i48(full_res, bits);
12421411 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);
12431412#else
12441413 int64_t full_res;
12451414 bool overflow = zig_subo_i64(&full_res, lhs, rhs, bits);
1246 *res = (int48_t)full_res;
1415 *res = zig_i48_intCast_i64(full_res);
12471416 return overflow;
12481417#endif
12491418}
1419
12501420#endif
12511421
12521422static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
12531423#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
12541424 uint32_t full_res;
12551425 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1256 *res = zig_wrap_u32(full_res, bits);
1426 *res = zig_u32_truncate_u32(full_res, bits);
12571427 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
12581428#else
12591429 *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
12611431#endif
12621432}
12631433
1264zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow);
12651434static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) {
1435 zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow);
12661436#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
12671437 int32_t full_res;
12681438 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
12711441 int32_t full_res = __mulosi4(lhs, rhs, &overflow_int);
12721442 bool overflow = overflow_int != 0;
12731443#endif
1274 *res = zig_wrap_i32(full_res, bits);
1444 *res = zig_i32_truncate_i32(full_res, bits);
12751445 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
12761446}
12771447
......@@ -1279,7 +1449,7 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8
12791449#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
12801450 uint64_t full_res;
12811451 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1282 *res = zig_wrap_u64(full_res, bits);
1452 *res = zig_u64_truncate_u64(full_res, bits);
12831453 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
12841454#else
12851455 *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
12871457#endif
12881458}
12891459
1290zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow);
12911460static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) {
1461 zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow);
12921462#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
12931463 int64_t full_res;
12941464 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
12971467 int64_t full_res = __mulodi4(lhs, rhs, &overflow_int);
12981468 bool overflow = overflow_int != 0;
12991469#endif
1300 *res = zig_wrap_i64(full_res, bits);
1470 *res = zig_i64_truncate_i64(full_res, bits);
13011471 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
13021472}
13031473
......@@ -1305,12 +1475,12 @@ static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b
13051475#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13061476 uint8_t full_res;
13071477 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1308 *res = zig_wrap_u8(full_res, bits);
1478 *res = zig_u8_truncate_u8(full_res, bits);
13091479 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
13101480#else
13111481 uint32_t full_res;
13121482 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
1313 *res = (uint8_t)full_res;
1483 *res = zig_u8_intCast_u32(full_res);
13141484 return overflow;
13151485#endif
13161486}
......@@ -1319,12 +1489,12 @@ static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
13191489#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13201490 int8_t full_res;
13211491 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1322 *res = zig_wrap_i8(full_res, bits);
1492 *res = zig_i8_truncate_i8(full_res, bits);
13231493 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
13241494#else
13251495 int32_t full_res;
13261496 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
1327 *res = (int8_t)full_res;
1497 *res = zig_i8_intCast_i32(full_res);
13281498 return overflow;
13291499#endif
13301500}
......@@ -1333,12 +1503,12 @@ static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
13331503#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13341504 uint16_t full_res;
13351505 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1336 *res = zig_wrap_u16(full_res, bits);
1506 *res = zig_u16_truncate_u16(full_res, bits);
13371507 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
13381508#else
13391509 uint32_t full_res;
13401510 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
1341 *res = (uint16_t)full_res;
1511 *res = zig_u16_intCast_u32(full_res);
13421512 return overflow;
13431513#endif
13441514}
......@@ -1347,27 +1517,28 @@ static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
13471517#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13481518 int16_t full_res;
13491519 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1350 *res = zig_wrap_i16(full_res, bits);
1520 *res = zig_i16_truncate_i16(full_res, bits);
13511521 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
13521522#else
13531523 int32_t full_res;
13541524 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
1355 *res = (int16_t)full_res;
1525 *res = zig_i16_intCast_i32(full_res);
13561526 return overflow;
13571527#endif
13581528}
13591529
13601530#if defined(zig_ez80)
1531
13611532static inline bool zig_mulo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {
13621533#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13631534 uint24_t full_res;
13641535 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1365 *res = zig_wrap_u24(full_res, bits);
1536 *res = zig_u24_truncate_u24(full_res, bits);
13661537 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);
13671538#else
13681539 uint32_t full_res;
13691540 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
1370 *res = (uint24_t)full_res;
1541 *res = zig_u24_intCast_u32(full_res);
13711542 return overflow;
13721543#endif
13731544}
......@@ -1376,28 +1547,26 @@ static inline bool zig_mulo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t
13761547#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13771548 int24_t full_res;
13781549 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1379 *res = zig_wrap_i24(full_res, bits);
1550 *res = zig_i24_truncate_i24(full_res, bits);
13801551 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);
13811552#else
13821553 int32_t full_res;
13831554 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
1384 *res = (int24_t)full_res;
1555 *res = zig_i24_intCast_i32(full_res);
13851556 return overflow;
13861557#endif
13871558}
1388#endif
13891559
1390#if defined(zig_ez80)
13911560static inline bool zig_mulo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {
13921561#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13931562 uint48_t full_res;
13941563 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1395 *res = zig_wrap_u48(full_res, bits);
1564 *res = zig_u48_truncate_u48(full_res, bits);
13961565 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);
13971566#else
13981567 uint64_t full_res;
13991568 bool overflow = zig_mulo_u64(&full_res, lhs, rhs, bits);
1400 *res = (uint48_t)full_res;
1569 *res = zig_u48_intCast_u64(full_res);
14011570 return overflow;
14021571#endif
14031572}
......@@ -1406,18 +1575,32 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
14061575#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
14071576 int48_t full_res;
14081577 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1409 *res = zig_wrap_i48(full_res, bits);
1578 *res = zig_i48_truncate_i48(full_res, bits);
14101579 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);
14111580#else
14121581 int64_t full_res;
14131582 bool overflow = zig_mulo_i64(&full_res, lhs, rhs, bits);
1414 *res = (int48_t)full_res;
1583 *res = zig_i48_intCast_i64(full_res);
14151584 return overflow;
14161585#endif
14171586}
1587
14181588#endif
14191589
1420#define zig_int_builtins(w) \
1590#define zig_shls_builtins(lw, rw) \
1591 static inline uint##lw##_t zig_shls_u##lw##_u##rw(uint##lw##_t lhs, uint##rw##_t rhs, uint8_t bits) { \
1592 uint##lw##_t res; \
1593 if (rhs < bits && !zig_shlo_u##lw(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \
1594 return lhs == INT##lw##_C(0) ? zig_minInt_u(lw, bits) : zig_maxInt_u(lw, bits); \
1595 } \
1596\
1597 static inline int##lw##_t zig_shls_i##lw##_u##rw(int##lw##_t lhs, uint##rw##_t rhs, uint8_t bits) { \
1598 int##lw##_t res; \
1599 if (rhs < bits && !zig_shlo_i##lw(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \
1600 return lhs == INT##lw##_C(0) ? INT##lw##_C(0) : \
1601 lhs < INT##lw##_C(0) ? zig_minInt_i(lw, bits) : zig_maxInt_i(lw, bits); \
1602 }
1603#define zig_int_sat_builtins(w) \
14211604 static inline bool zig_shlo_u##w(uint##w##_t *res, uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \
14221605 *res = zig_shlw_u##w(lhs, rhs, bits); \
14231606 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
14291612 return (lhs & mask) != INT##w##_C(0) && (lhs & mask) != mask; \
14301613 } \
14311614\
1432 static inline uint##w##_t zig_shls_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
1433 uint##w##_t res; \
1434 if (rhs < bits && !zig_shlo_u##w(&res, lhs, rhs, bits)) return res; \
1435 return lhs == INT##w##_C(0) ? INT##w##_C(0) : zig_maxInt_u(w, bits); \
1436 } \
1437\
1438 static inline int##w##_t zig_shls_i##w(int##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
1439 int##w##_t res; \
1440 if (rhs < bits && !zig_shlo_i##w(&res, lhs, rhs, bits)) return res; \
1441 return lhs == INT##w##_C(0) ? INT##w##_C(0) : \
1442 lhs < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \
1443 } \
1615 zig_shls_builtins(w, 8) \
1616 zig_shls_builtins(w, 16) \
1617 zig_shls_builtins(w, 32) \
1618 zig_shls_builtins(w, 64) \
14441619\
14451620 static inline uint##w##_t zig_adds_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
14461621 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
14741649 if (!zig_mulo_i##w(&res, lhs, rhs, bits)) return res; \
14751650 return (lhs ^ rhs) < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \
14761651 }
1477zig_int_builtins(8)
1478zig_int_builtins(16)
1479#if defined(zig_ez80)
1480zig_int_builtins(24)
1481#endif
1482zig_int_builtins(32)
1652zig_int_sat_builtins(8)
1653zig_int_sat_builtins(16)
1654zig_int_sat_builtins(32)
1655zig_int_sat_builtins(64)
14831656#if defined(zig_ez80)
1484zig_int_builtins(48)
1657zig_int_sat_builtins(24)
1658zig_int_sat_builtins(48)
14851659#endif
1486zig_int_builtins(64)
14871660
1488#define zig_builtin8(name, val) __builtin_##name(val)
1661#define zig_builtin8(name, arg) __builtin_##name(arg)
14891662typedef unsigned int zig_Builtin8;
14901663
1491#define zig_builtin16(name, val) __builtin_##name(val)
1664#define zig_builtin16(name, arg) __builtin_##name(arg)
14921665typedef unsigned int zig_Builtin16;
14931666
1494#if defined(zig_ez80)
1495#define zig_builtin24(name, val) __builtin_##name(val)
1496typedef unsigned int zig_Builtin24;
1497#endif
1498
14991667#if INT_MIN <= INT32_MIN
1500#define zig_builtin32(name, val) __builtin_##name(val)
1668#define zig_builtin32(name, arg) __builtin_##name(arg)
15011669typedef unsigned int zig_Builtin32;
15021670#elif LONG_MIN <= INT32_MIN
1503#define zig_builtin32(name, val) __builtin_##name##l(val)
1671#define zig_builtin32(name, arg) __builtin_##name##l(arg)
15041672typedef unsigned long zig_Builtin32;
15051673#endif
15061674
1507#if defined(zig_ez80)
1508#define zig_builtin48(name, val) __builtin_##name(val)
1509typedef unsigned long long zig_Builtin48;
1510#endif
1511
15121675#if INT_MIN <= INT64_MIN
1513#define zig_builtin64(name, val) __builtin_##name(val)
1676#define zig_builtin64(name, arg) __builtin_##name(arg)
15141677typedef unsigned int zig_Builtin64;
15151678#elif LONG_MIN <= INT64_MIN
1516#define zig_builtin64(name, val) __builtin_##name##l(val)
1679#define zig_builtin64(name, arg) __builtin_##name##l(arg)
15171680typedef unsigned long zig_Builtin64;
15181681#elif LLONG_MIN <= INT64_MIN
1519#define zig_builtin64(name, val) __builtin_##name##ll(val)
1682#define zig_builtin64(name, arg) __builtin_##name##ll(arg)
15201683typedef unsigned long long zig_Builtin64;
15211684#endif
15221685
1523static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) {
1524 return zig_wrap_u8(val >> (8 - bits), bits);
1686#if defined(zig_ez80)
1687#define zig_builtin24(name, arg) __builtin_##name(arg)
1688typedef unsigned int zig_Builtin24;
1689#define zig_builtin48(name, arg) __builtin_##name(arg)
1690typedef unsigned long long zig_Builtin48;
1691#endif
1692
1693static inline uint8_t zig_byteSwap_u8(uint8_t arg, uint8_t bits) {
1694 return zig_u8_truncate_u8(arg >> (8 - bits), bits);
15251695}
15261696
1527static inline int8_t zig_byte_swap_i8(int8_t val, uint8_t bits) {
1528 return zig_wrap_i8((int8_t)zig_byte_swap_u8((uint8_t)val, bits), bits);
1697static inline int8_t zig_byteSwap_i8(int8_t arg, uint8_t bits) {
1698 return zig_i8_truncate_i8((int8_t)zig_byteSwap_u8((uint8_t)arg, bits), bits);
15291699}
15301700
1531static inline uint16_t zig_byte_swap_u16(uint16_t val, uint8_t bits) {
1701static inline uint16_t zig_byteSwap_u16(uint16_t arg, uint8_t bits) {
15321702 uint16_t full_res;
15331703#if zig_has_builtin(bswap16) || defined(zig_gcc)
1534 full_res = __builtin_bswap16(val);
1704 full_res = __builtin_bswap16(arg);
15351705#else
1536 full_res = (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 8 |
1537 (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 8), 8) >> 0;
1706 full_res = (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 8 |
1707 (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 8), 8) >> 0;
15381708#endif
1539 return zig_wrap_u16(full_res >> (16 - bits), bits);
1709 return zig_u16_truncate_u16(full_res >> (16 - bits), bits);
15401710}
15411711
1542static inline int16_t zig_byte_swap_i16(int16_t val, uint8_t bits) {
1543 return zig_wrap_i16((int16_t)zig_byte_swap_u16((uint16_t)val, bits), bits);
1712static inline int16_t zig_byteSwap_i16(int16_t arg, uint8_t bits) {
1713 return zig_i16_truncate_i16((int16_t)zig_byteSwap_u16((uint16_t)arg, bits), bits);
15441714}
15451715
15461716#if defined(zig_ez80)
1547static inline uint16_t zig_byte_swap_u24(uint24_t val, uint8_t bits) {
1717static inline uint16_t zig_byteSwap_u24(uint24_t arg, uint8_t bits) {
15481718 uint24_t full_res;
15491719#if zig_has_builtin(bswap24) || defined(zig_gcc)
1550 full_res = __builtin_bswap24(val);
1720 full_res = __builtin_bswap24(arg);
15511721#else
1552 full_res = (uint24_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 16 |
1553 (uint24_t)zig_byte_swap_u16((uint16_t)(val >> 8), 16) >> 0;
1722 full_res = (uint24_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 16 |
1723 (uint24_t)zig_byteSwap_u16((uint16_t)(arg >> 8), 16) >> 0;
15541724#endif
1555 return zig_wrap_u24(full_res >> (24 - bits), bits);
1725 return zig_u24_truncate_u24(full_res >> (24 - bits), bits);
15561726}
15571727
1558static inline int16_t zig_byte_swap_i24(int24_t val, uint8_t bits) {
1559 return zig_wrap_i24((int24_t)zig_byte_swap_u24((uint24_t)val, bits), bits);
1728static inline int16_t zig_byteSwap_i24(int24_t arg, uint8_t bits) {
1729 return zig_i24_truncate_i24((int24_t)zig_byteSwap_u24((uint24_t)arg, bits), bits);
15601730}
15611731#endif
15621732
1563static inline uint32_t zig_byte_swap_u32(uint32_t val, uint8_t bits) {
1733static inline uint32_t zig_byteSwap_u32(uint32_t arg, uint8_t bits) {
15641734 uint32_t full_res;
15651735#if zig_has_builtin(bswap32) || defined(zig_gcc)
1566 full_res = __builtin_bswap32(val);
1736 full_res = __builtin_bswap32(arg);
15671737#else
1568 full_res = (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 0), 16) << 16 |
1569 (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 16), 16) >> 0;
1738 full_res = (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 0), 16) << 16 |
1739 (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 16), 16) >> 0;
15701740#endif
1571 return zig_wrap_u32(full_res >> (32 - bits), bits);
1741 return zig_u32_truncate_u32(full_res >> (32 - bits), bits);
15721742}
15731743
1574static inline int32_t zig_byte_swap_i32(int32_t val, uint8_t bits) {
1575 return zig_wrap_i32((int32_t)zig_byte_swap_u32((uint32_t)val, bits), bits);
1744static inline int32_t zig_byteSwap_i32(int32_t arg, uint8_t bits) {
1745 return zig_i32_truncate_i32((int32_t)zig_byteSwap_u32((uint32_t)arg, bits), bits);
15761746}
15771747
15781748#if defined(zig_ez80)
1579static inline uint32_t zig_byte_swap_u48(uint48_t val, uint8_t bits) {
1749static inline uint32_t zig_byteSwap_u48(uint48_t arg, uint8_t bits) {
15801750 uint48_t full_res;
15811751#if zig_has_builtin(bswap48) || defined(zig_gcc)
1582 full_res = __builtin_bswap48(val);
1752 full_res = __builtin_bswap48(arg);
15831753#else
1584 full_res = (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 0), 24) << 24 |
1585 (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 24), 24) >> 0;
1754 full_res = (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 0), 24) << 24 |
1755 (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 24), 24) >> 0;
15861756#endif
1587 return zig_wrap_u48(full_res >> (48 - bits), bits);
1757 return zig_u48_truncate_u48(full_res >> (48 - bits), bits);
15881758}
15891759
1590static inline int32_t zig_byte_swap_i48(int48_t val, uint8_t bits) {
1591 return zig_wrap_i48((int48_t)zig_byte_swap_u48((uint48_t)val, bits), bits);
1760static inline int32_t zig_byteSwap_i48(int48_t arg, uint8_t bits) {
1761 return zig_i48_truncate_i48((int48_t)zig_byteSwap_u48((uint48_t)arg, bits), bits);
15921762}
15931763#endif
15941764
1595static inline uint64_t zig_byte_swap_u64(uint64_t val, uint8_t bits) {
1765static inline uint64_t zig_byteSwap_u64(uint64_t arg, uint8_t bits) {
15961766 uint64_t full_res;
15971767#if zig_has_builtin(bswap64) || defined(zig_gcc)
1598 full_res = __builtin_bswap64(val);
1768 full_res = __builtin_bswap64(arg);
15991769#else
1600 full_res = (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 0), 32) << 32 |
1601 (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 32), 32) >> 0;
1770 full_res = (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 0), 32) << 32 |
1771 (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 32), 32) >> 0;
16021772#endif
1603 return zig_wrap_u64(full_res >> (64 - bits), bits);
1773 return zig_u64_truncate_u64(full_res >> (64 - bits), bits);
16041774}
16051775
1606static inline int64_t zig_byte_swap_i64(int64_t val, uint8_t bits) {
1607 return zig_wrap_i64((int64_t)zig_byte_swap_u64((uint64_t)val, bits), bits);
1776static inline int64_t zig_byteSwap_i64(int64_t arg, uint8_t bits) {
1777 return zig_i64_truncate_i64((int64_t)zig_byteSwap_u64((uint64_t)arg, bits), bits);
16081778}
16091779
1610static inline uint8_t zig_bit_reverse_u8(uint8_t val, uint8_t bits) {
1780static inline uint8_t zig_bitReverse_u8(uint8_t arg, uint8_t bits) {
16111781 uint8_t full_res;
16121782#if zig_has_builtin(bitreverse8)
1613 full_res = __builtin_bitreverse8(val);
1783 full_res = __builtin_bitreverse8(arg);
16141784#else
16151785 static uint8_t const lut[0x10] = {
16161786 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
16171787 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
16181788 };
1619 full_res = lut[val >> 0 & 0xF] << 4 | lut[val >> 4 & 0xF] << 0;
1789 full_res = lut[arg >> 0 & 0xF] << 4 | lut[arg >> 4 & 0xF] << 0;
16201790#endif
1621 return zig_wrap_u8(full_res >> (8 - bits), bits);
1791 return zig_u8_truncate_u8(full_res >> (8 - bits), bits);
16221792}
16231793
1624static inline int8_t zig_bit_reverse_i8(int8_t val, uint8_t bits) {
1625 return zig_wrap_i8((int8_t)zig_bit_reverse_u8((uint8_t)val, bits), bits);
1794static inline int8_t zig_bitReverse_i8(int8_t arg, uint8_t bits) {
1795 return zig_i8_truncate_i8((int8_t)zig_bitReverse_u8((uint8_t)arg, bits), bits);
16261796}
16271797
1628static inline uint16_t zig_bit_reverse_u16(uint16_t val, uint8_t bits) {
1798static inline uint16_t zig_bitReverse_u16(uint16_t arg, uint8_t bits) {
16291799 uint16_t full_res;
16301800#if zig_has_builtin(bitreverse16)
1631 full_res = __builtin_bitreverse16(val);
1801 full_res = __builtin_bitreverse16(arg);
16321802#else
1633 full_res = (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 8 |
1634 (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 8), 8) >> 0;
1803 full_res = (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 8 |
1804 (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 8), 8) >> 0;
16351805#endif
1636 return zig_wrap_u16(full_res >> (16 - bits), bits);
1806 return zig_u16_truncate_u16(full_res >> (16 - bits), bits);
16371807}
16381808
1639static inline int16_t zig_bit_reverse_i16(int16_t val, uint8_t bits) {
1640 return zig_wrap_i16((int16_t)zig_bit_reverse_u16((uint16_t)val, bits), bits);
1809static inline int16_t zig_bitReverse_i16(int16_t arg, uint8_t bits) {
1810 return zig_i16_truncate_i16((int16_t)zig_bitReverse_u16((uint16_t)arg, bits), bits);
16411811}
16421812
16431813#if defined(zig_ez80)
1644static inline uint24_t zig_bit_reverse_u24(uint24_t val, uint8_t bits) {
1814static inline uint24_t zig_bitReverse_u24(uint24_t arg, uint8_t bits) {
16451815 uint24_t full_res;
16461816#if zig_has_builtin(bitreverse24)
1647 full_res = __builtin_bitreverse24(val);
1817 full_res = __builtin_bitreverse24(arg);
16481818#else
1649 full_res = (uint24_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 16 |
1650 (uint24_t)zig_bit_reverse_u16((uint16_t)(val >> 8), 16) >> 0;
1819 full_res = (uint24_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 16 |
1820 (uint24_t)zig_bitReverse_u16((uint16_t)(arg >> 8), 16) >> 0;
16511821#endif
1652 return zig_wrap_u24(full_res >> (24 - bits), bits);
1822 return zig_u24_truncate_u24(full_res >> (24 - bits), bits);
16531823}
16541824
1655static inline int24_t zig_bit_reverse_i24(int24_t val, uint8_t bits) {
1656 return zig_wrap_i24((int24_t)zig_bit_reverse_u24((uint24_t)val, bits), bits);
1825static inline int24_t zig_bitReverse_i24(int24_t arg, uint8_t bits) {
1826 return zig_i24_truncate_i24((int24_t)zig_bitReverse_u24((uint24_t)arg, bits), bits);
16571827}
16581828#endif
16591829
1660static inline uint32_t zig_bit_reverse_u32(uint32_t val, uint8_t bits) {
1830static inline uint32_t zig_bitReverse_u32(uint32_t arg, uint8_t bits) {
16611831 uint32_t full_res;
16621832#if zig_has_builtin(bitreverse32)
1663 full_res = __builtin_bitreverse32(val);
1833 full_res = __builtin_bitreverse32(arg);
16641834#else
1665 full_res = (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 0), 16) << 16 |
1666 (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 16), 16) >> 0;
1835 full_res = (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 0), 16) << 16 |
1836 (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 16), 16) >> 0;
16671837#endif
1668 return zig_wrap_u32(full_res >> (32 - bits), bits);
1838 return zig_u32_truncate_u32(full_res >> (32 - bits), bits);
16691839}
16701840
1671static inline int32_t zig_bit_reverse_i32(int32_t val, uint8_t bits) {
1672 return zig_wrap_i32((int32_t)zig_bit_reverse_u32((uint32_t)val, bits), bits);
1841static inline int32_t zig_bitReverse_i32(int32_t arg, uint8_t bits) {
1842 return zig_i32_truncate_i32((int32_t)zig_bitReverse_u32((uint32_t)arg, bits), bits);
16731843}
16741844
16751845#if defined(zig_ez80)
1676static inline uint32_t zig_bit_reverse_u48(uint48_t val, uint8_t bits) {
1846static inline uint32_t zig_bitReverse_u48(uint48_t arg, uint8_t bits) {
16771847 uint48_t full_res;
16781848#if zig_has_builtin(bitreverse48)
1679 full_res = __builtin_bitreverse48(val);
1849 full_res = __builtin_bitreverse48(arg);
16801850#else
1681 full_res = (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 0), 24) << 24 |
1682 (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 24), 24) >> 0;
1851 full_res = (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 0), 24) << 24 |
1852 (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 24), 24) >> 0;
16831853#endif
1684 return zig_wrap_u32(full_res >> (48 - bits), bits);
1854 return zig_u48_truncate_u48(full_res >> (48 - bits), bits);
16851855}
16861856
1687static inline int32_t zig_bit_reverse_i48(int48_t val, uint8_t bits) {
1688 return zig_wrap_i48((int48_t)zig_bit_reverse_u48((uint48_t)val, bits), bits);
1857static inline int32_t zig_bitReverse_i48(int48_t arg, uint8_t bits) {
1858 return zig_i48_truncate_i48((int48_t)zig_bitReverse_u48((uint48_t)arg, bits), bits);
16891859}
16901860#endif
16911861
1692static inline uint64_t zig_bit_reverse_u64(uint64_t val, uint8_t bits) {
1862static inline uint64_t zig_bitReverse_u64(uint64_t arg, uint8_t bits) {
16931863 uint64_t full_res;
16941864#if zig_has_builtin(bitreverse64)
1695 full_res = __builtin_bitreverse64(val);
1865 full_res = __builtin_bitreverse64(arg);
16961866#else
1697 full_res = (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 0), 32) << 32 |
1698 (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 32), 32) >> 0;
1867 full_res = (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 0), 32) << 32 |
1868 (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 32), 32) >> 0;
16991869#endif
1700 return zig_wrap_u64(full_res >> (64 - bits), bits);
1870 return zig_u64_truncate_u64(full_res >> (64 - bits), bits);
17011871}
17021872
1703static inline int64_t zig_bit_reverse_i64(int64_t val, uint8_t bits) {
1704 return zig_wrap_i64((int64_t)zig_bit_reverse_u64((uint64_t)val, bits), bits);
1873static inline int64_t zig_bitReverse_i64(int64_t arg, uint8_t bits) {
1874 return zig_i64_truncate_i64((int64_t)zig_bitReverse_u64((uint64_t)arg, bits), bits);
17051875}
17061876
1707#define zig_builtin_popcount_common(w) \
1708 static inline uint8_t zig_popcount_i##w(int##w##_t val, uint8_t bits) { \
1709 return zig_popcount_u##w((uint##w##_t)val, bits); \
1877#define zig_builtin_popCount_common(w) \
1878 static inline uint8_t zig_popCount_i##w(int##w##_t arg, uint8_t bits) { \
1879 return zig_popCount_u##w((uint##w##_t)arg, bits); \
17101880 }
1711#if zig_has_builtin(popcount) || defined(zig_gcc) || defined(zig_tinyc)
1712#define zig_builtin_popcount(w) \
1713 static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \
1881#if zig_has_builtin(popCount) || defined(zig_gcc) || defined(zig_tinyc)
1882#define zig_builtin_popCount(w) \
1883 static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \
17141884 (void)bits; \
1715 return zig_builtin##w(popcount, val); \
1885 return zig_builtin##w(popcount, arg); \
17161886 } \
17171887\
1718 zig_builtin_popcount_common(w)
1888 zig_builtin_popCount_common(w)
17191889#else
1720#define zig_builtin_popcount(w) \
1721 static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \
1890#define zig_builtin_popCount(w) \
1891 static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \
17221892 (void)bits; \
1723 uint##w##_t temp = val - ((val >> 1) & (UINT##w##_MAX / 3)); \
1893 uint##w##_t temp = arg - ((arg >> 1) & (UINT##w##_MAX / 3)); \
17241894 temp = (temp & (UINT##w##_MAX / 5)) + ((temp >> 2) & (UINT##w##_MAX / 5)); \
17251895 temp = (temp + (temp >> 4)) & (UINT##w##_MAX / 17); \
17261896 return temp * (UINT##w##_MAX / 255) >> (UINT8_C(w) - UINT8_C(8)); \
17271897 } \
17281898\
1729 zig_builtin_popcount_common(w)
1730#endif
1731zig_builtin_popcount(8)
1732zig_builtin_popcount(16)
1733#if defined(zig_ez80)
1734zig_builtin_popcount(24)
1899 zig_builtin_popCount_common(w)
17351900#endif
1736zig_builtin_popcount(32)
1901zig_builtin_popCount(8)
1902zig_builtin_popCount(16)
1903zig_builtin_popCount(32)
1904zig_builtin_popCount(64)
17371905#if defined(zig_ez80)
1738zig_builtin_popcount(48)
1906zig_builtin_popCount(24)
1907zig_builtin_popCount(48)
17391908#endif
1740zig_builtin_popcount(64)
17411909
17421910#define zig_builtin_ctz_common(w) \
1743 static inline uint8_t zig_ctz_i##w(int##w##_t val, uint8_t bits) { \
1744 return zig_ctz_u##w((uint##w##_t)val, bits); \
1911 static inline uint8_t zig_ctz_i##w(int##w##_t arg, uint8_t bits) { \
1912 return zig_ctz_u##w((uint##w##_t)arg, bits); \
17451913 }
17461914#if zig_has_builtin(ctz) || defined(zig_gcc) || defined(zig_tinyc)
17471915#define zig_builtin_ctz(w) \
1748 static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \
1749 if (val == 0) return bits; \
1750 return zig_builtin##w(ctz, val); \
1916 static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \
1917 if (arg == 0) return bits; \
1918 return zig_builtin##w(ctz, arg); \
17511919 } \
17521920\
17531921 zig_builtin_ctz_common(w)
17541922#else
17551923#define zig_builtin_ctz(w) \
1756 static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \
1757 return zig_popcount_u##w(zig_not_u##w(val, bits) & zig_subw_u##w(val, 1, bits), bits); \
1924 static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \
1925 return zig_popCount_u##w(zig_not_u##w(arg, bits) & zig_subw_u##w(arg, 1, bits), bits); \
17581926 } \
17591927\
17601928 zig_builtin_ctz_common(w)
17611929#endif
17621930zig_builtin_ctz(8)
17631931zig_builtin_ctz(16)
1764#if defined(zig_ez80)
1765zig_builtin_ctz(24)
1766#endif
17671932zig_builtin_ctz(32)
1933zig_builtin_ctz(64)
17681934#if defined(zig_ez80)
1935zig_builtin_ctz(24)
17691936zig_builtin_ctz(48)
17701937#endif
1771zig_builtin_ctz(64)
17721938
17731939#define zig_builtin_clz_common(w) \
1774 static inline uint8_t zig_clz_i##w(int##w##_t val, uint8_t bits) { \
1775 return zig_clz_u##w((uint##w##_t)val, bits); \
1940 static inline uint8_t zig_clz_i##w(int##w##_t arg, uint8_t bits) { \
1941 return zig_clz_u##w((uint##w##_t)arg, bits); \
17761942 }
17771943#if zig_has_builtin(clz) || defined(zig_gcc) || defined(zig_tinyc)
17781944#define zig_builtin_clz(w) \
1779 static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \
1780 if (val == 0) return bits; \
1781 return zig_builtin##w(clz, val) - (zig_bitSizeOf(zig_Builtin##w) - bits); \
1945 static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \
1946 if (arg == 0) return bits; \
1947 return zig_builtin##w(clz, arg) - (zig_bitSizeOf(zig_Builtin##w) - bits); \
17821948 } \
17831949\
17841950 zig_builtin_clz_common(w)
17851951#else
17861952#define zig_builtin_clz(w) \
1787 static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \
1788 return zig_ctz_u##w(zig_bit_reverse_u##w(val, bits), bits); \
1953 static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \
1954 return zig_ctz_u##w(zig_bitReverse_u##w(arg, bits), bits); \
17891955 } \
17901956\
17911957 zig_builtin_clz_common(w)
17921958#endif
17931959zig_builtin_clz(8)
17941960zig_builtin_clz(16)
1795#if defined(zig_ez80)
1796zig_builtin_clz(24)
1797#endif
17981961zig_builtin_clz(32)
1962zig_builtin_clz(64)
17991963#if defined(zig_ez80)
1964zig_builtin_clz(24)
18001965zig_builtin_clz(48)
18011966#endif
1802zig_builtin_clz(64)
18031967
18041968/* ======================== 128-bit Integer Support ========================= */
18051969
......@@ -1816,16 +1980,14 @@ zig_builtin_clz(64)
18161980typedef unsigned __int128 zig_u128;
18171981typedef signed __int128 zig_i128;
18181982
1819#define zig_make_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))
1820#define zig_make_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo))
1821#define zig_init_u128(hi, lo) zig_make_u128(hi, lo)
1822#define zig_init_i128(hi, lo) zig_make_i128(hi, lo)
1823#define zig_hi_u128(val) ((uint64_t)((val) >> 64))
1824#define zig_lo_u128(val) ((uint64_t)((val) >> 0))
1825#define zig_hi_i128(val) (( int64_t)((val) >> 64))
1826#define zig_lo_i128(val) ((uint64_t)((val) >> 0))
1827#define zig_bitCast_u128(val) ((zig_u128)(val))
1828#define zig_bitCast_i128(val) ((zig_i128)(val))
1983#define zig_init_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))
1984#define zig_init_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo))
1985#define zig_make_u128(hi, lo) zig_init_u128(hi, lo)
1986#define zig_make_i128(hi, lo) zig_init_i128(hi, lo)
1987#define zig_hi_u128(arg) ((uint64_t)((arg) >> 64))
1988#define zig_lo_u128(arg) ((uint64_t)((arg) >> 0))
1989#define zig_hi_i128(arg) (( int64_t)((arg) >> 64))
1990#define zig_lo_i128(arg) ((uint64_t)((arg) >> 0))
18291991#define zig_cmp_int128(Type) \
18301992 static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
18311993 return (lhs > rhs) - (lhs < rhs); \
......@@ -1835,32 +1997,49 @@ typedef signed __int128 zig_i128;
18351997 return lhs operator rhs; \
18361998 }
18371999
1838#else /* zig_has_int128 */
2000static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
2001 return lhs << rhs;
2002}
18392003
1840#if zig_little_endian
1841typedef struct { zig_align(16) uint64_t lo; uint64_t hi; } zig_u128;
1842typedef struct { zig_align(16) uint64_t lo; int64_t hi; } zig_i128;
2004static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
2005 return lhs >> rhs;
2006}
2007
2008static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {
2009 return lhs << rhs;
2010}
2011
2012static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
2013 // This works around a GCC miscompilation, but it has the side benefit of
2014 // emitting better code. It is behind the `#if` because it depends on
2015 // arithmetic right shift, which is implementation-defined in C, but should
2016 // be guaranteed on any GCC-compatible compiler.
2017#if defined(zig_gnuc)
2018 return lhs >> rhs;
18432019#else
1844typedef struct { zig_align(16) uint64_t hi; uint64_t lo; } zig_u128;
1845typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;
2020 zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0);
2021 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask;
18462022#endif
2023}
18472024
1848#define zig_make_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) })
1849#define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) })
2025#else /* zig_has_int128 */
18502026
1851#if defined(zig_msvc) /* MSVC doesn't allow struct literals in constant expressions */
1852#define zig_init_u128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1853#define zig_init_i128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1854#else /* But non-MSVC doesn't like the unprotected commas */
1855#define zig_init_u128(hi, lo) zig_make_u128(hi, lo)
1856#define zig_init_i128(hi, lo) zig_make_i128(hi, lo)
1857#endif
1858#define zig_hi_u128(val) ((val).hi)
1859#define zig_lo_u128(val) ((val).lo)
1860#define zig_hi_i128(val) ((val).hi)
1861#define zig_lo_i128(val) ((val).lo)
1862#define zig_bitCast_u128(val) zig_make_u128((uint64_t)(val).hi, (val).lo)
1863#define zig_bitCast_i128(val) zig_make_i128(( int64_t)(val).hi, (val).lo)
2027#if zig_little_endian
2028typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; uint64_t hi; } zig_u128;
2029typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; int64_t hi; } zig_i128;
2030#else
2031typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t hi; uint64_t lo; } zig_u128;
2032typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) int64_t hi; uint64_t lo; } zig_i128;
2033#endif
2034
2035#define zig_init_u128(hi, lo) { .h##i = hi, .l##o = lo }
2036#define zig_init_i128(hi, lo) { .h##i = hi, .l##o = lo }
2037#define zig_make_u128(hi, lo) (zig_u128)zig_init_u128(hi, lo)
2038#define zig_make_i128(hi, lo) (zig_i128)zig_init_i128(hi, lo)
2039#define zig_hi_u128(arg) (arg).hi
2040#define zig_lo_u128(arg) (arg).lo
2041#define zig_hi_i128(arg) (arg).hi
2042#define zig_lo_i128(arg) (arg).lo
18642043#define zig_cmp_int128(Type) \
18652044 static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
18662045 return (lhs.hi == rhs.hi) \
......@@ -1872,6 +2051,30 @@ typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;
18722051 return (zig_##Type){ .hi = lhs.hi operator rhs.hi, .lo = lhs.lo operator rhs.lo }; \
18732052 }
18742053
2054static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
2055 if (rhs == UINT8_C(0)) return lhs;
2056 if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
2057 return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
2058}
2059
2060static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
2061 if (rhs == UINT8_C(0)) return lhs;
2062 if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - UINT8_C(64)) };
2063 return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (UINT8_C(64) - rhs) | lhs.lo >> rhs };
2064}
2065
2066static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {
2067 if (rhs == UINT8_C(0)) return lhs;
2068 if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
2069 return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
2070}
2071
2072static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
2073 if (rhs == UINT8_C(0)) return lhs;
2074 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))) };
2075 return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) };
2076}
2077
18752078#endif /* zig_has_int128 */
18762079
18772080#define zig_minInt_u128 zig_make_u128(zig_minInt_u64, zig_minInt_u64)
......@@ -1891,42 +2094,177 @@ zig_bit_int128(i128, or, |)
18912094zig_bit_int128(u128, xor, ^)
18922095zig_bit_int128(i128, xor, ^)
18932096
1894static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs);
2097static inline uint8_t zig_u8_intCast_u128(zig_u128 arg) {
2098 return (uint8_t)zig_lo_u128(arg);
2099}
2100static inline uint8_t zig_u8_intCast_i128(zig_i128 arg) {
2101 return (uint8_t)zig_lo_i128(arg);
2102}
2103static inline int8_t zig_i8_intCast_i128(zig_i128 arg) {
2104 return (int8_t)zig_lo_i128(arg);
2105}
2106static inline int8_t zig_i8_intCast_u128(zig_u128 arg) {
2107 return (int8_t)zig_lo_u128(arg);
2108}
18952109
1896#if zig_has_int128
2110static inline uint16_t zig_u16_intCast_u128(zig_u128 arg) {
2111 return (uint16_t)zig_lo_u128(arg);
2112}
2113static inline uint16_t zig_u16_intCast_i128(zig_i128 arg) {
2114 return (uint16_t)zig_lo_i128(arg);
2115}
2116static inline int16_t zig_i16_intCast_i128(zig_i128 arg) {
2117 return (int16_t)zig_lo_i128(arg);
2118}
2119static inline int16_t zig_i16_intCast_u128(zig_u128 arg) {
2120 return (int16_t)zig_lo_u128(arg);
2121}
18972122
1898static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) {
1899 return val ^ zig_maxInt_u(128, bits);
2123static inline uint32_t zig_u32_intCast_u128(zig_u128 arg) {
2124 return (uint32_t)zig_lo_u128(arg);
2125}
2126static inline uint32_t zig_u32_intCast_i128(zig_i128 arg) {
2127 return (uint32_t)zig_lo_i128(arg);
2128}
2129static inline int32_t zig_i32_intCast_i128(zig_i128 arg) {
2130 return (int32_t)zig_lo_i128(arg);
2131}
2132static inline int32_t zig_i32_intCast_u128(zig_u128 arg) {
2133 return (int32_t)zig_lo_u128(arg);
19002134}
19012135
1902static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) {
1903 (void)bits;
1904 return ~val;
2136static inline uint64_t zig_u64_intCast_u128(zig_u128 arg) {
2137 return zig_lo_u128(arg);
2138}
2139static inline uint64_t zig_u64_intCast_i128(zig_i128 arg) {
2140 return zig_lo_i128(arg);
2141}
2142static inline int64_t zig_i64_intCast_i128(zig_i128 arg) {
2143 return (int64_t)zig_lo_i128(arg);
2144}
2145static inline int64_t zig_i64_intCast_u128(zig_u128 arg) {
2146 return (int64_t)zig_lo_u128(arg);
19052147}
19062148
1907static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
1908 return lhs >> rhs;
2149static inline zig_u128 zig_u128_intCast_u8(uint8_t arg) {
2150 return zig_make_u128(UINT8_C(0), arg);
2151}
2152static inline zig_u128 zig_u128_intCast_i8(int8_t arg) {
2153 return zig_make_u128(UINT8_C(0), (uint8_t)arg);
2154}
2155static inline zig_i128 zig_i128_intCast_i8(int8_t arg) {
2156 return zig_make_i128(zig_shr_i64(arg, 63), (uint8_t)arg);
2157}
2158static inline zig_i128 zig_i128_intCast_u8(uint8_t arg) {
2159 return zig_make_i128(INT8_C(0), arg);
19092160}
19102161
1911static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
1912 return lhs << rhs;
2162static inline zig_u128 zig_u128_intCast_u16(uint16_t arg) {
2163 return zig_make_u128(UINT16_C(0), arg);
2164}
2165static inline zig_u128 zig_u128_intCast_i16(int16_t arg) {
2166 return zig_make_u128(UINT16_C(0), (uint16_t)arg);
2167}
2168static inline zig_i128 zig_i128_intCast_i16(int16_t arg) {
2169 return zig_make_i128(zig_shr_i64(arg, 63), (uint16_t)arg);
2170}
2171static inline zig_i128 zig_i128_intCast_u16(uint16_t arg) {
2172 return zig_make_i128(INT16_C(0), arg);
19132173}
19142174
1915static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
1916 // This works around a GCC miscompilation, but it has the side benefit of
1917 // emitting better code. It is behind the `#if` because it depends on
1918 // arithmetic right shift, which is implementation-defined in C, but should
1919 // be guaranteed on any GCC-compatible compiler.
1920#if defined(zig_gnuc)
1921 return lhs >> rhs;
2175static inline zig_u128 zig_u128_intCast_u32(uint32_t arg) {
2176 return zig_make_u128(UINT32_C(0), arg);
2177}
2178static inline zig_u128 zig_u128_intCast_i32(int32_t arg) {
2179 return zig_make_u128(UINT32_C(0), (uint32_t)arg);
2180}
2181static inline zig_i128 zig_i128_intCast_i32(int32_t arg) {
2182 return zig_make_i128(zig_shr_i64(arg, 63), (uint32_t)arg);
2183}
2184static inline zig_i128 zig_i128_intCast_u32(uint32_t arg) {
2185 return zig_make_i128(INT32_C(0), arg);
2186}
2187
2188static inline zig_u128 zig_u128_intCast_u64(uint64_t arg) {
2189 return zig_make_u128(UINT64_C(0), arg);
2190}
2191static inline zig_u128 zig_u128_intCast_i64(int64_t arg) {
2192 return zig_make_u128(UINT64_C(0), (uint64_t)arg);
2193}
2194static inline zig_i128 zig_i128_intCast_i64(int64_t arg) {
2195 return zig_make_i128(zig_shr_i64(arg, 63), (uint64_t)arg);
2196}
2197static inline zig_i128 zig_i128_intCast_u64(uint64_t arg) {
2198 return zig_make_i128(INT64_C(0), arg);
2199}
2200
2201static inline zig_u128 zig_u128_intCast_u128(zig_u128 arg) {
2202 return arg;
2203}
2204static inline zig_u128 zig_u128_intCast_i128(zig_i128 arg) {
2205#if zig_has_int128
2206 return (zig_u128)arg;
19222207#else
1923 zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0);
1924 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask;
2208 return zig_make_u128(zig_u64_bitCast_i64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg));
2209#endif
2210}
2211static inline zig_i128 zig_i128_intCast_i128(zig_i128 arg) {
2212 return arg;
2213}
2214static inline zig_i128 zig_i128_intCast_u128(zig_u128 arg) {
2215#if zig_has_int128
2216 return (zig_i128)arg;
2217#else
2218 return zig_make_i128(zig_i64_bitCast_u64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg));
19252219#endif
19262220}
19272221
1928static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {
1929 return lhs << rhs;
2222#define zig_int128_cast_builtins(w) \
2223 static inline uint##w##_t zig_u##w##_truncate_u128(zig_u128 arg, uint8_t bits) { \
2224 return zig_u##w##_truncate_u##w((uint##w##_t)zig_lo_u128(arg), bits); \
2225 } \
2226\
2227 static inline int##w##_t zig_i##w##_truncate_i128(zig_i128 arg, uint8_t bits) { \
2228 return zig_i##w##_truncate_i##w((int##w##_t)zig_lo_i128(arg), bits); \
2229 }
2230zig_int128_cast_builtins(8)
2231zig_int128_cast_builtins(16)
2232zig_int128_cast_builtins(32)
2233zig_int128_cast_builtins(64)
2234
2235static inline zig_u128 zig_u128_truncate_u128(zig_u128 arg, uint8_t bits) {
2236 return zig_and_u128(arg, zig_maxInt_u(128, bits));
2237}
2238static inline zig_i128 zig_i128_truncate_i128(zig_i128 arg, uint8_t bits) {
2239 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));
2240 int64_t lo = zig_i64_truncate_i128(arg, bits);
2241 return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo);
2242}
2243
2244static inline zig_u128 zig_u128_bitCast_u128(zig_u128 arg, uint8_t bits) {
2245 (void)bits;
2246 return arg;
2247}
2248static inline zig_u128 zig_u128_bitCast_i128(zig_i128 arg, uint8_t bits) {
2249 return zig_u128_truncate_u128(zig_u128_intCast_i128(arg), bits);
2250}
2251static inline zig_i128 zig_i128_bitCast_i128(zig_i128 arg, uint8_t bits) {
2252 (void)bits;
2253 return arg;
2254}
2255static inline zig_i128 zig_i128_bitCast_u128(zig_u128 arg, uint8_t bits) {
2256 return zig_i128_truncate_i128(zig_i128_intCast_u128(arg), bits);
2257}
2258
2259#if zig_has_int128
2260
2261static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) {
2262 return arg ^ zig_maxInt_u(128, bits);
2263}
2264
2265static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) {
2266 (void)bits;
2267 return ~arg;
19302268}
19312269
19322270static 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) {
19532291 return lhs * rhs;
19542292}
19552293
1956static inline zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) {
2294static inline zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) {
19572295 return lhs / rhs;
19582296}
19592297
1960static inline zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) {
2298static inline zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) {
19612299 return lhs / rhs;
19622300}
19632301
......@@ -1971,36 +2309,14 @@ static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
19712309
19722310#else /* zig_has_int128 */
19732311
1974static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) {
1975 return (zig_u128){ .hi = zig_not_u64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) };
1976}
1977
1978static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) {
1979 return (zig_i128){ .hi = zig_not_i64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) };
1980}
1981
1982static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
1983 if (rhs == UINT8_C(0)) return lhs;
1984 if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - UINT8_C(64)) };
1985 return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (UINT8_C(64) - rhs) | lhs.lo >> rhs };
1986}
1987
1988static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
1989 if (rhs == UINT8_C(0)) return lhs;
1990 if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
1991 return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
1992}
1993
1994static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
1995 if (rhs == UINT8_C(0)) return lhs;
1996 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))) };
1997 return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) };
2312static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) {
2313 if (bits <= UINT8_C(64)) return (zig_u128){ .hi = UINT64_C(0), .lo = zig_not_u64(arg.lo, bits) };
2314 return (zig_u128){ .hi = zig_not_u64(arg.hi, bits - UINT8_C(64)), .lo = zig_not_u64(arg.lo, UINT8_C(64)) };
19982315}
19992316
2000static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {
2001 if (rhs == UINT8_C(0)) return lhs;
2002 if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
2003 return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
2317static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) {
2318 (void)bits;
2319 return (zig_i128){ .hi = ~arg.hi, .lo = ~arg.lo };
20042320}
20052321
20062322static 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) {
20272343 return res;
20282344}
20292345
2030zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs);
20312346static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {
2347 zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs);
20322348 return __multi3(lhs, rhs);
20332349}
20342350
20352351static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) {
2036 return zig_bitCast_u128(zig_mul_i128(zig_bitCast_i128(lhs), zig_bitCast_i128(rhs)));
2352 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));
20372353}
20382354
2039zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs);
2040static zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) {
2355static zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) {
2356 zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs);
20412357 return __udivti3(lhs, rhs);
20422358}
20432359
2044zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs);
2045static zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) {
2360static zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) {
2361 zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs);
20462362 return __divti3(lhs, rhs);
20472363}
20482364
2049zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs);
20502365static zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) {
2366 zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs);
20512367 return __umodti3(lhs, rhs);
20522368}
20532369
2054zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs);
20552370static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
2371 zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs);
20562372 return __modti3(lhs, rhs);
20572373}
20582374
20592375#endif /* zig_has_int128 */
20602376
2061#define zig_div_floor_u128 zig_div_trunc_u128
2377#define zig_divFloor_u128 zig_divTrunc_u128
20622378
2063static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) {
2379static inline zig_i128 zig_divFloor_i128(zig_i128 lhs, zig_i128 rhs) {
20642380 zig_i128 rem = zig_rem_i128(lhs, rhs);
20652381 int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0)
20662382 ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) : INT64_C(0);
2067 return zig_add_i128(zig_div_trunc_i128(lhs, rhs), zig_make_i128(mask, (uint64_t)mask));
2383 return zig_add_i128(zig_divTrunc_i128(lhs, rhs), zig_make_i128(mask, (uint64_t)mask));
20682384}
20692385
2070static inline zig_u128 zig_div_ceil_u128(zig_u128 lhs, zig_u128 rhs) {
2386static inline zig_u128 zig_divCeil_u128(zig_u128 lhs, zig_u128 rhs) {
20712387 zig_u128 rem = zig_rem_u128(lhs, rhs);
20722388 uint64_t mask = zig_or_u64(zig_hi_u128(rem), zig_lo_u128(rem)) != UINT64_C(0)
20732389 ? UINT64_C(1) : UINT64_C(0);
2074 return zig_add_u128(zig_div_trunc_u128(lhs, rhs), zig_make_u128(UINT64_C(0), mask));
2390 return zig_add_u128(zig_divTrunc_u128(lhs, rhs), zig_make_u128(UINT64_C(0), mask));
20752391}
20762392
2077static inline zig_i128 zig_div_ceil_i128(zig_i128 lhs, zig_i128 rhs) {
2393static inline zig_i128 zig_divCeil_i128(zig_i128 lhs, zig_i128 rhs) {
20782394 zig_i128 rem = zig_rem_i128(lhs, rhs);
20792395 int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0)
20802396 ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) + INT64_C(1)
20812397 : INT64_C(0);
2082 return zig_add_i128(zig_div_trunc_i128(lhs, rhs), zig_make_i128(INT64_C(0), (uint64_t)mask));
2398 return zig_add_i128(zig_divTrunc_i128(lhs, rhs), zig_make_i128(INT64_C(0), (uint64_t)mask));
20832399}
20842400
20852401#define zig_mod_u128 zig_rem_u128
......@@ -2107,51 +2423,41 @@ static inline zig_i128 zig_max_i128(zig_i128 lhs, zig_i128 rhs) {
21072423 return zig_cmp_i128(lhs, rhs) > INT32_C(0) ? lhs : rhs;
21082424}
21092425
2110static inline zig_u128 zig_wrap_u128(zig_u128 val, uint8_t bits) {
2111 return zig_and_u128(val, zig_maxInt_u(128, bits));
2112}
2113
2114static inline zig_i128 zig_wrap_i128(zig_i128 val, uint8_t bits) {
2115 if (bits > UINT8_C(64)) return zig_make_i128(zig_wrap_i64(zig_hi_i128(val), bits - UINT8_C(64)), zig_lo_i128(val));
2116 int64_t lo = zig_wrap_i64((int64_t)zig_lo_i128(val), bits);
2117 return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo);
2118}
2119
21202426static inline zig_u128 zig_shlw_u128(zig_u128 lhs, uint8_t rhs, uint8_t bits) {
2121 return zig_wrap_u128(zig_shl_u128(lhs, rhs), bits);
2427 return zig_u128_truncate_u128(zig_shl_u128(lhs, rhs), bits);
21222428}
21232429
21242430static inline zig_i128 zig_shlw_i128(zig_i128 lhs, uint8_t rhs, uint8_t bits) {
2125 return zig_wrap_i128(zig_bitCast_i128(zig_shl_u128(zig_bitCast_u128(lhs), rhs)), bits);
2431 return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_shl_u128(zig_u128_bitCast_i128(lhs, bits), rhs), bits), bits);
21262432}
21272433
21282434static inline zig_u128 zig_addw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2129 return zig_wrap_u128(zig_add_u128(lhs, rhs), bits);
2435 return zig_u128_truncate_u128(zig_add_u128(lhs, rhs), bits);
21302436}
21312437
21322438static inline zig_i128 zig_addw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2133 return zig_wrap_i128(zig_bitCast_i128(zig_add_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits);
2439 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);
21342440}
21352441
21362442static inline zig_u128 zig_subw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2137 return zig_wrap_u128(zig_sub_u128(lhs, rhs), bits);
2443 return zig_u128_truncate_u128(zig_sub_u128(lhs, rhs), bits);
21382444}
21392445
21402446static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2141 return zig_wrap_i128(zig_bitCast_i128(zig_sub_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits);
2447 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);
21422448}
21432449
21442450static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2145 return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits);
2451 return zig_u128_truncate_u128(zig_mul_u128(lhs, rhs), bits);
21462452}
21472453
21482454static inline zig_i128 zig_mulw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2149 return zig_wrap_i128(zig_bitCast_i128(zig_mul_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits);
2455 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);
21502456}
21512457
2152static inline zig_u128 zig_abs_i128(zig_i128 val) {
2153 zig_i128 tmp = zig_shr_i128(val, 127);
2154 return zig_bitCast_u128(zig_sub_i128(zig_xor_i128(val, tmp), tmp));
2458static inline zig_u128 zig_abs_i128(zig_i128 arg) {
2459 zig_u128 tmp = zig_u128_bitCast_i128(zig_shr_i128(arg, 127), UINT8_C(128));
2460 return zig_sub_u128(zig_xor_u128(zig_u128_bitCast_i128(arg, UINT8_C(128)), tmp), tmp);
21552461}
21562462
21572463#if zig_has_int128
......@@ -2160,7 +2466,7 @@ static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
21602466#if zig_has_builtin(add_overflow)
21612467 zig_u128 full_res;
21622468 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
2163 *res = zig_wrap_u128(full_res, bits);
2469 *res = zig_u128_truncate_u128(full_res, bits);
21642470 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
21652471#else
21662472 *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
21762482 zig_i128 full_res = (zig_i128)((zig_u128)lhs + (zig_u128)rhs);
21772483 bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0;
21782484#endif
2179 *res = zig_wrap_i128(full_res, bits);
2485 *res = zig_i128_truncate_i128(full_res, bits);
21802486 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
21812487}
21822488
......@@ -2184,7 +2490,7 @@ static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
21842490#if zig_has_builtin(sub_overflow)
21852491 zig_u128 full_res;
21862492 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
2187 *res = zig_wrap_u128(full_res, bits);
2493 *res = zig_u128_truncate_u128(full_res, bits);
21882494 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
21892495#else
21902496 *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
22002506 zig_i128 full_res = (zig_i128)((zig_u128)lhs - (zig_u128)rhs);
22012507 bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0;
22022508#endif
2203 *res = zig_wrap_i128(full_res, bits);
2509 *res = zig_i128_truncate_i128(full_res, bits);
22042510 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
22052511}
22062512
......@@ -2208,7 +2514,7 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
22082514#if zig_has_builtin(mul_overflow)
22092515 zig_u128 full_res;
22102516 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
2211 *res = zig_wrap_u128(full_res, bits);
2517 *res = zig_u128_truncate_u128(full_res, bits);
22122518 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
22132519#else
22142520 *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
22162522#endif
22172523}
22182524
2219zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
22202525static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2526 zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
22212527#if zig_has_builtin(mul_overflow)
22222528 zig_i128 full_res;
22232529 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
22262532 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);
22272533 bool overflow = overflow_int != 0;
22282534#endif
2229 *res = zig_wrap_i128(full_res, bits);
2535 *res = zig_i128_truncate_i128(full_res, bits);
22302536 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
22312537}
22322538
22332539#else /* zig_has_int128 */
22342540
22352541static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2236 uint64_t hi;
2237 bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - 64);
2238 return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
2542 if (bits <= UINT8_C(64)) {
2543 uint64_t lo;
2544 bool overflow = zig_addo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits);
2545 *res = zig_u128_intCast_u64(lo);
2546 return overflow;
2547 } else {
2548 uint64_t hi;
2549 bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64));
2550 return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64));
2551 }
22392552}
22402553
22412554static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2242 int64_t hi;
2243 bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - 64);
2244 return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
2555 if (bits <= UINT8_C(64)) {
2556 int64_t lo;
2557 bool overflow = zig_addo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits);
2558 *res = zig_i128_intCast_i64(lo);
2559 return overflow;
2560 } else {
2561 int64_t hi;
2562 bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64));
2563 return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64));
2564 }
22452565}
22462566
22472567static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2248 uint64_t hi;
2249 bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - 64);
2250 return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
2568 if (bits <= UINT8_C(64)) {
2569 uint64_t lo;
2570 bool overflow = zig_subo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits);
2571 *res = zig_u128_intCast_u64(lo);
2572 return overflow;
2573 } else {
2574 uint64_t hi;
2575 bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64));
2576 return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64));
2577 }
22512578}
22522579
22532580static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2254 int64_t hi;
2255 bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - 64);
2256 return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
2581 if (bits <= UINT8_C(64)) {
2582 int64_t lo;
2583 bool overflow = zig_subo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits);
2584 *res = zig_i128_intCast_i64(lo);
2585 return overflow;
2586 } else {
2587 int64_t hi;
2588 bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64));
2589 return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64));
2590 }
22572591}
22582592
22592593static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
22602594 *res = zig_mulw_u128(lhs, rhs, bits);
2261 return zig_cmp_u128(*res, zig_make_u128(0, 0)) != INT32_C(0) &&
2262 zig_cmp_u128(lhs, zig_div_trunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0);
2595 return zig_cmp_u128(rhs, zig_make_u128(0, 0)) != INT32_C(0) &&
2596 zig_cmp_u128(lhs, zig_divTrunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0);
22632597}
22642598
2265zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
22662599static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2600 zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
22672601 int overflow_int;
22682602 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);
22692603 bool overflow = overflow_int != 0 ||
22702604 zig_cmp_i128(full_res, zig_minInt_i(128, bits)) < INT32_C(0) ||
22712605 zig_cmp_i128(full_res, zig_maxInt_i(128, bits)) > INT32_C(0);
2272 *res = zig_wrap_i128(full_res, bits);
2606 *res = zig_i128_truncate_i128(full_res, bits);
22732607 return overflow;
22742608}
22752609
......@@ -2282,28 +2616,54 @@ static inline bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, uint8_t rhs, uint8
22822616
22832617static inline bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, uint8_t rhs, uint8_t bits) {
22842618 *res = zig_shlw_i128(lhs, rhs, bits);
2285 zig_i128 mask = zig_bitCast_i128(zig_shl_u128(zig_maxInt_u128, bits - rhs - UINT8_C(1)));
2619 zig_i128 mask = zig_i128_bitCast_u128(zig_shl_u128(zig_maxInt_u128, bits - rhs - UINT8_C(1)), bits);
22862620 return zig_cmp_i128(zig_and_i128(lhs, mask), zig_make_i128(0, 0)) != INT32_C(0) &&
22872621 zig_cmp_i128(zig_and_i128(lhs, mask), mask) != INT32_C(0);
22882622}
22892623
2290static inline zig_u128 zig_shls_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2624#define zig_int128_shls_builtins(rw) \
2625 static inline zig_u128 zig_shls_u128_u##rw(zig_u128 lhs, uint##rw##_t rhs, uint8_t bits) { \
2626 zig_u128 res; \
2627 if (rhs < bits && !zig_shlo_u128(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \
2628 switch (zig_cmp_u128(lhs, zig_make_u128(UINT64_C(0), UINT64_C(0)))) { \
2629 case 0: return zig_minInt_u(128, bits); \
2630 case 1: return zig_maxInt_u(128, bits); \
2631 default: zig_unreachable(); \
2632 } \
2633 } \
2634\
2635 static inline zig_i128 zig_shls_i128_u##rw(zig_i128 lhs, uint##rw##_t rhs, uint8_t bits) { \
2636 zig_i128 res; \
2637 if (rhs < bits && !zig_shlo_i128(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \
2638 switch (zig_cmp_i128(lhs, zig_make_i128(INT64_C(0), UINT64_C(0)))) { \
2639 case -1: return zig_minInt_i(128, bits); \
2640 case 0: return zig_make_i128(INT64_C(0), UINT64_C(0)); \
2641 case 1: return zig_maxInt_i(128, bits); \
2642 default: zig_unreachable(); \
2643 } \
2644 }
2645zig_int128_shls_builtins(8)
2646zig_int128_shls_builtins(16)
2647zig_int128_shls_builtins(32)
2648zig_int128_shls_builtins(64)
2649
2650static inline zig_u128 zig_shls_u128_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
22912651 zig_u128 res;
22922652 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;
22932653 switch (zig_cmp_u128(lhs, zig_make_u128(0, 0))) {
2294 case 0: return zig_make_u128(0, 0);
2295 case 1: return zig_maxInt_u(128, bits);
2654 case INT32_C(0): return zig_make_u128(0, 0);
2655 case INT32_C(1): return zig_maxInt_u(128, bits);
22962656 default: zig_unreachable();
22972657 }
22982658}
22992659
2300static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) {
2660static inline zig_i128 zig_shls_i128_u128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) {
23012661 zig_i128 res;
23022662 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;
23032663 switch (zig_cmp_i128(lhs, zig_make_i128(0, 0))) {
2304 case -1: return zig_minInt_i(128, bits);
2305 case 0: return zig_make_i128(0, 0);
2306 case 1: return zig_maxInt_i(128, bits);
2664 case -INT32_C(1): return zig_minInt_i(128, bits);
2665 case INT32_C(0): return zig_make_i128(0, 0);
2666 case INT32_C(1): return zig_maxInt_i(128, bits);
23072667 default: zig_unreachable();
23082668 }
23092669}
......@@ -2341,57 +2701,60 @@ static inline zig_i128 zig_muls_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
23412701 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);
23422702}
23432703
2344static inline uint8_t zig_clz_u128(zig_u128 val, uint8_t bits) {
2345 if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(val), bits);
2346 if (zig_hi_u128(val) != 0) return zig_clz_u64(zig_hi_u128(val), bits - UINT8_C(64));
2347 return zig_clz_u64(zig_lo_u128(val), UINT8_C(64)) + (bits - UINT8_C(64));
2704static inline uint8_t zig_clz_u128(zig_u128 arg, uint8_t bits) {
2705 if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(arg), bits);
2706 if (zig_hi_u128(arg) != 0) return zig_clz_u64(zig_hi_u128(arg), bits - UINT8_C(64));
2707 return zig_clz_u64(zig_lo_u128(arg), UINT8_C(64)) + (bits - UINT8_C(64));
23482708}
23492709
2350static inline uint8_t zig_clz_i128(zig_i128 val, uint8_t bits) {
2351 return zig_clz_u128(zig_bitCast_u128(val), bits);
2710static inline uint8_t zig_clz_i128(zig_i128 arg, uint8_t bits) {
2711 return zig_clz_u128(zig_u128_bitCast_i128(arg, bits), bits);
23522712}
23532713
2354static inline uint8_t zig_ctz_u128(zig_u128 val, uint8_t bits) {
2355 if (zig_lo_u128(val) != 0) return zig_ctz_u64(zig_lo_u128(val), UINT8_C(64));
2356 return zig_ctz_u64(zig_hi_u128(val), bits - UINT8_C(64)) + UINT8_C(64);
2714static inline uint8_t zig_ctz_u128(zig_u128 arg, uint8_t bits) {
2715 if (zig_lo_u128(arg) != 0) return zig_ctz_u64(zig_lo_u128(arg), UINT8_C(64));
2716 return zig_ctz_u64(zig_hi_u128(arg), bits - UINT8_C(64)) + UINT8_C(64);
23572717}
23582718
2359static inline uint8_t zig_ctz_i128(zig_i128 val, uint8_t bits) {
2360 return zig_ctz_u128(zig_bitCast_u128(val), bits);
2719static inline uint8_t zig_ctz_i128(zig_i128 arg, uint8_t bits) {
2720 return zig_ctz_u128(zig_u128_bitCast_i128(arg, bits), bits);
23612721}
23622722
2363static inline uint8_t zig_popcount_u128(zig_u128 val, uint8_t bits) {
2364 return zig_popcount_u64(zig_hi_u128(val), bits - UINT8_C(64)) +
2365 zig_popcount_u64(zig_lo_u128(val), UINT8_C(64));
2723static inline uint8_t zig_popCount_u128(zig_u128 arg, uint8_t bits) {
2724 return (bits > UINT8_C(64) ? zig_popCount_u64(zig_hi_u128(arg), bits - UINT8_C(64)) : UINT8_C(0)) +
2725 zig_popCount_u64(zig_lo_u128(arg), UINT8_C(64));
23662726}
23672727
2368static inline uint8_t zig_popcount_i128(zig_i128 val, uint8_t bits) {
2369 return zig_popcount_u128(zig_bitCast_u128(val), bits);
2728static inline uint8_t zig_popCount_i128(zig_i128 arg, uint8_t bits) {
2729 return zig_popCount_u128(zig_u128_bitCast_i128(arg, bits), bits);
23702730}
23712731
2372static inline zig_u128 zig_byte_swap_u128(zig_u128 val, uint8_t bits) {
2732static inline zig_u128 zig_byteSwap_u128(zig_u128 arg, uint8_t bits) {
23732733 zig_u128 full_res;
23742734#if zig_has_builtin(bswap128)
2375 full_res = __builtin_bswap128(val);
2735 full_res = __builtin_bswap128(arg);
23762736#else
2377 full_res = zig_make_u128(zig_byte_swap_u64(zig_lo_u128(val), UINT8_C(64)),
2378 zig_byte_swap_u64(zig_hi_u128(val), UINT8_C(64)));
2737 full_res = zig_make_u128(
2738 zig_byteSwap_u64(zig_lo_u128(arg), UINT8_C(64)),
2739 zig_byteSwap_u64(zig_hi_u128(arg), UINT8_C(64))
2740 );
23792741#endif
23802742 return zig_shr_u128(full_res, UINT8_C(128) - bits);
23812743}
23822744
2383static inline zig_i128 zig_byte_swap_i128(zig_i128 val, uint8_t bits) {
2384 return zig_bitCast_i128(zig_byte_swap_u128(zig_bitCast_u128(val), bits));
2745static inline zig_i128 zig_byteSwap_i128(zig_i128 arg, uint8_t bits) {
2746 return zig_i128_bitCast_u128(zig_byteSwap_u128(zig_u128_bitCast_i128(arg, bits), bits), bits);
23852747}
23862748
2387static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, uint8_t bits) {
2388 return zig_shr_u128(zig_make_u128(zig_bit_reverse_u64(zig_lo_u128(val), UINT8_C(64)),
2389 zig_bit_reverse_u64(zig_hi_u128(val), UINT8_C(64))),
2390 UINT8_C(128) - bits);
2749static inline zig_u128 zig_bitReverse_u128(zig_u128 arg, uint8_t bits) {
2750 return zig_shr_u128(zig_make_u128(
2751 zig_bitReverse_u64(zig_lo_u128(arg), UINT8_C(64)),
2752 zig_bitReverse_u64(zig_hi_u128(arg), UINT8_C(64))
2753 ), UINT8_C(128) - bits);
23912754}
23922755
2393static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) {
2394 return zig_bitCast_i128(zig_bit_reverse_u128(zig_bitCast_u128(val), bits));
2756static inline zig_i128 zig_bitReverse_i128(zig_i128 arg, uint8_t bits) {
2757 return zig_i128_bitCast_u128(zig_bitReverse_u128(zig_u128_bitCast_i128(arg, bits), bits), bits);
23952758}
23962759
23972760#if zig_has_int128
......@@ -2411,15 +2774,218 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) {
24112774/* ========================== Big Integer Support =========================== */
24122775
24132776static inline uint16_t zig_int_bytes(uint16_t bits) {
2414 uint16_t bytes = (bits + CHAR_BIT - 1) / CHAR_BIT;
2777 uint16_t bytes = (bits - UINT16_C(1)) / CHAR_BIT + UINT16_C(1);
24152778 uint16_t alignment = ZIG_TARGET_MAX_INT_ALIGNMENT;
2779
24162780 while (alignment / 2 >= bytes) alignment /= 2;
24172781 return (bytes + alignment - 1) / alignment * alignment;
24182782}
24192783
2420static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2784static inline void zig_minInt_big(void *res, bool is_signed, uint16_t bits) {
2785 uint8_t *res_bytes = res;
2786 uint16_t size = zig_int_bytes(bits);
2787 uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3));
2788 uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1);
2789 uint8_t sign_byte;
2790 uint8_t fill_byte;
2791
2792 if (is_signed) {
2793 int8_t signed_sign_byte = zig_minInt_i(8, remainder_bits);
2794
2795 sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8));
2796 fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8));
2797 } else {
2798 sign_byte = zig_minInt_u(8, remainder_bits);
2799 fill_byte = UINT8_C(0);
2800 }
2801
2802#if zig_little_endian
2803 memset(&res_bytes[0], zig_minInt_u8, byte_offset);
2804 res_bytes[byte_offset] = sign_byte;
2805 byte_offset += UINT16_C(1);
2806 memset(&res_bytes[byte_offset], fill_byte, size - byte_offset);
2807#else
2808 byte_offset = size - UINT16_C(1) - byte_offset;
2809 memset(&res_bytes[0], fill_byte, byte_offset);
2810 res_bytes[byte_offset] = sign_byte;
2811 byte_offset += UINT16_C(1);
2812 memset(&res_bytes[byte_offset], zig_minInt_u8, size - byte_offset);
2813#endif
2814}
2815
2816static inline void zig_maxInt_big(void *res, bool is_signed, uint16_t bits) {
2817 uint8_t *res_bytes = res;
2818 uint16_t size = zig_int_bytes(bits);
2819 uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3));
2820 uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1);
2821 uint8_t sign_byte;
2822 uint8_t fill_byte;
2823
2824 if (is_signed) {
2825 int8_t signed_sign_byte = zig_maxInt_i(8, remainder_bits);
2826
2827 sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8));
2828 fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8));
2829 } else {
2830 sign_byte = zig_maxInt_u(8, remainder_bits);
2831 fill_byte = UINT8_C(0);
2832 }
2833
2834#if zig_little_endian
2835 memset(&res_bytes[0], zig_maxInt_u8, byte_offset);
2836 res_bytes[byte_offset] = sign_byte;
2837 byte_offset += UINT16_C(1);
2838 memset(&res_bytes[byte_offset], fill_byte, size - byte_offset);
2839#else
2840 byte_offset = size - UINT16_C(1) - byte_offset;
2841 memset(&res_bytes[0], fill_byte, byte_offset);
2842 res_bytes[byte_offset] = sign_byte;
2843 byte_offset += UINT16_C(1);
2844 memset(&res_bytes[byte_offset], zig_maxInt_u8, size - byte_offset);
2845#endif
2846}
2847
2848static inline int8_t zig_signFill_big(const void *arg, bool is_signed, uint16_t bits) {
2849 const uint8_t *arg_bytes = arg;
2850 uint16_t byte_offset = 0;
2851
2852 if (!is_signed) return INT8_C(0);
2853#if zig_little_endian
2854 byte_offset = zig_int_bytes(bits) - 1;
2855#endif
2856 return zig_shr_i8(zig_i8_bitCast_u8(arg_bytes[byte_offset], UINT8_C(8)), UINT8_C(7));
2857}
2858
2859static 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) {
2860 uint8_t *res_bytes = res;
2861 const uint8_t *arg_bytes = arg;
2862 uint16_t res_size = zig_int_bytes(res_bits);
2863 uint16_t arg_size = zig_int_bytes(arg_bits);
2864 uint16_t copy_size = zig_min_u16(res_size, arg_size);
2865 uint8_t sign_fill = zig_u8_bitCast_i8(zig_signFill_big(arg, arg_is_signed, arg_bits), UINT8_C(8));
2866
2867#if zig_little_endian
2868 memcpy(&res_bytes[0], &arg_bytes[0], copy_size);
2869 memset(&res_bytes[copy_size], sign_fill, res_size - copy_size);
2870#else
2871 memset(&res_bytes[0], sign_fill, res_size - copy_size);
2872 memcpy(&res_bytes[res_size - copy_size], &arg_bytes[arg_size - copy_size], copy_size);
2873#endif
2874}
2875
2876static 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) {
2877 uint8_t *res_bytes = res;
2878 const uint8_t *arg_bytes = arg;
2879 uint16_t res_size = zig_int_bytes(res_bits);
2880
2881 if (res_is_signed != arg_is_signed) zig_unreachable();
2882 if (res_bits > arg_bits) zig_unreachable();
2883
2884 if (res_is_signed) {
2885 uint16_t arg_byte_offset = UINT16_C(0);
2886
2887#if zig_big_endian
2888 arg_byte_offset = zig_int_bytes(arg_bits) - res_size;
2889#endif
2890
2891 memcpy(&res_bytes[0], &arg_bytes[arg_byte_offset], res_size);
2892 } else {
2893 uint16_t res_byte_offset = zig_shr_u16(res_bits - UINT16_C(1), UINT8_C(3));
2894 uint16_t arg_byte_offset = res_byte_offset;
2895
2896#if zig_little_endian
2897 memcpy(&res_bytes[0], &arg_bytes[0], res_byte_offset);
2898#else
2899 res_byte_offset = res_size - UINT16_C(1) - res_byte_offset;
2900 arg_byte_offset = zig_int_bytes(arg_bits) - UINT16_C(1) - arg_byte_offset;
2901
2902 memset(&res_bytes[0], zig_minInt_u8, res_byte_offset);
2903#endif
2904
2905 res_bytes[res_byte_offset] = zig_u8_truncate_u8(
2906 arg_bytes[arg_byte_offset],
2907 zig_u8_truncate_u8(res_bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1)
2908 );
2909 res_byte_offset += UINT16_C(1);
2910 arg_byte_offset += UINT16_C(1);
2911
2912#if zig_little_endian
2913 memset(&res_bytes[res_byte_offset], zig_minInt_u8, res_size - res_byte_offset);
2914#else
2915 memcpy(&res_bytes[res_byte_offset], &arg_bytes[arg_byte_offset], res_size - res_byte_offset);
2916#endif
2917 }
2918}
2919
2920#define zig_big_casts(is, s, w, IntType) \
2921 static inline IntType zig_##s##w##_intCast_big(const void *arg, bool arg_is_signed, uint16_t arg_bits) { \
2922 IntType res; \
2923 zig_big_intCast_big(&res, arg, is, w, arg_is_signed, arg_bits); \
2924 return res; \
2925 } \
2926\
2927 static inline void zig_big_intCast_##s##w(void *res, IntType arg, bool res_is_signed, uint16_t res_bits) { \
2928 zig_big_intCast_big(res, &arg, res_is_signed, res_bits, is, w); \
2929 } \
2930\
2931 static inline IntType zig_##s##w##_truncate_big(const void *arg, uint8_t res_bits, bool arg_is_signed, uint16_t arg_bits) { \
2932 IntType res; \
2933 zig_big_truncate_big(&res, arg, is, res_bits, arg_is_signed, arg_bits); \
2934 return res; \
2935 } \
2936\
2937 static inline void zig_big_truncate_##s##w(void *res, IntType arg, bool res_is_signed, uint16_t res_bits) { \
2938 zig_big_truncate_big(res, &arg, res_is_signed, res_bits, is, w); \
2939 }
2940zig_big_casts(false, u, 8, uint8_t)
2941zig_big_casts(true , i, 8, int8_t)
2942zig_big_casts(false, u, 16, uint16_t)
2943zig_big_casts(true , i, 16, int16_t)
2944zig_big_casts(false, u, 32, uint32_t)
2945zig_big_casts(true , i, 32, int32_t)
2946zig_big_casts(false, u, 64, uint64_t)
2947zig_big_casts(true , i, 64, int64_t)
2948zig_big_casts(false, u, 128, zig_u128)
2949zig_big_casts(true , i, 128, zig_i128)
2950
2951static inline void zig_big_bitCast_big(void *res, const void *arg, bool res_is_signed, uint16_t bits) {
2952 uint8_t *res_bytes = res;
2953 const uint8_t *arg_bytes = arg;
2954 uint16_t size = zig_int_bytes(bits);
2955 uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3));
2956 uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1);
2957 uint8_t sign_byte;
2958 uint8_t fill_byte;
2959
2960#if zig_big_endian
2961 byte_offset = size - UINT16_C(1) - byte_offset;
2962#endif
2963
2964 if (res_is_signed) {
2965 int8_t signed_sign_byte = zig_i8_bitCast_u8(arg_bytes[byte_offset], remainder_bits);
2966
2967 sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8));
2968 fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8));
2969 } else {
2970 sign_byte = zig_u8_bitCast_u8(arg_bytes[byte_offset], remainder_bits);
2971 fill_byte = UINT8_C(0);
2972 }
2973
2974#if zig_little_endian
2975 memcpy(&res_bytes[0], &arg_bytes[0], byte_offset);
2976 res_bytes[byte_offset] = sign_byte;
2977 byte_offset += UINT16_C(1);
2978 memset(&res_bytes[byte_offset], fill_byte, size - byte_offset);
2979#else
2980 memset(&res_bytes[0], fill_byte, byte_offset);
2981 res_bytes[byte_offset] = sign_byte;
2982 byte_offset += UINT16_C(1);
2983 memcpy(&res_bytes[byte_offset], &arg_bytes[byte_offset], size - byte_offset);
2984#endif
2985}
2986
2987static inline int32_t zig_cmp_big_u8(const void *lhs, uint8_t rhs, bool is_signed, uint16_t bits) {
24212988 const uint8_t *lhs_bytes = lhs;
2422 const uint8_t *rhs_bytes = rhs;
24232989 uint16_t byte_offset = 0;
24242990 bool do_signed = is_signed;
24252991 uint16_t remaining_bytes = zig_int_bytes(bits);
......@@ -2429,6 +2995,7 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
24292995#endif
24302996
24312997 while (remaining_bytes >= 128 / CHAR_BIT) {
2998 uint8_t rhs_byte = remaining_bytes == 128 / CHAR_BIT ? rhs : UINT8_C(0);
24322999 int32_t limb_cmp;
24333000
24343001#if zig_little_endian
......@@ -2437,18 +3004,16 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
24373004
24383005 if (do_signed) {
24393006 zig_i128 lhs_limb;
2440 zig_i128 rhs_limb;
3007 zig_i128 rhs_limb = zig_i128_intCast_u8(rhs_byte);
24413008
24423009 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2443 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
24443010 limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb);
24453011 do_signed = false;
24463012 } else {
24473013 zig_u128 lhs_limb;
2448 zig_u128 rhs_limb;
3014 zig_u128 rhs_limb = zig_u128_intCast_u8(rhs_byte);
24493015
24503016 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2451 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
24523017 limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb);
24533018 }
24543019
......@@ -2461,24 +3026,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
24613026 }
24623027
24633028 while (remaining_bytes >= 64 / CHAR_BIT) {
3029 uint8_t rhs_byte = remaining_bytes == 64 / CHAR_BIT ? rhs : UINT8_C(0);
3030
24643031#if zig_little_endian
24653032 byte_offset -= 64 / CHAR_BIT;
24663033#endif
24673034
24683035 if (do_signed) {
24693036 int64_t lhs_limb;
2470 int64_t rhs_limb;
3037 int64_t rhs_limb = zig_i64_intCast_u8(rhs_byte);
24713038
24723039 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2473 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
24743040 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
24753041 do_signed = false;
24763042 } else {
24773043 uint64_t lhs_limb;
2478 uint64_t rhs_limb;
3044 uint64_t rhs_limb = zig_u64_intCast_u8(rhs_byte);
24793045
24803046 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2481 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
24823047 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
24833048 }
24843049
......@@ -2490,24 +3055,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
24903055 }
24913056
24923057 while (remaining_bytes >= 32 / CHAR_BIT) {
3058 uint8_t rhs_byte = remaining_bytes == 32 / CHAR_BIT ? rhs : UINT8_C(0);
3059
24933060#if zig_little_endian
24943061 byte_offset -= 32 / CHAR_BIT;
24953062#endif
24963063
24973064 if (do_signed) {
24983065 int32_t lhs_limb;
2499 int32_t rhs_limb;
3066 int32_t rhs_limb = zig_i32_intCast_u8(rhs_byte);
25003067
25013068 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2502 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
25033069 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
25043070 do_signed = false;
25053071 } else {
25063072 uint32_t lhs_limb;
2507 uint32_t rhs_limb;
3073 uint32_t rhs_limb = zig_u32_intCast_u8(rhs_byte);
25083074
25093075 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2510 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
25113076 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
25123077 }
25133078
......@@ -2519,24 +3084,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
25193084 }
25203085
25213086 while (remaining_bytes >= 16 / CHAR_BIT) {
3087 uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0);
3088
25223089#if zig_little_endian
25233090 byte_offset -= 16 / CHAR_BIT;
25243091#endif
25253092
25263093 if (do_signed) {
25273094 int16_t lhs_limb;
2528 int16_t rhs_limb;
3095 int16_t rhs_limb = zig_i16_intCast_u8(rhs_byte);
25293096
25303097 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2531 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
25323098 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
25333099 do_signed = false;
25343100 } else {
25353101 uint16_t lhs_limb;
2536 uint16_t rhs_limb;
3102 uint16_t rhs_limb = zig_u16_intCast_u8(rhs_byte);
25373103
25383104 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2539 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
25403105 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
25413106 }
25423107
......@@ -2548,24 +3113,26 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
25483113 }
25493114
25503115 while (remaining_bytes >= 8 / CHAR_BIT) {
3116 uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0);
3117
25513118#if zig_little_endian
25523119 byte_offset -= 8 / CHAR_BIT;
25533120#endif
25543121
25553122 if (do_signed) {
25563123 int8_t lhs_limb;
2557 int8_t rhs_limb;
3124 int16_t lhs_cmp_limb;
3125 int16_t rhs_cmp_limb = zig_i16_intCast_u8(rhs_byte);
25583126
25593127 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2560 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2561 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3128 lhs_cmp_limb = zig_i16_intCast_i8(lhs_limb);
3129 if (lhs_cmp_limb != rhs_cmp_limb) return (lhs_cmp_limb > rhs_cmp_limb) - (lhs_cmp_limb < rhs_cmp_limb);
25623130 do_signed = false;
25633131 } else {
25643132 uint8_t lhs_limb;
2565 uint8_t rhs_limb;
3133 uint8_t rhs_limb = rhs_byte;
25663134
25673135 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2568 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
25693136 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
25703137 }
25713138
......@@ -2579,148 +3146,472 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
25793146 return 0;
25803147}
25813148
2582static inline void zig_and_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2583 uint8_t *res_bytes = res;
3149static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
25843150 const uint8_t *lhs_bytes = lhs;
25853151 const uint8_t *rhs_bytes = rhs;
25863152 uint16_t byte_offset = 0;
3153 bool do_signed = is_signed;
25873154 uint16_t remaining_bytes = zig_int_bytes(bits);
2588 (void)is_signed;
3155
3156#if zig_little_endian
3157 byte_offset = remaining_bytes;
3158#endif
25893159
25903160 while (remaining_bytes >= 128 / CHAR_BIT) {
2591 zig_u128 res_limb;
2592 zig_u128 lhs_limb;
2593 zig_u128 rhs_limb;
3161 int32_t limb_cmp;
25943162
2595 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2596 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2597 res_limb = zig_and_u128(lhs_limb, rhs_limb);
2598 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3163#if zig_little_endian
3164 byte_offset -= 128 / CHAR_BIT;
3165#endif
3166
3167 if (do_signed) {
3168 zig_i128 lhs_limb;
3169 zig_i128 rhs_limb;
3170
3171 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3172 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3173 limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb);
3174 do_signed = false;
3175 } else {
3176 zig_u128 lhs_limb;
3177 zig_u128 rhs_limb;
3178
3179 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3180 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3181 limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb);
3182 }
25993183
3184 if (limb_cmp != 0) return limb_cmp;
26003185 remaining_bytes -= 128 / CHAR_BIT;
3186
3187#if zig_big_endian
26013188 byte_offset += 128 / CHAR_BIT;
3189#endif
26023190 }
26033191
26043192 while (remaining_bytes >= 64 / CHAR_BIT) {
2605 uint64_t res_limb;
2606 uint64_t lhs_limb;
2607 uint64_t rhs_limb;
3193#if zig_little_endian
3194 byte_offset -= 64 / CHAR_BIT;
3195#endif
26083196
2609 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2610 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2611 res_limb = zig_and_u64(lhs_limb, rhs_limb);
2612 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3197 if (do_signed) {
3198 int64_t lhs_limb;
3199 int64_t rhs_limb;
3200
3201 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3202 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3203 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3204 do_signed = false;
3205 } else {
3206 uint64_t lhs_limb;
3207 uint64_t rhs_limb;
3208
3209 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3210 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3211 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3212 }
26133213
26143214 remaining_bytes -= 64 / CHAR_BIT;
3215
3216#if zig_big_endian
26153217 byte_offset += 64 / CHAR_BIT;
3218#endif
26163219 }
26173220
26183221 while (remaining_bytes >= 32 / CHAR_BIT) {
2619 uint32_t res_limb;
2620 uint32_t lhs_limb;
2621 uint32_t rhs_limb;
3222#if zig_little_endian
3223 byte_offset -= 32 / CHAR_BIT;
3224#endif
26223225
2623 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2624 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2625 res_limb = zig_and_u32(lhs_limb, rhs_limb);
2626 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3226 if (do_signed) {
3227 int32_t lhs_limb;
3228 int32_t rhs_limb;
3229
3230 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3231 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3232 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3233 do_signed = false;
3234 } else {
3235 uint32_t lhs_limb;
3236 uint32_t rhs_limb;
3237
3238 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3239 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3240 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3241 }
26273242
26283243 remaining_bytes -= 32 / CHAR_BIT;
3244
3245#if zig_big_endian
26293246 byte_offset += 32 / CHAR_BIT;
3247#endif
26303248 }
26313249
26323250 while (remaining_bytes >= 16 / CHAR_BIT) {
2633 uint16_t res_limb;
2634 uint16_t lhs_limb;
2635 uint16_t rhs_limb;
3251#if zig_little_endian
3252 byte_offset -= 16 / CHAR_BIT;
3253#endif
26363254
2637 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2638 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2639 res_limb = zig_and_u16(lhs_limb, rhs_limb);
2640 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3255 if (do_signed) {
3256 int16_t lhs_limb;
3257 int16_t rhs_limb;
3258
3259 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3260 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3261 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3262 do_signed = false;
3263 } else {
3264 uint16_t lhs_limb;
3265 uint16_t rhs_limb;
3266
3267 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3268 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3269 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3270 }
26413271
26423272 remaining_bytes -= 16 / CHAR_BIT;
3273
3274#if zig_big_endian
26433275 byte_offset += 16 / CHAR_BIT;
3276#endif
26443277 }
26453278
26463279 while (remaining_bytes >= 8 / CHAR_BIT) {
2647 uint8_t res_limb;
2648 uint8_t lhs_limb;
2649 uint8_t rhs_limb;
3280#if zig_little_endian
3281 byte_offset -= 8 / CHAR_BIT;
3282#endif
26503283
2651 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2652 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2653 res_limb = zig_and_u8(lhs_limb, rhs_limb);
2654 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3284 if (do_signed) {
3285 int8_t lhs_limb;
3286 int8_t rhs_limb;
3287
3288 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3289 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3290 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3291 do_signed = false;
3292 } else {
3293 uint8_t lhs_limb;
3294 uint8_t rhs_limb;
3295
3296 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3297 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3298 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3299 }
26553300
26563301 remaining_bytes -= 8 / CHAR_BIT;
3302
3303#if zig_big_endian
26573304 byte_offset += 8 / CHAR_BIT;
3305#endif
26583306 }
3307
3308 return 0;
26593309}
26603310
2661static inline void zig_or_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3311static inline void zig_not_big(void *res, const void *arg, bool is_signed, uint16_t bits) {
26623312 uint8_t *res_bytes = res;
2663 const uint8_t *lhs_bytes = lhs;
2664 const uint8_t *rhs_bytes = rhs;
3313 const uint8_t *arg_bytes = arg;
26653314 uint16_t byte_offset = 0;
26663315 uint16_t remaining_bytes = zig_int_bytes(bits);
2667 (void)is_signed;
3316 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
3317
3318#if zig_big_endian
3319 byte_offset = remaining_bytes;
3320#endif
26683321
26693322 while (remaining_bytes >= 128 / CHAR_BIT) {
2670 zig_u128 res_limb;
2671 zig_u128 lhs_limb;
2672 zig_u128 rhs_limb;
3323 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
26733324
2674 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2675 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2676 res_limb = zig_or_u128(lhs_limb, rhs_limb);
2677 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3325#if zig_big_endian
3326 byte_offset -= 128 / CHAR_BIT;
3327#endif
3328
3329 if (remaining_bytes != 128 / CHAR_BIT || is_signed) {
3330 zig_i128 res_limb;
3331 zig_i128 arg_limb;
3332
3333 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3334 res_limb = zig_not_i128(arg_limb, limb_bits);
3335 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3336 } else {
3337 zig_u128 res_limb;
3338 zig_u128 arg_limb;
3339
3340 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3341 res_limb = zig_not_u128(arg_limb, limb_bits);
3342 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3343 }
26783344
26793345 remaining_bytes -= 128 / CHAR_BIT;
3346
3347#if zig_little_endian
26803348 byte_offset += 128 / CHAR_BIT;
3349#endif
26813350 }
26823351
26833352 while (remaining_bytes >= 64 / CHAR_BIT) {
2684 uint64_t res_limb;
2685 uint64_t lhs_limb;
2686 uint64_t rhs_limb;
3353 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
26873354
2688 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2689 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2690 res_limb = zig_or_u64(lhs_limb, rhs_limb);
2691 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3355#if zig_big_endian
3356 byte_offset -= 64 / CHAR_BIT;
3357#endif
3358
3359 if (remaining_bytes != 64 / CHAR_BIT || is_signed) {
3360 int64_t res_limb;
3361 int64_t arg_limb;
3362
3363 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3364 res_limb = zig_not_i64(arg_limb, limb_bits);
3365 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3366 } else {
3367 uint64_t res_limb;
3368 uint64_t arg_limb;
3369
3370 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3371 res_limb = zig_not_u64(arg_limb, limb_bits);
3372 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3373 }
26923374
26933375 remaining_bytes -= 64 / CHAR_BIT;
3376
3377#if zig_little_endian
26943378 byte_offset += 64 / CHAR_BIT;
3379#endif
26953380 }
26963381
26973382 while (remaining_bytes >= 32 / CHAR_BIT) {
2698 uint32_t res_limb;
2699 uint32_t lhs_limb;
2700 uint32_t rhs_limb;
3383 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
27013384
2702 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2703 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2704 res_limb = zig_or_u32(lhs_limb, rhs_limb);
2705 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3385#if zig_big_endian
3386 byte_offset -= 32 / CHAR_BIT;
3387#endif
3388
3389 if (remaining_bytes != 32 / CHAR_BIT || is_signed) {
3390 int32_t res_limb;
3391 int32_t arg_limb;
3392
3393 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3394 res_limb = zig_not_i32(arg_limb, limb_bits);
3395 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3396 } else {
3397 uint32_t res_limb;
3398 uint32_t arg_limb;
3399
3400 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3401 res_limb = zig_not_u32(arg_limb, limb_bits);
3402 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3403 }
27063404
27073405 remaining_bytes -= 32 / CHAR_BIT;
3406
3407#if zig_little_endian
27083408 byte_offset += 32 / CHAR_BIT;
3409#endif
27093410 }
27103411
27113412 while (remaining_bytes >= 16 / CHAR_BIT) {
2712 uint16_t res_limb;
2713 uint16_t lhs_limb;
2714 uint16_t rhs_limb;
3413 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
27153414
2716 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2717 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2718 res_limb = zig_or_u16(lhs_limb, rhs_limb);
2719 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3415#if zig_big_endian
3416 byte_offset -= 16 / CHAR_BIT;
3417#endif
27203418
2721 remaining_bytes -= 16 / CHAR_BIT;
2722 byte_offset += 16 / CHAR_BIT;
2723 }
3419 if (remaining_bytes != 16 / CHAR_BIT || is_signed) {
3420 int16_t res_limb;
3421 int16_t arg_limb;
3422
3423 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3424 res_limb = zig_not_i16(arg_limb, limb_bits);
3425 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3426 } else {
3427 uint16_t res_limb;
3428 uint16_t arg_limb;
3429
3430 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3431 res_limb = zig_not_u16(arg_limb, limb_bits);
3432 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3433 }
3434
3435 remaining_bytes -= 16 / CHAR_BIT;
3436
3437#if zig_little_endian
3438 byte_offset += 16 / CHAR_BIT;
3439#endif
3440 }
3441
3442 while (remaining_bytes >= 8 / CHAR_BIT) {
3443 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
3444
3445#if zig_big_endian
3446 byte_offset -= 8 / CHAR_BIT;
3447#endif
3448
3449 if (remaining_bytes != 8 / CHAR_BIT || is_signed) {
3450 int8_t res_limb;
3451 int8_t arg_limb;
3452
3453 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3454 res_limb = zig_not_i8(arg_limb, limb_bits);
3455 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3456 } else {
3457 uint8_t res_limb;
3458 uint8_t arg_limb;
3459
3460 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3461 res_limb = zig_not_u8(arg_limb, limb_bits);
3462 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3463 }
3464
3465 remaining_bytes -= 8 / CHAR_BIT;
3466
3467#if zig_little_endian
3468 byte_offset += 8 / CHAR_BIT;
3469#endif
3470 }
3471}
3472
3473static inline void zig_and_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3474 uint8_t *res_bytes = res;
3475 const uint8_t *lhs_bytes = lhs;
3476 const uint8_t *rhs_bytes = rhs;
3477 uint16_t byte_offset = 0;
3478 uint16_t remaining_bytes = zig_int_bytes(bits);
3479 (void)is_signed;
3480
3481 while (remaining_bytes >= 128 / CHAR_BIT) {
3482 zig_u128 res_limb;
3483 zig_u128 lhs_limb;
3484 zig_u128 rhs_limb;
3485
3486 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3487 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3488 res_limb = zig_and_u128(lhs_limb, rhs_limb);
3489 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3490
3491 remaining_bytes -= 128 / CHAR_BIT;
3492 byte_offset += 128 / CHAR_BIT;
3493 }
3494
3495 while (remaining_bytes >= 64 / CHAR_BIT) {
3496 uint64_t res_limb;
3497 uint64_t lhs_limb;
3498 uint64_t rhs_limb;
3499
3500 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3501 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3502 res_limb = zig_and_u64(lhs_limb, rhs_limb);
3503 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3504
3505 remaining_bytes -= 64 / CHAR_BIT;
3506 byte_offset += 64 / CHAR_BIT;
3507 }
3508
3509 while (remaining_bytes >= 32 / CHAR_BIT) {
3510 uint32_t res_limb;
3511 uint32_t lhs_limb;
3512 uint32_t rhs_limb;
3513
3514 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3515 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3516 res_limb = zig_and_u32(lhs_limb, rhs_limb);
3517 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3518
3519 remaining_bytes -= 32 / CHAR_BIT;
3520 byte_offset += 32 / CHAR_BIT;
3521 }
3522
3523 while (remaining_bytes >= 16 / CHAR_BIT) {
3524 uint16_t res_limb;
3525 uint16_t lhs_limb;
3526 uint16_t rhs_limb;
3527
3528 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3529 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3530 res_limb = zig_and_u16(lhs_limb, rhs_limb);
3531 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3532
3533 remaining_bytes -= 16 / CHAR_BIT;
3534 byte_offset += 16 / CHAR_BIT;
3535 }
3536
3537 while (remaining_bytes >= 8 / CHAR_BIT) {
3538 uint8_t res_limb;
3539 uint8_t lhs_limb;
3540 uint8_t rhs_limb;
3541
3542 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3543 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3544 res_limb = zig_and_u8(lhs_limb, rhs_limb);
3545 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3546
3547 remaining_bytes -= 8 / CHAR_BIT;
3548 byte_offset += 8 / CHAR_BIT;
3549 }
3550}
3551
3552static inline void zig_or_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3553 uint8_t *res_bytes = res;
3554 const uint8_t *lhs_bytes = lhs;
3555 const uint8_t *rhs_bytes = rhs;
3556 uint16_t byte_offset = 0;
3557 uint16_t remaining_bytes = zig_int_bytes(bits);
3558 (void)is_signed;
3559
3560 while (remaining_bytes >= 128 / CHAR_BIT) {
3561 zig_u128 res_limb;
3562 zig_u128 lhs_limb;
3563 zig_u128 rhs_limb;
3564
3565 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3566 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3567 res_limb = zig_or_u128(lhs_limb, rhs_limb);
3568 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3569
3570 remaining_bytes -= 128 / CHAR_BIT;
3571 byte_offset += 128 / CHAR_BIT;
3572 }
3573
3574 while (remaining_bytes >= 64 / CHAR_BIT) {
3575 uint64_t res_limb;
3576 uint64_t lhs_limb;
3577 uint64_t rhs_limb;
3578
3579 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3580 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3581 res_limb = zig_or_u64(lhs_limb, rhs_limb);
3582 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3583
3584 remaining_bytes -= 64 / CHAR_BIT;
3585 byte_offset += 64 / CHAR_BIT;
3586 }
3587
3588 while (remaining_bytes >= 32 / CHAR_BIT) {
3589 uint32_t res_limb;
3590 uint32_t lhs_limb;
3591 uint32_t rhs_limb;
3592
3593 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3594 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3595 res_limb = zig_or_u32(lhs_limb, rhs_limb);
3596 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3597
3598 remaining_bytes -= 32 / CHAR_BIT;
3599 byte_offset += 32 / CHAR_BIT;
3600 }
3601
3602 while (remaining_bytes >= 16 / CHAR_BIT) {
3603 uint16_t res_limb;
3604 uint16_t lhs_limb;
3605 uint16_t rhs_limb;
3606
3607 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3608 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3609 res_limb = zig_or_u16(lhs_limb, rhs_limb);
3610 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3611
3612 remaining_bytes -= 16 / CHAR_BIT;
3613 byte_offset += 16 / CHAR_BIT;
3614 }
27243615
27253616 while (remaining_bytes >= 8 / CHAR_BIT) {
27263617 uint8_t res_limb;
......@@ -2816,13 +3707,415 @@ static inline void zig_xor_big(void *res, const void *lhs, const void *rhs, bool
28163707 }
28173708}
28183709
3710static inline void zig_increment_big(void *res, bool is_signed, uint16_t bits) {
3711 uint8_t *res_bytes = res;
3712 uint16_t byte_offset = 0;
3713 uint16_t remaining_bytes = zig_int_bytes(bits);
3714 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
3715
3716#if zig_big_endian
3717 byte_offset = remaining_bytes;
3718#endif
3719
3720 while (remaining_bytes >= 128 / CHAR_BIT) {
3721 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
3722
3723#if zig_big_endian
3724 byte_offset -= 128 / CHAR_BIT;
3725#endif
3726
3727 {
3728 zig_u128 res_limb;
3729 bool limb_overflow;
3730
3731 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3732 limb_overflow = zig_addo_u128(&res_limb, res_limb, zig_make_u128(UINT64_C(0), UINT64_C(1)), limb_bits);
3733 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3734 if (!limb_overflow) return;
3735 }
3736
3737 remaining_bytes -= 128 / CHAR_BIT;
3738
3739#if zig_little_endian
3740 byte_offset += 128 / CHAR_BIT;
3741#endif
3742 }
3743
3744 while (remaining_bytes >= 64 / CHAR_BIT) {
3745 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
3746
3747#if zig_big_endian
3748 byte_offset -= 64 / CHAR_BIT;
3749#endif
3750
3751 {
3752 uint64_t res_limb;
3753 bool limb_overflow;
3754
3755 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3756 limb_overflow = zig_addo_u64(&res_limb, res_limb, UINT64_C(1), limb_bits);
3757 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3758 if (!limb_overflow) return;
3759 }
3760
3761 remaining_bytes -= 64 / CHAR_BIT;
3762
3763#if zig_little_endian
3764 byte_offset += 64 / CHAR_BIT;
3765#endif
3766 }
3767
3768 while (remaining_bytes >= 32 / CHAR_BIT) {
3769 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
3770
3771#if zig_big_endian
3772 byte_offset -= 32 / CHAR_BIT;
3773#endif
3774
3775 {
3776 uint32_t res_limb;
3777 bool limb_overflow;
3778
3779 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3780 limb_overflow = zig_addo_u32(&res_limb, res_limb, UINT32_C(1), limb_bits);
3781 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3782 if (!limb_overflow) return;
3783 }
3784
3785 remaining_bytes -= 32 / CHAR_BIT;
3786
3787#if zig_little_endian
3788 byte_offset += 32 / CHAR_BIT;
3789#endif
3790 }
3791
3792 while (remaining_bytes >= 16 / CHAR_BIT) {
3793 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
3794
3795#if zig_big_endian
3796 byte_offset -= 16 / CHAR_BIT;
3797#endif
3798
3799 {
3800 uint16_t res_limb;
3801 bool limb_overflow;
3802
3803 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3804 limb_overflow = zig_addo_u16(&res_limb, res_limb, UINT16_C(1), limb_bits);
3805 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3806 if (!limb_overflow) return;
3807 }
3808
3809 remaining_bytes -= 16 / CHAR_BIT;
3810
3811#if zig_little_endian
3812 byte_offset += 16 / CHAR_BIT;
3813#endif
3814 }
3815
3816 while (remaining_bytes >= 8 / CHAR_BIT) {
3817 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
3818
3819#if zig_big_endian
3820 byte_offset -= 8 / CHAR_BIT;
3821#endif
3822
3823 {
3824 uint8_t res_limb;
3825 bool limb_overflow;
3826
3827 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3828 limb_overflow = zig_addo_u8(&res_limb, res_limb, UINT8_C(1), limb_bits);
3829 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3830 if (!limb_overflow) return;
3831 }
3832
3833 remaining_bytes -= 8 / CHAR_BIT;
3834
3835#if zig_little_endian
3836 byte_offset += 8 / CHAR_BIT;
3837#endif
3838 }
3839}
3840
3841static inline void zig_decrement_big(void *res, bool is_signed, uint16_t bits) {
3842 uint8_t *res_bytes = res;
3843 uint16_t byte_offset = 0;
3844 uint16_t remaining_bytes = zig_int_bytes(bits);
3845 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
3846
3847#if zig_big_endian
3848 byte_offset = remaining_bytes;
3849#endif
3850
3851 while (remaining_bytes >= 128 / CHAR_BIT) {
3852 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
3853
3854#if zig_big_endian
3855 byte_offset -= 128 / CHAR_BIT;
3856#endif
3857
3858 {
3859 zig_u128 res_limb;
3860 bool limb_overflow;
3861
3862 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3863 limb_overflow = zig_subo_u128(&res_limb, res_limb, zig_make_u128(UINT64_C(0), UINT64_C(1)), limb_bits);
3864 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3865 if (!limb_overflow) return;
3866 }
3867
3868 remaining_bytes -= 128 / CHAR_BIT;
3869
3870#if zig_little_endian
3871 byte_offset += 128 / CHAR_BIT;
3872#endif
3873 }
3874
3875 while (remaining_bytes >= 64 / CHAR_BIT) {
3876 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
3877
3878#if zig_big_endian
3879 byte_offset -= 64 / CHAR_BIT;
3880#endif
3881
3882 {
3883 uint64_t res_limb;
3884 bool limb_overflow;
3885
3886 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3887 limb_overflow = zig_subo_u64(&res_limb, res_limb, UINT64_C(1), limb_bits);
3888 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3889 if (!limb_overflow) return;
3890 }
3891
3892 remaining_bytes -= 64 / CHAR_BIT;
3893
3894#if zig_little_endian
3895 byte_offset += 64 / CHAR_BIT;
3896#endif
3897 }
3898
3899 while (remaining_bytes >= 32 / CHAR_BIT) {
3900 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
3901
3902#if zig_big_endian
3903 byte_offset -= 32 / CHAR_BIT;
3904#endif
3905
3906 {
3907 uint32_t res_limb;
3908 bool limb_overflow;
3909
3910 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3911 limb_overflow = zig_subo_u32(&res_limb, res_limb, UINT32_C(1), limb_bits);
3912 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3913 if (!limb_overflow) return;
3914 }
3915
3916 remaining_bytes -= 32 / CHAR_BIT;
3917
3918#if zig_little_endian
3919 byte_offset += 32 / CHAR_BIT;
3920#endif
3921 }
3922
3923 while (remaining_bytes >= 16 / CHAR_BIT) {
3924 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
3925
3926#if zig_big_endian
3927 byte_offset -= 16 / CHAR_BIT;
3928#endif
3929
3930 {
3931 uint16_t res_limb;
3932 bool limb_overflow;
3933
3934 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3935 limb_overflow = zig_subo_u16(&res_limb, res_limb, UINT16_C(1), limb_bits);
3936 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3937 if (!limb_overflow) return;
3938 }
3939
3940 remaining_bytes -= 16 / CHAR_BIT;
3941
3942#if zig_little_endian
3943 byte_offset += 16 / CHAR_BIT;
3944#endif
3945 }
3946
3947 while (remaining_bytes >= 8 / CHAR_BIT) {
3948 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
3949
3950#if zig_big_endian
3951 byte_offset -= 8 / CHAR_BIT;
3952#endif
3953
3954 {
3955 uint8_t res_limb;
3956 bool limb_overflow;
3957
3958 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3959 limb_overflow = zig_subo_u8(&res_limb, res_limb, UINT8_C(1), limb_bits);
3960 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3961 if (!limb_overflow) return;
3962 }
3963
3964 remaining_bytes -= 8 / CHAR_BIT;
3965
3966#if zig_little_endian
3967 byte_offset += 8 / CHAR_BIT;
3968#endif
3969 }
3970}
3971
3972static inline void zig_abs_big(void *res, const void *arg, bool is_signed, uint16_t bits) {
3973 uint8_t *res_bytes = res;
3974 const uint8_t *arg_bytes = arg;
3975 uint16_t byte_offset = 0;
3976 uint16_t remaining_bytes = zig_int_bytes(bits);
3977 if (zig_signFill_big(arg, is_signed, bits) >= INT8_C(0)) {
3978 memcpy(res, arg, remaining_bytes);
3979 return;
3980 }
3981 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
3982 bool overflow = true;
3983
3984#if zig_big_endian
3985 byte_offset = remaining_bytes;
3986#endif
3987
3988 while (remaining_bytes >= 128 / CHAR_BIT) {
3989 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
3990
3991#if zig_big_endian
3992 byte_offset -= 128 / CHAR_BIT;
3993#endif
3994
3995 {
3996 zig_u128 res_limb;
3997 zig_u128 arg_limb;
3998
3999 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
4000 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);
4001 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
4002 }
4003
4004 remaining_bytes -= 128 / CHAR_BIT;
4005
4006#if zig_little_endian
4007 byte_offset += 128 / CHAR_BIT;
4008#endif
4009 }
4010
4011 while (remaining_bytes >= 64 / CHAR_BIT) {
4012 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
4013
4014#if zig_big_endian
4015 byte_offset -= 64 / CHAR_BIT;
4016#endif
4017
4018 {
4019 uint64_t res_limb;
4020 uint64_t arg_limb;
4021
4022 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
4023 overflow = zig_addo_u64(&res_limb, zig_not_u64(arg_limb, UINT8_C(64)), overflow ? UINT64_C(1) : UINT64_C(0), limb_bits);
4024 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
4025 }
4026
4027 remaining_bytes -= 64 / CHAR_BIT;
4028
4029#if zig_little_endian
4030 byte_offset += 64 / CHAR_BIT;
4031#endif
4032 }
4033
4034 while (remaining_bytes >= 32 / CHAR_BIT) {
4035 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
4036
4037#if zig_big_endian
4038 byte_offset -= 32 / CHAR_BIT;
4039#endif
4040
4041 {
4042 uint32_t res_limb;
4043 uint32_t arg_limb;
4044
4045 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
4046 overflow = zig_addo_u32(&res_limb, zig_not_u32(arg_limb, UINT8_C(32)), overflow ? UINT32_C(1) : UINT32_C(0), limb_bits);
4047 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
4048 }
4049
4050 remaining_bytes -= 32 / CHAR_BIT;
4051
4052#if zig_little_endian
4053 byte_offset += 32 / CHAR_BIT;
4054#endif
4055 }
4056
4057 while (remaining_bytes >= 16 / CHAR_BIT) {
4058 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
4059
4060#if zig_big_endian
4061 byte_offset -= 16 / CHAR_BIT;
4062#endif
4063
4064 {
4065 uint16_t res_limb;
4066 uint16_t arg_limb;
4067
4068 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
4069 overflow = zig_addo_u16(&res_limb, zig_not_u16(arg_limb, UINT8_C(16)), overflow ? UINT16_C(1) : UINT16_C(0), limb_bits);
4070 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
4071 }
4072
4073 remaining_bytes -= 16 / CHAR_BIT;
4074
4075#if zig_little_endian
4076 byte_offset += 16 / CHAR_BIT;
4077#endif
4078 }
4079
4080 while (remaining_bytes >= 8 / CHAR_BIT) {
4081 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
4082
4083#if zig_big_endian
4084 byte_offset -= 8 / CHAR_BIT;
4085#endif
4086
4087 {
4088 uint8_t res_limb;
4089 uint8_t arg_limb;
4090
4091 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
4092 overflow = zig_addo_u8(&res_limb, zig_not_u8(arg_limb, UINT8_C(8)), overflow ? UINT8_C(1) : UINT8_C(0), limb_bits);
4093 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
4094 }
4095
4096 remaining_bytes -= 8 / CHAR_BIT;
4097
4098#if zig_little_endian
4099 byte_offset += 8 / CHAR_BIT;
4100#endif
4101 }
4102}
4103
4104static inline void zig_min_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4105 memcpy(res, zig_cmp_big(lhs, rhs, is_signed, bits) < INT32_C(0) ? lhs : rhs, zig_int_bytes(bits));
4106}
4107
4108static inline void zig_max_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4109 memcpy(res, zig_cmp_big(lhs, rhs, is_signed, bits) >= INT32_C(0) ? lhs : rhs, zig_int_bytes(bits));
4110}
4111
28194112static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
28204113 uint8_t *res_bytes = res;
28214114 const uint8_t *lhs_bytes = lhs;
28224115 const uint8_t *rhs_bytes = rhs;
28234116 uint16_t byte_offset = 0;
28244117 uint16_t remaining_bytes = zig_int_bytes(bits);
2825 uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits);
4118 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
28264119 bool overflow = false;
28274120
28284121#if zig_big_endian
......@@ -3038,7 +4331,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
30384331 const uint8_t *rhs_bytes = rhs;
30394332 uint16_t byte_offset = 0;
30404333 uint16_t remaining_bytes = zig_int_bytes(bits);
3041 uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits);
4334 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
30424335 bool overflow = false;
30434336
30444337#if zig_big_endian
......@@ -3238,218 +4531,890 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
32384531 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
32394532 }
32404533
3241 remaining_bytes -= 8 / CHAR_BIT;
4534 remaining_bytes -= 8 / CHAR_BIT;
4535
4536#if zig_little_endian
4537 byte_offset += 8 / CHAR_BIT;
4538#endif
4539 }
4540
4541 return overflow;
4542}
4543
4544static inline void zig_add_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4545 if (zig_addo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow
4546}
4547
4548static inline void zig_addw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4549 (void)zig_addo_big(res, lhs, rhs, is_signed, bits);
4550}
4551
4552static inline void zig_adds_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4553 int8_t sat_sign = zig_signFill_big(lhs, is_signed, bits);
4554
4555 if (!zig_addo_big(res, lhs, rhs, is_signed, bits)) return;
4556 switch (sat_sign) {
4557 case -INT8_C(1): return zig_minInt_big(res, is_signed, bits);
4558 case INT8_C(0): return zig_maxInt_big(res, is_signed, bits);
4559 }
4560}
4561
4562static inline void zig_sub_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4563 if (zig_subo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow
4564}
4565
4566static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4567 (void)zig_subo_big(res, lhs, rhs, is_signed, bits);
4568}
4569
4570static inline void zig_subs_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4571 int8_t sat_sign = is_signed ? zig_signFill_big(lhs, is_signed, bits) : -INT8_C(1);
4572
4573 if (!zig_subo_big(res, lhs, rhs, is_signed, bits)) return;
4574 switch (sat_sign) {
4575 case -INT8_C(1): return zig_minInt_big(res, is_signed, bits);
4576 case INT8_C(0): return zig_maxInt_big(res, is_signed, bits);
4577 }
4578}
4579
4580static inline bool zig_mulo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4581 uint8_t *res_bytes = res;
4582 const uint8_t *lhs_bytes = lhs;
4583 const uint8_t *rhs_bytes = rhs;
4584 uint16_t size = zig_int_bytes(bits);
4585 uint16_t sign_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
4586 uint8_t lhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(lhs, is_signed, bits), UINT8_C(8));
4587 uint8_t rhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(rhs, is_signed, bits), UINT8_C(8));
4588 uint16_t lhs_byte_offset = sign_byte_offset;
4589 uint16_t lhs_end_byte_offset = UINT16_C(0);
4590 bool overflow = false;
4591
4592#if zig_big_endian
4593 lhs_byte_offset = size - lhs_byte_offset;
4594 lhs_end_byte_offset = size - lhs_end_byte_offset;
4595#endif
4596
4597 while (lhs_byte_offset != lhs_end_byte_offset) {
4598 uint16_t rhs_byte_offset = UINT16_C(0);
4599 uint16_t end_byte_offset = sign_byte_offset;
4600 uint16_t res_byte_offset;
4601 uint16_t lhs_byte;
4602 uint8_t res_byte = UINT8_C(0);
4603 uint16_t mul_res = UINT16_C(0);
4604 uint8_t carry = UINT8_C(0);
4605
4606#if zig_little_endian
4607 lhs_byte_offset -= UINT16_C(1);
4608#else
4609 rhs_byte_offset = size - rhs_byte_offset;
4610 end_byte_offset = size - end_byte_offset;
4611#endif
4612
4613 lhs_byte = zig_u16_intCast_u8(lhs_bytes[lhs_byte_offset]) ^ lhs_sign_fill;
4614
4615#if zig_big_endian
4616 lhs_byte_offset += UINT16_C(1);
4617#endif
4618
4619 res_byte_offset = lhs_byte_offset;
4620
4621 while (res_byte_offset != end_byte_offset) {
4622 bool res_byte_initialized = res_byte_offset != lhs_byte_offset;
4623
4624#if zig_big_endian
4625 rhs_byte_offset -= UINT16_C(1);
4626 res_byte_offset -= UINT16_C(1);
4627#endif
4628
4629 if (res_byte_initialized) res_byte = res_bytes[res_byte_offset];
4630 carry = zig_addo_u8(&res_byte, res_byte, carry, UINT8_C(8));
4631 carry += zig_addo_u8(&res_byte, res_byte, zig_u8_intCast_u16(
4632 zig_shr_u16(mul_res, UINT8_C(8))
4633 ), UINT8_C(8));
4634 mul_res = lhs_byte * zig_u16_intCast_u8(rhs_bytes[rhs_byte_offset] ^ rhs_sign_fill);
4635 carry += zig_addo_u8(&res_bytes[res_byte_offset], res_byte, zig_u8_truncate_u16(
4636 mul_res,
4637 UINT8_C(8)
4638 ), UINT8_C(8));
4639
4640#if zig_little_endian
4641 rhs_byte_offset += UINT16_C(1);
4642 res_byte_offset += UINT16_C(1);
4643#endif
4644 }
4645
4646 while (rhs_byte_offset != end_byte_offset) {
4647#if zig_big_endian
4648 rhs_byte_offset -= UINT16_C(1);
4649#endif
4650
4651 carry = zig_addo_u8(
4652 &res_byte,
4653 zig_u8_intCast_u16(zig_shr_u16(mul_res, UINT8_C(8))),
4654 carry,
4655 UINT8_C(8)
4656 );
4657 mul_res = lhs_byte * zig_u16_intCast_u8(rhs_bytes[rhs_byte_offset] ^ rhs_sign_fill);
4658 carry += zig_addo_u8(&res_byte, res_byte, zig_u8_truncate_u16(
4659 mul_res,
4660 UINT8_C(8)
4661 ), UINT8_C(8));
4662 overflow |= res_byte != UINT8_C(0);
4663
4664#if zig_little_endian
4665 rhs_byte_offset += UINT16_C(1);
4666#endif
4667 }
4668
4669 overflow |= zig_shr_u16(mul_res, UINT8_C(8)) != UINT16_C(0);
4670 overflow |= carry != UINT8_C(0);
4671 }
4672
4673#if zig_little_endian
4674 sign_byte_offset -= UINT64_C(1);
4675#else
4676 sign_byte_offset = size - sign_byte_offset;
4677#endif
4678
4679 if (lhs_sign_fill != rhs_sign_fill) {
4680 uint16_t byte_offset = UINT16_C(0);
4681 uint16_t end_byte_offset = sign_byte_offset;
4682 uint8_t res_byte;
4683 int8_t signed_res_byte;
4684 uint8_t carry = UINT8_C(0);
4685
4686#if zig_big_endian
4687 byte_offset = size - byte_offset;
4688 end_byte_offset += UINT16_C(1);
4689#endif
4690
4691 while (byte_offset != end_byte_offset) {
4692#if zig_big_endian
4693 byte_offset -= UINT16_C(1);
4694#endif
4695
4696 carry = zig_subo_u8(&res_byte, UINT8_C(0), carry, UINT8_C(8));
4697 carry += zig_subo_u8(&res_byte, res_byte, res_bytes[byte_offset], UINT8_C(8));
4698 carry += zig_subo_u8(
4699 &res_bytes[byte_offset],
4700 res_byte,
4701 (lhs_sign_fill == UINT8_C(0) ? lhs_bytes : rhs_bytes)[byte_offset],
4702 UINT8_C(8)
4703 );
4704
4705#if zig_little_endian
4706 byte_offset += UINT16_C(1);
4707#endif
4708 }
4709
4710#if zig_big_endian
4711 byte_offset -= UINT16_C(1);
4712#endif
4713
4714 signed_res_byte = zig_i8_bitCast_u8(res_bytes[byte_offset], UINT8_C(8));
4715 overflow |= signed_res_byte < INT8_C(0);
4716 overflow |= zig_subo_i8(&signed_res_byte, INT8_C(0), signed_res_byte, UINT8_C(8));
4717 overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_intCast_u8(carry), UINT8_C(8));
4718 overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8(
4719 (lhs_sign_fill == UINT8_C(0) ? lhs_bytes : rhs_bytes)[byte_offset],
4720 UINT8_C(8)
4721 ), UINT8_C(8));
4722 res_bytes[byte_offset] = zig_i8_bitCast_u8(signed_res_byte, UINT8_C(8));
4723 } else if (lhs_sign_fill != UINT8_C(0)) {
4724 uint16_t byte_offset = UINT16_C(0);
4725 uint16_t end_byte_offset = sign_byte_offset;
4726 uint8_t res_byte;
4727 int8_t signed_res_byte;
4728 uint8_t carry = UINT8_C(1);
4729
4730#if zig_big_endian
4731 byte_offset = size - byte_offset;
4732 end_byte_offset += UINT16_C(1);
4733#endif
4734
4735 while (byte_offset != end_byte_offset) {
4736#if zig_big_endian
4737 byte_offset -= UINT16_C(1);
4738#endif
4739
4740 carry = zig_subo_u8(&res_byte, res_bytes[byte_offset], carry, UINT8_C(8));
4741 carry += zig_subo_u8(&res_byte, res_byte, lhs_bytes[byte_offset], UINT8_C(8));
4742 carry += zig_subo_u8(&res_bytes[byte_offset], res_byte, rhs_bytes[byte_offset], UINT8_C(8));
4743
4744#if zig_little_endian
4745 byte_offset += UINT16_C(1);
4746#endif
4747 }
4748
4749#if zig_big_endian
4750 byte_offset -= UINT16_C(1);
4751#endif
4752
4753 signed_res_byte = zig_i8_bitCast_u8(res_bytes[byte_offset], UINT8_C(8));
4754 overflow |= signed_res_byte < INT8_C(0);
4755 overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_intCast_u8(carry), UINT8_C(8));
4756 overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8(
4757 lhs_bytes[byte_offset],
4758 UINT8_C(8)
4759 ), UINT8_C(8));
4760 overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8(
4761 rhs_bytes[byte_offset],
4762 UINT8_C(8)
4763 ), UINT8_C(8));
4764 res_bytes[byte_offset] = zig_i8_bitCast_u8(signed_res_byte, UINT8_C(8));
4765 } else if (is_signed) {
4766 int8_t signed_res_byte = zig_i8_bitCast_u8(res_bytes[sign_byte_offset], UINT8_C(8));
4767
4768 overflow |= signed_res_byte < INT8_C(0);
4769 }
4770
4771 {
4772 uint8_t truncate_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
4773 uint8_t fill_byte = UINT8_C(0);
4774
4775 if (is_signed) {
4776 int8_t sign_byte = zig_i8_bitCast_u8(res_bytes[sign_byte_offset], UINT8_C(8));
4777 int8_t truncated = zig_i8_truncate_i8(sign_byte, truncate_bits);
4778
4779 overflow |= sign_byte != truncated;
4780 res_bytes[sign_byte_offset] = zig_u8_bitCast_i8(truncated, UINT8_C(8));
4781 fill_byte = zig_u8_bitCast_i8(zig_shr_i8(truncated, UINT8_C(7)), UINT8_C(8));
4782 } else {
4783 uint8_t sign_byte = res_bytes[sign_byte_offset];
4784 uint8_t truncated = zig_u8_truncate_u8(sign_byte, truncate_bits);
4785
4786 overflow |= sign_byte != truncated;
4787 res_bytes[sign_byte_offset] = truncated;
4788 }
4789
4790#if zig_little_endian
4791 sign_byte_offset += UINT16_C(1);
4792 memset(&res_bytes[sign_byte_offset], fill_byte, size - sign_byte_offset);
4793#else
4794 memset(&res_bytes[0], fill_byte, sign_byte_offset);
4795#endif
4796 }
4797
4798 return overflow;
4799}
4800
4801static inline void zig_mul_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4802 if (zig_mulo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow
4803}
4804
4805static inline void zig_mulw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4806 (void)zig_mulo_big(res, lhs, rhs, is_signed, bits);
4807}
4808
4809static inline void zig_muls_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4810 int8_t sat_sign = zig_signFill_big(lhs, is_signed, bits) ^ zig_signFill_big(rhs, is_signed, bits);
4811
4812 if (!zig_mulo_big(res, lhs, rhs, is_signed, bits)) return;
4813 switch (sat_sign) {
4814 case -INT8_C(1): return zig_minInt_big(res, is_signed, bits);
4815 case INT8_C(0): return zig_maxInt_big(res, is_signed, bits);
4816 }
4817}
4818
4819static inline void zig_divTrunc_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) {
4820 if (is_signed) {
4821 zig_extern void __divei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits);
4822 __divei5(res, lhs, rhs, temp, bits);
4823 } else {
4824 zig_extern void __udivei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits);
4825 __udivei5(res, lhs, rhs, temp, bits);
4826 }
4827}
4828
4829static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) {
4830 if (is_signed) {
4831 zig_extern void __modei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits);
4832 __modei5(res, lhs, rhs, temp, bits);
4833 } else {
4834 zig_extern void __umodei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits);
4835 __umodei5(res, lhs, rhs, temp, bits);
4836 }
4837}
4838
4839static inline void zig_divFloor_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) {
4840 bool decrement = false;
4841
4842 if (is_signed) {
4843 zig_rem_big(res, lhs, rhs, temp, is_signed, bits);
4844 decrement = zig_u32_bitCast_i32(zig_xor_i32(
4845 zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits),
4846 zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32)
4847 ), UINT8_C(32)) > zig_u32_bitCast_i32(zig_minInt_i32, UINT8_C(32));
4848 }
4849 zig_divTrunc_big(res, lhs, rhs, temp, is_signed, bits);
4850 if (decrement) zig_decrement_big(res, is_signed, bits);
4851}
4852
4853static inline void zig_divCeil_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) {
4854 bool increment = false;
4855
4856 zig_rem_big(res, lhs, rhs, temp, is_signed, bits);
4857 increment = zig_xor_i32(
4858 zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits),
4859 zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32)
4860 ) > INT32_C(0);
4861 zig_divTrunc_big(res, lhs, rhs, temp, is_signed, bits);
4862 if (increment) zig_increment_big(res, is_signed, bits);
4863}
4864
4865static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) {
4866 bool fixup = false;
4867
4868 zig_rem_big(res, lhs, rhs, temp, is_signed, bits);
4869 if (is_signed && zig_u32_bitCast_i32(zig_xor_i32(
4870 zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits),
4871 zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32)
4872 ), UINT8_C(32)) > zig_u32_bitCast_i32(zig_minInt_i32, UINT8_C(32))) zig_add_big(res, res, rhs, is_signed, bits);
4873}
4874
4875static inline void zig_shr_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) {
4876 uint8_t *res_bytes = res;
4877 const uint8_t *lhs_bytes = lhs;
4878 uint16_t size = zig_int_bytes(bits);
4879 uint16_t res_byte_offset = UINT16_C(0);
4880 uint16_t lhs_byte_offset = zig_shr_u16(rhs, UINT8_C(3));
4881 uint16_t end_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
4882 uint8_t lhs_prev_byte;
4883 uint8_t byte_shift = zig_u8_truncate_u16(rhs, UINT8_C(3));
4884
4885#if zig_big_endian
4886 res_byte_offset = size - res_byte_offset;
4887 lhs_byte_offset = size - lhs_byte_offset;
4888 end_byte_offset = size - end_byte_offset;
4889#endif
4890
4891 {
4892#if zig_big_endian
4893 lhs_byte_offset -= UINT16_C(1);
4894#endif
4895
4896 lhs_prev_byte = lhs_bytes[lhs_byte_offset];
4897
4898#if zig_little_endian
4899 lhs_byte_offset += UINT16_C(1);
4900#endif
4901 }
4902
4903 while (lhs_byte_offset != end_byte_offset) {
4904#if zig_big_endian
4905 res_byte_offset -= UINT16_C(1);
4906 lhs_byte_offset -= UINT16_C(1);
4907#endif
4908
4909 {
4910 uint8_t lhs_byte = lhs_bytes[lhs_byte_offset];
4911
4912 res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16(
4913 zig_shl_u16(zig_u16_intCast_u8(lhs_byte), UINT8_C(8)),
4914 zig_u16_intCast_u8(lhs_prev_byte)
4915 ), byte_shift));
4916 lhs_prev_byte = lhs_byte;
4917 }
4918
4919#if zig_little_endian
4920 res_byte_offset += UINT16_C(1);
4921 lhs_byte_offset += UINT16_C(1);
4922#endif
4923 }
4924
4925 {
4926 uint8_t lhs_sign_fill = UINT8_C(0);
4927
4928#if zig_big_endian
4929 res_byte_offset -= UINT16_C(1);
4930#endif
4931
4932 if (is_signed) {
4933 int8_t signed_byte = zig_i8_bitCast_u8(lhs_prev_byte, UINT8_C(8));
4934
4935 res_bytes[res_byte_offset] = zig_shr_i8(signed_byte, byte_shift);
4936 lhs_sign_fill = zig_u8_bitCast_i8(zig_shr_i8(signed_byte, UINT8_C(7)), UINT8_C(8));
4937 } else {
4938 res_bytes[res_byte_offset] = zig_shr_u8(lhs_prev_byte, byte_shift);
4939 }
4940
4941#if zig_little_endian
4942 res_byte_offset += UINT16_C(1);
4943 memset(&res_bytes[res_byte_offset], lhs_sign_fill, size - res_byte_offset);
4944#else
4945 memset(&res_bytes[0], lhs_sign_fill, res_byte_offset);
4946#endif
4947 }
4948}
4949
4950static inline bool zig_shlo_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) {
4951 uint8_t *res_bytes = res;
4952 const uint8_t *lhs_bytes = lhs;
4953 uint8_t lhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(lhs, is_signed, bits), UINT8_C(8));
4954 uint16_t size = zig_int_bytes(bits);
4955 uint16_t res_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
4956 uint16_t lhs_byte_offset = UINT16_C(0);
4957 uint16_t end_byte_offset = res_byte_offset - UINT16_C(1) - zig_shr_u16(rhs, UINT8_C(3));
4958 uint8_t lhs_prev_byte = lhs_sign_fill;
4959 uint8_t byte_shift = UINT8_C(8) - zig_u8_truncate_u16(rhs, UINT8_C(3));
4960 bool overflow = false;
4961
4962#if zig_little_endian
4963 lhs_byte_offset = size - lhs_byte_offset;
4964#else
4965 res_byte_offset = size - res_byte_offset;
4966 end_byte_offset = size - end_byte_offset;
4967#endif
4968
4969 while (lhs_byte_offset != end_byte_offset) {
4970#if zig_little_endian
4971 lhs_byte_offset -= UINT16_C(1);
4972#endif
4973
4974 overflow |= lhs_prev_byte != lhs_sign_fill;
4975 lhs_prev_byte = lhs_bytes[lhs_byte_offset];
4976
4977#if zig_big_endian
4978 lhs_byte_offset += UINT16_C(1);
4979#endif
4980 }
4981
4982#if zig_little_endian
4983 end_byte_offset = UINT16_C(0);
4984#else
4985 end_byte_offset = size;
4986#endif
4987
4988 {
4989 bool lhs_more_bytes = lhs_byte_offset != end_byte_offset;
4990
4991#if zig_little_endian
4992 if (lhs_more_bytes) lhs_byte_offset -= UINT16_C(1);
4993#endif
4994
4995 {
4996 uint8_t lhs_byte = UINT8_C(0);
4997
4998 if (lhs_more_bytes) lhs_byte = lhs_bytes[lhs_byte_offset];
4999
5000 if (is_signed) {
5001 int16_t shifted = zig_shr_i16(zig_or_i16(
5002 zig_shl_i16(zig_i16_intCast_u8(lhs_prev_byte), UINT8_C(8)),
5003 zig_i16_intCast_u8(lhs_byte)
5004 ), byte_shift);
5005 int8_t truncated = zig_i8_truncate_i16(
5006 shifted,
5007 zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1)
5008 );
5009 uint8_t fill = zig_u8_bitCast_i8(zig_shr_i8(truncated, UINT8_C(7)), UINT8_C(8));
5010
5011 overflow |= zig_i16_intCast_i8(truncated) != shifted;
5012#if zig_little_endian
5013 memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset);
5014 res_byte_offset -= UINT16_C(1);
5015#else
5016 memset(&res_bytes[0], fill, res_byte_offset);
5017#endif
5018 res_bytes[res_byte_offset] = zig_u8_bitCast_i8(truncated, UINT8_C(8));
5019 } else {
5020 uint16_t shifted = zig_shr_u16(zig_or_u16(
5021 zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)),
5022 zig_u16_intCast_u8(lhs_byte)
5023 ), byte_shift);
5024 uint8_t truncated = zig_u8_truncate_u16(
5025 shifted,
5026 zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1)
5027 );
5028
5029 overflow |= zig_u16_intCast_u8(truncated) != shifted;
5030#if zig_little_endian
5031 memset(&res_bytes[res_byte_offset], zig_minInt_u8, size - res_byte_offset);
5032 res_byte_offset -= UINT16_C(1);
5033#else
5034 memset(&res_bytes[0], zig_minInt_u8, res_byte_offset);
5035#endif
5036 res_bytes[res_byte_offset] = truncated;
5037 }
5038
5039 lhs_prev_byte = lhs_byte;
5040 }
5041
5042#if zig_big_endian
5043 res_byte_offset += UINT16_C(1);
5044 if (lhs_more_bytes) lhs_byte_offset += UINT16_C(1);
5045#endif
5046 }
5047
5048 while (lhs_byte_offset != end_byte_offset) {
5049#if zig_little_endian
5050 res_byte_offset -= UINT16_C(1);
5051 lhs_byte_offset -= UINT16_C(1);
5052#endif
5053
5054 {
5055 uint8_t lhs_byte = lhs_bytes[lhs_byte_offset];
5056
5057 res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16(
5058 zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)),
5059 zig_u16_intCast_u8(lhs_byte)
5060 ), byte_shift));
5061 lhs_prev_byte = lhs_byte;
5062 }
5063
5064#if zig_big_endian
5065 res_byte_offset += UINT16_C(1);
5066 lhs_byte_offset += UINT16_C(1);
5067#endif
5068 }
5069
5070 {
5071#if zig_little_endian
5072 res_byte_offset -= UINT16_C(1);
5073#endif
5074
5075 res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(
5076 zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)),
5077 byte_shift
5078 ));
5079
5080#if zig_big_endian
5081 res_byte_offset += UINT16_C(1);
5082#endif
5083 }
5084
5085#if zig_little_endian
5086 memset(&res_bytes[0], zig_minInt_u8, res_byte_offset);
5087#else
5088 memset(&res_bytes[res_byte_offset], zig_minInt_u8, size - res_byte_offset);
5089#endif
5090
5091 return overflow;
5092}
5093
5094static inline void zig_shl_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) {
5095 if (zig_shlo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: left shift overflowed bits
5096}
5097
5098static inline void zig_shlw_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) {
5099 (void)zig_shlo_big(res, lhs, rhs, is_signed, bits);
5100}
5101
5102#define zig_big_shls_builtin(w) \
5103 static inline uint##w##_t zig_shls_u##w##_big(uint##w##_t lhs, const void *rhs, \
5104 uint8_t lhs_bits, bool rhs_is_signed, uint16_t rhs_bits) { \
5105 uint##w##_t res; \
5106 const uint8_t *rhs_bytes = rhs; \
5107 if (zig_cmp_big_u8(rhs, lhs_bits, rhs_is_signed, rhs_bits) < INT32_C(0) && \
5108 !zig_shlo_u##w(&res, lhs, rhs_bytes[0], lhs_bits)) return res; \
5109 return lhs == INT##w##_C(0) ? zig_minInt_u(w, lhs_bits) : zig_maxInt_u(w, lhs_bits); \
5110 } \
5111\
5112 static inline int##w##_t zig_shls_i##w##_big(int##w##_t lhs, const void *rhs, \
5113 uint8_t lhs_bits, bool rhs_is_signed, uint16_t rhs_bits) { \
5114 int##w##_t res; \
5115 const uint8_t *rhs_bytes = rhs; \
5116 if (zig_cmp_big_u8(rhs, lhs_bits, rhs_is_signed, rhs_bits) < INT32_C(0) && \
5117 !zig_shlo_i##w(&res, lhs, rhs_bytes[0], lhs_bits)) return res; \
5118 return lhs == INT##w##_C(0) ? INT##w##_C(0) : \
5119 lhs < INT##w##_C(0) ? zig_minInt_i(w, lhs_bits) : zig_maxInt_i(w, lhs_bits); \
5120 } \
5121\
5122 static inline void zig_shls_big_u##w(void *res, const void *lhs, uint##w##_t rhs, bool is_signed, uint16_t bits) { \
5123 const uint8_t *lhs_bytes = lhs; \
5124 if (rhs < bits && !zig_shlo_big(res, lhs, zig_u16_intCast_u##w(rhs), is_signed, bits)) return; \
5125 switch (zig_cmp_big_u8(lhs, UINT8_C(0), is_signed, bits)) { \
5126 case -INT32_C(1): return zig_minInt_big(res, is_signed, bits); \
5127 case INT32_C(0): return zig_minInt_big(res, false, bits); \
5128 case INT32_C(1): return zig_maxInt_big(res, is_signed, bits); \
5129 default: zig_unreachable(); \
5130 } \
5131 }
5132zig_big_shls_builtin(8)
5133zig_big_shls_builtin(16)
5134zig_big_shls_builtin(32)
5135zig_big_shls_builtin(64)
5136
5137static inline void zig_byteSwap_big(void *res, const void *arg, bool is_signed, uint16_t bits) {
5138 uint8_t *res_bytes = res;
5139 const uint8_t *arg_bytes = arg;
5140 uint16_t res_byte_offset = UINT16_C(0);
5141 uint16_t arg_byte_offset = bits / CHAR_BIT;
5142 uint16_t end_byte_offset = UINT16_C(1);
5143 uint16_t size = zig_int_bytes(bits);
5144
5145#if zig_big_endian
5146 res_byte_offset = size - res_byte_offset;
5147 arg_byte_offset = size - arg_byte_offset;
5148 end_byte_offset = size - end_byte_offset;
5149#endif
5150
5151 while (arg_byte_offset != end_byte_offset) {
5152#if zig_little_endian
5153 arg_byte_offset -= UINT16_C(1);
5154#else
5155 res_byte_offset -= UINT16_C(1);
5156#endif
5157
5158 res_bytes[res_byte_offset] = arg_bytes[arg_byte_offset];
32425159
32435160#if zig_little_endian
3244 byte_offset += 8 / CHAR_BIT;
5161 res_byte_offset += UINT16_C(1);
5162#else
5163 arg_byte_offset += UINT16_C(1);
32455164#endif
32465165 }
32475166
3248 return overflow;
3249}
5167 {
5168#if zig_little_endian
5169 arg_byte_offset -= UINT16_C(1);
5170#else
5171 res_byte_offset -= UINT16_C(1);
5172#endif
32505173
3251static inline void zig_addw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3252 (void)zig_addo_big(res, lhs, rhs, is_signed, bits);
3253}
5174 {
5175 uint8_t byte = arg_bytes[arg_byte_offset];
5176 uint8_t fill = is_signed
5177 ? zig_u8_bitCast_i8(zig_shr_i8(zig_i8_bitCast_u8(byte, UINT8_C(8)), UINT8_C(7)), UINT8_C(8))
5178 : UINT8_C(0);
32545179
3255static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3256 (void)zig_subo_big(res, lhs, rhs, is_signed, bits);
3257}
5180 res_bytes[res_byte_offset] = byte;
32585181
3259zig_extern void __udivei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits);
3260static inline void zig_div_trunc_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3261 if (!is_signed) {
3262 __udivei4(res, lhs, rhs, bits);
3263 return;
5182#if zig_little_endian
5183 res_byte_offset += UINT16_C(1);
5184 memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset);
5185#else
5186 memset(&res_bytes[0], fill, res_byte_offset);
5187#endif
5188 }
32645189 }
3265
3266 zig_trap();
32675190}
32685191
3269static inline void zig_div_floor_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3270 if (!is_signed) {
3271 zig_div_trunc_big(res, lhs, rhs, is_signed, bits);
3272 return;
3273 }
5192static inline void zig_bitReverse_big(void *res, const void *arg, bool is_signed, uint16_t bits) {
5193 uint8_t *res_bytes = res;
5194 const uint8_t *arg_bytes = arg;
5195 uint16_t size = zig_int_bytes(bits);
5196 uint16_t res_byte_offset = UINT16_C(0);
5197 uint16_t arg_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
5198 uint16_t end_byte_offset = UINT16_C(0);
5199 uint8_t arg_prev_byte;
5200 uint8_t byte_shift = zig_u8_intCast_u16(zig_subw_u16(UINT16_C(0), bits, UINT8_C(3)));
32745201
3275 zig_trap();
3276}
5202#if zig_big_endian
5203 res_byte_offset = size - res_byte_offset;
5204 arg_byte_offset = size - arg_byte_offset;
5205 end_byte_offset = size - end_byte_offset;
5206#endif
32775207
3278static inline void zig_div_ceil_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3279 zig_trap();
3280}
5208 {
5209#if zig_little_endian
5210 arg_byte_offset -= UINT16_C(1);
5211#endif
32815212
3282zig_extern void __umodei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits);
3283static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3284 if (!is_signed) {
3285 __umodei4(res, lhs, rhs, bits);
3286 return;
5213 arg_prev_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8));
5214
5215#if zig_big_endian
5216 arg_byte_offset += UINT16_C(1);
5217#endif
32875218 }
32885219
3289 zig_trap();
3290}
5220 while (arg_byte_offset != end_byte_offset) {
5221#if zig_big_endian
5222 res_byte_offset -= UINT16_C(1);
5223#else
5224 arg_byte_offset -= UINT16_C(1);
5225#endif
32915226
3292static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3293 if (!is_signed) {
3294 zig_rem_big(res, lhs, rhs, is_signed, bits);
3295 return;
5227 {
5228 uint8_t arg_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8));
5229
5230 res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16(
5231 zig_shl_u16(zig_u16_intCast_u8(arg_byte), UINT8_C(8)),
5232 zig_u16_intCast_u8(arg_prev_byte)
5233 ), byte_shift));
5234 arg_prev_byte = arg_byte;
5235 }
5236
5237#if zig_little_endian
5238 res_byte_offset += UINT16_C(1);
5239#else
5240 arg_byte_offset += UINT16_C(1);
5241#endif
32965242 }
32975243
3298 zig_trap();
5244 {
5245 uint8_t arg_sign_fill = UINT8_C(0);
5246
5247#if zig_big_endian
5248 res_byte_offset -= UINT16_C(1);
5249#endif
5250
5251 if (is_signed) {
5252 int8_t signed_byte = zig_i8_bitCast_u8(arg_prev_byte, UINT8_C(8));
5253
5254 res_bytes[res_byte_offset] = zig_shr_i8(signed_byte, byte_shift);
5255 arg_sign_fill = zig_u8_bitCast_i8(zig_shr_i8(signed_byte, UINT8_C(7)), UINT8_C(8));
5256 } else {
5257 res_bytes[res_byte_offset] = zig_shr_u8(arg_prev_byte, byte_shift);
5258 }
5259
5260#if zig_little_endian
5261 res_byte_offset += UINT16_C(1);
5262 memset(&res_bytes[res_byte_offset], arg_sign_fill, size - res_byte_offset);
5263#else
5264 memset(&res_bytes[0], arg_sign_fill, res_byte_offset);
5265#endif
5266 }
32995267}
33005268
3301static inline uint16_t zig_clz_big(const void *val, bool is_signed, uint16_t bits) {
3302 const uint8_t *val_bytes = val;
5269static inline uint16_t zig_popCount_big(const void *arg, bool is_signed, uint16_t bits) {
5270 const uint8_t *arg_bytes = arg;
33035271 uint16_t byte_offset = 0;
3304 uint16_t remaining_bytes = zig_int_bytes(bits);
3305 uint16_t skip_bits = remaining_bytes * 8 - bits;
3306 uint16_t total_lz = 0;
3307 uint16_t limb_lz;
5272 uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
5273 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
5274 uint16_t total_pc = 0;
33085275 (void)is_signed;
33095276
3310#if zig_little_endian
3311 byte_offset = remaining_bytes;
5277#if zig_big_endian
5278 byte_offset = zig_int_bytes(bits);
33125279#endif
33135280
33145281 while (remaining_bytes >= 128 / CHAR_BIT) {
3315#if zig_little_endian
5282 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
5283
5284#if zig_big_endian
33165285 byte_offset -= 128 / CHAR_BIT;
33175286#endif
33185287
33195288 {
3320 zig_u128 val_limb;
5289 zig_u128 arg_limb;
33215290
3322 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3323 limb_lz = zig_clz_u128(val_limb, 128 - skip_bits);
5291 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5292 total_pc += zig_popCount_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits);
33245293 }
33255294
3326 total_lz += limb_lz;
3327 if (limb_lz < 128 - skip_bits) return total_lz;
3328 skip_bits = 0;
33295295 remaining_bytes -= 128 / CHAR_BIT;
33305296
3331#if zig_big_endian
5297#if zig_little_endian
33325298 byte_offset += 128 / CHAR_BIT;
33335299#endif
33345300 }
33355301
33365302 while (remaining_bytes >= 64 / CHAR_BIT) {
3337#if zig_little_endian
5303 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
5304
5305#if zig_big_endian
33385306 byte_offset -= 64 / CHAR_BIT;
33395307#endif
33405308
33415309 {
3342 uint64_t val_limb;
5310 uint64_t arg_limb;
33435311
3344 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3345 limb_lz = zig_clz_u64(val_limb, 64 - skip_bits);
5312 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5313 total_pc += zig_popCount_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits);
33465314 }
33475315
3348 total_lz += limb_lz;
3349 if (limb_lz < 64 - skip_bits) return total_lz;
3350 skip_bits = 0;
33515316 remaining_bytes -= 64 / CHAR_BIT;
33525317
3353#if zig_big_endian
5318#if zig_little_endian
33545319 byte_offset += 64 / CHAR_BIT;
33555320#endif
33565321 }
33575322
33585323 while (remaining_bytes >= 32 / CHAR_BIT) {
3359#if zig_little_endian
5324 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
5325
5326#if zig_big_endian
33605327 byte_offset -= 32 / CHAR_BIT;
33615328#endif
33625329
33635330 {
3364 uint32_t val_limb;
5331 uint32_t arg_limb;
33655332
3366 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3367 limb_lz = zig_clz_u32(val_limb, 32 - skip_bits);
5333 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5334 total_pc += zig_popCount_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits);
33685335 }
33695336
3370 total_lz += limb_lz;
3371 if (limb_lz < 32 - skip_bits) return total_lz;
3372 skip_bits = 0;
33735337 remaining_bytes -= 32 / CHAR_BIT;
33745338
3375#if zig_big_endian
5339#if zig_little_endian
33765340 byte_offset += 32 / CHAR_BIT;
33775341#endif
33785342 }
33795343
33805344 while (remaining_bytes >= 16 / CHAR_BIT) {
3381#if zig_little_endian
5345 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
5346
5347#if zig_big_endian
33825348 byte_offset -= 16 / CHAR_BIT;
33835349#endif
33845350
33855351 {
3386 uint16_t val_limb;
5352 uint16_t arg_limb;
33875353
3388 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3389 limb_lz = zig_clz_u16(val_limb, 16 - skip_bits);
5354 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5355 total_pc += zig_popCount_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits);
33905356 }
33915357
3392 total_lz += limb_lz;
3393 if (limb_lz < 16 - skip_bits) return total_lz;
3394 skip_bits = 0;
33955358 remaining_bytes -= 16 / CHAR_BIT;
33965359
3397#if zig_big_endian
5360#if zig_little_endian
33985361 byte_offset += 16 / CHAR_BIT;
33995362#endif
34005363 }
34015364
34025365 while (remaining_bytes >= 8 / CHAR_BIT) {
3403#if zig_little_endian
5366 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
5367
5368#if zig_big_endian
34045369 byte_offset -= 8 / CHAR_BIT;
34055370#endif
34065371
34075372 {
3408 uint8_t val_limb;
5373 uint8_t arg_limb;
34095374
3410 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3411 limb_lz = zig_clz_u8(val_limb, 8 - skip_bits);
5375 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5376 total_pc += zig_popCount_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits);
34125377 }
34135378
3414 total_lz += limb_lz;
3415 if (limb_lz < 8 - skip_bits) return total_lz;
3416 skip_bits = 0;
34175379 remaining_bytes -= 8 / CHAR_BIT;
34185380
3419#if zig_big_endian
5381#if zig_little_endian
34205382 byte_offset += 8 / CHAR_BIT;
34215383#endif
34225384 }
34235385
3424 return total_lz;
5386 return total_pc;
34255387}
34265388
3427static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bits) {
3428 const uint8_t *val_bytes = val;
3429 uint16_t byte_offset = 0;
3430 uint16_t remaining_bytes = zig_int_bytes(bits);
3431 uint16_t total_tz = 0;
5389static inline uint16_t zig_ctz_big(const void *arg, bool is_signed, uint16_t bits) {
5390 const uint8_t *arg_bytes = arg;
5391 uint16_t byte_offset = UINT16_C(0);
5392 uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
5393 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
5394 uint16_t total_tz = UINT16_C(0);
34325395 uint16_t limb_tz;
34335396 (void)is_signed;
34345397
34355398#if zig_big_endian
3436 byte_offset = remaining_bytes;
5399 byte_offset = zig_int_bytes(bits);
34375400#endif
34385401
34395402 while (remaining_bytes >= 128 / CHAR_BIT) {
5403 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
5404
34405405#if zig_big_endian
34415406 byte_offset -= 128 / CHAR_BIT;
34425407#endif
34435408
34445409 {
3445 zig_u128 val_limb;
5410 zig_u128 arg_limb;
34465411
3447 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3448 limb_tz = zig_ctz_u128(val_limb, 128);
5412 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5413 limb_tz = zig_ctz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits);
34495414 }
34505415
34515416 total_tz += limb_tz;
3452 if (limb_tz < 128) return total_tz;
5417 if (limb_tz < limb_bits) return total_tz;
34535418 remaining_bytes -= 128 / CHAR_BIT;
34545419
34555420#if zig_little_endian
......@@ -3458,19 +5423,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
34585423 }
34595424
34605425 while (remaining_bytes >= 64 / CHAR_BIT) {
5426 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
5427
34615428#if zig_big_endian
34625429 byte_offset -= 64 / CHAR_BIT;
34635430#endif
34645431
34655432 {
3466 uint64_t val_limb;
5433 uint64_t arg_limb;
34675434
3468 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3469 limb_tz = zig_ctz_u64(val_limb, 64);
5435 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5436 limb_tz = zig_ctz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits);
34705437 }
34715438
34725439 total_tz += limb_tz;
3473 if (limb_tz < 64) return total_tz;
5440 if (limb_tz < limb_bits) return total_tz;
34745441 remaining_bytes -= 64 / CHAR_BIT;
34755442
34765443#if zig_little_endian
......@@ -3479,19 +5446,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
34795446 }
34805447
34815448 while (remaining_bytes >= 32 / CHAR_BIT) {
5449 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
5450
34825451#if zig_big_endian
34835452 byte_offset -= 32 / CHAR_BIT;
34845453#endif
34855454
34865455 {
3487 uint32_t val_limb;
5456 uint32_t arg_limb;
34885457
3489 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3490 limb_tz = zig_ctz_u32(val_limb, 32);
5458 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5459 limb_tz = zig_ctz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits);
34915460 }
34925461
34935462 total_tz += limb_tz;
3494 if (limb_tz < 32) return total_tz;
5463 if (limb_tz < limb_bits) return total_tz;
34955464 remaining_bytes -= 32 / CHAR_BIT;
34965465
34975466#if zig_little_endian
......@@ -3500,19 +5469,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
35005469 }
35015470
35025471 while (remaining_bytes >= 16 / CHAR_BIT) {
5472 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
5473
35035474#if zig_big_endian
35045475 byte_offset -= 16 / CHAR_BIT;
35055476#endif
35065477
35075478 {
3508 uint16_t val_limb;
5479 uint16_t arg_limb;
35095480
3510 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3511 limb_tz = zig_ctz_u16(val_limb, 16);
5481 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5482 limb_tz = zig_ctz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits);
35125483 }
35135484
35145485 total_tz += limb_tz;
3515 if (limb_tz < 16) return total_tz;
5486 if (limb_tz < limb_bits) return total_tz;
35165487 remaining_bytes -= 16 / CHAR_BIT;
35175488
35185489#if zig_little_endian
......@@ -3521,19 +5492,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
35215492 }
35225493
35235494 while (remaining_bytes >= 8 / CHAR_BIT) {
5495 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
5496
35245497#if zig_big_endian
35255498 byte_offset -= 8 / CHAR_BIT;
35265499#endif
35275500
35285501 {
3529 uint8_t val_limb;
5502 uint8_t arg_limb;
35305503
3531 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3532 limb_tz = zig_ctz_u8(val_limb, 8);
5504 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5505 limb_tz = zig_ctz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits);
35335506 }
35345507
35355508 total_tz += limb_tz;
3536 if (limb_tz < 8) return total_tz;
5509 if (limb_tz < limb_bits) return total_tz;
35375510 remaining_bytes -= 8 / CHAR_BIT;
35385511
35395512#if zig_little_endian
......@@ -3544,113 +5517,141 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
35445517 return total_tz;
35455518}
35465519
3547static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_t bits) {
3548 const uint8_t *val_bytes = val;
3549 uint16_t byte_offset = 0;
3550 uint16_t remaining_bytes = zig_int_bytes(bits);
3551 uint16_t total_pc = 0;
5520static inline uint16_t zig_clz_big(const void *arg, bool is_signed, uint16_t bits) {
5521 const uint8_t *arg_bytes = arg;
5522 uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
5523 uint16_t remaining_bytes = byte_offset;
5524 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
5525 bool sign_limb = true;
5526 uint16_t total_lz = UINT16_C(0);
5527 uint16_t limb_lz;
35525528 (void)is_signed;
35535529
35545530#if zig_big_endian
3555 byte_offset = remaining_bytes;
5531 byte_offset = zig_int_bytes(bits) - remaining_bytes;
35565532#endif
35575533
35585534 while (remaining_bytes >= 128 / CHAR_BIT) {
3559#if zig_big_endian
5535 uint8_t limb_bits = UINT8_C(128) - (sign_limb ? top_bits : UINT8_C(0));
5536
5537#if zig_little_endian
35605538 byte_offset -= 128 / CHAR_BIT;
35615539#endif
35625540
35635541 {
3564 zig_u128 val_limb;
5542 zig_u128 arg_limb;
35655543
3566 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3567 total_pc += zig_popcount_u128(val_limb, 128);
5544 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5545 limb_lz = zig_clz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits);
35685546 }
35695547
5548 total_lz += limb_lz;
5549 if (limb_lz < limb_bits) return total_lz;
5550 sign_limb = false;
35705551 remaining_bytes -= 128 / CHAR_BIT;
35715552
3572#if zig_little_endian
5553#if zig_big_endian
35735554 byte_offset += 128 / CHAR_BIT;
35745555#endif
35755556 }
35765557
35775558 while (remaining_bytes >= 64 / CHAR_BIT) {
3578#if zig_big_endian
5559 uint8_t limb_bits = UINT8_C(64) - (sign_limb ? top_bits : UINT8_C(0));
5560
5561#if zig_little_endian
35795562 byte_offset -= 64 / CHAR_BIT;
35805563#endif
35815564
35825565 {
3583 uint64_t val_limb;
5566 uint64_t arg_limb;
35845567
3585 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3586 total_pc += zig_popcount_u64(val_limb, 64);
5568 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5569 limb_lz = zig_clz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits);
35875570 }
35885571
5572 total_lz += limb_lz;
5573 if (limb_lz < limb_bits) return total_lz;
5574 sign_limb = false;
35895575 remaining_bytes -= 64 / CHAR_BIT;
35905576
3591#if zig_little_endian
5577#if zig_big_endian
35925578 byte_offset += 64 / CHAR_BIT;
35935579#endif
35945580 }
35955581
35965582 while (remaining_bytes >= 32 / CHAR_BIT) {
3597#if zig_big_endian
5583 uint8_t limb_bits = UINT8_C(32) - (sign_limb ? top_bits : UINT8_C(0));
5584
5585#if zig_little_endian
35985586 byte_offset -= 32 / CHAR_BIT;
35995587#endif
36005588
36015589 {
3602 uint32_t val_limb;
5590 uint32_t arg_limb;
36035591
3604 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3605 total_pc += zig_popcount_u32(val_limb, 32);
5592 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5593 limb_lz = zig_clz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits);
36065594 }
36075595
5596 total_lz += limb_lz;
5597 if (limb_lz < limb_bits) return total_lz;
5598 sign_limb = false;
36085599 remaining_bytes -= 32 / CHAR_BIT;
36095600
3610#if zig_little_endian
5601#if zig_big_endian
36115602 byte_offset += 32 / CHAR_BIT;
36125603#endif
36135604 }
36145605
36155606 while (remaining_bytes >= 16 / CHAR_BIT) {
3616#if zig_big_endian
5607 uint8_t limb_bits = UINT8_C(16) - (sign_limb ? top_bits : UINT8_C(0));
5608
5609#if zig_little_endian
36175610 byte_offset -= 16 / CHAR_BIT;
36185611#endif
36195612
36205613 {
3621 uint16_t val_limb;
5614 uint16_t arg_limb;
36225615
3623 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3624 total_pc = zig_popcount_u16(val_limb, 16);
5616 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5617 limb_lz = zig_clz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits);
36255618 }
36265619
5620 total_lz += limb_lz;
5621 if (limb_lz < limb_bits) return total_lz;
5622 sign_limb = false;
36275623 remaining_bytes -= 16 / CHAR_BIT;
36285624
3629#if zig_little_endian
5625#if zig_big_endian
36305626 byte_offset += 16 / CHAR_BIT;
36315627#endif
36325628 }
36335629
36345630 while (remaining_bytes >= 8 / CHAR_BIT) {
3635#if zig_big_endian
5631 uint8_t limb_bits = UINT8_C(8) - (sign_limb ? top_bits : UINT8_C(0));
5632
5633#if zig_little_endian
36365634 byte_offset -= 8 / CHAR_BIT;
36375635#endif
36385636
36395637 {
3640 uint8_t val_limb;
5638 uint8_t arg_limb;
36415639
3642 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3643 total_pc = zig_popcount_u8(val_limb, 8);
5640 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5641 limb_lz = zig_clz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits);
36445642 }
36455643
5644 total_lz += limb_lz;
5645 if (limb_lz < limb_bits) return total_lz;
5646 sign_limb = false;
36465647 remaining_bytes -= 8 / CHAR_BIT;
36475648
3648#if zig_little_endian
5649#if zig_big_endian
36495650 byte_offset += 8 / CHAR_BIT;
36505651#endif
36515652 }
36525653
3653 return total_pc;
5654 return total_lz;
36545655}
36555656
36565657/* ========================= Floating Point Support ========================= */
......@@ -3687,29 +5688,29 @@ long double __cdecl nanl(char const* input);
36875688#define zig_make_special_f80(sign, name, arg, repr) sign zig_make_f80 (__builtin_##name, )(arg)
36885689#define zig_make_special_f128(sign, name, arg, repr) sign zig_make_f128(__builtin_##name, )(arg)
36895690#else
3690#define zig_make_special_f16(sign, name, arg, repr) zig_bitCast_f16 (repr)
3691#define zig_make_special_f32(sign, name, arg, repr) zig_bitCast_f32 (repr)
3692#define zig_make_special_f64(sign, name, arg, repr) zig_bitCast_f64 (repr)
3693#define zig_make_special_f80(sign, name, arg, repr) zig_bitCast_f80 (repr)
3694#define zig_make_special_f128(sign, name, arg, repr) zig_bitCast_f128(repr)
5691#define zig_make_special_f16(sign, name, arg, repr) zig_f16_bitCast_u16 (repr)
5692#define zig_make_special_f32(sign, name, arg, repr) zig_f32_bitCast_u32 (repr)
5693#define zig_make_special_f64(sign, name, arg, repr) zig_f64_bitCast_u64 (repr)
5694#define zig_make_special_f80(sign, name, arg, repr) zig_f80_bitCast_u128(repr)
5695#define zig_make_special_f128(sign, name, arg, repr) zig_f128_bitCast_u128(repr)
36955696#endif
36965697
36975698#define zig_has_f16 1
36985699#define zig_libc_name_f16(name) __##name##h
36995700#define zig_init_special_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr)
3700#if FLT_MANT_DIG == 11
5701#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT_MANT_DIG == 11
37015702typedef float zig_f16;
37025703#define zig_make_f16(fp, repr) fp##f
3703#elif DBL_MANT_DIG == 11
5704#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && DBL_MANT_DIG == 11
37045705typedef double zig_f16;
37055706#define zig_make_f16(fp, repr) fp
3706#elif LDBL_MANT_DIG == 11
5707#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && LDBL_MANT_DIG == 11
37075708typedef long double zig_f16;
37085709#define zig_make_f16(fp, repr) fp##l
3709#elif FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gcc))
5710#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gcc))
37105711typedef _Float16 zig_f16;
37115712#define zig_make_f16(fp, repr) fp##f16
3712#elif defined(__SIZEOF_FP16__)
5713#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && defined(__SIZEOF_FP16__)
37135714typedef __fp16 zig_f16;
37145715#define zig_make_f16(fp, repr) fp##f16
37155716#else
......@@ -3723,11 +5724,6 @@ typedef uint16_t zig_f16;
37235724#undef zig_init_special_f16
37245725#define zig_init_special_f16(sign, name, arg, repr) repr
37255726#endif
3726#if defined(zig_darwin) && defined(zig_x86)
3727typedef uint16_t zig_compiler_rt_f16;
3728#else
3729typedef zig_f16 zig_compiler_rt_f16;
3730#endif
37315727
37325728#define zig_has_f32 1
37335729#define zig_libc_name_f32(name) name##f
......@@ -3736,16 +5732,16 @@ typedef zig_f16 zig_compiler_rt_f16;
37365732#else
37375733#define zig_init_special_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr)
37385734#endif
3739#if FLT_MANT_DIG == 24
5735#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT_MANT_DIG == 24
37405736typedef float zig_f32;
37415737#define zig_make_f32(fp, repr) fp##f
3742#elif DBL_MANT_DIG == 24
5738#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && DBL_MANT_DIG == 24
37435739typedef double zig_f32;
37445740#define zig_make_f32(fp, repr) fp
3745#elif LDBL_MANT_DIG == 24
5741#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && LDBL_MANT_DIG == 24
37465742typedef long double zig_f32;
37475743#define zig_make_f32(fp, repr) fp##l
3748#elif FLT32_MANT_DIG == 24
5744#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT32_MANT_DIG == 24
37495745typedef _Float32 zig_f32;
37505746#define zig_make_f32(fp, repr) fp##f32
37515747#else
......@@ -3768,19 +5764,19 @@ typedef uint32_t zig_f32;
37685764#else
37695765#define zig_init_special_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr)
37705766#endif
3771#if FLT_MANT_DIG == 53
5767#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT_MANT_DIG == 53
37725768typedef float zig_f64;
37735769#define zig_make_f64(fp, repr) fp##f
3774#elif DBL_MANT_DIG == 53
5770#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && DBL_MANT_DIG == 53
37755771typedef double zig_f64;
37765772#define zig_make_f64(fp, repr) fp
3777#elif LDBL_MANT_DIG == 53
5773#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && LDBL_MANT_DIG == 53
37785774typedef long double zig_f64;
37795775#define zig_make_f64(fp, repr) fp##l
3780#elif FLT64_MANT_DIG == 53
5776#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT64_MANT_DIG == 53
37815777typedef _Float64 zig_f64;
37825778#define zig_make_f64(fp, repr) fp##f64
3783#elif FLT32X_MANT_DIG == 53
5779#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT32X_MANT_DIG == 53
37845780typedef _Float32x zig_f64;
37855781#define zig_make_f64(fp, repr) fp##f32x
37865782#else
......@@ -3798,7 +5794,14 @@ typedef uint64_t zig_f64;
37985794#define zig_has_f80 1
37995795#define zig_libc_name_f80(name) __##name##x
38005796#define zig_init_special_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr)
3801#if FLT_MANT_DIG == 64
5797#ifdef ZIG_TARGET_SOFT_COMPILER_RT_F80_ABI
5798#undef zig_has_f80
5799typedef struct { uint64_t mantissa; uint16_t exponent; } zig_f80;
5800#define zig_init_repr_f80(mantissa, exponent) { .mant##issa = mantissa, .expo##nent = exponent }
5801#define zig_make_repr_f80(mantissa, exponent) (zig_f80)zig_init_repr_f80(mantissa, exponent)
5802#define zig_mantissa_repr_f80(arg) (arg).mantissa
5803#define zig_exponent_repr_f80(arg) (arg).exponent
5804#elif FLT_MANT_DIG == 64
38025805typedef float zig_f80;
38035806#define zig_make_f80(fp, repr) fp##f
38045807#elif DBL_MANT_DIG == 64
......@@ -3818,68 +5821,91 @@ typedef __float80 zig_f80;
38185821#define zig_make_f80(fp, repr) fp##l
38195822#else
38205823#undef zig_has_f80
3821#define zig_has_f80 0
3822#define zig_repr_f80 u128
38235824typedef zig_u128 zig_f80;
5825#define zig_init_repr_f80(mantissa, exponent) zig_init_u128(exponent, mantissa)
5826#define zig_make_repr_f80(mantissa, exponent) zig_make_u128(exponent, mantissa)
5827#define zig_mantissa_repr_f80(arg) zig_lo_u128(arg)
5828#define zig_exponent_repr_f80(arg) (uint16_t)zig_hi_u128(arg)
5829#endif
5830#ifndef zig_has_f80
5831#define zig_has_f80 0
38245832#define zig_make_f80(fp, repr) repr
5833#ifndef zig_make_repr_f80
5834#define zig_make_repr_f80(mantissa, exponent) (zig_f80)zig_init_repr_f80(mantissa, exponent)
5835#endif
38255836#undef zig_make_special_f80
38265837#define zig_make_special_f80(sign, name, arg, repr) repr
38275838#undef zig_init_special_f80
38285839#define zig_init_special_f80(sign, name, arg, repr) repr
38295840#endif
38305841
3831#if defined(zig_gcc) && defined(zig_x86)
3832#define zig_f128_has_miscompilations 1
3833#else
3834#define zig_f128_has_miscompilations 0
3835#endif
3836
38375842#define zig_has_f128 1
3838#define zig_libc_name_f128(name) name##q
5843#define zig_libc_name_f128(name) name##f128
38395844#define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr)
3840#if !zig_f128_has_miscompilations && FLT_MANT_DIG == 113
5845#ifdef ZIG_TARGET_SOFT_COMPILER_RT_F128_ABI
5846#undef zig_has_f128
5847#if zig_little_endian
5848typedef struct { uint64_t lo, hi; } zig_f128;
5849#else
5850typedef struct { uint64_t hi, lo; } zig_f128;
5851#endif
5852#define zig_init_repr_f128(hi, lo) { .h##i = hi, .l##o = lo }
5853#define zig_lo_repr_f128(arg) (arg).lo
5854#define zig_hi_repr_f128(arg) (arg).hi
5855#elif FLT_MANT_DIG == 113
38415856typedef float zig_f128;
38425857#define zig_make_f128(fp, repr) fp##f
3843#elif !zig_f128_has_miscompilations && DBL_MANT_DIG == 113
5858#elif DBL_MANT_DIG == 113
38445859typedef double zig_f128;
38455860#define zig_make_f128(fp, repr) fp
3846#elif !zig_f128_has_miscompilations && LDBL_MANT_DIG == 113
5861#elif LDBL_MANT_DIG == 113
38475862typedef long double zig_f128;
38485863#define zig_make_f128(fp, repr) fp##l
3849#elif !zig_f128_has_miscompilations && FLT128_MANT_DIG == 113
5864#elif FLT128_MANT_DIG == 113
38505865typedef _Float128 zig_f128;
38515866#define zig_make_f128(fp, repr) fp##f128
3852#elif !zig_f128_has_miscompilations && FLT64X_MANT_DIG == 113
5867#elif FLT64X_MANT_DIG == 113
38535868typedef _Float64x zig_f128;
38545869#define zig_make_f128(fp, repr) fp##f64x
3855#elif !zig_f128_has_miscompilations && defined(__SIZEOF_FLOAT128__)
5870#elif defined(__SIZEOF_FLOAT128__)
38565871typedef __float128 zig_f128;
38575872#define zig_make_f128(fp, repr) fp##q
38585873#undef zig_make_special_f128
38595874#define zig_make_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg)
38605875#else
38615876#undef zig_has_f128
3862#define zig_has_f128 0
3863#undef zig_make_special_f128
3864#undef zig_init_special_f128
3865#if defined(zig_darwin) || defined(zig_aarch64)
3866typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_v2u64;
3867zig_basic_operator(zig_v2u64, xor_v2u64, ^)
3868#define zig_repr_f128 v2u64
3869typedef zig_v2u64 zig_f128;
3870#define zig_make_f128_zig_make_u128(hi, lo) (zig_f128){ lo, hi }
3871#define zig_make_f128_zig_init_u128 zig_make_f128_zig_make_u128
3872#define zig_make_f128(fp, repr) zig_make_f128_##repr
3873#define zig_make_special_f128(sign, name, arg, repr) zig_make_f128_##repr
3874#define zig_init_special_f128(sign, name, arg, repr) zig_make_f128_##repr
3875#else
3876#define zig_repr_f128 u128
5877#if defined(zig_x86_64) && defined(ZIG_TARGET_ABI_MSVC)
5878#if defined(zig_msvc) && !defined(__clang__)
5879#include <emmintrin.h>
5880typedef __m128i zig_f128;
5881#define zig_init_repr_f128(hi, lo) { .m128i_u64 = { lo, hi } }
5882#define zig_lo_repr_f128(arg) (arg).m128i_u64[0]
5883#define zig_hi_repr_f128(arg) (arg).m128i_u64[1]
5884#else
5885typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_f128;
5886#define zig_init_repr_f128(hi, lo) { lo, hi }
5887#define zig_lo_repr_f128(arg) (arg)[0]
5888#define zig_hi_repr_f128(arg) (arg)[1]
5889#endif
5890#else
38775891typedef zig_u128 zig_f128;
5892#define zig_init_repr_f128(hi, lo) zig_init_u128(hi, lo)
5893#define zig_make_repr_f128(hi, lo) zig_make_u128(hi, lo)
5894#define zig_lo_repr_f128(arg) zig_lo_u128(arg)
5895#define zig_hi_repr_f128(arg) zig_hi_u128(arg)
5896#endif
5897#endif
5898#ifndef zig_has_f128
5899#define zig_has_f128 0
38785900#define zig_make_f128(fp, repr) repr
5901#ifndef zig_make_repr_f128
5902#define zig_make_repr_f128(hi, lo) (zig_f128)zig_init_repr_f128(hi, lo)
5903#endif
5904#undef zig_make_special_f128
38795905#define zig_make_special_f128(sign, name, arg, repr) repr
5906#undef zig_init_special_f128
38805907#define zig_init_special_f128(sign, name, arg, repr) repr
38815908#endif
3882#endif
38835909
38845910#if !defined(zig_msvc) && defined(ZIG_TARGET_ABI_MSVC)
38855911/* Emulate msvc abi on a gnu compiler */
......@@ -3892,84 +5918,141 @@ typedef zig_f128 zig_c_longdouble;
38925918typedef long double zig_c_longdouble;
38935919#endif
38945920
3895#define zig_bitCast_float(Type, ReprType) \
3896 static inline zig_##Type zig_bitCast_##Type(ReprType repr) { \
3897 zig_##Type result; \
3898 memcpy(&result, &repr, sizeof(result)); \
3899 return result; \
5921#if __AVR__
5922typedef signed char zig_FloatCompareResult;
5923#elif defined(zig_aarch64)
5924typedef signed int zig_FloatCompareResult;
5925#elif __SIZEOF_LONG__ >= __SIZEOF_POINTER__
5926typedef signed long zig_FloatCompareResult;
5927#else
5928typedef signed long long zig_FloatCompareResult;
5929#endif
5930
5931#define zig_bitCast_float(w, iw, UnsignedReprType, SignedReprType) \
5932 static inline zig_f##w zig_f##w##_bitCast_u##iw(UnsignedReprType arg) { \
5933 zig_f##w res; \
5934 memcpy(&res, &arg, sizeof(zig_f##w)); \
5935 return res; \
5936 } \
5937 static inline zig_f##w zig_f##w##_bitCast_i##iw(SignedReprType arg) { \
5938 zig_f##w res; \
5939 memcpy(&res, &arg, sizeof(zig_f##w)); \
5940 return res; \
5941 } \
5942 static inline UnsignedReprType zig_u##iw##_bitCast_f##w(zig_f##w arg) { \
5943 UnsignedReprType res; \
5944 memcpy(&res, &arg, sizeof(zig_f##w)); \
5945 return zig_u##iw##_truncate_u##iw(res, w); \
5946 } \
5947 static inline SignedReprType zig_i##iw##_bitCast_f##w(zig_f##w arg) { \
5948 SignedReprType res; \
5949 memcpy(&res, &arg, sizeof(zig_f##w)); \
5950 return zig_i##iw##_truncate_i##iw(res, w); \
39005951 }
3901zig_bitCast_float(f16, uint16_t)
3902zig_bitCast_float(f32, uint32_t)
3903zig_bitCast_float(f64, uint64_t)
3904zig_bitCast_float(f80, zig_u128)
3905zig_bitCast_float(f128, zig_u128)
5952zig_bitCast_float(16, 16, uint16_t, int16_t)
5953zig_bitCast_float(32, 32, uint32_t, int32_t)
5954zig_bitCast_float(64, 64, uint64_t, int64_t)
5955#if zig_has_f80
5956zig_bitCast_float(80, 128, zig_u128, zig_i128)
5957#else
5958static inline zig_f80 zig_f80_bitCast_u128(zig_u128 arg) {
5959 return zig_make_repr_f80(zig_lo_u128(arg), (uint16_t)zig_hi_u128(arg));
5960}
5961static inline zig_f80 zig_f80_bitCast_i128(zig_i128 arg) {
5962 return zig_make_repr_f80(zig_lo_i128(arg), (uint16_t)zig_hi_i128(arg));
5963}
5964static inline zig_u128 zig_u128_bitCast_f80(zig_f80 arg) {
5965 return zig_make_u128(zig_exponent_repr_f80(arg), zig_mantissa_repr_f80(arg));
5966}
5967static inline zig_i128 zig_i128_bitCast_f80(zig_f80 arg) {
5968 return zig_make_i128((int16_t)zig_exponent_repr_f80(arg), zig_mantissa_repr_f80(arg));
5969}
5970#endif
5971static inline zig_f80 zig_f80_bitCast_big(const void *arg) {
5972 return zig_f80_bitCast_u128(zig_u128_truncate_big(arg, UINT8_C(80), false, UINT16_C(80)));
5973}
5974static inline void zig_big_bitCast_f80(void *res, zig_f80 arg, bool res_is_signed, uint16_t res_bits) {
5975 if (res_is_signed) {
5976 zig_big_truncate_i128(res, zig_i128_bitCast_f80(arg), res_is_signed, res_bits);
5977 } else {
5978 zig_big_truncate_u128(res, zig_u128_bitCast_f80(arg), res_is_signed, res_bits);
5979 }
5980}
5981#if zig_has_f128
5982zig_bitCast_float(128, 128, zig_u128, zig_i128)
5983#else
5984static inline zig_f128 zig_f128_bitCast_u128(zig_u128 arg) {
5985 return zig_make_repr_f128(zig_hi_u128(arg), zig_lo_u128(arg));
5986}
5987static inline zig_f128 zig_f128_bitCast_i128(zig_i128 arg) {
5988 return zig_make_repr_f128((uint64_t)zig_hi_i128(arg), zig_lo_i128(arg));
5989}
5990static inline zig_u128 zig_u128_bitCast_f128(zig_f128 arg) {
5991 return zig_make_u128(zig_hi_repr_f128(arg), zig_lo_repr_f128(arg));
5992}
5993static inline zig_i128 zig_i128_bitCast_f128(zig_f128 arg) {
5994 return zig_make_i128((int64_t)zig_hi_repr_f128(arg), zig_lo_repr_f128(arg));
5995}
5996#endif
39065997
3907#define zig_convert_builtin(ExternResType, ResType, operation, ExternArgType, ArgType, version) \
3908 zig_extern ExternResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
3909 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ExternArgType); \
5998#define zig_convert_float_00(ResType, operation, ArgType, version) \
5999 zig_extern ResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
6000 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ArgType arg); \
6001 return zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
6002 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(arg)
6003#define zig_convert_float_01(ResType, operation, ArgType, version) \
6004 zig_convert_float_00(ResType, operation, ArgType, version)
6005#define zig_convert_float_10(ResType, operation, ArgType, version) \
6006 zig_convert_float_00(ResType, operation, ArgType, version)
6007#define zig_convert_float_11(ResType, operation, ArgType, version) \
6008 return (ResType)arg
6009#define zig_convert_float(res_when, ResType, operation, arg_when, ArgType, version) \
39106010 static inline ResType zig_expand_concat(zig_expand_concat(zig_##operation, \
39116011 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType)(ArgType arg) { \
3912 ResType res; \
3913 ExternResType extern_res; \
3914 ExternArgType extern_arg; \
3915 memcpy(&extern_arg, &arg, sizeof(extern_arg)); \
3916 extern_res = zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
3917 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(extern_arg); \
3918 memcpy(&res, &extern_res, sizeof(res)); \
3919 return extern_res; \
3920 }
3921zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f32, zig_f32, 2)
3922zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f64, zig_f64, 2)
3923zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f80, zig_f80, 2)
3924zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f128, zig_f128, 2)
3925zig_convert_builtin(zig_f32, zig_f32, extend, zig_compiler_rt_f16, zig_f16, 2)
3926zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f80, zig_f80, 2)
3927zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f128, zig_f128, 2)
3928zig_convert_builtin(zig_f64, zig_f64, extend, zig_compiler_rt_f16, zig_f16, 2)
3929zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f80, zig_f80, 2)
3930zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f128, zig_f128, 2)
3931zig_convert_builtin(zig_f80, zig_f80, extend, zig_f16, zig_f16, 2)
3932zig_convert_builtin(zig_f80, zig_f80, extend, zig_f32, zig_f32, 2)
3933zig_convert_builtin(zig_f80, zig_f80, extend, zig_f64, zig_f64, 2)
3934zig_convert_builtin(zig_f80, zig_f80, trunc, zig_f128, zig_f128, 2)
3935zig_convert_builtin(zig_f128, zig_f128, extend, zig_f16, zig_f16, 2)
3936zig_convert_builtin(zig_f128, zig_f128, extend, zig_f32, zig_f32, 2)
3937zig_convert_builtin(zig_f128, zig_f128, extend, zig_f64, zig_f64, 2)
3938zig_convert_builtin(zig_f128, zig_f128, extend, zig_f80, zig_f80, 2)
3939
3940#ifdef __ARM_EABI__
3941
3942zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_d2f(zig_f64);
3943static inline zig_f32 zig_truncdfsf(zig_f64 arg) { return __aeabi_d2f(arg); }
3944
3945zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_f2d(zig_f32);
3946static inline zig_f64 zig_extendsfdf(zig_f32 arg) { return __aeabi_f2d(arg); }
3947
3948#else /* __ARM_EABI__ */
3949
3950zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f64, zig_f64, 2)
3951zig_convert_builtin(zig_f64, zig_f64, extend, zig_f32, zig_f32, 2)
3952
3953#endif /* __ARM_EABI__ */
3954
3955#define zig_float_negate_builtin_0(w, c, sb) \
3956 zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, c sb))
3957#define zig_float_negate_builtin_1(w, c, sb) -arg
3958#define zig_float_negate_builtin(w, c, sb) \
6012 zig_expand_concat(zig_expand_concat(zig_convert_float_, zig_has_##res_when), \
6013 zig_has_##arg_when)(ResType, operation, ArgType, version); \
6014 }
6015
6016#define zig_convert_floats(SmallType, BigType) \
6017 zig_convert_float(SmallType, zig_##SmallType, trunc, BigType, zig_##BigType, 2) \
6018 zig_convert_float(BigType, zig_##BigType, extend, SmallType, zig_##SmallType, 2)
6019zig_convert_floats(f16, f32)
6020zig_convert_floats(f16, f64)
6021zig_convert_floats(f16, f80)
6022zig_convert_floats(f16, f128)
6023zig_convert_floats(f32, f64)
6024zig_convert_floats(f32, f80)
6025zig_convert_floats(f32, f128)
6026zig_convert_floats(f64, f80)
6027zig_convert_floats(f64, f128)
6028zig_convert_floats(f80, f128)
6029
6030#define zig_float_negate_builtin_0(w, sb) \
6031 zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, sb))
6032#define zig_float_negate_builtin_1(w, sb) -arg
6033#define zig_float_negate_builtin(w, sb) \
39596034 static inline zig_f##w zig_neg_f##w(zig_f##w arg) { \
3960 return zig_expand_concat(zig_float_negate_builtin_, zig_has_f##w)(w, c, sb); \
6035 return zig_expand_concat(zig_float_negate_builtin_, zig_has_f##w)(w, sb); \
39616036 }
3962zig_float_negate_builtin(16, , UINT16_C(1) << 15 )
3963zig_float_negate_builtin(32, , UINT32_C(1) << 31 )
3964zig_float_negate_builtin(64, , UINT64_C(1) << 63 )
3965zig_float_negate_builtin(80, zig_make_u128, (UINT64_C(1) << 15, UINT64_C(0)))
3966zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))
6037zig_float_negate_builtin(16, UINT16_C(1) << 15)
6038zig_float_negate_builtin(32, UINT32_C(1) << 31)
6039zig_float_negate_builtin(64, UINT64_C(1) << 63)
6040
6041#undef zig_float_negate_builtin_0
6042#define zig_float_negate_builtin_0(w, sb) \
6043 zig_make_repr_f##w(zig_mantissa_repr_f##w(arg), zig_xor_u16(zig_exponent_repr_f##w(arg), sb))
6044zig_float_negate_builtin(80, UINT16_C(1) << 15)
6045
6046#undef zig_float_negate_builtin_0
6047#define zig_float_negate_builtin_0(w, sb) \
6048 zig_make_repr_f##w(zig_xor_u64(zig_hi_repr_f##w(arg), sb), zig_lo_repr_f##w(arg))
6049zig_float_negate_builtin(128, UINT64_C(1) << 63)
39676050
39686051#define zig_float_less_builtin_0(Type, operation) \
3969 zig_extern int32_t zig_expand_concat(zig_expand_concat(__##operation, \
6052 zig_extern zig_FloatCompareResult zig_expand_concat(zig_expand_concat(__##operation, \
39706053 zig_compiler_rt_abbrev_zig_##Type), 2)(zig_##Type, zig_##Type); \
39716054 static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
3972 return zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 2)(lhs, rhs); \
6055 return (int32_t)zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 2)(lhs, rhs); \
39736056 }
39746057#define zig_float_less_builtin_1(Type, operation) \
39756058 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)))
39946077 return lhs operator rhs; \
39956078 }
39966079
6080#define zig_float_builtins(w) \
6081 zig_common_float_builtins(w) \
6082 zig_convert_float(f##w, zig_f##w, float, int128, zig_i128, ) \
6083 zig_convert_float(f##w, zig_f##w, floatun, int128, zig_u128, )
39976084#define zig_common_float_builtins(w) \
3998 zig_convert_builtin( int64_t, int64_t, fix, zig_f##w, zig_f##w, ) \
3999 zig_convert_builtin(zig_i128, zig_i128, fix, zig_f##w, zig_f##w, ) \
4000 zig_convert_builtin(zig_u128, zig_u128, fixuns, zig_f##w, zig_f##w, ) \
4001 zig_convert_builtin(zig_f##w, zig_f##w, float, int64_t, int64_t, ) \
4002 zig_convert_builtin(zig_f##w, zig_f##w, float, zig_i128, zig_i128, ) \
4003 zig_convert_builtin(zig_f##w, zig_f##w, floatun, zig_u128, zig_u128, ) \
6085 zig_convert_float(always, int32_t, fix, f##w, zig_f##w, ) \
6086 zig_convert_float(always, int64_t, fix, f##w, zig_f##w, ) \
6087 zig_convert_float(int128, zig_i128, fix, f##w, zig_f##w, ) \
6088 zig_convert_float(always, uint32_t, fixuns, f##w, zig_f##w, ) \
6089 zig_convert_float(always, uint64_t, fixuns, f##w, zig_f##w, ) \
6090 zig_convert_float(int128, zig_u128, fixuns, f##w, zig_f##w, ) \
6091 zig_convert_float(f##w, zig_f##w, float, always, int32_t, ) \
6092 zig_convert_float(f##w, zig_f##w, float, always, int64_t, ) \
6093 zig_convert_float(f##w, zig_f##w, floatun, always, uint32_t, ) \
6094 zig_convert_float(f##w, zig_f##w, floatun, always, uint64_t, ) \
6095\
6096 static inline void zig_expand_concat(zig_expand_concat(zig_fix, \
6097 zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \
6098 zig_extern void zig_expand_concat(zig_expand_concat(__fix, \
6099 zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \
6100 zig_expand_concat(zig_expand_concat(__fix, \
6101 zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \
6102 } \
6103\
6104 static inline void zig_expand_concat(zig_expand_concat(zig_fixuns, \
6105 zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \
6106 zig_extern void zig_expand_concat(zig_expand_concat(__fixuns, \
6107 zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \
6108 zig_expand_concat(zig_expand_concat(__fixuns, \
6109 zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \
6110 } \
6111\
6112 static inline zig_f##w zig_expand_concat(zig_floatei, \
6113 zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \
6114 zig_extern zig_f##w zig_expand_concat(__floatei, \
6115 zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \
6116 return zig_expand_concat(__floatei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \
6117 } \
6118\
6119 static inline zig_f##w zig_expand_concat(zig_floatunei, \
6120 zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \
6121 zig_extern zig_f##w zig_expand_concat(__floatunei, \
6122 zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \
6123 return zig_expand_concat(__floatunei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \
6124 } \
6125\
40046126 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, cmp) \
40056127 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, ne) \
40066128 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)))
40316153 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)) \
40326154 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)) \
40336155\
4034 static inline zig_f##w zig_div_trunc_f##w(zig_f##w lhs, zig_f##w rhs) { \
6156 static inline zig_f##w zig_divTrunc_f##w(zig_f##w lhs, zig_f##w rhs) { \
40356157 return zig_trunc_f##w(zig_div_f##w(lhs, rhs)); \
40366158 } \
40376159\
4038 static inline zig_f##w zig_div_floor_f##w(zig_f##w lhs, zig_f##w rhs) { \
6160 static inline zig_f##w zig_divFloor_f##w(zig_f##w lhs, zig_f##w rhs) { \
40396161 return zig_floor_f##w(zig_div_f##w(lhs, rhs)); \
40406162 } \
40416163\
4042 static inline zig_f##w zig_div_ceil_f##w(zig_f##w lhs, zig_f##w rhs) { \
6164 static inline zig_f##w zig_divCeil_f##w(zig_f##w lhs, zig_f##w rhs) { \
40436165 return zig_ceil_f##w(zig_div_f##w(lhs, rhs)); \
40446166 } \
40456167\
40466168 static inline zig_f##w zig_mod_f##w(zig_f##w lhs, zig_f##w rhs) { \
4047 return zig_sub_f##w(lhs, zig_mul_f##w(zig_div_floor_f##w(lhs, rhs), rhs)); \
6169 return zig_sub_f##w(lhs, zig_mul_f##w(zig_divFloor_f##w(lhs, rhs), rhs)); \
40486170 }
4049zig_common_float_builtins(16)
4050zig_common_float_builtins(32)
4051zig_common_float_builtins(64)
4052zig_common_float_builtins(80)
4053zig_common_float_builtins(128)
4054
4055#define zig_float_builtins(w) \
4056 zig_convert_builtin( int32_t, int32_t, fix, zig_f##w, zig_f##w, ) \
4057 zig_convert_builtin(uint32_t, uint32_t, fixuns, zig_f##w, zig_f##w, ) \
4058 zig_convert_builtin(uint64_t, uint64_t, fixuns, zig_f##w, zig_f##w, ) \
4059 zig_convert_builtin(zig_f##w, zig_f##w, float, int32_t, int32_t, ) \
4060 zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint32_t, uint32_t, ) \
4061 zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint64_t, uint64_t, )
40626171zig_float_builtins(16)
4063zig_float_builtins(80)
4064zig_float_builtins(128)
4065
4066#ifdef __ARM_EABI__
4067
4068zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_f2iz(zig_f32);
4069static inline int32_t zig_fixsfsi(zig_f32 arg) { return __aeabi_f2iz(arg); }
4070
4071zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_f2uiz(zig_f32);
4072static inline uint32_t zig_fixunssfsi(zig_f32 arg) { return __aeabi_f2uiz(arg); }
4073
4074zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_f2ulz(zig_f32);
4075static inline uint64_t zig_fixunssfdi(zig_f32 arg) { return __aeabi_f2ulz(arg); }
4076
4077zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_i2f(int32_t);
4078static inline zig_f32 zig_floatsisf(int32_t arg) { return __aeabi_i2f(arg); }
4079
4080zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ui2f(uint32_t);
4081static inline zig_f32 zig_floatunsisf(uint32_t arg) { return __aeabi_ui2f(arg); }
4082
4083zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ul2f(uint64_t);
4084static inline zig_f32 zig_floatundisf(uint64_t arg) { return __aeabi_ul2f(arg); }
4085
4086zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_d2iz(zig_f64);
4087static inline int32_t zig_fixdfsi(zig_f64 arg) { return __aeabi_d2iz(arg); }
4088
4089zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_d2uiz(zig_f64);
4090static inline uint32_t zig_fixunsdfsi(zig_f64 arg) { return __aeabi_d2uiz(arg); }
4091
4092zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_d2ulz(zig_f64);
4093static inline uint64_t zig_fixunsdfdi(zig_f64 arg) { return __aeabi_d2ulz(arg); }
4094
4095zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_i2d(int32_t);
4096static inline zig_f64 zig_floatsidf(int32_t arg) { return __aeabi_i2d(arg); }
4097
4098zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ui2d(uint32_t);
4099static inline zig_f64 zig_floatunsidf(uint32_t arg) { return __aeabi_ui2d(arg); }
4100
4101zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ul2d(uint64_t);
4102static inline zig_f64 zig_floatundidf(uint64_t arg) { return __aeabi_ul2d(arg); }
4103
4104#else /* __ARM_EABI__ */
4105
41066172zig_float_builtins(32)
41076173zig_float_builtins(64)
4108
4109#endif /* __ARM_EABI__ */
6174zig_float_builtins(80)
6175#if defined(zig_x86_32)
6176zig_common_float_builtins(128)
6177static inline zig_f128 zig_floattitf(zig_i128 arg) {
6178 extern zig_f128 __floattitf(zig_f128 arg);
6179 return __floattitf(zig_f128_bitCast_i128(arg));
6180}
6181static inline zig_f128 zig_floatuntitf(zig_u128 arg) {
6182 extern zig_f128 __floatuntitf(zig_f128 arg);
6183 return __floatuntitf(zig_f128_bitCast_u128(arg));
6184}
6185#elif defined(zig_x86_64) && defined(zig_windows)
6186zig_common_float_builtins(128)
6187static inline zig_f128 zig_floattitf(zig_i128 arg) {
6188 extern zig_f128 __floattitf(zig_i128 arg);
6189 return __floattitf(arg);
6190}
6191static inline zig_f128 zig_floatuntitf(zig_u128 arg) {
6192 extern zig_f128 __floatuntitf(uint64_t arg_lo, uint64_t arg_hi);
6193 return __floatuntitf(zig_lo_u128(arg), zig_hi_u128(arg));
6194}
6195#else
6196zig_float_builtins(128)
6197#endif
41106198
41116199/* ============================ Atomics Support ============================= */
41126200
......@@ -4410,19 +6498,19 @@ typedef int zig_memory_order;
44106498 } \
44116499 static inline void zig_msvc_atomic_store_##ZigType(Type volatile* obj, Type value) { \
44126500 (void)_InterlockedExchange##suffix((SigType volatile*)obj, (SigType)value); \
4413 } \
6501 } \
44146502 static inline Type zig_msvc_atomic_load_zig_memory_order_relaxed_##ZigType(Type volatile* obj) { \
44156503 return __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
44166504 } \
44176505 static inline Type zig_msvc_atomic_load_zig_memory_order_acquire_##ZigType(Type volatile* obj) { \
4418 Type val = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
6506 Type value = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
44196507 _ReadWriteBarrier(); \
4420 return val; \
6508 return value; \
44216509 } \
44226510 static inline Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##ZigType(Type volatile* obj) { \
4423 Type val = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
6511 Type value = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
44246512 _ReadWriteBarrier(); \
4425 return val; \
6513 return value; \
44266514 }
44276515
44286516zig_msvc_atomics( u8, uint8_t, char, 8, 8)
......@@ -4465,14 +6553,14 @@ zig_msvc_atomics(i64, int64_t, __int64, 64, 64)
44656553 zig_##Type result; \
44666554 SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
44676555 _ReadWriteBarrier(); \
4468 memcpy(&result, &initial, sizeof(result)); \
6556 memcpy(&result, &initial, sizeof(result)); \
44696557 return result; \
44706558 } \
44716559 static inline zig_##Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##Type(zig_##Type volatile* obj) { \
44726560 zig_##Type result; \
44736561 SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
44746562 _ReadWriteBarrier(); \
4475 memcpy(&result, &initial, sizeof(result)); \
6563 memcpy(&result, &initial, sizeof(result)); \
44766564 return result; \
44776565 }
44786566
......@@ -4502,9 +6590,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p32(void volat
45026590}
45036591
45046592static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p32(void volatile* obj) {
4505 void* val = (void*)__iso_volatile_load32(obj);
6593 void* value = (void*)__iso_volatile_load32(obj);
45066594 _ReadWriteBarrier();
4507 return val;
6595 return value;
45086596}
45096597
45106598static 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
45326620}
45336621
45346622static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p64(void volatile* obj) {
4535 void* val = (void*)__iso_volatile_load64(obj);
6623 void* value = (void*)__iso_volatile_load64(obj);
45366624 _ReadWriteBarrier();
4537 return val;
6625 return value;
45386626}
45396627
45406628static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p64(void volatile* obj) {
stage1/zig1.wasm
Binary files a/stage1/zig1.wasm and b/stage1/zig1.wasm differ
test/behavior/abs.zig-2
......@@ -144,7 +144,6 @@ test "@abs big int <= 128 bits" {
144144 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
145145 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
146146 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
147 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
148147
149148 try comptime testAbsSignedBigInt();
150149 try testAbsSignedBigInt();
......@@ -256,7 +255,6 @@ fn testAbsFloats(comptime T: type) !void {
256255
257256test "@abs int vectors" {
258257 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
259 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
260258 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
261259 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
262260 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
test/behavior/align.zig+32-13
......@@ -129,8 +129,7 @@ test "alignment and size of structs with 128-bit fields" {
129129 y: u8,
130130 };
131131 const expected = switch (builtin.cpu.arch) {
132 .s390x,
133 => .{
132 .s390x => .{
134133 .a_align = 8,
135134 .a_size = 16,
136135
......@@ -142,7 +141,32 @@ test "alignment and size of structs with 128-bit fields" {
142141 .u129_align = 8,
143142 .u129_size = 24,
144143 },
145
144 .x86 => switch (builtin.os.tag) {
145 else => .{
146 .a_align = 4,
147 .a_size = 16,
148
149 .b_align = 4,
150 .b_size = 20,
151
152 .u128_align = 4,
153 .u128_size = 16,
154 .u129_align = 4,
155 .u129_size = 20,
156 },
157 .uefi, .windows => .{
158 .a_align = 8,
159 .a_size = 16,
160
161 .b_align = 8,
162 .b_size = 24,
163
164 .u128_align = 8,
165 .u128_size = 16,
166 .u129_align = 8,
167 .u129_size = 24,
168 },
169 },
146170 .amdgcn,
147171 .arm,
148172 .armeb,
......@@ -155,12 +179,13 @@ test "alignment and size of structs with 128-bit fields" {
155179 .powerpc,
156180 .powerpcle,
157181 .riscv32,
182 .sparc,
158183 => .{
159184 .a_align = 8,
160185 .a_size = 16,
161186
162 .b_align = 16,
163 .b_size = 32,
187 .b_align = 8,
188 .b_size = 24,
164189
165190 .u128_align = 8,
166191 .u128_size = 16,
......@@ -178,12 +203,10 @@ test "alignment and size of structs with 128-bit fields" {
178203 .nvptx64,
179204 .powerpc64,
180205 .powerpc64le,
181 .sparc,
182206 .sparc64,
183207 .riscv64,
184208 .wasm32,
185209 .wasm64,
186 .x86,
187210 .x86_64,
188211 => .{
189212 .a_align = 16,
......@@ -200,12 +223,11 @@ test "alignment and size of structs with 128-bit fields" {
200223
201224 else => return error.SkipZigTest,
202225 };
203 const min_struct_align = if (builtin.zig_backend == .stage2_c) if (builtin.cpu.arch == .s390x) 8 else 16 else 0;
204226 comptime {
205 assert(@alignOf(A) == @max(expected.a_align, min_struct_align));
227 assert(@alignOf(A) == expected.a_align);
206228 assert(@sizeOf(A) == expected.a_size);
207229
208 assert(@alignOf(B) == @max(expected.b_align, min_struct_align));
230 assert(@alignOf(B) == expected.b_align);
209231 assert(@sizeOf(B) == expected.b_size);
210232
211233 assert(@alignOf(u128) == expected.u128_align);
......@@ -547,8 +569,6 @@ test "sub-aligned pointer field access" {
547569}
548570
549571test "alignment of zero-bit types is respected" {
550 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
551 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
552572 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
553573 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
554574
......@@ -582,7 +602,6 @@ test "zero-bit fields in extern struct pad fields appropriately" {
582602 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
583603 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
584604 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
585 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
586605
587606 const S = extern struct {
588607 x: u8,
test/behavior/basic.zig-3
......@@ -797,10 +797,8 @@ test "auto created variables have correct alignment" {
797797}
798798
799799test "extern variable with non-pointer opaque type" {
800 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
801800 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
802801 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
803 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
804802 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
805803
806804 @export(&var_to_export, .{ .name = "opaque_extern_var" });
......@@ -1398,7 +1396,6 @@ test "allocation and looping over 3-byte integer" {
13981396 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
13991397 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
14001398 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1401 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag.isDarwin()) return error.SkipZigTest; // TODO
14021399
14031400 try expect(@sizeOf(u24) == 4);
14041401 try expect(@sizeOf([1]u24) == 4);
test/behavior/bit_shifting.zig-1
......@@ -147,7 +147,6 @@ test "Saturating Shift Left where lhs is of a computed type" {
147147
148148test "Saturating Shift Left" {
149149 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
150 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
151150 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
152151 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
153152 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
test/behavior/bitcast.zig+17-6
......@@ -210,7 +210,6 @@ test "triple level result location with bitcast sandwich passed as tuple element
210210
211211test "@bitCast packed struct of floats" {
212212 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
213 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
214213 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
215214 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
216215 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -247,7 +246,6 @@ test "@bitCast packed struct of floats" {
247246
248247test "comptime @bitCast packed struct to int and back" {
249248 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
250 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
251249 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
252250 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
253251 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -283,7 +281,6 @@ test "comptime @bitCast packed struct to int and back" {
283281test "bitcast vector to integer and back" {
284282 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
285283 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
286 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
287284 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
288285 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
289286
......@@ -329,10 +326,10 @@ fn bitCastWrapper128(x: f128) u128 {
329326}
330327test "bitcast nan float does not modify signaling bit" {
331328 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
332 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
333329 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
334330 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
335331 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
332 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
336333
337334 const snan_u16: u16 = 0x7D00;
338335 const snan_u32: u32 = 0x7FA00000;
......@@ -383,7 +380,6 @@ test "bitcast nan float does not modify signaling bit" {
383380test "@bitCast of packed struct of bools all true" {
384381 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
385382 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
386 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
387383 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
388384 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
389385
......@@ -404,7 +400,6 @@ test "@bitCast of packed struct of bools all true" {
404400test "@bitCast of packed struct of bools all false" {
405401 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
406402 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
407 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
408403 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
409404
410405 const P = packed struct {
......@@ -437,6 +432,22 @@ test "@bitCast of packed struct with void field to integer" {
437432 try comptime S.doTheTest(123);
438433}
439434
435test "@bitCast of packed struct with void field and multiple integers" {
436 const S = packed struct {
437 x: u8,
438 v: void,
439 y: u8,
440
441 fn doTheTest(x: u8, y: u8) !void {
442 const foo = @as(@This(), .{ .x = x, .v = {}, .y = y });
443 const as_int: u16 = @bitCast(foo);
444 try expect(as_int == @as(u16, y) << 8 | x);
445 }
446 };
447 try S.doTheTest(123, 45);
448 try comptime S.doTheTest(123, 45);
449}
450
440451test "@bitCast vector to array with different element size" {
441452 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
442453
test/behavior/builtin_functions_returning_void_or_noreturn.zig-1
......@@ -6,7 +6,6 @@ var x: u8 = 1;
66
77// This excludes builtin functions that return void or noreturn that cannot be tested.
88test {
9 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
109 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1110 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1211 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/call.zig-1
......@@ -21,7 +21,6 @@ test "super basic invocations" {
2121
2222test "basic invocations" {
2323 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
24 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2524 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2625 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2726 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/cast.zig+7-19
......@@ -120,6 +120,7 @@ test "@floatFromInt" {
120120 try expect(@as(i32, @floor(f)) == k);
121121 try expect(@as(i32, @ceil(f)) == k);
122122 try expect(@as(i32, @trunc(f)) == k);
123 try expect(@as(i32, @trunc(@floor(f))) == k);
123124 }
124125 };
125126 try S.doTheTest();
......@@ -134,7 +135,6 @@ test "@intFromFloat > 128 bits" {
134135 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
135136 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
136137 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
137 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
138138
139139 try testIntFromFloat(f16, 1024, u140, 1024);
140140 try testIntFromFloat(f16, -1024, i140, -1024);
......@@ -160,7 +160,6 @@ test "@floatFromInt > 128 bits" {
160160 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
161161 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
162162 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
163 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
164163
165164 try testFloatFromInt(u140, 1024, f16, 1024);
166165 try testFloatFromInt(i140, -1024, f16, -1024);
......@@ -182,8 +181,8 @@ test "@floatFromInt(f80)" {
182181 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
183182 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
184183 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
185 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
186184 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
185 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
187186
188187 const S = struct {
189188 fn doTheTest(comptime Int: type) !void {
......@@ -199,6 +198,7 @@ test "@floatFromInt(f80)" {
199198 try expect(@as(Int, @floor(f)) == k);
200199 try expect(@as(Int, @ceil(f)) == k);
201200 try expect(@as(Int, @trunc(f)) == k);
201 try expect(@as(Int, @trunc(@floor(f))) == k);
202202 }
203203 };
204204 try S.doTheTest(i31);
......@@ -207,7 +207,7 @@ test "@floatFromInt(f80)" {
207207 try S.doTheTest(i64);
208208 try S.doTheTest(i80);
209209 try S.doTheTest(i128);
210 // try S.doTheTest(i256); // TODO missing compiler_rt symbols
210 try S.doTheTest(i256);
211211 try comptime S.doTheTest(i31);
212212 try comptime S.doTheTest(i32);
213213 try comptime S.doTheTest(i45);
......@@ -281,6 +281,7 @@ test "type coercion from int to float" {
281281test "@intFromFloat" {
282282 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
283283 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
284
284285 try testIntFromFloats();
285286 try comptime testIntFromFloats();
286287}
......@@ -498,7 +499,7 @@ test "array coercion to undefined at runtime" {
498499
499500 @setRuntimeSafety(true);
500501
501 if (builtin.mode != .Debug and builtin.mode != .ReleaseSafe) {
502 if (builtin.mode != .debug and builtin.mode != .safe) {
502503 return error.SkipZigTest;
503504 }
504505
......@@ -1473,11 +1474,6 @@ fn foobar(func: PFN_void) !void {
14731474test "cast function with an opaque parameter" {
14741475 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
14751476
1476 if (builtin.zig_backend == .stage2_c) {
1477 // https://github.com/ziglang/zig/issues/16845
1478 return error.SkipZigTest;
1479 }
1480
14811477 const Container = struct {
14821478 const Ctx = opaque {};
14831479 ctx: *Ctx,
......@@ -1724,9 +1720,7 @@ test "cast f16 to wider types" {
17241720 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
17251721 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
17261722 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1727 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
17281723 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1729 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
17301724
17311725 const S = struct {
17321726 fn doTheTest() !void {
......@@ -1831,21 +1825,15 @@ test "pointer to empty struct literal to mutable slice" {
18311825
18321826test "coerce between pointers of compatible differently-named floats" {
18331827 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1834 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows and !builtin.link_libc) return error.SkipZigTest;
18351828 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
18361829 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
18371830 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
18381831
1839 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
1840 // https://github.com/ziglang/zig/issues/12396
1841 return error.SkipZigTest;
1842 }
1843
18441832 const F = switch (@typeInfo(c_longdouble).float.bits) {
18451833 64 => f64,
18461834 80 => f80,
18471835 128 => f128,
1848 else => @compileError("unreachable"),
1836 else => comptime unreachable,
18491837 };
18501838 var f1: F = 12.34;
18511839 const f2: *c_longdouble = &f1;
test/behavior/cast_int.zig-1
......@@ -168,7 +168,6 @@ test "@intCast <= 64 bits" {
168168
169169test "@intCast > 128 bits" {
170170 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
171 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
172171 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
173172
174173 try testIntCast(u8, 123, u140, 123);
test/behavior/eval.zig-1
......@@ -513,7 +513,6 @@ test "runtime 128 bit integer division" {
513513 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
514514 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
515515 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
516 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
517516 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
518517
519518 var a: u128 = 152313999999999991610955792383;
test/behavior/export_builtin.zig-15
......@@ -5,11 +5,6 @@ const expect = std.testing.expect;
55test "exporting enum value" {
66 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
77
8 if (builtin.cpu.arch.isWasm()) {
9 // https://github.com/ziglang/zig/issues/4866
10 return error.SkipZigTest;
11 }
12
138 const S = struct {
149 const E = enum(c_int) { one, two };
1510 const e: E = .two;
......@@ -35,11 +30,6 @@ test "exporting with internal linkage" {
3530test "exporting using namespace access" {
3631 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
3732
38 if (builtin.cpu.arch.isWasm()) {
39 // https://github.com/ziglang/zig/issues/4866
40 return error.SkipZigTest;
41 }
42
4333 const S = struct {
4434 const Inner = struct {
4535 const x: u32 = 5;
......@@ -57,11 +47,6 @@ test "exporting comptime-known value" {
5747 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
5848 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
5949
60 if (builtin.cpu.arch.isWasm()) {
61 // https://github.com/ziglang/zig/issues/4866
62 return error.SkipZigTest;
63 }
64
6550 const x: u32 = 10;
6651 @export(&x, .{ .name = "exporting_comptime_known_value_foo" });
6752 const S = struct {
test/behavior/extern.zig-1
......@@ -3,7 +3,6 @@ const std = @import("std");
33const expect = std.testing.expect;
44
55test "anyopaque extern symbol" {
6 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
76 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
87 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
98
test/behavior/field_parent_ptr.zig-3
......@@ -586,7 +586,6 @@ test "@fieldParentPtr extern struct last zero-bit field" {
586586}
587587
588588test "@fieldParentPtr unaligned packed struct" {
589 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
590589 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
591590 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
592591 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
......@@ -725,7 +724,6 @@ test "@fieldParentPtr unaligned packed struct" {
725724}
726725
727726test "@fieldParentPtr aligned packed struct" {
728 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
729727 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
730728 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
731729 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
......@@ -1897,7 +1895,6 @@ test "@fieldParentPtr packed union" {
18971895}
18981896
18991897test "@fieldParentPtr tagged union all zero-bit fields" {
1900 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
19011898 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
19021899 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
19031900
test/behavior/floatop.zig+10-50
......@@ -118,7 +118,6 @@ fn testMul(comptime T: type) !void {
118118test "cmp f16" {
119119 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
120120 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
121 if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
122121
123122 try testCmp(f16);
124123 try comptime testCmp(f16);
......@@ -127,7 +126,6 @@ test "cmp f16" {
127126test "cmp f32" {
128127 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
129128 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
130 if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
131129
132130 try testCmp(f32);
133131 try comptime testCmp(f32);
......@@ -142,7 +140,6 @@ test "cmp f64" {
142140
143141test "cmp f128" {
144142 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
145 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
146143 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
147144 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
148145
......@@ -152,7 +149,6 @@ test "cmp f128" {
152149
153150test "cmp f80/c_longdouble" {
154151 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
155 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
156152 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
157153 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
158154
......@@ -220,7 +216,6 @@ test "vector cmp f16" {
220216 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
221217 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
222218 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
223 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isArm()) return error.SkipZigTest;
224219 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
225220
226221 try testCmpVector(f16);
......@@ -233,7 +228,7 @@ test "vector cmp f32" {
233228 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
234229 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
235230 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isArm()) return error.SkipZigTest;
236 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
231 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/214198
237232 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
238233
239234 try testCmpVector(f32);
......@@ -253,10 +248,9 @@ test "vector cmp f64" {
253248test "vector cmp f128" {
254249 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
255250 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
256 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
257251 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
258252 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
259 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .powerpc64le) return error.SkipZigTest;
253 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/214198
260254 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
261255
262256 try testCmpVector(f128);
......@@ -266,7 +260,7 @@ test "vector cmp f128" {
266260test "vector cmp f80/c_longdouble" {
267261 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
268262 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
269 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .powerpc64le) return error.SkipZigTest;
263 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/214198
270264 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
271265 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
272266
......@@ -381,11 +375,7 @@ test "@sqrt f80/f128/c_longdouble" {
381375 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
382376 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
383377 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
384
385 if (builtin.os.tag == .freebsd) {
386 // TODO https://github.com/ziglang/zig/issues/10875
387 return error.SkipZigTest;
388 }
378 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
389379
390380 try testSqrt(f80);
391381 try comptime testSqrt(f80);
......@@ -431,9 +421,9 @@ fn testSqrt(comptime T: type) !void {
431421 var inf: T = math.inf(T);
432422 try expect(math.isPositiveInf(@sqrt(inf)));
433423 var zero: T = 0.0;
434 try expect(@sqrt(zero) == 0.0);
424 try expect(math.isPositiveZero(@sqrt(zero)));
435425 var neg_zero: T = -0.0;
436 try expect(@sqrt(neg_zero) == 0.0);
426 try expect(math.isNegativeZero(@sqrt(neg_zero)));
437427 var neg_one: T = -1.0;
438428 try expect(math.isNan(@sqrt(neg_one)));
439429 var nan: T = math.nan(T);
......@@ -947,7 +937,7 @@ test "@log2 with vectors" {
947937 builtin.cpu.arch == .aarch64 and
948938 builtin.os.tag == .windows) return error.SkipZigTest;
949939
950 if (builtin.os.tag == .windows and builtin.cpu.arch == .x86) {
940 if (builtin.os.tag == .windows and builtin.cpu.arch == .x86 and builtin.abi == .msvc) {
951941 // https://codeberg.org/ziglang/zig/issues/35518
952942 return error.SkipZigTest;
953943 }
......@@ -1054,7 +1044,6 @@ test "@abs f32/f64" {
10541044
10551045test "@abs f80/f128/c_longdouble" {
10561046 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1057 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
10581047 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10591048 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
10601049 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
......@@ -1172,16 +1161,10 @@ test "@floor f32/f64" {
11721161
11731162test "@floor f80/f128/c_longdouble" {
11741163 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1175 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
11761164 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11771165 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
11781166 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11791167
1180 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
1181 // https://github.com/ziglang/zig/issues/12602
1182 return error.SkipZigTest;
1183 }
1184
11851168 try testFloor(f80);
11861169 try comptime testFloor(f80);
11871170 try testFloor(f128);
......@@ -1261,16 +1244,10 @@ test "@ceil f32/f64" {
12611244
12621245test "@ceil f80/f128/c_longdouble" {
12631246 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1264 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
12651247 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12661248 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
12671249 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
12681250
1269 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
1270 // https://github.com/ziglang/zig/issues/12602
1271 return error.SkipZigTest;
1272 }
1273
12741251 try testCeil(f80);
12751252 try comptime testCeil(f80);
12761253 try testCeil(f128);
......@@ -1281,16 +1258,10 @@ test "@ceil f80/f128/c_longdouble" {
12811258
12821259test "@ceil f80 maxInt(u64)" {
12831260 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1284 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
12851261 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12861262 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
12871263 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
12881264
1289 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
1290 // https://github.com/ziglang/zig/issues/12602
1291 return error.SkipZigTest;
1292 }
1293
12941265 var x: u64 = std.math.maxInt(u64);
12951266 x = x;
12961267 const float: f80 = @floatFromInt(x);
......@@ -1368,16 +1339,10 @@ test "@trunc f32/f64" {
13681339
13691340test "@trunc f80/f128/c_longdouble" {
13701341 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1371 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
13721342 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
13731343 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
13741344 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13751345
1376 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
1377 // https://github.com/ziglang/zig/issues/12602
1378 return error.SkipZigTest;
1379 }
1380
13811346 try testTrunc(f80);
13821347 try comptime testTrunc(f80);
13831348 try testTrunc(f128);
......@@ -1440,11 +1405,6 @@ test "neg f16" {
14401405 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14411406 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
14421407
1443 if (builtin.os.tag == .freebsd) {
1444 // TODO file issue to track this failure
1445 return error.SkipZigTest;
1446 }
1447
14481408 try testNeg(f16);
14491409 try comptime testNeg(f16);
14501410}
......@@ -1501,9 +1461,9 @@ fn testNeg(comptime T: type) !void {
15011461
15021462 // subnormals
15031463 var zero: T = 0.0;
1504 try expect(-zero == -0.0);
1464 try expect(math.isNegativeZero(-zero));
15051465 var neg_zero: T = -0.0;
1506 try expect(-neg_zero == 0.0);
1466 try expect(math.isPositiveZero(-neg_zero));
15071467 var true_min: T = math.floatTrueMin(T);
15081468 try expect(-true_min == -math.floatTrueMin(T));
15091469 var neg_true_min: T = -math.floatTrueMin(T);
......@@ -1678,7 +1638,7 @@ test "runtime isNan(inf * 0)" {
16781638
16791639test "optimized float mode" {
16801640 if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest;
1681 if (builtin.mode == .Debug) return error.SkipZigTest;
1641 if (builtin.mode == .debug) return error.SkipZigTest;
16821642
16831643 const big = 0x1p40;
16841644 const small = 0.001;
test/behavior/fn.zig-2
......@@ -147,7 +147,6 @@ fn fnWithUnreachable() noreturn {
147147
148148test "extern struct with stdcallcc fn pointer" {
149149 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
150 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .x86) return error.SkipZigTest;
151150 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
152151
153152 const S = extern struct {
......@@ -419,7 +418,6 @@ test "import passed byref to function in return type" {
419418
420419test "implicit cast function to function ptr" {
421420 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
422 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
423421 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
424422
425423 const S1 = struct {
test/behavior/int128.zig+1-1
......@@ -31,7 +31,7 @@ test "undefined 128 bit int" {
3131 @setRuntimeSafety(true);
3232
3333 // TODO implement @setRuntimeSafety
34 if (builtin.mode != .Debug and builtin.mode != .ReleaseSafe) {
34 if (builtin.mode != .debug and builtin.mode != .safe) {
3535 return error.SkipZigTest;
3636 }
3737
test/behavior/math.zig-35
......@@ -873,7 +873,6 @@ test "umax wrapped squaring" {
873873test "128-bit multiplication" {
874874 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
875875 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
876 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
877876 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
878877
879878 {
......@@ -968,7 +967,6 @@ test "@addWithOverflow > 128 bits" {
968967 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
969968 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
970969 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
971 if (builtin.zig_backend == .stage2_c and builtin.target.abi == .msvc) return error.SkipZigTest;
972970
973971 try testAddWithOverflow(u129, 4, 105, 109, 0);
974972 try testAddWithOverflow(u129, 1000, 100, 1100, 0);
......@@ -1136,7 +1134,6 @@ test "Multiply unwrap error * immediate" {
11361134
11371135test "@mulWithOverflow bitsize 128 bits" {
11381136 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1139 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
11401137 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11411138 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11421139 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1163,7 +1160,6 @@ test "@mulWithOverflow bitsize 128 bits" {
11631160
11641161test "@mulWithOverflow > 128 bits" {
11651162 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1166 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
11671163 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
11681164
11691165 try testMulWithOverflow(u140, 0, maxInt(u140), 0, 0);
......@@ -1193,7 +1189,6 @@ test "@mulWithOverflow > 128 bits" {
11931189
11941190test "@mulWithOverflow bitsize 256 bits" {
11951191 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1196 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
11971192 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
11981193 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11991194
......@@ -1298,7 +1293,6 @@ test "@subWithOverflow > 128 bits" {
12981293 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12991294 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13001295 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
1301 if (builtin.zig_backend == .stage2_c and builtin.target.abi == .msvc) return error.SkipZigTest;
13021296
13031297 try testSubWithOverflow(u129, 4, 105, maxInt(u129) - 100, 1);
13041298 try testSubWithOverflow(u129, 1000, 100, 900, 0);
......@@ -1389,7 +1383,6 @@ test "@shlWithOverflow > 64 bits" {
13891383
13901384test "@shlWithOverflow > 128 bits" {
13911385 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1392 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
13931386 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
13941387
13951388 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 {
14191412
14201413test "and > 128 bits" {
14211414 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1422 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
14231415
14241416 try testAnd(u140, (1 << 139) | (1 << 70) | 0xaa, (1 << 139) | (1 << 69) | 0xcc, (1 << 139) | 0x88);
14251417 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 {
14481440
14491441test "or > 128 bits" {
14501442 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1451 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
14521443
14531444 try testOr(u140, 0, 1 << 139, 1 << 139);
14541445 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 {
14771468
14781469test "xor > 128 bits" {
14791470 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1480 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
14811471
14821472 try testXor(u140, 0, maxInt(u140), maxInt(u140));
14831473 try testXor(u140, 1 << 139, 1 << 139, 0);
......@@ -1506,7 +1496,6 @@ fn testNot(comptime T: type, a: T, expected: T) !void {
15061496
15071497test "not > 128 bits" {
15081498 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1509 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
15101499
15111500 try testNot(u140, 0, maxInt(u140));
15121501 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 {
15351524
15361525test "shl > 128 bits" {
15371526 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1538 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
15391527
15401528 try testShl(u140, 1 << 5, 10, 1 << 15);
15411529 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 {
15641552
15651553test "shr > 128 bits" {
15661554 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1567 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
15681555
15691556 try testShr(u140, 1 << 139, 39, 1 << 100);
15701557 try testShr(u140, (1 << 70) | 8, 3, (1 << 67) | 1);
......@@ -1593,7 +1580,6 @@ fn testClz(comptime T: type, a: T, expected: u16) !void {
15931580
15941581test "@clz > 128 bits" {
15951582 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1596 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
15971583 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
15981584
15991585 try testClz(u140, 0, 140);
......@@ -1623,7 +1609,6 @@ fn testCtz(comptime T: type, a: T, expected: u16) !void {
16231609
16241610test "@ctz > 128 bits" {
16251611 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1626 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
16271612 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
16281613
16291614 try testCtz(u140, 0, 140);
......@@ -1653,7 +1638,6 @@ fn testPopCount(comptime T: type, a: T, expected: u16) !void {
16531638
16541639test "@popCount > 128 bits" {
16551640 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1656 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
16571641 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
16581642
16591643 try testPopCount(u140, 0, 0);
......@@ -1683,7 +1667,6 @@ fn testBitReverse(comptime T: type, a: T, expected: T) !void {
16831667
16841668test "@bitReverse > 128 bits" {
16851669 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1686 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
16871670 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
16881671
16891672 try testBitReverse(u140, 1 << 139, 1);
......@@ -1713,7 +1696,6 @@ fn testByteSwap(comptime T: type, a: T, expected: T) !void {
17131696
17141697test "@byteSwap > 128 bits" {
17151698 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1716 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
17171699 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
17181700
17191701 try testByteSwap(u144, 1 << 136, 1);
......@@ -1743,7 +1725,6 @@ fn testMax(comptime T: type, a: T, b: T, expected: T) !void {
17431725
17441726test "@max > 128 bits" {
17451727 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1746 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
17471728 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
17481729
17491730 try testMax(u140, 0, maxInt(u140), maxInt(u140));
......@@ -1773,7 +1754,6 @@ fn testMin(comptime T: type, a: T, b: T, expected: T) !void {
17731754
17741755test "@min > 128 bits" {
17751756 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1776 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
17771757 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
17781758
17791759 try testMin(u140, 0, maxInt(u140), 0);
......@@ -1803,7 +1783,6 @@ fn testAbs(comptime T: type, a: T, expected: anytype) !void {
18031783
18041784test "@abs > 128 bits" {
18051785 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1806 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
18071786
18081787 try testAbs(u140, 0, 0);
18091788 try testAbs(u140, 1 << 139, 1 << 139);
......@@ -1827,7 +1806,6 @@ fn testRem(comptime T: type, numerator: T, denominator: T, expected: T) !void {
18271806
18281807test "@rem > 128 bits" {
18291808 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1830 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
18311809 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
18321810
18331811 try testRem(u140, 0, maxInt(u140), 0);
......@@ -1855,7 +1833,6 @@ fn testMod(comptime T: type, numerator: T, denominator: T, expected: T) !void {
18551833
18561834test "@mod > 128 bits" {
18571835 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1858 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
18591836 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
18601837
18611838 try testMod(u140, 0, maxInt(u140), 0);
......@@ -1883,7 +1860,6 @@ fn testDivFloor(comptime T: type, numerator: T, denominator: T, expected: T) !vo
18831860
18841861test "@divFloor > 128 bits" {
18851862 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1886 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
18871863 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
18881864
18891865 try testDivFloor(u140, 0, maxInt(u140), 0);
......@@ -1912,7 +1888,6 @@ fn testDivCeil(comptime T: type, numerator: T, denominator: T, expected: T) !voi
19121888
19131889test "@divCeil > 128 bits" {
19141890 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1915 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
19161891 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
19171892
19181893 try testDivCeil(u140, 0, maxInt(u140), 0);
......@@ -1941,7 +1916,6 @@ fn testDivTrunc(comptime T: type, numerator: T, denominator: T, expected: T) !vo
19411916
19421917test "@divTrunc > 128 bits" {
19431918 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1944 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
19451919 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
19461920
19471921 try testDivTrunc(u140, 0, maxInt(u140), 0);
......@@ -2166,14 +2140,8 @@ test "remainder division" {
21662140 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
21672141 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
21682142 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2169 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
21702143 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
21712144
2172 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
2173 // https://github.com/ziglang/zig/issues/12602
2174 return error.SkipZigTest;
2175 }
2176
21772145 if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff and builtin.abi != .gnu) return error.SkipZigTest;
21782146
21792147 try comptime remdiv(f16);
......@@ -2315,7 +2283,6 @@ test "@round f80" {
23152283 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
23162284 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
23172285 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2318 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
23192286 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
23202287
23212288 try testRound(f80, 12.0);
......@@ -2326,7 +2293,6 @@ test "@round f128" {
23262293 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
23272294 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
23282295 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2329 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
23302296 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
23312297
23322298 try testRound(f128, 12.0);
......@@ -2366,7 +2332,6 @@ test "NaN comparison" {
23662332 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
23672333 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
23682334 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2369 if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
23702335
23712336 try testNanEqNan(f16);
23722337 try testNanEqNan(f32);
test/behavior/maximum_minimum.zig-1
......@@ -115,7 +115,6 @@ test "@min/max for floats" {
115115 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
116116 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
117117 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
118 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
119118 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
120119
121120 const S = struct {
test/behavior/muladd.zig-4
......@@ -49,7 +49,6 @@ test "@mulAdd f80" {
4949 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
5050 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
5151 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
5352 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
5453
5554 try comptime testMulAdd80();
......@@ -68,7 +67,6 @@ test "@mulAdd f128" {
6867 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
6968 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
7069 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
71 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
7270 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
7371
7472 try comptime testMulAdd128();
......@@ -169,7 +167,6 @@ test "vector f80" {
169167 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
170168 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
171169 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
172 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
173170 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
174171
175172 try comptime vector80();
......@@ -194,7 +191,6 @@ test "vector f128" {
194191 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
195192 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
196193 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
197 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
198194 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
199195
200196 try comptime vector128();
test/behavior/packed-struct.zig-4
......@@ -404,7 +404,6 @@ test "nested packed struct field pointers" {
404404 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
405405 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
406406 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
407 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // ubsan unaligned pointer access
408407 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
409408 const S2 = packed struct {
410409 base: u8,
......@@ -579,7 +578,6 @@ test "packed struct fields modification" {
579578}
580579
581580test "nested packed struct field access test" {
582 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
583581 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
584582 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
585583 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -733,7 +731,6 @@ test "nested packed struct at non-zero offset 2" {
733731 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
734732 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
735733 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
736 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
737734 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
738735
739736 const S = struct {
......@@ -1171,7 +1168,6 @@ test "packed struct equality" {
11711168
11721169test "packed struct equality ignores padding bits" {
11731170 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1174 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
11751171 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
11761172
11771173 const S = packed struct { b: bool };
test/behavior/pointers.zig+1-1
......@@ -275,7 +275,7 @@ test "compare equality of optional and non-optional pointer" {
275275}
276276
277277test "allowzero pointer and slice" {
278 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
278 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
279279 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
280280 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
281281 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/saturating_arithmetic.zig-7
......@@ -144,7 +144,6 @@ test "saturating multiplication <= 32 bits" {
144144 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
145145 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
146146 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
147 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
148147 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
149148
150149 try testSatMul(u8, 0, maxInt(u8), 0);
......@@ -238,7 +237,6 @@ test "saturating multiplication" {
238237 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
239238 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
240239 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
241 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
242240 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
243241
244242 const S = struct {
......@@ -313,7 +311,6 @@ test "saturating shift-left" {
313311
314312test "saturating shift-left large rhs" {
315313 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
316 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
317314 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
318315 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
319316 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
......@@ -361,7 +358,6 @@ test "saturating shl uses the LHS type" {
361358
362359test "sat add > 128 bits" {
363360 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
364 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
365361 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
366362
367363 try testSatAdd(u140, 0, 0, 0);
......@@ -377,7 +373,6 @@ test "sat add > 128 bits" {
377373
378374test "sat sub > 128 bits" {
379375 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
380 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
381376 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
382377
383378 try testSatSub(u140, 0, 1, 0);
......@@ -393,7 +388,6 @@ test "sat sub > 128 bits" {
393388
394389test "sat mul > 128 bits" {
395390 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
396 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
397391 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
398392
399393 try testSatMul(u140, 0, maxInt(u140), 0);
......@@ -409,7 +403,6 @@ test "sat mul > 128 bits" {
409403
410404test "sat shl > 128 bits" {
411405 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
412 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
413406 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
414407
415408 try testSatShl(u140, 0, u8, 17, 0);
test/behavior/select.zig+14
......@@ -31,6 +31,20 @@ fn selectVectors() !void {
3131 _ = .{ &x, &y, &z };
3232 const xyz = @select(f32, x, y, z);
3333 try expect(mem.eql(f32, &@as([4]f32, xyz), &[4]f32{ 0.0, 312.1, -145.9, -3381.233 }));
34
35 var vec_u0: @Vector(4, u0) = @splat(0);
36 var mask_u0 = @Vector(4, bool){ true, false, true, false };
37 var mask_empty = @Vector(0, i32){};
38 var vec_empty = @Vector(0, i32){};
39 _ = .{ &vec_u0, &mask_u0, &mask_empty, &vec_empty };
40 const sel_u0 = @select(u0, mask_u0, vec_u0, vec_u0);
41 const sel_u0_undefined = @select(u0, mask_u0, undefined, undefined);
42 comptime if (sel_u0[0] != 0) unreachable;
43 comptime if (sel_u0_undefined[1] != 0) unreachable;
44 const sel_empty = @select(i32, mask_empty, vec_empty, vec_empty);
45 const sel_empty_undefined = @select(i32, @Vector(0, bool){}, undefined, undefined);
46 comptime if (@as(u0, @bitCast(sel_empty)) != 0) unreachable;
47 comptime if (@as(u0, @bitCast(sel_empty_undefined)) != 0) unreachable;
3448}
3549
3650test "@select arrays" {
test/behavior/shuffle.zig+20
......@@ -170,3 +170,23 @@ test "@shuffle bool 2" {
170170 try S.doTheTest();
171171 try comptime S.doTheTest();
172172}
173
174test "@shuffle u0" {
175 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
176 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
177 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
178 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
179 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
180
181 const S = struct {
182 fn doTheTest() !void {
183 var v: @Vector(4, u0) = @splat(0);
184 const mask = @Vector(4, i32){ undefined, 0, -1, 3 };
185 _ = .{ &v, &mask };
186 const res = @shuffle(u0, v, v, mask);
187 comptime if (!std.mem.eql(u0, &@as([4]u0, res), &[4]u0{ 0, 0, 0, 0 })) unreachable;
188 }
189 };
190 try S.doTheTest();
191 try comptime S.doTheTest();
192}
test/behavior/slice.zig+82
......@@ -1089,3 +1089,85 @@ test "slice field alignment" {
10891089 var arr: [10]u8 = @splat(0);
10901090 try S.doTheTest(&&arr);
10911091}
1092
1093test "directly deref slice with comptime-known length" {
1094 {
1095 const slice: []const u16 = &.{ 1, 2, 3 };
1096 const array = slice.*;
1097
1098 comptime assert(@TypeOf(array) == [3]u16);
1099 comptime assert(array[0] == 1);
1100 comptime assert(array[1] == 2);
1101 comptime assert(array[2] == 3);
1102 }
1103 {
1104 const slice: [:0]const u16 = &.{ 1, 2, 3 };
1105 const array = slice.*;
1106
1107 comptime assert(@TypeOf(array) == [3:0]u16);
1108 comptime assert(array[0] == 1);
1109 comptime assert(array[1] == 2);
1110 comptime assert(array[2] == 3);
1111 comptime assert(array[3] == 0);
1112 }
1113}
1114
1115test "address of dereferenced slice is array pointer" {
1116 {
1117 const slice: []const u16 = &.{ 1, 2, 3 };
1118 const array_ptr = &slice.*;
1119
1120 comptime assert(@TypeOf(array_ptr) == *const [3]u16);
1121 comptime assert(array_ptr[0] == 1);
1122 comptime assert(array_ptr[1] == 2);
1123 comptime assert(array_ptr[2] == 3);
1124 }
1125 {
1126 const slice: [:0]const u16 = &.{ 1, 2, 3 };
1127 const array_ptr = &slice.*;
1128
1129 comptime assert(@TypeOf(array_ptr) == *const [3:0]u16);
1130 comptime assert(array_ptr[0] == 1);
1131 comptime assert(array_ptr[1] == 2);
1132 comptime assert(array_ptr[2] == 3);
1133 comptime assert(array_ptr[3] == 0);
1134 }
1135}
1136
1137test "coerce slice with comptime-known length to array pointer" {
1138 {
1139 const slice: []const u16 = &.{ 1, 2, 3 };
1140 const array_ptr: *const [3]u16 = slice;
1141
1142 comptime assert(array_ptr[0] == 1);
1143 comptime assert(array_ptr[1] == 2);
1144 comptime assert(array_ptr[2] == 3);
1145 }
1146 {
1147 const slice: [:0]const u16 = &.{ 1, 2, 3 };
1148 const array_ptr: *const [3:0]u16 = slice;
1149
1150 comptime assert(array_ptr[0] == 1);
1151 comptime assert(array_ptr[1] == 2);
1152 comptime assert(array_ptr[2] == 3);
1153 comptime assert(array_ptr[3] == 0);
1154 }
1155 {
1156 const slice: [:0]const u16 = &.{ 1, 2, 3 };
1157 const array_ptr: *const [3]u16 = slice;
1158
1159 comptime assert(array_ptr[0] == 1);
1160 comptime assert(array_ptr[1] == 2);
1161 comptime assert(array_ptr[2] == 3);
1162 }
1163}
1164
1165test "modify slice through coerced array pointer" {
1166 comptime {
1167 var array: [3]u16 = .{ 1, 2, 3 };
1168 const slice: []u16 = &array;
1169 const array_ptr: *[3]u16 = slice;
1170 array_ptr[2] = 0;
1171 assert(slice[2] == 0);
1172 }
1173}
test/behavior/struct.zig+2-6
......@@ -535,7 +535,6 @@ test "zero-bit field in packed struct" {
535535test "packed struct with non-ABI-aligned field" {
536536 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
537537 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
538 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
539538 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
540539 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
541540 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
......@@ -792,7 +791,6 @@ test "non-packed struct with u128 entry in union" {
792791 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
793792 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
794793 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
795 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
796794 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
797795
798796 const U = union(enum) {
......@@ -1539,7 +1537,6 @@ test "instantiate struct with comptime field" {
15391537}
15401538
15411539test "struct field pointer has correct alignment" {
1542 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
15431540 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15441541 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
15451542 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -1569,7 +1566,6 @@ test "struct field pointer has correct alignment" {
15691566}
15701567
15711568test "extern struct field pointer has correct alignment" {
1572 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
15731569 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15741570 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
15751571 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -2007,7 +2003,6 @@ test "initiate global variable with runtime value" {
20072003}
20082004
20092005test "struct containing optional pointer to array of @This()" {
2010 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
20112006 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
20122007
20132008 const S = struct {
......@@ -2266,7 +2261,8 @@ test "struct contains aligned pointer to itself through type decl" {
22662261
22672262test "struct contains underaligned field with overaligned pointer to itself" {
22682263 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2269 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
2264 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2265
22702266 const S = struct {
22712267 ptr: *align(8) @This() align(1),
22722268 };
test/behavior/switch.zig+1-1
......@@ -1267,7 +1267,7 @@ test "switch with complex item expressions" {
12671267test "switch evaluation order" {
12681268 const eu: anyerror!u32 = 0;
12691269 _ = eu catch |err| switch (err) {
1270 if (true) @compileError("unreachable") => unreachable,
1270 if (true) comptime unreachable => unreachable,
12711271 else => unreachable,
12721272 };
12731273}
test/behavior/switch_loop.zig+1-2
......@@ -223,7 +223,6 @@ test "unanalyzed continue with operand" {
223223
224224test "switch loop on larger than pointer integer" {
225225 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
226 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
227226 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
228227
229228 var entry: @Int(.unsigned, @bitSizeOf(usize) + 1) = undefined;
......@@ -268,7 +267,7 @@ test "switch loop on non-exhaustive enum" {
268267
269268test "switch loop with discarded tag capture" {
270269 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
271 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
270
272271 const S = struct {
273272 const U = union(enum) {
274273 a: u32,
test/behavior/switch_on_captured_error.zig+3-3
......@@ -243,7 +243,7 @@ test "switch on error union catch capture" {
243243 var a: error{}!u64 = 0;
244244 _ = &a;
245245 const b = a catch |err| switch (err) {
246 undefined => @compileError("unreachable"),
246 undefined => comptime unreachable,
247247 };
248248 try expectEqual(@as(u64, 0), b);
249249 }
......@@ -829,7 +829,7 @@ test "switch on error union if else capture" {
829829 var a: error{}!u64 = 0;
830830 _ = &a;
831831 const b = if (a) |x| x else |err| switch (err) {
832 undefined => @compileError("unreachable"),
832 undefined => comptime unreachable,
833833 };
834834 try expectEqual(@as(u64, 0), b);
835835 }
......@@ -840,7 +840,7 @@ test "switch on error union if else capture" {
840840 var a: error{}!u64 = 0;
841841 _ = &a;
842842 const b = if (a) |*x| x.* else |err| switch (err) {
843 undefined => @compileError("unreachable"),
843 undefined => comptime unreachable,
844844 };
845845 try expectEqual(@as(u64, 0), b);
846846 }
test/behavior/threadlocal.zig-5
......@@ -9,11 +9,6 @@ test "thread local variable" {
99 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1010 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
1111
12 if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag.isDarwin()) {
13 // Fails due to register hazards.
14 return error.SkipZigTest;
15 }
16
1712 const S = struct {
1813 threadlocal var t: i32 = 1234;
1914 };
test/behavior/truncate.zig-1
......@@ -49,7 +49,6 @@ fn testTruncate(comptime S: type, a: S, comptime D: type, expected: D) !void {
4949
5050test "@truncate > 128 bits" {
5151 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
5352 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
5453
5554 try testTruncate(u140, 0, u128, 0);
test/behavior/union.zig+4-8
......@@ -1437,7 +1437,6 @@ test "coerce enum literal to union in result loc" {
14371437}
14381438
14391439test "defined-layout union field pointer has correct alignment" {
1440 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14411440 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14421441 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14431442 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -1472,7 +1471,6 @@ test "defined-layout union field pointer has correct alignment" {
14721471}
14731472
14741473test "undefined-layout union field pointer has correct alignment" {
1475 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14761474 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14771475 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14781476 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -1611,6 +1609,10 @@ fn littleToNativeEndian(comptime T: type, v: T) T {
16111609}
16121610
16131611test "reinterpret extern union" {
1612 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1613 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isRiscv32() and builtin.link_libc) return error.SkipZigTest;
1614 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isWasm()) return error.SkipZigTest;
1615
16141616 if (true) {
16151617 // https://github.com/ziglang/zig/issues/19389
16161618 return error.SkipZigTest;
......@@ -1678,8 +1680,6 @@ test "reinterpret extern union" {
16781680 };
16791681
16801682 try comptime S.doTheTest();
1681
1682 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
16831683 try S.doTheTest();
16841684}
16851685
......@@ -1758,8 +1758,6 @@ test "reinterpret packed union" {
17581758 };
17591759
17601760 try comptime S.doTheTest();
1761
1762 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
17631761 try S.doTheTest();
17641762}
17651763
......@@ -1800,8 +1798,6 @@ test "reinterpret packed union inside packed struct" {
18001798 };
18011799
18021800 try comptime S.doTheTest();
1803
1804 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
18051801 try S.doTheTest();
18061802}
18071803
test/behavior/vector.zig+19-18
......@@ -128,13 +128,6 @@ test "vector float operators" {
128128 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
129129 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
130130 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
131 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
132
133 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {
134 // Triggers an assertion with LLVM 18:
135 // https://github.com/ziglang/zig/issues/20680
136 return error.SkipZigTest;
137 }
138131
139132 const S = struct {
140133 fn doTheTest(T: type) !void {
......@@ -280,7 +273,6 @@ test "array to vector with element type coercion" {
280273 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
281274 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
282275 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
283 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
284276
285277 const S = struct {
286278 fn doTheTest() !void {
......@@ -736,9 +728,7 @@ test "vector reduce operation" {
736728 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
737729 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
738730 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
739 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
740731 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
741 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/195562
742732
743733 const S = struct {
744734 fn testReduce(comptime op: std.builtin.ReduceOp, x: anytype, expected: anytype) !void {
......@@ -776,6 +766,8 @@ test "vector reduce operation" {
776766 try testReduce(.Add, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 42.9));
777767 try testReduce(.Add, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 42.9));
778768 try testReduce(.Add, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 42.9));
769 try testReduce(.Add, [4]f80{ -1.9, 5.1, -60.3, 100.0 }, @as(f80, 42.9));
770 try testReduce(.Add, [4]f128{ -1.9, 5.1, -60.3, 100.0 }, @as(f128, 42.9));
779771
780772 try testReduce(.And, [4]bool{ true, false, true, true }, @as(bool, false));
781773 try testReduce(.And, [4]u1{ 1, 0, 1, 1 }, @as(u1, 0));
......@@ -794,6 +786,8 @@ test "vector reduce operation" {
794786 try testReduce(.Min, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, -100.0));
795787 try testReduce(.Min, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, -100.0));
796788 try testReduce(.Min, [4]f64{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f64, -100.0));
789 try testReduce(.Min, [4]f80{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f80, -100.0));
790 try testReduce(.Min, [4]f128{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f128, -100.0));
797791
798792 try testReduce(.Max, [4]i16{ -1, 2, 3, 4 }, @as(i16, 4));
799793 try testReduce(.Max, [4]u16{ 1, 2, 3, 4 }, @as(u16, 4));
......@@ -806,6 +800,8 @@ test "vector reduce operation" {
806800 try testReduce(.Max, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, 10.0e9));
807801 try testReduce(.Max, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, 10.0e9));
808802 try testReduce(.Max, [4]f64{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f64, 10.0e9));
803 try testReduce(.Max, [4]f80{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f80, 10.0e9));
804 try testReduce(.Max, [4]f128{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f128, 10.0e9));
809805
810806 try testReduce(.Mul, [4]i16{ -1, 2, 3, 4 }, @as(i16, -24));
811807 try testReduce(.Mul, [4]u16{ 1, 2, 3, 4 }, @as(u16, 24));
......@@ -818,6 +814,8 @@ test "vector reduce operation" {
818814 try testReduce(.Mul, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 58430.7));
819815 try testReduce(.Mul, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 58430.7));
820816 try testReduce(.Mul, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 58430.7));
817 try testReduce(.Mul, [4]f80{ -1.9, 5.1, -60.3, 100.0 }, @as(f80, 58430.7));
818 try testReduce(.Mul, [4]f128{ -1.9, 5.1, -60.3, 100.0 }, @as(f128, 58430.7));
821819
822820 try testReduce(.Or, [4]bool{ false, true, false, false }, @as(bool, true));
823821 try testReduce(.Or, [4]u1{ 0, 1, 0, 0 }, @as(u1, 1));
......@@ -825,6 +823,7 @@ test "vector reduce operation" {
825823 try testReduce(.Or, [4]u32{ 0xffff0000, 0xff00, 0xf0, 0xf }, ~@as(u32, 0));
826824 try testReduce(.Or, [4]u64{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u64, 0xffffffff));
827825 try testReduce(.Or, [4]u128{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u128, 0xffffffff));
826 try testReduce(.Or, [4]u80{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u80, 0xffffffff));
828827
829828 try testReduce(.Xor, [4]bool{ true, true, true, false }, @as(bool, true));
830829 try testReduce(.Xor, [4]u1{ 1, 1, 1, 0 }, @as(u1, 1));
......@@ -837,22 +836,32 @@ test "vector reduce operation" {
837836 const f16_nan = math.nan(f16);
838837 const f32_nan = math.nan(f32);
839838 const f64_nan = math.nan(f64);
839 const f80_nan = math.nan(f80);
840 const f128_nan = math.nan(f128);
840841
841842 try testReduce(.Add, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
842843 try testReduce(.Add, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);
843844 try testReduce(.Add, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan);
845 try testReduce(.Add, [4]f80{ -1.9, 5.1, f80_nan, 100.0 }, f80_nan);
846 try testReduce(.Add, [4]f128{ -1.9, 5.1, f128_nan, 100.0 }, f128_nan);
844847
845848 try testReduce(.Min, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, @as(f16, -1.9));
846849 try testReduce(.Min, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, @as(f32, -1.9));
847850 try testReduce(.Min, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, @as(f64, -1.9));
851 try testReduce(.Min, [4]f80{ -1.9, 5.1, f80_nan, 100.0 }, @as(f80, -1.9));
852 try testReduce(.Min, [4]f128{ -1.9, 5.1, f128_nan, 100.0 }, @as(f128, -1.9));
848853
849854 try testReduce(.Max, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, @as(f16, 100.0));
850855 try testReduce(.Max, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, @as(f32, 100.0));
851856 try testReduce(.Max, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, @as(f64, 100.0));
857 try testReduce(.Max, [4]f80{ -1.9, 5.1, f80_nan, 100.0 }, @as(f80, 100.0));
858 try testReduce(.Max, [4]f128{ -1.9, 5.1, f128_nan, 100.0 }, @as(f128, 100.0));
852859
853860 try testReduce(.Mul, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
854861 try testReduce(.Mul, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);
855862 try testReduce(.Mul, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan);
863 try testReduce(.Mul, [4]f80{ -1.9, 5.1, f80_nan, 100.0 }, f80_nan);
864 try testReduce(.Mul, [4]f128{ -1.9, 5.1, f128_nan, 100.0 }, f128_nan);
856865 }
857866 };
858867
......@@ -1321,11 +1330,6 @@ test "byte vector initialized in inline function" {
13211330 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13221331 if (builtin.cpu.arch == .hexagon and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
13231332
1324 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and comptime builtin.cpu.has(.x86, .avx512f)) {
1325 // TODO https://github.com/ziglang/zig/issues/13279
1326 return error.SkipZigTest;
1327 }
1328
13291333 const S = struct {
13301334 fn boolx4(e0: bool, e1: bool, e2: bool, e3: bool) @Vector(4, bool) {
13311335 return .{ e0, e1, e2, e3 };
......@@ -1437,7 +1441,6 @@ test "store packed vector element" {
14371441 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
14381442 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14391443 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1440 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14411444 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
14421445
14431446 var v = @Vector(4, u1){ 1, 1, 1, 1 };
......@@ -1469,7 +1472,6 @@ test "store vector with memset" {
14691472 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14701473 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14711474 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
1472 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14731475 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
14741476
14751477 var a: [5]@Vector(2, i1) = undefined;
......@@ -1610,7 +1612,6 @@ test "bitcast vector to array of smaller vectors" {
16101612 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
16111613 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16121614 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1613 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
16141615
16151616 const u8x32 = @Vector(32, u8);
16161617 const u8x64 = @Vector(64, u8);
test/behavior/widening.zig-1
......@@ -41,7 +41,6 @@ test "float widening" {
4141 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
4242 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
4343 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
44 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
4544
4645 var a: f16 = 12.34;
4746 var b: f32 = a;
test/behavior/x86_64/unary.zig+1-1
......@@ -56,7 +56,7 @@ fn unary(comptime op: anytype, comptime opts: struct {
5656 f32 => libc_name ++ "f",
5757 f64 => libc_name,
5858 f80 => "__" ++ libc_name ++ "x",
59 f128 => libc_name ++ "q",
59 f128 => libc_name ++ "f128",
6060 else => break :libc,
6161 },
6262 .library_name = switch (@import("builtin").object_format) {
test/c_abi/cfuncs.c+601-40
......@@ -77,7 +77,7 @@ static void assert_or_panic(bool ok) {
7777# define ZIG_NO_COMPLEX
7878#endif
7979
80#ifdef ZIG_PPC32
80#ifdef __powerpc__
8181# define ZIG_NO_COMPLEX
8282#endif
8383
......@@ -191,9 +191,6 @@ void zig_struct_i128(struct i128);
191191#endif
192192void zig_five_integers(int32_t, int32_t, int32_t, int32_t, int32_t);
193193
194void zig_f32(float);
195void zig_f64(double);
196void zig_longdouble(long double);
197194void zig_five_floats(float, float, float, float, float);
198195
199196bool zig_ret_bool();
......@@ -219,7 +216,203 @@ float complex zig_cmultf(float complex a, float complex b);
219216double complex zig_cmultd(double complex a, double complex b);
220217#endif
221218
222#if defined(ZIG_BACKEND_STAGE2_X86_64) || defined(ZIG_PPC32) || defined(__wasm__)
219float zig_ret_f32(void);
220void zig_f32(float, size_t);
221void zig_1_f32(size_t, float, size_t);
222void zig_2_f32(size_t, size_t, float, size_t);
223void zig_3_f32(size_t, size_t, size_t, float, size_t);
224void zig_4_f32(size_t, size_t, size_t, size_t, float, size_t);
225void zig_5_f32(size_t, size_t, size_t, size_t, size_t, float, size_t);
226void zig_6_f32(size_t, size_t, size_t, size_t, size_t, size_t, float, size_t);
227void zig_7_f32(size_t, size_t, size_t, size_t, size_t, size_t, size_t, float, size_t);
228void zig_8_f32(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, float, size_t);
229
230float c_ret_f32(void) {
231 return 11;
232}
233void c_f32(float f, size_t i) {
234 assert_or_panic(f == 12);
235 assert_or_panic(i == 1);
236}
237void c_1_f32(size_t a0, float f, size_t i) {
238 assert_or_panic(f == 13);
239 assert_or_panic(i == 2);
240}
241void c_2_f32(size_t a0, size_t a1, float f, size_t i) {
242 assert_or_panic(f == 14);
243 assert_or_panic(i == 3);
244}
245void c_3_f32(size_t a0, size_t a1, size_t a2, float f, size_t i) {
246 assert_or_panic(f == 15);
247 assert_or_panic(i == 4);
248}
249void c_4_f32(size_t a0, size_t a1, size_t a2, size_t a3, float f, size_t i) {
250 assert_or_panic(f == 16);
251 assert_or_panic(i == 5);
252}
253void c_5_f32(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, float f, size_t i) {
254 assert_or_panic(f == 17);
255 assert_or_panic(i == 6);
256}
257void 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) {
258 assert_or_panic(f == 18);
259 assert_or_panic(i == 7);
260}
261void 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) {
262 assert_or_panic(f == 19);
263 assert_or_panic(i == 8);
264}
265void 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) {
266 assert_or_panic(f == 20);
267 assert_or_panic(i == 9);
268}
269void c_test_f32(void) {
270 float f = zig_ret_f32();
271 assert_or_panic(f == 1);
272 zig_f32(2, 1);
273 zig_1_f32(0, 3, 2);
274 zig_2_f32(0, 1, 4, 3);
275 zig_3_f32(0, 1, 2, 5, 4);
276 zig_4_f32(0, 1, 2, 3, 6, 5);
277 zig_5_f32(0, 1, 2, 3, 4, 7, 6);
278 zig_6_f32(0, 1, 2, 3, 4, 5, 8, 7);
279 zig_7_f32(0, 1, 2, 3, 4, 5, 6, 9, 8);
280 zig_8_f32(0, 1, 2, 3, 4, 5, 6, 7, 10, 9);
281}
282
283double zig_ret_f64(void);
284void zig_f64(double, size_t);
285void zig_1_f64(size_t, double, size_t);
286void zig_2_f64(size_t, size_t, double, size_t);
287void zig_3_f64(size_t, size_t, size_t, double, size_t);
288void zig_4_f64(size_t, size_t, size_t, size_t, double, size_t);
289void zig_5_f64(size_t, size_t, size_t, size_t, size_t, double, size_t);
290void zig_6_f64(size_t, size_t, size_t, size_t, size_t, size_t, double, size_t);
291void zig_7_f64(size_t, size_t, size_t, size_t, size_t, size_t, size_t, double, size_t);
292void zig_8_f64(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, double, size_t);
293
294double c_ret_f64(void) {
295 return 11;
296}
297void c_f64(double f, size_t i) {
298 assert_or_panic(f == 12);
299 assert_or_panic(i == 1);
300}
301void c_1_f64(size_t a0, double f, size_t i) {
302 assert_or_panic(f == 13);
303 assert_or_panic(i == 2);
304}
305void c_2_f64(size_t a0, size_t a1, double f, size_t i) {
306 assert_or_panic(f == 14);
307 assert_or_panic(i == 3);
308}
309void c_3_f64(size_t a0, size_t a1, size_t a2, double f, size_t i) {
310 assert_or_panic(f == 15);
311 assert_or_panic(i == 4);
312}
313void c_4_f64(size_t a0, size_t a1, size_t a2, size_t a3, double f, size_t i) {
314 assert_or_panic(f == 16);
315 assert_or_panic(i == 5);
316}
317void c_5_f64(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, double f, size_t i) {
318 assert_or_panic(f == 17);
319 assert_or_panic(i == 6);
320}
321void 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) {
322 assert_or_panic(f == 18);
323 assert_or_panic(i == 7);
324}
325void 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) {
326 assert_or_panic(f == 19);
327 assert_or_panic(i == 8);
328}
329void 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) {
330 assert_or_panic(f == 20);
331 assert_or_panic(i == 9);
332}
333void c_test_f64(void) {
334 double f = zig_ret_f64();
335 assert_or_panic(f == 1);
336 zig_f64(2, 1);
337 zig_1_f64(0, 3, 2);
338 zig_2_f64(0, 1, 4, 3);
339 zig_3_f64(0, 1, 2, 5, 4);
340 zig_4_f64(0, 1, 2, 3, 6, 5);
341 zig_5_f64(0, 1, 2, 3, 4, 7, 6);
342 zig_6_f64(0, 1, 2, 3, 4, 5, 8, 7);
343 zig_7_f64(0, 1, 2, 3, 4, 5, 6, 9, 8);
344 zig_8_f64(0, 1, 2, 3, 4, 5, 6, 7, 10, 9);
345}
346
347long double zig_ret_longdouble(void);
348void zig_longdouble(long double, size_t);
349void zig_1_longdouble(size_t, long double, size_t);
350void zig_2_longdouble(size_t, size_t, long double, size_t);
351void zig_3_longdouble(size_t, size_t, size_t, long double, size_t);
352void zig_4_longdouble(size_t, size_t, size_t, size_t, long double, size_t);
353void zig_5_longdouble(size_t, size_t, size_t, size_t, size_t, long double, size_t);
354void zig_6_longdouble(size_t, size_t, size_t, size_t, size_t, size_t, long double, size_t);
355void zig_7_longdouble(size_t, size_t, size_t, size_t, size_t, size_t, size_t, long double, size_t);
356void zig_8_longdouble(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, long double, size_t);
357
358long double c_ret_longdouble(void) {
359 return 11;
360}
361void c_longdouble(long double f, size_t i) {
362 assert_or_panic(f == 12);
363 assert_or_panic(i == 1);
364}
365void c_1_longdouble(size_t a0, long double f, size_t i) {
366 assert_or_panic(f == 13);
367 assert_or_panic(i == 2);
368}
369void c_2_longdouble(size_t a0, size_t a1, long double f, size_t i) {
370 assert_or_panic(f == 14);
371 assert_or_panic(i == 3);
372}
373void c_3_longdouble(size_t a0, size_t a1, size_t a2, long double f, size_t i) {
374 assert_or_panic(f == 15);
375 assert_or_panic(i == 4);
376}
377void c_4_longdouble(size_t a0, size_t a1, size_t a2, size_t a3, long double f, size_t i) {
378 assert_or_panic(f == 16);
379 assert_or_panic(i == 5);
380}
381void c_5_longdouble(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, long double f, size_t i) {
382 assert_or_panic(f == 17);
383 assert_or_panic(i == 6);
384}
385void 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) {
386 assert_or_panic(f == 18);
387 assert_or_panic(i == 7);
388}
389void 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) {
390 assert_or_panic(f == 19);
391 assert_or_panic(i == 8);
392}
393void 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) {
394 assert_or_panic(f == 20);
395 assert_or_panic(i == 9);
396}
397void c_test_longdouble(void) {
398 long double f = zig_ret_longdouble();
399 assert_or_panic(f == 1);
400 zig_longdouble(2, 1);
401 zig_1_longdouble(0, 3, 2);
402 zig_2_longdouble(0, 1, 4, 3);
403 zig_3_longdouble(0, 1, 2, 5, 4);
404 zig_4_longdouble(0, 1, 2, 3, 6, 5);
405 zig_5_longdouble(0, 1, 2, 3, 4, 7, 6);
406 zig_6_longdouble(0, 1, 2, 3, 4, 5, 8, 7);
407 zig_7_longdouble(0, 1, 2, 3, 4, 5, 6, 9, 8);
408 zig_8_longdouble(0, 1, 2, 3, 4, 5, 6, 7, 10, 9);
409}
410
411#ifndef __hexagon__
412#ifndef __loongarch__
413#ifndef __mips__
414#ifndef ZIG_PPC64
415#if !(defined(__i386__) && defined(_WIN32))
223416
224417typedef bool Vector_2_bool __attribute__((ext_vector_type(2)));
225418
......@@ -4468,6 +4661,10 @@ void c_test_vector_512_bool(void) {
44684661 });
44694662}
44704663
4664#endif
4665#endif
4666#endif
4667#endif
44714668#endif
44724669
44734670typedef uint8_t Vector_1_u8 __attribute__((vector_size(1 * sizeof(uint8_t))));
......@@ -14997,6 +15194,242 @@ void c_test_struct_f32_f32_f32_f32_f32(void) {
1499715194 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);
1499815195}
1499915196
15197struct Struct_f32 zig_ret_struct_void_f32(void);
15198void zig_struct_void_f32(struct Struct_f32, size_t);
15199
15200struct Struct_f32 c_ret_struct_void_f32(void) {
15201 return (struct Struct_f32){ .a = 4 };
15202}
15203void c_struct_void_f32(struct Struct_f32 s, size_t i) {
15204 assert_or_panic(s.a == 5);
15205 assert_or_panic(i == 6);
15206}
15207void c_test_struct_void_f32(void) {
15208 struct Struct_f32 s = zig_ret_struct_void_f32();
15209 assert_or_panic(s.a == 1);
15210 zig_struct_void_f32((struct Struct_f32){ .a = 2 }, 3);
15211}
15212
15213struct Struct_array_1_f32 {
15214 float a[1];
15215};
15216
15217struct Struct_array_1_f32 zig_ret_struct_array_1_f32(void);
15218void zig_struct_array_1_f32(struct Struct_array_1_f32, size_t);
15219
15220struct Struct_array_1_f32 c_ret_struct_array_1_f32(void) {
15221 return (struct Struct_array_1_f32){ .a = { 4 } };
15222}
15223void c_struct_array_1_f32(struct Struct_array_1_f32 s, size_t i) {
15224 assert_or_panic(s.a[0] == 5);
15225 assert_or_panic(i == 6);
15226}
15227void c_test_struct_array_1_f32(void) {
15228 struct Struct_array_1_f32 s = zig_ret_struct_array_1_f32();
15229 assert_or_panic(s.a[0] == 1);
15230 zig_struct_array_1_f32((struct Struct_array_1_f32){ .a = { 2 } }, 3);
15231}
15232
15233struct Struct_array_2_f32 {
15234 float a[2];
15235};
15236
15237struct Struct_array_2_f32 zig_ret_struct_array_2_f32(void);
15238void zig_struct_array_2_f32(struct Struct_array_2_f32, size_t);
15239
15240struct Struct_array_2_f32 c_ret_struct_array_2_f32(void) {
15241 return (struct Struct_array_2_f32){ .a = { 6, 7 } };
15242}
15243void c_struct_array_2_f32(struct Struct_array_2_f32 s, size_t i) {
15244 assert_or_panic(s.a[0] == 8);
15245 assert_or_panic(s.a[1] == 9);
15246 assert_or_panic(i == 10);
15247}
15248void c_test_struct_array_2_f32(void) {
15249 struct Struct_array_2_f32 s = zig_ret_struct_array_2_f32();
15250 assert_or_panic(s.a[0] == 1);
15251 assert_or_panic(s.a[1] == 2);
15252 zig_struct_array_2_f32((struct Struct_array_2_f32){ .a = { 3, 4 } }, 5);
15253}
15254
15255struct Struct_array_3_f32 {
15256 float a[3];
15257};
15258
15259struct Struct_array_3_f32 zig_ret_struct_array_3_f32(void);
15260void zig_struct_array_3_f32(struct Struct_array_3_f32, size_t);
15261
15262struct Struct_array_3_f32 c_ret_struct_array_3_f32(void) {
15263 return (struct Struct_array_3_f32){ .a = { 8, 9, 10 } };
15264}
15265void c_struct_array_3_f32(struct Struct_array_3_f32 s, size_t i) {
15266 assert_or_panic(s.a[0] == 11);
15267 assert_or_panic(s.a[1] == 12);
15268 assert_or_panic(s.a[2] == 13);
15269 assert_or_panic(i == 14);
15270}
15271void c_test_struct_array_3_f32(void) {
15272 struct Struct_array_3_f32 s = zig_ret_struct_array_3_f32();
15273 assert_or_panic(s.a[0] == 1);
15274 assert_or_panic(s.a[1] == 2);
15275 assert_or_panic(s.a[2] == 3);
15276 zig_struct_array_3_f32((struct Struct_array_3_f32){ .a = { 4, 5, 6 } }, 7);
15277}
15278
15279struct Struct_array_4_f32 {
15280 float a[4];
15281};
15282
15283struct Struct_array_4_f32 zig_ret_struct_array_4_f32(void);
15284void zig_struct_array_4_f32(struct Struct_array_4_f32, size_t);
15285
15286struct Struct_array_4_f32 c_ret_struct_array_4_f32(void) {
15287 return (struct Struct_array_4_f32){ .a = { 10, 11, 12, 13 } };
15288}
15289void c_struct_array_4_f32(struct Struct_array_4_f32 s, size_t i) {
15290 assert_or_panic(s.a[0] == 14);
15291 assert_or_panic(s.a[1] == 15);
15292 assert_or_panic(s.a[2] == 16);
15293 assert_or_panic(s.a[3] == 17);
15294 assert_or_panic(i == 18);
15295}
15296void c_test_struct_array_4_f32(void) {
15297 struct Struct_array_4_f32 s = zig_ret_struct_array_4_f32();
15298 assert_or_panic(s.a[0] == 1);
15299 assert_or_panic(s.a[1] == 2);
15300 assert_or_panic(s.a[2] == 3);
15301 assert_or_panic(s.a[3] == 4);
15302 zig_struct_array_4_f32((struct Struct_array_4_f32){ .a = { 5, 6, 7, 8 } }, 9);
15303}
15304
15305struct Struct_array_5_f32 {
15306 float a[5];
15307};
15308
15309struct Struct_array_5_f32 zig_ret_struct_array_5_f32(void);
15310void zig_struct_array_5_f32(struct Struct_array_5_f32, size_t);
15311
15312struct Struct_array_5_f32 c_ret_struct_array_5_f32(void) {
15313 return (struct Struct_array_5_f32){ .a = { 12, 13, 14, 15, 16 } };
15314}
15315void c_struct_array_5_f32(struct Struct_array_5_f32 s, size_t i) {
15316 assert_or_panic(s.a[0] == 17);
15317 assert_or_panic(s.a[1] == 18);
15318 assert_or_panic(s.a[2] == 19);
15319 assert_or_panic(s.a[3] == 20);
15320 assert_or_panic(s.a[4] == 21);
15321 assert_or_panic(i == 22);
15322}
15323void c_test_struct_array_5_f32(void) {
15324 struct Struct_array_5_f32 s = zig_ret_struct_array_5_f32();
15325 assert_or_panic(s.a[0] == 1);
15326 assert_or_panic(s.a[1] == 2);
15327 assert_or_panic(s.a[2] == 3);
15328 assert_or_panic(s.a[3] == 4);
15329 assert_or_panic(s.a[4] == 5);
15330 zig_struct_array_5_f32((struct Struct_array_5_f32){ .a = { 6, 7, 8, 9, 10 } }, 11);
15331}
15332
15333struct Struct_array_1_f32 zig_ret_struct_array_0_sentinel_f32(void);
15334void zig_struct_array_0_sentinel_f32(struct Struct_array_1_f32, size_t);
15335
15336struct Struct_array_1_f32 c_ret_struct_array_0_sentinel_f32(void) {
15337 return (struct Struct_array_1_f32){ .a = { 0x1e1 } };
15338}
15339void c_struct_array_0_sentinel_f32(struct Struct_array_1_f32 s, size_t i) {
15340 assert_or_panic(s.a[0] == 0x1e1);
15341 assert_or_panic(i == 2);
15342}
15343void c_test_struct_array_0_sentinel_f32(void) {
15344 struct Struct_array_1_f32 s = zig_ret_struct_array_0_sentinel_f32();
15345 assert_or_panic(s.a[0] == 0x1e1);
15346 zig_struct_array_0_sentinel_f32((struct Struct_array_1_f32){ .a = { 0x1e1 } }, 1);
15347}
15348
15349struct Struct_array_2_f32 zig_ret_struct_array_1_sentinel_f32(void);
15350void zig_struct_array_1_sentinel_f32(struct Struct_array_2_f32, size_t);
15351
15352struct Struct_array_2_f32 c_ret_struct_array_1_sentinel_f32(void) {
15353 return (struct Struct_array_2_f32){ .a = { 4, 0x1e1 } };
15354}
15355void c_struct_array_1_sentinel_f32(struct Struct_array_2_f32 s, size_t i) {
15356 assert_or_panic(s.a[0] == 5);
15357 assert_or_panic(s.a[1] == 0x1e1);
15358 assert_or_panic(i == 6);
15359}
15360void c_test_struct_array_1_sentinel_f32(void) {
15361 struct Struct_array_2_f32 s = zig_ret_struct_array_1_sentinel_f32();
15362 assert_or_panic(s.a[0] == 1);
15363 assert_or_panic(s.a[1] == 0x1e1);
15364 zig_struct_array_1_sentinel_f32((struct Struct_array_2_f32){ .a = { 2, 0x1e1 } }, 3);
15365}
15366
15367struct Struct_array_3_f32 zig_ret_struct_array_2_sentinel_f32(void);
15368void zig_struct_array_2_sentinel_f32(struct Struct_array_3_f32, size_t);
15369
15370struct Struct_array_3_f32 c_ret_struct_array_2_sentinel_f32(void) {
15371 return (struct Struct_array_3_f32){ .a = { 6, 7, 0x1e1 } };
15372}
15373void c_struct_array_2_sentinel_f32(struct Struct_array_3_f32 s, size_t i) {
15374 assert_or_panic(s.a[0] == 8);
15375 assert_or_panic(s.a[1] == 9);
15376 assert_or_panic(s.a[2] == 0x1e1);
15377 assert_or_panic(i == 10);
15378}
15379void c_test_struct_array_2_sentinel_f32(void) {
15380 struct Struct_array_3_f32 s = zig_ret_struct_array_2_sentinel_f32();
15381 assert_or_panic(s.a[0] == 1);
15382 assert_or_panic(s.a[1] == 2);
15383 assert_or_panic(s.a[2] == 0x1e1);
15384 zig_struct_array_2_sentinel_f32((struct Struct_array_3_f32){ .a = { 3, 4, 0x1e1 } }, 5);
15385}
15386
15387struct Struct_array_4_f32 zig_ret_struct_array_3_sentinel_f32(void);
15388void zig_struct_array_3_sentinel_f32(struct Struct_array_4_f32, size_t);
15389
15390struct Struct_array_4_f32 c_ret_struct_array_3_sentinel_f32(void) {
15391 return (struct Struct_array_4_f32){ .a = { 8, 9, 10, 0x1e1 } };
15392}
15393void c_struct_array_3_sentinel_f32(struct Struct_array_4_f32 s, size_t i) {
15394 assert_or_panic(s.a[0] == 11);
15395 assert_or_panic(s.a[1] == 12);
15396 assert_or_panic(s.a[2] == 13);
15397 assert_or_panic(s.a[3] == 0x1e1);
15398 assert_or_panic(i == 14);
15399}
15400void c_test_struct_array_3_sentinel_f32(void) {
15401 struct Struct_array_4_f32 s = zig_ret_struct_array_3_sentinel_f32();
15402 assert_or_panic(s.a[0] == 1);
15403 assert_or_panic(s.a[1] == 2);
15404 assert_or_panic(s.a[2] == 3);
15405 assert_or_panic(s.a[3] == 0x1e1);
15406 zig_struct_array_3_sentinel_f32((struct Struct_array_4_f32){ .a = { 4, 5, 6, 0x1e1 } }, 7);
15407}
15408
15409struct Struct_array_5_f32 zig_ret_struct_array_4_sentinel_f32(void);
15410void zig_struct_array_4_sentinel_f32(struct Struct_array_5_f32, size_t);
15411
15412struct Struct_array_5_f32 c_ret_struct_array_4_sentinel_f32(void) {
15413 return (struct Struct_array_5_f32){ .a = { 10, 11, 12, 13, 0x1e1 } };
15414}
15415void c_struct_array_4_sentinel_f32(struct Struct_array_5_f32 s, size_t i) {
15416 assert_or_panic(s.a[0] == 14);
15417 assert_or_panic(s.a[1] == 15);
15418 assert_or_panic(s.a[2] == 16);
15419 assert_or_panic(s.a[3] == 17);
15420 assert_or_panic(s.a[4] == 0x1e1);
15421 assert_or_panic(i == 18);
15422}
15423void c_test_struct_array_4_sentinel_f32(void) {
15424 struct Struct_array_5_f32 s = zig_ret_struct_array_4_sentinel_f32();
15425 assert_or_panic(s.a[0] == 1);
15426 assert_or_panic(s.a[1] == 2);
15427 assert_or_panic(s.a[2] == 3);
15428 assert_or_panic(s.a[3] == 4);
15429 assert_or_panic(s.a[4] == 0x1e1);
15430 zig_struct_array_4_sentinel_f32((struct Struct_array_5_f32){ .a = { 5, 6, 7, 8, 0x1e1 } }, 9);
15431}
15432
1500015433struct Struct_f32a8 {
1500115434 alignas(8) float a;
1500215435};
......@@ -15212,6 +15645,146 @@ void c_test_struct_f64_f64_f64_f64_f64(void) {
1521215645 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);
1521315646}
1521415647
15648struct Struct_array_1_f64 {
15649 double a[1];
15650};
15651
15652struct Struct_array_1_f64 zig_ret_struct_array_1_f64(void);
15653void zig_struct_array_1_f64(struct Struct_array_1_f64, size_t);
15654
15655struct Struct_array_1_f64 c_ret_struct_array_1_f64(void) {
15656 return (struct Struct_array_1_f64){ .a = { 4 } };
15657}
15658void c_struct_array_1_f64(struct Struct_array_1_f64 s, size_t i) {
15659 assert_or_panic(s.a[0] == 5);
15660 assert_or_panic(i == 6);
15661}
15662void c_test_struct_array_1_f64(void) {
15663 struct Struct_array_1_f64 s = zig_ret_struct_array_1_f64();
15664 assert_or_panic(s.a[0] == 1);
15665 zig_struct_array_1_f64((struct Struct_array_1_f64){ .a = { 2 } }, 3);
15666}
15667
15668struct Struct_array_2_f64 {
15669 double a[2];
15670};
15671
15672struct Struct_array_2_f64 zig_ret_struct_array_2_f64(void);
15673void zig_struct_array_2_f64(struct Struct_array_2_f64, size_t);
15674
15675struct Struct_array_2_f64 c_ret_struct_array_2_f64(void) {
15676 return (struct Struct_array_2_f64){ .a = { 6, 7 } };
15677}
15678void c_struct_array_2_f64(struct Struct_array_2_f64 s, size_t i) {
15679 assert_or_panic(s.a[0] == 8);
15680 assert_or_panic(s.a[1] == 9);
15681 assert_or_panic(i == 10);
15682}
15683void c_test_struct_array_2_f64(void) {
15684 struct Struct_array_2_f64 s = zig_ret_struct_array_2_f64();
15685 assert_or_panic(s.a[0] == 1);
15686 assert_or_panic(s.a[1] == 2);
15687 zig_struct_array_2_f64((struct Struct_array_2_f64){ .a = { 3, 4 } }, 5);
15688}
15689
15690struct Struct_array_3_f64 {
15691 double a[3];
15692};
15693
15694struct Struct_array_3_f64 zig_ret_struct_array_3_f64(void);
15695void zig_struct_array_3_f64(struct Struct_array_3_f64, size_t);
15696
15697struct Struct_array_3_f64 c_ret_struct_array_3_f64(void) {
15698 return (struct Struct_array_3_f64){ .a = { 8, 9, 10 } };
15699}
15700void c_struct_array_3_f64(struct Struct_array_3_f64 s, size_t i) {
15701 assert_or_panic(s.a[0] == 11);
15702 assert_or_panic(s.a[1] == 12);
15703 assert_or_panic(s.a[2] == 13);
15704 assert_or_panic(i == 14);
15705}
15706void c_test_struct_array_3_f64(void) {
15707 struct Struct_array_3_f64 s = zig_ret_struct_array_3_f64();
15708 assert_or_panic(s.a[0] == 1);
15709 assert_or_panic(s.a[1] == 2);
15710 assert_or_panic(s.a[2] == 3);
15711 zig_struct_array_3_f64((struct Struct_array_3_f64){ .a = { 4, 5, 6 } }, 7);
15712}
15713
15714struct Struct_array_4_f64 {
15715 double a[4];
15716};
15717
15718struct Struct_array_4_f64 zig_ret_struct_array_4_f64(void);
15719void zig_struct_array_4_f64(struct Struct_array_4_f64, size_t);
15720
15721struct Struct_array_4_f64 c_ret_struct_array_4_f64(void) {
15722 return (struct Struct_array_4_f64){ .a = { 10, 11, 12, 13 } };
15723}
15724void c_struct_array_4_f64(struct Struct_array_4_f64 s, size_t i) {
15725 assert_or_panic(s.a[0] == 14);
15726 assert_or_panic(s.a[1] == 15);
15727 assert_or_panic(s.a[2] == 16);
15728 assert_or_panic(s.a[3] == 17);
15729 assert_or_panic(i == 18);
15730}
15731void c_test_struct_array_4_f64(void) {
15732 struct Struct_array_4_f64 s = zig_ret_struct_array_4_f64();
15733 assert_or_panic(s.a[0] == 1);
15734 assert_or_panic(s.a[1] == 2);
15735 assert_or_panic(s.a[2] == 3);
15736 assert_or_panic(s.a[3] == 4);
15737 zig_struct_array_4_f64((struct Struct_array_4_f64){ .a = { 5, 6, 7, 8 } }, 9);
15738}
15739
15740struct Struct_array_5_f64 {
15741 double a[5];
15742};
15743
15744struct Struct_array_5_f64 zig_ret_struct_array_5_f64(void);
15745void zig_struct_array_5_f64(struct Struct_array_5_f64, size_t);
15746
15747struct Struct_array_5_f64 c_ret_struct_array_5_f64(void) {
15748 return (struct Struct_array_5_f64){ .a = { 12, 13, 14, 15, 16 } };
15749}
15750void c_struct_array_5_f64(struct Struct_array_5_f64 s, size_t i) {
15751 assert_or_panic(s.a[0] == 17);
15752 assert_or_panic(s.a[1] == 18);
15753 assert_or_panic(s.a[2] == 19);
15754 assert_or_panic(s.a[3] == 20);
15755 assert_or_panic(s.a[4] == 21);
15756 assert_or_panic(i == 22);
15757}
15758void c_test_struct_array_5_f64(void) {
15759 struct Struct_array_5_f64 s = zig_ret_struct_array_5_f64();
15760 assert_or_panic(s.a[0] == 1);
15761 assert_or_panic(s.a[1] == 2);
15762 assert_or_panic(s.a[2] == 3);
15763 assert_or_panic(s.a[3] == 4);
15764 assert_or_panic(s.a[4] == 5);
15765 zig_struct_array_5_f64((struct Struct_array_5_f64){ .a = { 6, 7, 8, 9, 10 } }, 11);
15766}
15767
15768union Union_f64 {
15769 double a;
15770};
15771
15772union Union_f64 zig_ret_union_f64(void);
15773void zig_union_f64(union Union_f64, size_t);
15774
15775union Union_f64 c_ret_union_f64(void) {
15776 return (union Union_f64){ .a = 4 };
15777}
15778void c_union_f64(union Union_f64 s, size_t i) {
15779 assert_or_panic(s.a == 5);
15780 assert_or_panic(i == 6);
15781}
15782void c_test_union_f64(void) {
15783 union Union_f64 s = zig_ret_union_f64();
15784 assert_or_panic(s.a == 1);
15785 zig_union_f64((union Union_f64){ .a = 2 }, 3);
15786}
15787
1521515788struct Struct_u32_Union_u32_u32u32 {
1521615789 uint32_t a;
1521715790 union {
......@@ -15326,9 +15899,6 @@ void run_c_tests(void) {
1532615899
1532715900 zig_five_integers(12, 34, 56, 78, 90);
1532815901
15329 zig_f32(12.34f);
15330 zig_f64(56.78);
15331 zig_longdouble(12.34l);
1533215902 zig_five_floats(1.0f, 2.0f, 3.0f, 4.0f, 5.0f);
1533315903
1533415904 zig_ptr((void *)0xdeadbeefL);
......@@ -15377,8 +15947,7 @@ void run_c_tests(void) {
1537715947#if !(defined(__i386__) && defined(_WIN32))
1537815948#ifndef __loongarch__
1537915949#ifndef ZIG_MIPS64
15380#ifndef __powerpc__
15381#ifndef __s390x__
15950#ifndef ZIG_PPC32
1538215951 {
1538315952 struct Struct_i32_i32 s = {1, 2};
1538415953 zig_struct_i32_i32(s);
......@@ -15387,13 +15956,11 @@ void run_c_tests(void) {
1538715956#endif
1538815957#endif
1538915958#endif
15390#endif
1539115959
1539215960#ifndef __hexagon__
1539315961#ifndef __loongarch__
1539415962#ifndef ZIG_MIPS64
15395#ifndef __powerpc__
15396#ifndef __s390x__
15963#ifndef ZIG_PPC32
1539715964 {
1539815965 struct BigStruct s = {1, 2, 3, 4, 5};
1539915966 zig_big_struct(s);
......@@ -15402,7 +15969,6 @@ void run_c_tests(void) {
1540215969#endif
1540315970#endif
1540415971#endif
15405#endif
1540615972
1540715973#ifndef ZIG_NO_I128
1540815974 {
......@@ -15426,8 +15992,7 @@ void run_c_tests(void) {
1542615992#ifndef __i386__
1542715993#ifndef __loongarch__
1542815994#ifndef ZIG_MIPS64
15429#ifndef __powerpc__
15430#ifndef __s390x__
15995#ifndef ZIG_PPC32
1543115996 {
1543215997 struct SplitStructInts s = {1234, 100, 1337};
1543315998 zig_split_struct_ints(s);
......@@ -15437,13 +16002,11 @@ void run_c_tests(void) {
1543716002#endif
1543816003#endif
1543916004#endif
15440#endif
1544116005
1544216006#ifndef __hexagon__
1544316007#ifndef __loongarch__
1544416008#ifndef ZIG_MIPS64
15445#ifndef __powerpc__
15446#ifndef __s390x__
16009#ifndef ZIG_PPC32
1544716010 {
1544816011 struct MedStructMixed s = {1234, 100.0f, 1337.0f};
1544916012 zig_med_struct_mixed(s);
......@@ -15452,14 +16015,12 @@ void run_c_tests(void) {
1545216015#endif
1545316016#endif
1545416017#endif
15455#endif
1545616018
1545716019#ifndef __hexagon__
1545816020#ifndef __i386__
1545916021#ifndef __loongarch__
1546016022#ifndef ZIG_MIPS64
15461#ifndef __powerpc__
15462#ifndef __s390x__
16023#ifndef ZIG_PPC32
1546316024 {
1546416025 struct SplitStructMixed s = {1234, 100, 1337.0f};
1546516026 zig_split_struct_mixed(s);
......@@ -15469,13 +16030,11 @@ void run_c_tests(void) {
1546916030#endif
1547016031#endif
1547116032#endif
15472#endif
1547316033
1547416034#ifndef __hexagon__
1547516035#ifndef __loongarch__
1547616036#ifndef ZIG_MIPS64
15477#ifndef __powerpc__
15478#ifndef __s390x__
16037#ifndef ZIG_PPC32
1547916038 {
1548016039 struct BigStruct s = {30, 31, 32, 33, 34};
1548116040 struct BigStruct res = zig_big_struct_both(s);
......@@ -15488,7 +16047,6 @@ void run_c_tests(void) {
1548816047#endif
1548916048#endif
1549016049#endif
15491#endif
1549216050#endif
1549316051
1549416052 {
......@@ -15550,18 +16108,6 @@ void c_struct_i128(struct i128 x) {
1555016108}
1555116109#endif
1555216110
15553void c_f32(float x) {
15554 assert_or_panic(x == 12.34f);
15555}
15556
15557void c_f64(double x) {
15558 assert_or_panic(x == 56.78);
15559}
15560
15561void c_long_double(long double x) {
15562 assert_or_panic(x == 12.34l);
15563}
15564
1556516111void c_ptr(void *x) {
1556616112 assert_or_panic(x == (void *)0xdeadbeefL);
1556716113}
......@@ -16078,6 +16624,16 @@ struct ByRef __attribute__((sysv_abi)) c_explict_sys_v(struct ByRef in) {
1607816624}
1607916625#endif
1608016626
16627#if defined __x86_64__ || defined __aarch64__
16628int __attribute__((preserve_none)) c_preserve_none(int x) {
16629 return x + 1;
16630}
16631int __attribute__((preserve_none)) zig_preserve_none(int);
16632void c_preserve_none_check(void) {
16633 assert_or_panic(zig_preserve_none(41) == 42);
16634}
16635#endif
16636
1608116637struct byval_tail_callsite_attr_Point {
1608216638 double x;
1608316639 double y;
......@@ -16212,7 +16768,13 @@ void __attribute__((vectorcall)) c_vectorcall_check(int a, float b, double c, vo
1621216768}
1621316769#endif
1621416770
16215#if defined(__x86_64__) && defined(_WIN64)
16771void c_x86_64_sysv_uint_int_uint_int(unsigned a, int b, unsigned c, int d) {
16772 assert_or_panic(a == 1);
16773 assert_or_panic(b == -2);
16774 assert_or_panic(c == 3);
16775 assert_or_panic(d == -4);
16776}
16777
1621616778void c_win64_varargs_u64_f64_u64_f64(uint64_t a, double b, uint64_t c, double d) {
1621716779 assert_or_panic(a == UINT64_C(0x3ff0000000000000));
1621816780 assert_or_panic(b == 2.0);
......@@ -16225,4 +16787,3 @@ void c_win64_varargs_f64_u64_f64_u64(double a, uint64_t b, double c, uint64_t d)
1622516787 assert_or_panic(c == 7.0);
1622616788 assert_or_panic(d == UINT64_C(0x4020000000000000));
1622716789}
16228#endif
test/c_abi/main.zig+1049-286
......@@ -13,7 +13,7 @@ const expectEqual = std.testing.expectEqual;
1313const have_i128 = builtin.cpu.arch != .x86 and !builtin.cpu.arch.isArm() and
1414 !builtin.cpu.arch.isMIPS() and !builtin.cpu.arch.isPowerPC32() and builtin.cpu.arch != .riscv32 and
1515 builtin.cpu.arch != .hexagon and
16 builtin.cpu.arch != .s390x; // https://github.com/llvm/llvm-project/issues/168460
16 builtin.cpu.arch != .s390x;
1717
1818const have_f128 = builtin.cpu.arch.isWasm() or (builtin.cpu.arch.isX86() and !builtin.os.tag.isDarwin() and builtin.abi != .msvc);
1919const have_f80 = builtin.cpu.arch.isX86() and builtin.abi != .msvc;
......@@ -104,10 +104,6 @@ export fn zig_struct_u128(a: U128) void {
104104 expect(a.value == 0xfffffffffffffffc) catch @panic("test failure: zig_struct_u128");
105105}
106106
107extern fn c_f32(f32) void;
108extern fn c_f64(f64) void;
109extern fn c_long_double(c_longdouble) void;
110
111107// On windows x64, the first 4 are passed via registers, others on the stack.
112108extern fn c_five_floats(f32, f32, f32, f32, f32) void;
113109
......@@ -120,28 +116,9 @@ export fn zig_five_floats(a: f32, b: f32, c: f32, d: f32, e: f32) void {
120116}
121117
122118test "floats" {
123 c_f32(12.34);
124 c_f64(56.78);
125119 c_five_floats(1.0, 2.0, 3.0, 4.0, 5.0);
126120}
127121
128test "long double" {
129 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
130
131 c_long_double(12.34);
132}
133
134export fn zig_f32(x: f32) void {
135 expect(x == 12.34) catch @panic("test failure: zig_f32");
136}
137export fn zig_f64(x: f64) void {
138 expect(x == 56.78) catch @panic("test failure: zig_f64");
139}
140export fn zig_longdouble(x: c_longdouble) void {
141 if (!builtin.target.cpu.arch.isWasm()) return; // waiting for #1481
142 expect(x == 12.34) catch @panic("test failure: zig_longdouble");
143}
144
145122extern fn c_ptr(*anyopaque) void;
146123
147124test "pointer" {
......@@ -184,7 +161,7 @@ extern fn c_cmultf(a: ComplexFloat, b: ComplexFloat) ComplexFloat;
184161extern fn c_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble;
185162
186163const complex_abi_compatible = builtin.cpu.arch != .x86 and !builtin.cpu.arch.isMIPS() and
187 !builtin.cpu.arch.isArm() and !builtin.cpu.arch.isPowerPC32() and !builtin.cpu.arch.isRISCV() and
164 !builtin.cpu.arch.isArm() and !builtin.cpu.arch.isPowerPC() and !builtin.cpu.arch.isRISCV() and
188165 builtin.cpu.arch != .hexagon and
189166 builtin.cpu.arch != .s390x and
190167 !(builtin.cpu.arch.isLoongArch() and builtin.abi.float() == .soft);
......@@ -269,10 +246,217 @@ export fn zig_cmultd_comp(a_r: f64, a_i: f64, b_r: f64, b_i: f64) ComplexDouble
269246 return .{ .real = 1.5, .imag = 13.5 };
270247}
271248
249export fn zig_ret_f32() f32 {
250 return 1;
251}
252export fn zig_f32(f: f32, i: usize) void {
253 expect(f == 2) catch @panic("test failure");
254 expect(i == 1) catch @panic("test failure");
255}
256export fn zig_1_f32(_: usize, f: f32, i: usize) void {
257 expect(f == 3) catch @panic("test failure");
258 expect(i == 2) catch @panic("test failure");
259}
260export fn zig_2_f32(_: usize, _: usize, f: f32, i: usize) void {
261 expect(f == 4) catch @panic("test failure");
262 expect(i == 3) catch @panic("test failure");
263}
264export fn zig_3_f32(_: usize, _: usize, _: usize, f: f32, i: usize) void {
265 expect(f == 5) catch @panic("test failure");
266 expect(i == 4) catch @panic("test failure");
267}
268export fn zig_4_f32(_: usize, _: usize, _: usize, _: usize, f: f32, i: usize) void {
269 expect(f == 6) catch @panic("test failure");
270 expect(i == 5) catch @panic("test failure");
271}
272export fn zig_5_f32(_: usize, _: usize, _: usize, _: usize, _: usize, f: f32, i: usize) void {
273 expect(f == 7) catch @panic("test failure");
274 expect(i == 6) catch @panic("test failure");
275}
276export fn zig_6_f32(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, f: f32, i: usize) void {
277 expect(f == 8) catch @panic("test failure");
278 expect(i == 7) catch @panic("test failure");
279}
280export fn zig_7_f32(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, f: f32, i: usize) void {
281 expect(f == 9) catch @panic("test failure");
282 expect(i == 8) catch @panic("test failure");
283}
284export fn zig_8_f32(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, f: f32, i: usize) void {
285 expect(f == 10) catch @panic("test failure");
286 expect(i == 9) catch @panic("test failure");
287}
288
289extern fn c_ret_f32() f32;
290extern fn c_f32(f32, usize) void;
291extern fn c_1_f32(usize, f32, usize) void;
292extern fn c_2_f32(usize, usize, f32, usize) void;
293extern fn c_3_f32(usize, usize, usize, f32, usize) void;
294extern fn c_4_f32(usize, usize, usize, usize, f32, usize) void;
295extern fn c_5_f32(usize, usize, usize, usize, usize, f32, usize) void;
296extern fn c_6_f32(usize, usize, usize, usize, usize, usize, f32, usize) void;
297extern fn c_7_f32(usize, usize, usize, usize, usize, usize, usize, f32, usize) void;
298extern fn c_8_f32(usize, usize, usize, usize, usize, usize, usize, usize, f32, usize) void;
299extern fn c_test_f32() void;
300
301test "f32" {
302 const f = c_ret_f32();
303 try expect(f == 11);
304 c_f32(12, 1);
305 c_1_f32(0, 13, 2);
306 c_2_f32(0, 1, 14, 3);
307 c_3_f32(0, 1, 2, 15, 4);
308 c_4_f32(0, 1, 2, 3, 16, 5);
309 c_5_f32(0, 1, 2, 3, 4, 17, 6);
310 c_6_f32(0, 1, 2, 3, 4, 5, 18, 7);
311 c_7_f32(0, 1, 2, 3, 4, 5, 6, 19, 8);
312 c_8_f32(0, 1, 2, 3, 4, 5, 6, 7, 20, 9);
313 c_test_f32();
314}
315
316export fn zig_ret_f64() f64 {
317 return 1;
318}
319export fn zig_f64(f: f64, i: usize) void {
320 expect(f == 2) catch @panic("test failure");
321 expect(i == 1) catch @panic("test failure");
322}
323export fn zig_1_f64(_: usize, f: f64, i: usize) void {
324 expect(f == 3) catch @panic("test failure");
325 expect(i == 2) catch @panic("test failure");
326}
327export fn zig_2_f64(_: usize, _: usize, f: f64, i: usize) void {
328 expect(f == 4) catch @panic("test failure");
329 expect(i == 3) catch @panic("test failure");
330}
331export fn zig_3_f64(_: usize, _: usize, _: usize, f: f64, i: usize) void {
332 expect(f == 5) catch @panic("test failure");
333 expect(i == 4) catch @panic("test failure");
334}
335export fn zig_4_f64(_: usize, _: usize, _: usize, _: usize, f: f64, i: usize) void {
336 expect(f == 6) catch @panic("test failure");
337 expect(i == 5) catch @panic("test failure");
338}
339export fn zig_5_f64(_: usize, _: usize, _: usize, _: usize, _: usize, f: f64, i: usize) void {
340 expect(f == 7) catch @panic("test failure");
341 expect(i == 6) catch @panic("test failure");
342}
343export fn zig_6_f64(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, f: f64, i: usize) void {
344 expect(f == 8) catch @panic("test failure");
345 expect(i == 7) catch @panic("test failure");
346}
347export fn zig_7_f64(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, f: f64, i: usize) void {
348 expect(f == 9) catch @panic("test failure");
349 expect(i == 8) catch @panic("test failure");
350}
351export fn zig_8_f64(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, f: f64, i: usize) void {
352 expect(f == 10) catch @panic("test failure");
353 expect(i == 9) catch @panic("test failure");
354}
355
356extern fn c_ret_f64() f64;
357extern fn c_f64(f64, usize) void;
358extern fn c_1_f64(usize, f64, usize) void;
359extern fn c_2_f64(usize, usize, f64, usize) void;
360extern fn c_3_f64(usize, usize, usize, f64, usize) void;
361extern fn c_4_f64(usize, usize, usize, usize, f64, usize) void;
362extern fn c_5_f64(usize, usize, usize, usize, usize, f64, usize) void;
363extern fn c_6_f64(usize, usize, usize, usize, usize, usize, f64, usize) void;
364extern fn c_7_f64(usize, usize, usize, usize, usize, usize, usize, f64, usize) void;
365extern fn c_8_f64(usize, usize, usize, usize, usize, usize, usize, usize, f64, usize) void;
366extern fn c_test_f64() void;
367
368test "f64" {
369 const f = c_ret_f64();
370 try expect(f == 11);
371 c_f64(12, 1);
372 c_1_f64(0, 13, 2);
373 c_2_f64(0, 1, 14, 3);
374 c_3_f64(0, 1, 2, 15, 4);
375 c_4_f64(0, 1, 2, 3, 16, 5);
376 c_5_f64(0, 1, 2, 3, 4, 17, 6);
377 c_6_f64(0, 1, 2, 3, 4, 5, 18, 7);
378 c_7_f64(0, 1, 2, 3, 4, 5, 6, 19, 8);
379 c_8_f64(0, 1, 2, 3, 4, 5, 6, 7, 20, 9);
380 c_test_f64();
381}
382
383export fn zig_ret_longdouble() c_longdouble {
384 return 1;
385}
386export fn zig_longdouble(f: c_longdouble, i: usize) void {
387 expect(f == 2) catch @panic("test failure");
388 expect(i == 1) catch @panic("test failure");
389}
390export fn zig_1_longdouble(_: usize, f: c_longdouble, i: usize) void {
391 expect(f == 3) catch @panic("test failure");
392 expect(i == 2) catch @panic("test failure");
393}
394export fn zig_2_longdouble(_: usize, _: usize, f: c_longdouble, i: usize) void {
395 expect(f == 4) catch @panic("test failure");
396 expect(i == 3) catch @panic("test failure");
397}
398export fn zig_3_longdouble(_: usize, _: usize, _: usize, f: c_longdouble, i: usize) void {
399 expect(f == 5) catch @panic("test failure");
400 expect(i == 4) catch @panic("test failure");
401}
402export fn zig_4_longdouble(_: usize, _: usize, _: usize, _: usize, f: c_longdouble, i: usize) void {
403 expect(f == 6) catch @panic("test failure");
404 expect(i == 5) catch @panic("test failure");
405}
406export fn zig_5_longdouble(_: usize, _: usize, _: usize, _: usize, _: usize, f: c_longdouble, i: usize) void {
407 expect(f == 7) catch @panic("test failure");
408 expect(i == 6) catch @panic("test failure");
409}
410export fn zig_6_longdouble(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, f: c_longdouble, i: usize) void {
411 expect(f == 8) catch @panic("test failure");
412 expect(i == 7) catch @panic("test failure");
413}
414export fn zig_7_longdouble(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, f: c_longdouble, i: usize) void {
415 expect(f == 9) catch @panic("test failure");
416 expect(i == 8) catch @panic("test failure");
417}
418export fn zig_8_longdouble(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, f: c_longdouble, i: usize) void {
419 expect(f == 10) catch @panic("test failure");
420 expect(i == 9) catch @panic("test failure");
421}
422
423extern fn c_ret_longdouble() c_longdouble;
424extern fn @"c_longdouble"(c_longdouble, usize) void;
425extern fn c_1_longdouble(usize, c_longdouble, usize) void;
426extern fn c_2_longdouble(usize, usize, c_longdouble, usize) void;
427extern fn c_3_longdouble(usize, usize, usize, c_longdouble, usize) void;
428extern fn c_4_longdouble(usize, usize, usize, usize, c_longdouble, usize) void;
429extern fn c_5_longdouble(usize, usize, usize, usize, usize, c_longdouble, usize) void;
430extern fn c_6_longdouble(usize, usize, usize, usize, usize, usize, c_longdouble, usize) void;
431extern fn c_7_longdouble(usize, usize, usize, usize, usize, usize, usize, c_longdouble, usize) void;
432extern fn c_8_longdouble(usize, usize, usize, usize, usize, usize, usize, usize, c_longdouble, usize) void;
433extern fn c_test_longdouble() void;
434
435test "long double" {
436 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
437
438 const f = c_ret_longdouble();
439 try expect(f == 11);
440 @"c_longdouble"(12, 1);
441 c_1_longdouble(0, 13, 2);
442 c_2_longdouble(0, 1, 14, 3);
443 c_3_longdouble(0, 1, 2, 15, 4);
444 c_4_longdouble(0, 1, 2, 3, 16, 5);
445 c_5_longdouble(0, 1, 2, 3, 4, 17, 6);
446 c_6_longdouble(0, 1, 2, 3, 4, 5, 18, 7);
447 c_7_longdouble(0, 1, 2, 3, 4, 5, 6, 19, 8);
448 c_8_longdouble(0, 1, 2, 3, 4, 5, 6, 7, 20, 9);
449 c_test_longdouble();
450}
451
272452comptime {
273453 skip: {
274 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
275 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
454 if (builtin.zig_backend == .stage2_wasm) break :skip;
455 if (builtin.cpu.arch == .hexagon) break :skip;
456 if (builtin.cpu.arch == .loongarch64) break :skip;
457 if (builtin.cpu.arch.isMIPS()) break :skip;
458 if (builtin.cpu.arch.isPowerPC64()) break :skip;
459 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip;
276460
277461 _ = struct {
278462 export fn zig_ret_vector_2_bool() @Vector(2, bool) {
......@@ -294,7 +478,14 @@ extern fn c_vector_2_bool(@Vector(2, bool)) void;
294478extern fn c_test_vector_2_bool() void;
295479
296480test "@Vector(2, bool)" {
297 if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
481 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
482 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
483 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
484 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
485 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
486 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
487 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
488 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
298489
299490 const vec = c_ret_vector_2_bool();
300491 try expect(vec[0] == true);
......@@ -308,8 +499,12 @@ test "@Vector(2, bool)" {
308499
309500comptime {
310501 skip: {
311 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
312 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
502 if (builtin.zig_backend == .stage2_wasm) break :skip;
503 if (builtin.cpu.arch == .hexagon) break :skip;
504 if (builtin.cpu.arch == .loongarch64) break :skip;
505 if (builtin.cpu.arch.isMIPS()) break :skip;
506 if (builtin.cpu.arch.isPowerPC64()) break :skip;
507 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip;
313508
314509 _ = struct {
315510 export fn zig_ret_vector_4_bool() @Vector(4, bool) {
......@@ -335,7 +530,14 @@ extern fn c_vector_4_bool(@Vector(4, bool)) void;
335530extern fn c_test_vector_4_bool() void;
336531
337532test "@Vector(4, bool)" {
338 if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
533 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
534 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
535 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
536 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
537 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
538 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
539 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
540 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
339541
340542 const vec = c_ret_vector_4_bool();
341543 try expect(vec[0] == true);
......@@ -353,8 +555,12 @@ test "@Vector(4, bool)" {
353555
354556comptime {
355557 skip: {
356 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
357 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
558 if (builtin.zig_backend == .stage2_wasm) break :skip;
559 if (builtin.cpu.arch == .hexagon) break :skip;
560 if (builtin.cpu.arch == .loongarch64) break :skip;
561 if (builtin.cpu.arch.isMIPS()) break :skip;
562 if (builtin.cpu.arch.isPowerPC64()) break :skip;
563 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip;
358564
359565 _ = struct {
360566 export fn zig_ret_vector_8_bool() @Vector(8, bool) {
......@@ -388,7 +594,14 @@ extern fn c_vector_8_bool(@Vector(8, bool)) void;
388594extern fn c_test_vector_8_bool() void;
389595
390596test "@Vector(8, bool)" {
391 if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
597 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
598 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
599 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
600 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
601 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
602 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
603 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
604 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
392605
393606 const vec = c_ret_vector_8_bool();
394607 try expect(vec[0] == false);
......@@ -414,8 +627,12 @@ test "@Vector(8, bool)" {
414627
415628comptime {
416629 skip: {
417 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
418 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
630 if (builtin.zig_backend == .stage2_wasm) break :skip;
631 if (builtin.cpu.arch == .hexagon) break :skip;
632 if (builtin.cpu.arch == .loongarch64) break :skip;
633 if (builtin.cpu.arch.isMIPS()) break :skip;
634 if (builtin.cpu.arch.isPowerPC64()) break :skip;
635 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip;
419636
420637 _ = struct {
421638 export fn zig_ret_vector_16_bool() @Vector(16, bool) {
......@@ -465,7 +682,14 @@ extern fn c_vector_16_bool(@Vector(16, bool)) void;
465682extern fn c_test_vector_16_bool() void;
466683
467684test "@Vector(16, bool)" {
468 if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
685 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
686 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
687 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
688 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
689 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
690 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
691 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
692 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
469693
470694 const vec = c_ret_vector_16_bool();
471695 try expect(vec[0] == true);
......@@ -507,8 +731,12 @@ test "@Vector(16, bool)" {
507731
508732comptime {
509733 skip: {
510 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
511 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
734 if (builtin.zig_backend == .stage2_wasm) break :skip;
735 if (builtin.cpu.arch == .hexagon) break :skip;
736 if (builtin.cpu.arch == .loongarch64) break :skip;
737 if (builtin.cpu.arch.isMIPS()) break :skip;
738 if (builtin.cpu.arch.isPowerPC64()) break :skip;
739 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip;
512740
513741 _ = struct {
514742 export fn zig_ret_vector_32_bool() @Vector(32, bool) {
......@@ -590,7 +818,14 @@ extern fn c_vector_32_bool(@Vector(32, bool)) void;
590818extern fn c_test_vector_32_bool() void;
591819
592820test "@Vector(32, bool)" {
593 if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
821 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
822 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
823 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
824 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
825 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
826 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
827 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
828 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
594829
595830 const vec = c_ret_vector_32_bool();
596831 try expect(vec[0] == true);
......@@ -664,8 +899,12 @@ test "@Vector(32, bool)" {
664899
665900comptime {
666901 skip: {
667 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
668 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
902 if (builtin.zig_backend == .stage2_wasm) break :skip;
903 if (builtin.cpu.arch == .hexagon) break :skip;
904 if (builtin.cpu.arch == .loongarch64) break :skip;
905 if (builtin.cpu.arch.isMIPS()) break :skip;
906 if (builtin.cpu.arch.isPowerPC64()) break :skip;
907 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip;
669908
670909 _ = struct {
671910 export fn zig_ret_vector_64_bool() @Vector(64, bool) {
......@@ -811,7 +1050,12 @@ extern fn c_vector_64_bool(@Vector(64, bool)) void;
8111050extern fn c_test_vector_64_bool() void;
8121051
8131052test "@Vector(64, bool)" {
814 if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
1053 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
1054 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1055 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1056 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1057 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
1058 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
8151059
8161060 const vec = c_ret_vector_64_bool();
8171061 try expect(vec[0] == false);
......@@ -949,8 +1193,12 @@ test "@Vector(64, bool)" {
9491193
9501194comptime {
9511195 skip: {
952 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
953 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
1196 if (builtin.zig_backend == .stage2_wasm) break :skip;
1197 if (builtin.cpu.arch == .hexagon) break :skip;
1198 if (builtin.cpu.arch == .loongarch64) break :skip;
1199 if (builtin.cpu.arch.isMIPS()) break :skip;
1200 if (builtin.cpu.arch.isPowerPC64()) break :skip;
1201 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip;
9541202
9551203 _ = struct {
9561204 export fn zig_ret_vector_128_bool() @Vector(128, bool) {
......@@ -1224,7 +1472,12 @@ extern fn c_vector_128_bool(@Vector(128, bool)) void;
12241472extern fn c_test_vector_128_bool() void;
12251473
12261474test "@Vector(128, bool)" {
1227 if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
1475 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
1476 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1477 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1478 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1479 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
1480 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
12281481
12291482 const vec = c_ret_vector_128_bool();
12301483 try expect(vec[0] == false);
......@@ -1490,8 +1743,12 @@ test "@Vector(128, bool)" {
14901743
14911744comptime {
14921745 skip: {
1493 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
1494 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
1746 if (builtin.zig_backend == .stage2_wasm) break :skip;
1747 if (builtin.cpu.arch == .hexagon) break :skip;
1748 if (builtin.cpu.arch == .loongarch64) break :skip;
1749 if (builtin.cpu.arch.isMIPS()) break :skip;
1750 if (builtin.cpu.arch.isPowerPC64()) break :skip;
1751 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip;
14951752
14961753 _ = struct {
14971754 export fn zig_ret_vector_256_bool() @Vector(256, bool) {
......@@ -2021,7 +2278,12 @@ extern fn c_vector_256_bool(@Vector(256, bool)) void;
20212278extern fn c_test_vector_256_bool() void;
20222279
20232280test "@Vector(256, bool)" {
2024 if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
2281 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
2282 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
2283 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
2284 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
2285 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
2286 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
20252287
20262288 const vec = c_ret_vector_256_bool();
20272289 try expect(vec[0] == true);
......@@ -2543,8 +2805,12 @@ test "@Vector(256, bool)" {
25432805
25442806comptime {
25452807 skip: {
2546 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
2547 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
2808 if (builtin.zig_backend == .stage2_wasm) break :skip;
2809 if (builtin.cpu.arch == .hexagon) break :skip;
2810 if (builtin.cpu.arch == .loongarch64) break :skip;
2811 if (builtin.cpu.arch.isMIPS()) break :skip;
2812 if (builtin.cpu.arch.isPowerPC64()) break :skip;
2813 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip;
25482814
25492815 _ = struct {
25502816 export fn zig_ret_vector_512_bool() @Vector(512, bool) {
......@@ -3586,7 +3852,12 @@ extern fn c_vector_512_bool(@Vector(512, bool)) void;
35863852extern fn c_test_vector_512_bool() void;
35873853
35883854test "@Vector(512, bool)" {
3589 if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
3855 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
3856 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
3857 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
3858 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
3859 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
3860 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
35903861
35913862 const vec = c_ret_vector_512_bool();
35923863 try expect(vec[0] == false);
......@@ -4660,7 +4931,7 @@ test "@Vector(2, u8)" {
46604931 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
46614932 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
46624933 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
4663 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) return error.SkipZigTest;
4934 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag == .windows) return error.SkipZigTest;
46644935
46654936 const v = c_ret_vector_2_u8();
46664937 try expect(v[0] == 9);
......@@ -4689,7 +4960,6 @@ test "@Vector(3, u8)" {
46894960 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
46904961 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
46914962 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
4692 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest;
46934963
46944964 const v = c_ret_vector_3_u8();
46954965 try expect(v[0] == 19);
......@@ -4732,7 +5002,7 @@ test "@Vector(4, u8)" {
47325002 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
47335003 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
47345004 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
4735 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) return error.SkipZigTest;
5005 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag == .windows) return error.SkipZigTest;
47365006
47375007 const v = c_ret_vector_4_u8();
47385008 try expect(v[0] == 41);
......@@ -4766,7 +5036,6 @@ test "@Vector(6, u8)" {
47665036 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
47675037 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
47685038 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
4769 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest;
47705039
47715040 const v = c_ret_vector_6_u8();
47725041 try expect(v[0] == 53);
......@@ -4956,7 +5225,6 @@ test "@Vector(24, u8)" {
49565225 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
49575226 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
49585227 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
4959 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
49605228
49615229 const v = c_ret_vector_24_u8();
49625230 try expect(v[0] == 57);
......@@ -5040,7 +5308,6 @@ test "@Vector(32, u8)" {
50405308 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
50415309 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
50425310 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
5043 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
50445311
50455312 const v = c_ret_vector_32_u8();
50465313 try expect(v[0] == 69);
......@@ -5150,7 +5417,6 @@ test "@Vector(48, u8)" {
51505417 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
51515418 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
51525419 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
5153 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
51545420
51555421 const v = c_ret_vector_48_u8();
51565422 try expect(v[0] == 29);
......@@ -5293,7 +5559,6 @@ test "@Vector(64, u8)" {
52935559 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
52945560 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
52955561 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
5296 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
52975562
52985563 const v = c_ret_vector_64_u8();
52995564 try expect(v[0] == 53);
......@@ -5488,7 +5753,6 @@ test "@Vector(96, u8)" {
54885753 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
54895754 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
54905755 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
5491 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
54925756
54935757 const v = c_ret_vector_96_u8();
54945758 try expect(v[0] == 82);
......@@ -5751,7 +6015,6 @@ test "@Vector(128, u8)" {
57516015 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
57526016 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
57536017 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
5754 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
57556018
57566019 const v = c_ret_vector_128_u8();
57576020 try expect(v[0] == 30);
......@@ -6116,7 +6379,6 @@ test "@Vector(192, u8)" {
61166379 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
61176380 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
61186381 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
6119 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
61206382
61216383 const v = c_ret_vector_192_u8();
61226384 try expect(v[0] == 70);
......@@ -6617,7 +6879,6 @@ test "@Vector(256, u8)" {
66176879 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
66186880 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
66196881 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
6620 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
66216882
66226883 const v = c_ret_vector_256_u8();
66236884 try expect(v[0] == 66);
......@@ -7322,7 +7583,6 @@ test "@Vector(384, u8)" {
73227583 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
73237584 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
73247585 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
7325 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
73267586
73277587 const v = c_ret_vector_384_u8();
73287588 try expect(v[0] == 46);
......@@ -8299,7 +8559,6 @@ test "@Vector(512, u8)" {
82998559 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
83008560 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
83018561 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
8302 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
83038562
83048563 const v = c_ret_vector_512_u8();
83058564 try expect(v[0] == 38);
......@@ -8893,7 +9152,7 @@ test "@Vector(2, u16)" {
88939152 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
88949153 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
88959154 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
8896 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) return error.SkipZigTest;
9155 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag == .windows) return error.SkipZigTest;
88979156
88989157 const v = c_ret_vector_2_u16();
88999158 try expect(v[0] == 9);
......@@ -8921,7 +9180,6 @@ test "@Vector(3, u16)" {
89219180 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
89229181 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
89239182 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
8924 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest;
89259183
89269184 const v = c_ret_vector_3_u16();
89279185 try expect(v[0] == 19);
......@@ -9070,7 +9328,6 @@ test "@Vector(12, u16)" {
90709328 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
90719329 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
90729330 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9073 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
90749331
90759332 const v = c_ret_vector_12_u16();
90769333 try expect(v[0] == 121);
......@@ -9120,7 +9377,6 @@ test "@Vector(16, u16)" {
91209377 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
91219378 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
91229379 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9123 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
91249380
91259381 const v = c_ret_vector_16_u16();
91269382 try expect(v[0] == 177);
......@@ -9186,7 +9442,6 @@ test "@Vector(24, u16)" {
91869442 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
91879443 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
91889444 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9189 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
91909445
91919446 const v = c_ret_vector_24_u16();
91929447 try expect(v[0] == 257);
......@@ -9270,7 +9525,6 @@ test "@Vector(32, u16)" {
92709525 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
92719526 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
92729527 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9273 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
92749528
92759529 const v = c_ret_vector_32_u16();
92769530 try expect(v[0] == 369);
......@@ -9380,7 +9634,6 @@ test "@Vector(48, u16)" {
93809634 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
93819635 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
93829636 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9383 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
93849637
93859638 const v = c_ret_vector_48_u16();
93869639 try expect(v[0] == 529);
......@@ -9524,7 +9777,6 @@ test "@Vector(64, u16)" {
95249777 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
95259778 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
95269779 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9527 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
95289780
95299781 const v = c_ret_vector_64_u16();
95309782 try expect(v[0] == 753);
......@@ -9719,7 +9971,6 @@ test "@Vector(96, u16)" {
97199971 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
97209972 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
97219973 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9722 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
97239974
97249975 const v = c_ret_vector_96_u16();
97259976 try expect(v[0] == 1082);
......@@ -9982,7 +10233,6 @@ test "@Vector(128, u16)" {
998210233 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
998310234 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
998410235 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9985 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
998610236
998710237 const v = c_ret_vector_128_u16();
998810238 try expect(v[0] == 1530);
......@@ -10347,7 +10597,6 @@ test "@Vector(192, u16)" {
1034710597 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1034810598 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1034910599 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
10350 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1035110600
1035210601 const v = c_ret_vector_192_u16();
1035310602 try expect(v[0] == 2170);
......@@ -10848,7 +11097,6 @@ test "@Vector(256, u16)" {
1084811097 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1084911098 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1085011099 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
10851 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1085211100
1085311101 const v = c_ret_vector_256_u16();
1085411102 try expect(v[0] == 3066);
......@@ -11265,7 +11513,6 @@ test "@Vector(6, u32)" {
1126511513 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1126611514 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1126711515 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11268 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1126911516
1127011517 const v = c_ret_vector_6_u32();
1127111518 try expect(v[0] == 53);
......@@ -11301,7 +11548,6 @@ test "@Vector(8, u32)" {
1130111548 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
1130211549 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1130311550 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11304 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1130511551
1130611552 const v = c_ret_vector_8_u32();
1130711553 try expect(v[0] == 81);
......@@ -11344,7 +11590,6 @@ test "@Vector(12, u32)" {
1134411590 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1134511591 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1134611592 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11347 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1134811593
1134911594 const v = c_ret_vector_12_u32();
1135011595 try expect(v[0] == 121);
......@@ -11394,7 +11639,6 @@ test "@Vector(16, u32)" {
1139411639 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
1139511640 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1139611641 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11397 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1139811642
1139911643 const v = c_ret_vector_16_u32();
1140011644 try expect(v[0] == 177);
......@@ -11460,7 +11704,6 @@ test "@Vector(24, u32)" {
1146011704 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1146111705 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1146211706 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11463 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1146411707
1146511708 const v = c_ret_vector_24_u32();
1146611709 try expect(v[0] == 257);
......@@ -11545,7 +11788,6 @@ test "@Vector(32, u32)" {
1154511788 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1154611789 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1154711790 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11548 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1154911791
1155011792 const v = c_ret_vector_32_u32();
1155111793 try expect(v[0] == 369);
......@@ -11655,7 +11897,6 @@ test "@Vector(48, u32)" {
1165511897 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1165611898 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1165711899 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11658 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1165911900
1166011901 const v = c_ret_vector_48_u32();
1166111902 try expect(v[0] == 529);
......@@ -11799,7 +12040,6 @@ test "@Vector(64, u32)" {
1179912040 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1180012041 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1180112042 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11802 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1180312043
1180412044 const v = c_ret_vector_64_u32();
1180512045 try expect(v[0] == 753);
......@@ -11994,7 +12234,6 @@ test "@Vector(96, u32)" {
1199412234 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1199512235 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1199612236 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11997 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1199812237
1199912238 const v = c_ret_vector_96_u32();
1200012239 try expect(v[0] == 1082);
......@@ -12257,7 +12496,6 @@ test "@Vector(128, u32)" {
1225712496 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1225812497 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1225912498 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
12260 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1226112499
1226212500 const v = c_ret_vector_128_u32();
1226312501 try expect(v[0] == 1530);
......@@ -12414,8 +12652,6 @@ extern fn c_vector_1_u64(@Vector(1, u64), usize) void;
1241412652extern fn c_test_vector_1_u64() void;
1241512653
1241612654test "@Vector(1, u64)" {
12417 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest;
12418
1241912655 const v = c_ret_vector_1_u64();
1242012656 try expect(v[0] == 3);
1242112657 c_vector_1_u64(.{4}, 1);
......@@ -12464,7 +12700,6 @@ test "@Vector(3, u64)" {
1246412700 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1246512701 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1246612702 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
12467 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1246812703
1246912704 const v = c_ret_vector_3_u64();
1247012705 try expect(v[0] == 19);
......@@ -12493,7 +12728,6 @@ test "@Vector(4, u64)" {
1249312728 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
1249412729 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1249512730 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
12496 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1249712731
1249812732 const v = c_ret_vector_4_u64();
1249912733 try expect(v[0] == 33);
......@@ -12560,7 +12794,6 @@ test "@Vector(8, u64)" {
1256012794 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
1256112795 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1256212796 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
12563 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1256412797
1256512798 const v = c_ret_vector_8_u64();
1256612799 try expect(v[0] == 81);
......@@ -12652,7 +12885,6 @@ test "@Vector(16, u64)" {
1265212885 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1265312886 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1265412887 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
12655 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1265612888
1265712889 const v = c_ret_vector_16_u64();
1265812890 try expect(v[0] == 177);
......@@ -12801,7 +13033,6 @@ test "@Vector(32, u64)" {
1280113033 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1280213034 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1280313035 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
12804 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1280513036
1280613037 const v = c_ret_vector_32_u64();
1280713038 try expect(v[0] == 369);
......@@ -13053,7 +13284,6 @@ test "@Vector(64, u64)" {
1305313284 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1305413285 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1305513286 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13056 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1305713287
1305813288 const v = c_ret_vector_64_u64();
1305913289 try expect(v[0] == 753);
......@@ -13147,7 +13377,6 @@ test "@Vector(1, f32)" {
1314713377 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1314813378 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1314913379 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13150 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest;
1315113380
1315213381 const v = c_ret_vector_1_f32();
1315313382 try expect(v[0] == 3);
......@@ -13269,7 +13498,6 @@ test "@Vector(6, f32)" {
1326913498 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1327013499 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1327113500 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13272 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1327313501
1327413502 const v = c_ret_vector_6_f32();
1327513503 try expect(v[0] == 53);
......@@ -13306,7 +13534,6 @@ test "@Vector(8, f32)" {
1330613534 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1330713535 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1330813536 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13309 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1331013537
1331113538 const v = c_ret_vector_8_f32();
1331213539 try expect(v[0] == 81);
......@@ -13349,7 +13576,6 @@ test "@Vector(12, f32)" {
1334913576 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1335013577 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1335113578 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13352 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1335313579
1335413580 const v = c_ret_vector_12_f32();
1335513581 try expect(v[0] == 121);
......@@ -13400,7 +13626,6 @@ test "@Vector(16, f32)" {
1340013626 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1340113627 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1340213628 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13403 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1340413629
1340513630 const v = c_ret_vector_16_f32();
1340613631 try expect(v[0] == 177);
......@@ -13466,7 +13691,6 @@ test "@Vector(24, f32)" {
1346613691 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1346713692 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1346813693 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13469 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1347013694
1347113695 const v = c_ret_vector_24_f32();
1347213696 try expect(v[0] == 257);
......@@ -13551,7 +13775,6 @@ test "@Vector(32, f32)" {
1355113775 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1355213776 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1355313777 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13554 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1355513778
1355613779 const v = c_ret_vector_32_f32();
1355713780 try expect(v[0] == 369);
......@@ -13661,7 +13884,6 @@ test "@Vector(48, f32)" {
1366113884 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1366213885 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1366313886 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13664 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1366513887
1366613888 const v = c_ret_vector_48_f32();
1366713889 try expect(v[0] == 529);
......@@ -13805,7 +14027,6 @@ test "@Vector(64, f32)" {
1380514027 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1380614028 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1380714029 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13808 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1380914030
1381014031 const v = c_ret_vector_64_f32();
1381114032 try expect(v[0] == 753);
......@@ -14000,7 +14221,6 @@ test "@Vector(96, f32)" {
1400014221 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1400114222 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1400214223 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14003 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1400414224
1400514225 const v = c_ret_vector_96_f32();
1400614226 try expect(v[0] == 1082);
......@@ -14263,7 +14483,6 @@ test "@Vector(128, f32)" {
1426314483 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1426414484 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1426514485 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14266 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1426714486
1426814487 const v = c_ret_vector_128_f32();
1426914488 try expect(v[0] == 1530);
......@@ -14471,7 +14690,6 @@ test "@Vector(3, f64)" {
1447114690 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1447214691 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1447314692 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14474 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1447514693
1447614694 const v = c_ret_vector_3_f64();
1447714695 try expect(v[0] == 19);
......@@ -14500,8 +14718,6 @@ test "@Vector(4, f64)" {
1450014718 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1450114719 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1450214720 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14503 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
14504 if (builtin.cpu.arch.isArm()) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35899
1450514721
1450614722 const v = c_ret_vector_4_f64();
1450714723 try expect(v[0] == 33);
......@@ -14534,7 +14750,6 @@ test "@Vector(6, f64)" {
1453414750 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1453514751 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1453614752 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14537 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1453814753
1453914754 const v = c_ret_vector_6_f64();
1454014755 try expect(v[0] == 53);
......@@ -14570,8 +14785,6 @@ test "@Vector(8, f64)" {
1457014785 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1457114786 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1457214787 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14573 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
14574 if (builtin.cpu.arch.isArm()) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35899
1457514788
1457614789 const v = c_ret_vector_8_f64();
1457714790 try expect(v[0] == 81);
......@@ -14614,7 +14827,6 @@ test "@Vector(12, f64)" {
1461414827 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1461514828 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1461614829 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14617 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1461814830
1461914831 const v = c_ret_vector_12_f64();
1462014832 try expect(v[0] == 121);
......@@ -14665,7 +14877,6 @@ test "@Vector(16, f64)" {
1466514877 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1466614878 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1466714879 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14668 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1466914880
1467014881 const v = c_ret_vector_16_f64();
1467114882 try expect(v[0] == 177);
......@@ -14731,7 +14942,6 @@ test "@Vector(24, f64)" {
1473114942 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1473214943 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1473314944 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14734 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1473514945
1473614946 const v = c_ret_vector_24_f64();
1473714947 try expect(v[0] == 257);
......@@ -14816,7 +15026,6 @@ test "@Vector(32, f64)" {
1481615026 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1481715027 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1481815028 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14819 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1482015029
1482115030 const v = c_ret_vector_32_f64();
1482215031 try expect(v[0] == 369);
......@@ -14926,7 +15135,6 @@ test "@Vector(48, f64)" {
1492615135 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1492715136 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1492815137 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14929 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1493015138
1493115139 const v = c_ret_vector_48_f64();
1493215140 try expect(v[0] == 529);
......@@ -15070,7 +15278,6 @@ test "@Vector(64, f64)" {
1507015278 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1507115279 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1507215280 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
15073 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1507415281
1507515282 const v = c_ret_vector_64_f64();
1507615283 try expect(v[0] == 753);
......@@ -15165,7 +15372,6 @@ extern fn c_test_struct_u8() void;
1516515372test "struct u8" {
1516615373 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1516715374 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15168 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1516915375 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1517015376
1517115377 const s = c_ret_struct_u8();
......@@ -15196,8 +15402,7 @@ test "struct u8, u8" {
1519615402 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1519715403 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1519815404 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15199 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15200 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15405 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1520115406 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1520215407
1520315408 const s = c_ret_struct_u8_u8();
......@@ -15231,8 +15436,7 @@ test "struct u8, u8, u8" {
1523115436 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1523215437 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1523315438 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15234 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15235 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15439 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1523615440 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1523715441
1523815442 const s = c_ret_struct_u8_u8_u8();
......@@ -15269,8 +15473,7 @@ test "struct u8, u8, u8, u8" {
1526915473 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1527015474 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1527115475 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15272 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15273 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15476 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1527415477 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1527515478
1527615479 const s = c_ret_struct_u8_u8_u8_u8();
......@@ -15301,7 +15504,6 @@ extern fn c_test_struct_u16() void;
1530115504test "struct u16" {
1530215505 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1530315506 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15304 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1530515507 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1530615508
1530715509 const s = c_ret_struct_u16();
......@@ -15332,8 +15534,7 @@ test "struct u16, u16" {
1533215534 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1533315535 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1533415536 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15335 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15336 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15537 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1533715538 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1533815539
1533915540 const s = c_ret_struct_u16_u16();
......@@ -15367,9 +15568,8 @@ test "struct u16, u16, u16" {
1536715568 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1536815569 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1536915570 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15370 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15571 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1537115572 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
15372 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1537315573 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1537415574
1537515575 const s = c_ret_struct_u16_u16_u16();
......@@ -15406,9 +15606,8 @@ test "struct u16, u16, u16, u16" {
1540615606 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1540715607 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1540815608 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15409 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15609 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1541015610 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
15411 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1541215611 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1541315612
1541415613 const s = c_ret_struct_u16_u16_u16_u16();
......@@ -15439,7 +15638,6 @@ extern fn c_test_struct_u32() void;
1543915638test "struct u32" {
1544015639 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1544115640 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15442 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1544315641 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1544415642
1544515643 const s = c_ret_struct_u32();
......@@ -15469,9 +15667,8 @@ extern fn c_test_struct_u32_u32() void;
1546915667test "struct u32, u32" {
1547015668 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1547115669 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15472 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15670 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1547315671 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
15474 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1547515672 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1547615673
1547715674 const s = c_ret_struct_u32_u32();
......@@ -15505,8 +15702,7 @@ test "struct u32, u32, u32" {
1550515702 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1550615703 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1550715704 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15508 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15509 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15705 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1551015706
1551115707 const s = c_ret_struct_u32_u32_u32();
1551215708 try expect(s.a == 8);
......@@ -15542,8 +15738,7 @@ test "struct u32, u32, u32, u32" {
1554215738 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1554315739 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1554415740 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15545 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15546 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15741 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1554715742
1554815743 const s = c_ret_struct_u32_u32_u32_u32();
1554915744 try expect(s.a == 10);
......@@ -15573,7 +15768,6 @@ extern fn c_test_struct_u64() void;
1557315768test "struct u64" {
1557415769 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1557515770 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
15576 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1557715771 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1557815772
1557915773 const s = c_ret_struct_u64();
......@@ -15651,7 +15845,6 @@ extern fn c_test_struct_u64_u64() void;
1565115845test "struct u64, u64" {
1565215846 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1565315847 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15654 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1565515848
1565615849 const s = c_ret_struct_u64_u64();
1565715850 try expect(s.a == 21);
......@@ -15691,8 +15884,7 @@ extern fn c_test_struct_u64_u64_u64() void;
1569115884test "struct u64, u64, u64" {
1569215885 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1569315886 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
15694 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15695 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15887 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1569615888
1569715889 const s = c_ret_struct_u64_u64_u64();
1569815890 try expect(s.a == 8);
......@@ -15727,8 +15919,7 @@ extern fn c_test_struct_u64_u64_u64_u64() void;
1572715919test "struct u64, u64, u64, u64" {
1572815920 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1572915921 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
15730 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15731 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15922 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1573215923
1573315924 const s = c_ret_struct_u64_u64_u64_u64();
1573415925 try expect(s.a == 10);
......@@ -15757,8 +15948,7 @@ extern fn c_test_struct_f32() void;
1575715948
1575815949test "struct f32" {
1575915950 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15760 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15761 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15951 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1576215952 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1576315953
1576415954 const s = c_ret_struct_f32();
......@@ -15791,7 +15981,6 @@ test "struct f32, f32" {
1579115981 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1579215982 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1579315983 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
15794 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1579515984 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1579615985
1579715986 const s = c_ret_struct_f32_f32();
......@@ -15827,7 +16016,6 @@ test "struct f32, f32, f32" {
1582716016 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1582816017 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1582916018 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15830 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1583116019
1583216020 const s = c_ret_struct_f32_f32_f32();
1583316021 try expect(s.a == 8);
......@@ -15865,7 +16053,6 @@ test "struct f32, f32, f32, f32" {
1586516053 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1586616054 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1586716055 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15868 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1586916056
1587016057 const s = c_ret_struct_f32_f32_f32_f32();
1587116058 try expect(s.a == 10);
......@@ -15905,7 +16092,6 @@ test "struct f32, f32, f32, f32, f32" {
1590516092 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1590616093 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1590716094 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15908 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1590916095
1591016096 const s = c_ret_struct_f32_f32_f32_f32_f32();
1591116097 try expect(s.a == 12);
......@@ -15917,31 +16103,408 @@ test "struct f32, f32, f32, f32, f32" {
1591716103 c_test_struct_f32_f32_f32_f32_f32();
1591816104}
1591916105
15920const Struct_f32a8 = extern struct {
15921 a: f32 align(8),
16106const Struct_void_f32 = extern struct {
16107 _: void = {},
16108 a: f32,
1592216109};
1592316110
15924export fn zig_ret_struct_f32a8() Struct_f32a8 {
15925 return .{ .a = 1.25 };
16111export fn zig_ret_struct_void_f32() Struct_void_f32 {
16112 return .{ .a = 1 };
1592616113}
15927export fn zig_struct_f32a8(s: Struct_f32a8, f: f32) void {
15928 expect(s.a == 2.75) catch @panic("test failure");
15929 expect(f == 3.5) catch @panic("test failure");
16114export fn zig_struct_void_f32(s: Struct_void_f32, i: usize) void {
16115 expect(s.a == 2) catch @panic("test failure");
16116 expect(i == 3) catch @panic("test failure");
1593016117}
1593116118
15932extern fn c_ret_struct_f32a8() Struct_f32a8;
15933extern fn c_struct_f32a8(Struct_f32a8, f32) void;
15934extern fn c_test_struct_f32a8() void;
16119extern fn c_ret_struct_void_f32() Struct_void_f32;
16120extern fn c_struct_void_f32(Struct_void_f32, usize) void;
16121extern fn c_test_struct_void_f32() void;
1593516122
15936test "struct f32 align(8)" {
15937 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
15938 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
15939 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
16123test "struct void, f32" {
1594016124 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1594116125 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15942 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
15943 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15944 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
16126 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
16127
16128 const s = c_ret_struct_void_f32();
16129 try expect(s.a == 4);
16130 c_struct_void_f32(.{ .a = 5 }, 6);
16131 c_test_struct_void_f32();
16132}
16133
16134const Struct_array_1_f32 = extern struct {
16135 a: [1]f32,
16136};
16137
16138export fn zig_ret_struct_array_1_f32() Struct_array_1_f32 {
16139 return .{ .a = .{1} };
16140}
16141export fn zig_struct_array_1_f32(s: Struct_array_1_f32, i: usize) void {
16142 expect(s.a[0] == 2) catch @panic("test failure");
16143 expect(i == 3) catch @panic("test failure");
16144}
16145
16146extern fn c_ret_struct_array_1_f32() Struct_array_1_f32;
16147extern fn c_struct_array_1_f32(Struct_array_1_f32, usize) void;
16148extern fn c_test_struct_array_1_f32() void;
16149
16150test "struct [1]f32" {
16151 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16152 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16153 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16154 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16155 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16156
16157 const s = c_ret_struct_array_1_f32();
16158 try expect(s.a[0] == 4);
16159 c_struct_array_1_f32(.{ .a = .{5} }, 6);
16160 c_test_struct_array_1_f32();
16161}
16162
16163const Struct_array_2_f32 = extern struct {
16164 a: [2]f32,
16165};
16166
16167export fn zig_ret_struct_array_2_f32() Struct_array_2_f32 {
16168 return .{ .a = .{ 1, 2 } };
16169}
16170export fn zig_struct_array_2_f32(s: Struct_array_2_f32, i: usize) void {
16171 expect(s.a[0] == 3) catch @panic("test failure");
16172 expect(s.a[1] == 4) catch @panic("test failure");
16173 expect(i == 5) catch @panic("test failure");
16174}
16175
16176extern fn c_ret_struct_array_2_f32() Struct_array_2_f32;
16177extern fn c_struct_array_2_f32(Struct_array_2_f32, usize) void;
16178extern fn c_test_struct_array_2_f32() void;
16179
16180test "struct [2]f32" {
16181 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16182 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16183 if (builtin.cpu.arch == .loongarch64 and builtin.abi.float() == .hard) return error.SkipZigTest;
16184 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16185 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16186 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16187
16188 const s = c_ret_struct_array_2_f32();
16189 try expect(s.a[0] == 6);
16190 try expect(s.a[1] == 7);
16191 c_struct_array_2_f32(.{ .a = .{ 8, 9 } }, 10);
16192 c_test_struct_array_2_f32();
16193}
16194
16195const Struct_array_3_f32 = extern struct {
16196 a: [3]f32,
16197};
16198
16199export fn zig_ret_struct_array_3_f32() Struct_array_3_f32 {
16200 return .{ .a = .{ 1, 2, 3 } };
16201}
16202export fn zig_struct_array_3_f32(s: Struct_array_3_f32, i: usize) void {
16203 expect(s.a[0] == 4) catch @panic("test failure");
16204 expect(s.a[1] == 5) catch @panic("test failure");
16205 expect(s.a[2] == 6) catch @panic("test failure");
16206 expect(i == 7) catch @panic("test failure");
16207}
16208
16209extern fn c_ret_struct_array_3_f32() Struct_array_3_f32;
16210extern fn c_struct_array_3_f32(Struct_array_3_f32, usize) void;
16211extern fn c_test_struct_array_3_f32() void;
16212
16213test "struct [3]f32" {
16214 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16215 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16216 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16217 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16218 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16219
16220 const s = c_ret_struct_array_3_f32();
16221 try expect(s.a[0] == 8);
16222 try expect(s.a[1] == 9);
16223 try expect(s.a[2] == 10);
16224 c_struct_array_3_f32(.{ .a = .{ 11, 12, 13 } }, 14);
16225 c_test_struct_array_3_f32();
16226}
16227
16228const Struct_array_4_f32 = extern struct {
16229 a: [4]f32,
16230};
16231
16232export fn zig_ret_struct_array_4_f32() Struct_array_4_f32 {
16233 return .{ .a = .{ 1, 2, 3, 4 } };
16234}
16235export fn zig_struct_array_4_f32(s: Struct_array_4_f32, i: usize) void {
16236 expect(s.a[0] == 5) catch @panic("test failure");
16237 expect(s.a[1] == 6) catch @panic("test failure");
16238 expect(s.a[2] == 7) catch @panic("test failure");
16239 expect(s.a[3] == 8) catch @panic("test failure");
16240 expect(i == 9) catch @panic("test failure");
16241}
16242
16243extern fn c_ret_struct_array_4_f32() Struct_array_4_f32;
16244extern fn c_struct_array_4_f32(Struct_array_4_f32, usize) void;
16245extern fn c_test_struct_array_4_f32() void;
16246
16247test "struct [4]f32" {
16248 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16249 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16250 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16251 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16252 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16253
16254 const s = c_ret_struct_array_4_f32();
16255 try expect(s.a[0] == 10);
16256 try expect(s.a[1] == 11);
16257 try expect(s.a[2] == 12);
16258 try expect(s.a[3] == 13);
16259 c_struct_array_4_f32(.{ .a = .{ 14, 15, 16, 17 } }, 18);
16260 c_test_struct_array_4_f32();
16261}
16262
16263const Struct_array_5_f32 = extern struct {
16264 a: [5]f32,
16265};
16266
16267export fn zig_ret_struct_array_5_f32() Struct_array_5_f32 {
16268 return .{ .a = .{ 1, 2, 3, 4, 5 } };
16269}
16270export fn zig_struct_array_5_f32(s: Struct_array_5_f32, i: usize) void {
16271 expect(s.a[0] == 6) catch @panic("test failure");
16272 expect(s.a[1] == 7) catch @panic("test failure");
16273 expect(s.a[2] == 8) catch @panic("test failure");
16274 expect(s.a[3] == 9) catch @panic("test failure");
16275 expect(s.a[4] == 10) catch @panic("test failure");
16276 expect(i == 11) catch @panic("test failure");
16277}
16278
16279extern fn c_ret_struct_array_5_f32() Struct_array_5_f32;
16280extern fn c_struct_array_5_f32(Struct_array_5_f32, usize) void;
16281extern fn c_test_struct_array_5_f32() void;
16282
16283test "struct [5]f32" {
16284 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16285 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16286 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16287 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16288
16289 const s = c_ret_struct_array_5_f32();
16290 try expect(s.a[0] == 12);
16291 try expect(s.a[1] == 13);
16292 try expect(s.a[2] == 14);
16293 try expect(s.a[3] == 15);
16294 try expect(s.a[4] == 16);
16295 c_struct_array_5_f32(.{ .a = .{ 17, 18, 19, 20, 21 } }, 22);
16296 c_test_struct_array_5_f32();
16297}
16298
16299const Struct_array_0_sentinel_f32 = extern struct {
16300 a: [0:0x1e1]f32,
16301};
16302
16303export fn zig_ret_struct_array_0_sentinel_f32() Struct_array_0_sentinel_f32 {
16304 return .{ .a = .{} };
16305}
16306export fn zig_struct_array_0_sentinel_f32(s: Struct_array_0_sentinel_f32, i: usize) void {
16307 var sentinel_index: usize = 0;
16308 _ = &sentinel_index;
16309 expect(s.a[sentinel_index] == 0x1e1) catch @panic("test failure");
16310 expect(i == 1) catch @panic("test failure");
16311}
16312
16313extern fn c_ret_struct_array_0_sentinel_f32() Struct_array_0_sentinel_f32;
16314extern fn c_struct_array_0_sentinel_f32(Struct_array_0_sentinel_f32, usize) void;
16315extern fn c_test_struct_array_0_sentinel_f32() void;
16316
16317test "struct [0:sentinel]f32" {
16318 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16319 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16320 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16321 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16322 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16323
16324 var sentinel_index: usize = 0;
16325 _ = &sentinel_index;
16326 const s = c_ret_struct_array_0_sentinel_f32();
16327 try expect(s.a[sentinel_index] == 0x1e1);
16328 c_struct_array_0_sentinel_f32(.{ .a = .{} }, 2);
16329 c_test_struct_array_0_sentinel_f32();
16330}
16331
16332const Struct_array_1_sentinel_f32 = extern struct {
16333 a: [1:0x1e1]f32,
16334};
16335
16336export fn zig_ret_struct_array_1_sentinel_f32() Struct_array_1_sentinel_f32 {
16337 return .{ .a = .{1} };
16338}
16339export fn zig_struct_array_1_sentinel_f32(s: Struct_array_1_sentinel_f32, i: usize) void {
16340 var sentinel_index: usize = 1;
16341 _ = &sentinel_index;
16342 expect(s.a[0] == 2) catch @panic("test failure");
16343 expect(s.a[sentinel_index] == 0x1e1) catch @panic("test failure");
16344 expect(i == 3) catch @panic("test failure");
16345}
16346
16347extern fn c_ret_struct_array_1_sentinel_f32() Struct_array_1_sentinel_f32;
16348extern fn c_struct_array_1_sentinel_f32(Struct_array_1_sentinel_f32, usize) void;
16349extern fn c_test_struct_array_1_sentinel_f32() void;
16350
16351test "struct [1:sentinel]f32" {
16352 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16353 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16354 if (builtin.cpu.arch == .loongarch64 and builtin.abi.float() == .hard) return error.SkipZigTest;
16355 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16356 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16357 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16358
16359 var sentinel_index: usize = 1;
16360 _ = &sentinel_index;
16361 const s = c_ret_struct_array_1_sentinel_f32();
16362 try expect(s.a[0] == 4);
16363 try expect(s.a[sentinel_index] == 0x1e1);
16364 c_struct_array_1_sentinel_f32(.{ .a = .{5} }, 6);
16365 c_test_struct_array_1_sentinel_f32();
16366}
16367
16368const Struct_array_2_sentinel_f32 = extern struct {
16369 a: [2:0x1e1]f32,
16370};
16371
16372export fn zig_ret_struct_array_2_sentinel_f32() Struct_array_2_sentinel_f32 {
16373 return .{ .a = .{ 1, 2 } };
16374}
16375export fn zig_struct_array_2_sentinel_f32(s: Struct_array_2_sentinel_f32, i: usize) void {
16376 var sentinel_index: usize = 2;
16377 _ = &sentinel_index;
16378 expect(s.a[0] == 3) catch @panic("test failure");
16379 expect(s.a[1] == 4) catch @panic("test failure");
16380 expect(s.a[sentinel_index] == 0x1e1) catch @panic("test failure");
16381 expect(i == 5) catch @panic("test failure");
16382}
16383
16384extern fn c_ret_struct_array_2_sentinel_f32() Struct_array_2_sentinel_f32;
16385extern fn c_struct_array_2_sentinel_f32(Struct_array_2_sentinel_f32, usize) void;
16386extern fn c_test_struct_array_2_sentinel_f32() void;
16387
16388test "struct [2:sentinel]f32" {
16389 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16390 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16391 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16392 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16393 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16394
16395 var sentinel_index: usize = 2;
16396 _ = &sentinel_index;
16397 const s = c_ret_struct_array_2_sentinel_f32();
16398 try expect(s.a[0] == 6);
16399 try expect(s.a[1] == 7);
16400 try expect(s.a[sentinel_index] == 0x1e1);
16401 c_struct_array_2_sentinel_f32(.{ .a = .{ 8, 9 } }, 10);
16402 c_test_struct_array_2_sentinel_f32();
16403}
16404
16405const Struct_array_3_sentinel_f32 = extern struct {
16406 a: [3:0x1e1]f32,
16407};
16408
16409export fn zig_ret_struct_array_3_sentinel_f32() Struct_array_3_sentinel_f32 {
16410 return .{ .a = .{ 1, 2, 3 } };
16411}
16412export fn zig_struct_array_3_sentinel_f32(s: Struct_array_3_sentinel_f32, i: usize) void {
16413 var sentinel_index: usize = 3;
16414 _ = &sentinel_index;
16415 expect(s.a[0] == 4) catch @panic("test failure");
16416 expect(s.a[1] == 5) catch @panic("test failure");
16417 expect(s.a[2] == 6) catch @panic("test failure");
16418 expect(s.a[sentinel_index] == 0x1e1) catch @panic("test failure");
16419 expect(i == 7) catch @panic("test failure");
16420}
16421
16422extern fn c_ret_struct_array_3_sentinel_f32() Struct_array_3_sentinel_f32;
16423extern fn c_struct_array_3_sentinel_f32(Struct_array_3_sentinel_f32, usize) void;
16424extern fn c_test_struct_array_3_sentinel_f32() void;
16425
16426test "struct [3:sentinel]f32" {
16427 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16428 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16429 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16430 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16431 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16432
16433 var sentinel_index: usize = 3;
16434 _ = &sentinel_index;
16435 const s = c_ret_struct_array_3_sentinel_f32();
16436 try expect(s.a[0] == 8);
16437 try expect(s.a[1] == 9);
16438 try expect(s.a[2] == 10);
16439 try expect(s.a[sentinel_index] == 0x1e1);
16440 c_struct_array_3_sentinel_f32(.{ .a = .{ 11, 12, 13 } }, 14);
16441 c_test_struct_array_3_sentinel_f32();
16442}
16443
16444const Struct_array_4_sentinel_f32 = extern struct {
16445 a: [4:0x1e1]f32,
16446};
16447
16448export fn zig_ret_struct_array_4_sentinel_f32() Struct_array_4_sentinel_f32 {
16449 return .{ .a = .{ 1, 2, 3, 4 } };
16450}
16451export fn zig_struct_array_4_sentinel_f32(s: Struct_array_4_sentinel_f32, i: usize) void {
16452 var sentinel_index: usize = 4;
16453 _ = &sentinel_index;
16454 expect(s.a[0] == 5) catch @panic("test failure");
16455 expect(s.a[1] == 6) catch @panic("test failure");
16456 expect(s.a[2] == 7) catch @panic("test failure");
16457 expect(s.a[3] == 8) catch @panic("test failure");
16458 expect(s.a[sentinel_index] == 0x1e1) catch @panic("test failure");
16459 expect(i == 9) catch @panic("test failure");
16460}
16461
16462extern fn c_ret_struct_array_4_sentinel_f32() Struct_array_4_sentinel_f32;
16463extern fn c_struct_array_4_sentinel_f32(Struct_array_4_sentinel_f32, usize) void;
16464extern fn c_test_struct_array_4_sentinel_f32() void;
16465
16466test "struct [4:sentinel]f32" {
16467 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16468 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16469 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16470 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16471
16472 var sentinel_index: usize = 4;
16473 _ = &sentinel_index;
16474 const s = c_ret_struct_array_4_sentinel_f32();
16475 try expect(s.a[0] == 10);
16476 try expect(s.a[1] == 11);
16477 try expect(s.a[2] == 12);
16478 try expect(s.a[3] == 13);
16479 try expect(s.a[sentinel_index] == 0x1e1);
16480 c_struct_array_4_sentinel_f32(.{ .a = .{ 14, 15, 16, 17 } }, 18);
16481 c_test_struct_array_4_sentinel_f32();
16482}
16483
16484const Struct_f32a8 = extern struct {
16485 a: f32 align(8),
16486};
16487
16488export fn zig_ret_struct_f32a8() Struct_f32a8 {
16489 return .{ .a = 1.25 };
16490}
16491export fn zig_struct_f32a8(s: Struct_f32a8, f: f32) void {
16492 expect(s.a == 2.75) catch @panic("test failure");
16493 expect(f == 3.5) catch @panic("test failure");
16494}
16495
16496extern fn c_ret_struct_f32a8() Struct_f32a8;
16497extern fn c_struct_f32a8(Struct_f32a8, f32) void;
16498extern fn c_test_struct_f32a8() void;
16499
16500test "struct f32 align(8)" {
16501 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16502 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16503 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
16504 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16505 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16506 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
16507 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1594516508
1594616509 const s = c_ret_struct_f32a8();
1594716510 try expect(s.a == 4.125);
......@@ -15974,7 +16537,6 @@ test "struct f32 align(8), f32 align(8)" {
1597416537 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1597516538 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1597616539 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
15977 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1597816540 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1597916541
1598016542 const s = c_ret_struct_f32a8_f32a8();
......@@ -16007,8 +16569,7 @@ test "struct {f32, f32}, f32" {
1600716569 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1600816570 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1600916571 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16010 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16011 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16572 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1601216573
1601316574 const s = c_ret_struct_f32f32_f32();
1601416575 try expect(s.a.b == 1.0);
......@@ -16041,8 +16602,7 @@ test "struct f32, {f32, f32}" {
1604116602 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1604216603 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1604316604 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16044 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16045 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16605 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1604616606
1604716607 const s = c_ret_struct_f32_f32f32();
1604816608 try expect(s.a == 1.0);
......@@ -16070,9 +16630,8 @@ extern fn c_test_struct_f64() void;
1607016630
1607116631test "struct f64" {
1607216632 if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
16073 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16633 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1607416634 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
16075 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1607616635 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1607716636
1607816637 const s = c_ret_struct_f64();
......@@ -16102,8 +16661,7 @@ extern fn c_test_struct_f64_f64() void;
1610216661test "struct f64, f64" {
1610316662 if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
1610416663 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16105 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16106 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16664 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1610716665
1610816666 const s = c_ret_struct_f64_f64();
1610916667 try expect(s.a == 6);
......@@ -16135,8 +16693,7 @@ extern fn c_test_struct_f64_f64_f64() void;
1613516693test "struct f64, f64, f64" {
1613616694 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1613716695 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
16138 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16139 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16696 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1614016697
1614116698 const s = c_ret_struct_f64_f64_f64();
1614216699 try expect(s.a == 8);
......@@ -16171,8 +16728,7 @@ extern fn c_test_struct_f64_f64_f64_f64() void;
1617116728test "struct f64, f64, f64, f64" {
1617216729 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1617316730 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
16174 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16175 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16731 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1617616732
1617716733 const s = c_ret_struct_f64_f64_f64_f64();
1617816734 try expect(s.a == 10);
......@@ -16210,8 +16766,7 @@ extern fn c_test_struct_f64_f64_f64_f64_f64() void;
1621016766test "struct f64, f64, f64, f64, f64" {
1621116767 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1621216768 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
16213 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16214 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16769 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1621516770
1621616771 const s = c_ret_struct_f64_f64_f64_f64_f64();
1621716772 try expect(s.a == 12);
......@@ -16223,6 +16778,201 @@ test "struct f64, f64, f64, f64, f64" {
1622316778 c_test_struct_f64_f64_f64_f64_f64();
1622416779}
1622516780
16781const Struct_array_1_f64 = extern struct {
16782 a: [1]f64,
16783};
16784
16785export fn zig_ret_struct_array_1_f64() Struct_array_1_f64 {
16786 return .{ .a = .{1} };
16787}
16788export fn zig_struct_array_1_f64(s: Struct_array_1_f64, i: usize) void {
16789 expect(s.a[0] == 2) catch @panic("test failure");
16790 expect(i == 3) catch @panic("test failure");
16791}
16792
16793extern fn c_ret_struct_array_1_f64() Struct_array_1_f64;
16794extern fn c_struct_array_1_f64(Struct_array_1_f64, usize) void;
16795extern fn c_test_struct_array_1_f64() void;
16796
16797test "struct [1]f64" {
16798 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16799 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16800 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16801 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16802 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16803
16804 const s = c_ret_struct_array_1_f64();
16805 try expect(s.a[0] == 4);
16806 c_struct_array_1_f64(.{ .a = .{5} }, 6);
16807 c_test_struct_array_1_f64();
16808}
16809
16810const Struct_array_2_f64 = extern struct {
16811 a: [2]f64,
16812};
16813
16814export fn zig_ret_struct_array_2_f64() Struct_array_2_f64 {
16815 return .{ .a = .{ 1, 2 } };
16816}
16817export fn zig_struct_array_2_f64(s: Struct_array_2_f64, i: usize) void {
16818 expect(s.a[0] == 3) catch @panic("test failure");
16819 expect(s.a[1] == 4) catch @panic("test failure");
16820 expect(i == 5) catch @panic("test failure");
16821}
16822
16823extern fn c_ret_struct_array_2_f64() Struct_array_2_f64;
16824extern fn c_struct_array_2_f64(Struct_array_2_f64, usize) void;
16825extern fn c_test_struct_array_2_f64() void;
16826
16827test "struct [2]f64" {
16828 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16829 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16830 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16831 if (builtin.cpu.arch == .loongarch64 and builtin.abi.float() == .hard) return error.SkipZigTest;
16832 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16833 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16834 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16835
16836 const s = c_ret_struct_array_2_f64();
16837 try expect(s.a[0] == 6);
16838 try expect(s.a[1] == 7);
16839 c_struct_array_2_f64(.{ .a = .{ 8, 9 } }, 10);
16840 c_test_struct_array_2_f64();
16841}
16842
16843const Struct_array_3_f64 = extern struct {
16844 a: [3]f64,
16845};
16846
16847export fn zig_ret_struct_array_3_f64() Struct_array_3_f64 {
16848 return .{ .a = .{ 1, 2, 3 } };
16849}
16850export fn zig_struct_array_3_f64(s: Struct_array_3_f64, i: usize) void {
16851 expect(s.a[0] == 4) catch @panic("test failure");
16852 expect(s.a[1] == 5) catch @panic("test failure");
16853 expect(s.a[2] == 6) catch @panic("test failure");
16854 expect(i == 7) catch @panic("test failure");
16855}
16856
16857extern fn c_ret_struct_array_3_f64() Struct_array_3_f64;
16858extern fn c_struct_array_3_f64(Struct_array_3_f64, usize) void;
16859extern fn c_test_struct_array_3_f64() void;
16860
16861test "struct [3]f64" {
16862 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16863 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16864 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16865 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16866 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16867
16868 const s = c_ret_struct_array_3_f64();
16869 try expect(s.a[0] == 8);
16870 try expect(s.a[1] == 9);
16871 try expect(s.a[2] == 10);
16872 c_struct_array_3_f64(.{ .a = .{ 11, 12, 13 } }, 14);
16873 c_test_struct_array_3_f64();
16874}
16875
16876const Struct_array_4_f64 = extern struct {
16877 a: [4]f64,
16878};
16879
16880export fn zig_ret_struct_array_4_f64() Struct_array_4_f64 {
16881 return .{ .a = .{ 1, 2, 3, 4 } };
16882}
16883export fn zig_struct_array_4_f64(s: Struct_array_4_f64, i: usize) void {
16884 expect(s.a[0] == 5) catch @panic("test failure");
16885 expect(s.a[1] == 6) catch @panic("test failure");
16886 expect(s.a[2] == 7) catch @panic("test failure");
16887 expect(s.a[3] == 8) catch @panic("test failure");
16888 expect(i == 9) catch @panic("test failure");
16889}
16890
16891extern fn c_ret_struct_array_4_f64() Struct_array_4_f64;
16892extern fn c_struct_array_4_f64(Struct_array_4_f64, usize) void;
16893extern fn c_test_struct_array_4_f64() void;
16894
16895test "struct [4]f64" {
16896 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16897 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16898 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16899 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16900 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16901
16902 const s = c_ret_struct_array_4_f64();
16903 try expect(s.a[0] == 10);
16904 try expect(s.a[1] == 11);
16905 try expect(s.a[2] == 12);
16906 try expect(s.a[3] == 13);
16907 c_struct_array_4_f64(.{ .a = .{ 14, 15, 16, 17 } }, 18);
16908 c_test_struct_array_4_f64();
16909}
16910
16911const Struct_array_5_f64 = extern struct {
16912 a: [5]f64,
16913};
16914
16915export fn zig_ret_struct_array_5_f64() Struct_array_5_f64 {
16916 return .{ .a = .{ 1, 2, 3, 4, 5 } };
16917}
16918export fn zig_struct_array_5_f64(s: Struct_array_5_f64, i: usize) void {
16919 expect(s.a[0] == 6) catch @panic("test failure");
16920 expect(s.a[1] == 7) catch @panic("test failure");
16921 expect(s.a[2] == 8) catch @panic("test failure");
16922 expect(s.a[3] == 9) catch @panic("test failure");
16923 expect(s.a[4] == 10) catch @panic("test failure");
16924 expect(i == 11) catch @panic("test failure");
16925}
16926
16927extern fn c_ret_struct_array_5_f64() Struct_array_5_f64;
16928extern fn c_struct_array_5_f64(Struct_array_5_f64, usize) void;
16929extern fn c_test_struct_array_5_f64() void;
16930
16931test "struct [5]f64" {
16932 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16933 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16934 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16935
16936 const s = c_ret_struct_array_5_f64();
16937 try expect(s.a[0] == 12);
16938 try expect(s.a[1] == 13);
16939 try expect(s.a[2] == 14);
16940 try expect(s.a[3] == 15);
16941 try expect(s.a[4] == 16);
16942 c_struct_array_5_f64(.{ .a = .{ 17, 18, 19, 20, 21 } }, 22);
16943 c_test_struct_array_5_f64();
16944}
16945
16946const Union_f64 = extern union {
16947 a: f64,
16948};
16949
16950export fn zig_ret_union_f64() Union_f64 {
16951 return .{ .a = 1 };
16952}
16953export fn zig_union_f64(s: Union_f64, i: usize) void {
16954 expect(s.a == 2) catch @panic("test failure");
16955 expect(i == 3) catch @panic("test failure");
16956}
16957
16958extern fn c_ret_union_f64() Union_f64;
16959extern fn c_union_f64(Union_f64, usize) void;
16960extern fn c_test_union_f64() void;
16961
16962test "union f64" {
16963 if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
16964 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
16965 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16966 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
16967 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16968 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
16969
16970 const s = c_ret_union_f64();
16971 try expect(s.a == 4);
16972 c_union_f64(.{ .a = 5 }, 6);
16973 c_test_union_f64();
16974}
16975
1622616976const Struct_u32_Union_u32_u32u32 = extern struct {
1622716977 a: u32,
1622816978 b: extern union {
......@@ -16250,8 +17000,7 @@ test "struct{u32,union{u32,struct{u32,u32}}}" {
1625017000 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1625117001 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1625217002 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16253 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16254 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17003 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1625517004
1625617005 const s = c_ret_struct_u32_union_u32_u32u32();
1625717006 try expect(s.a == 1);
......@@ -16269,11 +17018,10 @@ extern fn c_mut_struct_i32_i32(Struct_i32_i32) Struct_i32_i32;
1626917018extern fn c_struct_i32_i32(Struct_i32_i32) void;
1627017019
1627117020test "struct i32 i32" {
17021 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1627217022 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16273 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
17023 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1627417024 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
16275 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16276 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1627717025 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1627817026
1627917027 const s: Struct_i32_i32 = .{
......@@ -16303,11 +17051,10 @@ const BigStruct = extern struct {
1630317051extern fn c_big_struct(BigStruct) void;
1630417052
1630517053test "big struct" {
16306 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16307 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16308 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1630917054 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16310 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17055 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17056 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17057 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1631117058
1631217059 const s = BigStruct{
1631317060 .a = 1,
......@@ -16333,10 +17080,9 @@ const BigUnion = extern union {
1633317080extern fn c_big_union(BigUnion) void;
1633417081
1633517082test "big union" {
16336 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16337 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1633817083 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16339 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17084 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17085 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1634017086
1634117087 const x = BigUnion{
1634217088 .a = BigStruct{
......@@ -16368,11 +17114,10 @@ extern fn c_med_struct_mixed(MedStructMixed) void;
1636817114extern fn c_ret_med_struct_mixed() MedStructMixed;
1636917115
1637017116test "medium struct of ints and floats" {
16371 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16372 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16373 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1637417117 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16375 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17118 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17119 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17120 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1637617121
1637717122 const s = MedStructMixed{
1637817123 .a = 1234,
......@@ -16448,12 +17193,11 @@ const SplitStructInt = extern struct {
1644817193extern fn c_split_struct_ints(SplitStructInt) void;
1644917194
1645017195test "split struct of ints" {
16451 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
16452 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16453 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16454 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1645517196 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16456 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17197 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17198 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17199 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
17200 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1645717201
1645817202 const s = SplitStructInt{
1645917203 .a = 1234,
......@@ -16478,12 +17222,11 @@ extern fn c_split_struct_mixed(SplitStructMixed) void;
1647817222extern fn c_ret_split_struct_mixed() SplitStructMixed;
1647917223
1648017224test "split struct of ints and floats" {
16481 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
16482 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16483 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16484 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1648517225 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16486 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17226 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17227 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17228 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
17229 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1648717230
1648817231 const s = SplitStructMixed{
1648917232 .a = 1234,
......@@ -16506,11 +17249,10 @@ export fn zig_split_struct_mixed(x: SplitStructMixed) void {
1650617249extern fn c_big_struct_both(BigStruct) BigStruct;
1650717250
1650817251test "sret and byval together" {
16509 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16510 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16511 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1651217252 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16513 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17253 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17254 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17255 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1651417256
1651517257 const s = BigStruct{
1651617258 .a = 1,
......@@ -16620,12 +17362,11 @@ extern fn c_struct_with_array(StructWithArray) void;
1662017362extern fn c_ret_struct_with_array() StructWithArray;
1662117363
1662217364test "Struct with array as padding." {
16623 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
16624 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16625 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16626 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1662717365 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16628 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17366 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17367 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17368 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
17369 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1662917370
1663017371 c_struct_with_array(.{ .a = 1, .padding = undefined, .b = 2 });
1663117372
......@@ -16649,11 +17390,10 @@ extern fn c_float_array_struct(FloatArrayStruct) void;
1664917390extern fn c_ret_float_array_struct() FloatArrayStruct;
1665017391
1665117392test "Float array like struct" {
16652 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16653 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16654 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1665517393 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16656 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17394 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17395 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17396 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1665717397
1665817398 c_float_array_struct(.{
1665917399 .origin = .{
......@@ -16684,37 +17424,37 @@ pub inline fn expectOk(c_err: c_int) !void {
1668417424/// Tests for Double + Char struct
1668517425const DC = extern struct { v1: f64, v2: u8 };
1668617426test "DC: Zig passes to C" {
17427 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
17428 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1668717429 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17430 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1668817431 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16689 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16690 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16691 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16692 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17432
1669317433 try expectOk(c_assert_DC(.{ .v1 = -0.25, .v2 = 15 }));
1669417434}
1669517435test "DC: Zig returns to C" {
17436 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1669617437 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17438 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1669717439 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16698 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16699 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16700 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17440
1670117441 try expectOk(c_assert_ret_DC());
1670217442}
1670317443test "DC: C passes to Zig" {
17444 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
17445 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1670417446 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17447 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1670517448 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16706 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16707 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16708 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16709 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17449
1671017450 try expectOk(c_send_DC());
1671117451}
1671217452test "DC: C returns to Zig" {
17453 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1671317454 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17455 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1671417456 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16715 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16716 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16717 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17457
1671817458 try expectEqual(DC{ .v1 = -0.25, .v2 = 15 }, c_ret_DC());
1671917459}
1672017460
......@@ -16739,36 +17479,35 @@ const CFF = extern struct { v1: u8, v2: f32, v3: f32 };
1673917479test "CFF: Zig passes to C" {
1674017480 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
1674117481 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16742 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
17482 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1674317483 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1674417484 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16745 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17485
1674617486 try expectOk(c_assert_CFF(.{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 }));
1674717487}
1674817488test "CFF: Zig returns to C" {
1674917489 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16750 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
17490 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1675117491 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16752 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17492
1675317493 try expectOk(c_assert_ret_CFF());
1675417494}
1675517495test "CFF: C passes to Zig" {
16756 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
16757 if (builtin.cpu.arch.isRISCV() and builtin.mode != .Debug) return error.SkipZigTest;
16758 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16759 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16760 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1676117496 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16762 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17497 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17498 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17499 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
17500 if (builtin.cpu.arch.isRISCV() and builtin.mode != .debug) return error.SkipZigTest;
17501 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
1676317502
1676417503 try expectOk(c_send_CFF());
1676517504}
1676617505test "CFF: C returns to Zig" {
16767 if (builtin.cpu.arch.isRISCV() and builtin.mode != .Debug) return error.SkipZigTest;
16768 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16769 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1677017506 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16771 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17507 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17508 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
17509 if (builtin.cpu.arch.isRISCV() and builtin.mode != .debug) return error.SkipZigTest;
17510
1677217511 try expectEqual(CFF{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 }, c_ret_CFF());
1677317512}
1677417513pub extern fn c_assert_CFF(lv: CFF) c_int;
......@@ -16791,35 +17530,35 @@ pub export fn zig_ret_CFF() CFF {
1679117530const PD = extern struct { v1: ?*anyopaque, v2: f64 };
1679217531
1679317532test "PD: Zig passes to C" {
16794 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16795 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16796 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1679717533 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16798 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17534 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17535 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17536 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1679917537 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
17538
1680017539 try expectOk(c_assert_PD(.{ .v1 = null, .v2 = 0.5 }));
1680117540}
1680217541test "PD: Zig returns to C" {
16803 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16804 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1680517542 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16806 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17543 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17544 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
17545
1680717546 try expectOk(c_assert_ret_PD());
1680817547}
1680917548test "PD: C passes to Zig" {
16810 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16811 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16812 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1681317549 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16814 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17550 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17551 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17552 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1681517553 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
17554
1681617555 try expectOk(c_send_PD());
1681717556}
1681817557test "PD: C returns to Zig" {
16819 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16820 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1682117558 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16822 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17559 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17560 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
17561
1682317562 try expectEqual(PD{ .v1 = null, .v2 = 0.5 }, c_ret_PD());
1682417563}
1682517564pub extern fn c_assert_PD(lv: PD) c_int;
......@@ -16853,7 +17592,6 @@ extern fn c_modify_by_ref_param(ByRef) ByRef;
1685317592test "C function modifies by ref param" {
1685417593 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1685517594 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16856 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1685717595
1685817596 const res = c_modify_by_ref_param(.{ .val = 1, .arr = undefined });
1685917597 try expect(res.val == 42);
......@@ -16874,11 +17612,10 @@ const ByVal = extern struct {
1687417612
1687517613extern fn c_func_ptr_byval(*anyopaque, *anyopaque, ByVal, c_ulong, *anyopaque, c_ulong) void;
1687617614test "C function that takes byval struct called via function pointer" {
17615 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
17616 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1687717617 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1687817618 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16879 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16880 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16881 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1688217619
1688317620 var fn_ptr = &c_func_ptr_byval;
1688417621 _ = &fn_ptr;
......@@ -16897,17 +17634,16 @@ test "C function that takes byval struct called via function pointer" {
1689717634
1689817635extern fn c_f16(f16) f16;
1689917636test "f16 bare" {
16900 if (builtin.cpu.arch == .x86_64) return error.SkipZigTest;
16901 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
17637 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
1690217638 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1690317639 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1690417640 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
17641 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1690517642 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
1690617643 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1690717644 if (builtin.cpu.arch.isWasm()) return error.SkipZigTest;
16908 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16909
16910 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
17645 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
17646 if (builtin.cpu.arch == .x86_64) return error.SkipZigTest;
1691117647
1691217648 const a = c_f16(12);
1691317649 try expect(a == 34);
......@@ -16918,9 +17654,9 @@ const f16_struct = extern struct {
1691817654};
1691917655extern fn c_f16_struct(f16_struct) f16_struct;
1692017656test "f16 struct" {
17657 if (builtin.cpu.arch.isArm() and builtin.mode != .debug) return error.SkipZigTest;
1692117658 if (builtin.target.cpu.arch.isMIPS64()) return error.SkipZigTest;
1692217659 if (builtin.target.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16923 if (builtin.cpu.arch.isArm() and builtin.mode != .Debug) return error.SkipZigTest;
1692417660 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1692517661 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1692617662
......@@ -17027,11 +17763,10 @@ const Coord2 = extern struct {
1702717763
1702817764extern fn stdcall_coord2(Coord2, Coord2, Coord2) callconv(stdcall_callconv) Coord2;
1702917765test "Stdcall ABI structs" {
17766 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
17767 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1703017768 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1703117769 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
17032 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17033 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
17034 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1703517770 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1703617771
1703717772 const res = stdcall_coord2(
......@@ -17045,10 +17780,9 @@ test "Stdcall ABI structs" {
1704517780
1704617781extern fn stdcall_big_union(BigUnion) callconv(stdcall_callconv) void;
1704717782test "Stdcall ABI big union" {
17048 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
17049 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1705017783 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
17051 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17784 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17785 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1705217786
1705317787 const x = BigUnion{
1705417788 .a = BigStruct{
......@@ -17120,11 +17854,10 @@ const byval_tail_callsite_attr = struct {
1712017854};
1712117855
1712217856test "byval tail callsite attribute" {
17123 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17124 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
17125 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1712617857 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
17127 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17858 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17859 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17860 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1712817861
1712917862 // Originally reported at https://github.com/ziglang/zig/issues/16290
1713017863 // the bug was that the extern function had the byval attribute, but
......@@ -17268,11 +18001,19 @@ test "x86 vectorcall calling convention" {
1726818001 static.c_vectorcall_check(1, 2.0, 3.0, @ptrFromInt(4), 5.0, 6.0, 7.0, 8.0, 9.0, 10);
1726918002}
1727018003
18004extern fn c_x86_64_sysv_uint_int_uint_int(a: u8, b: i8, c: u16, d: i16) void;
18005
18006test "x86_64 sysv args" {
18007 if (std.lang.CallingConvention.c != .x86_64_sysv) return error.SkipZigTest;
18008
18009 c_x86_64_sysv_uint_int_uint_int(1, -2, 3, -4);
18010}
18011
1727118012extern fn c_win64_varargs_u64_f64_u64_f64(...) void;
1727218013extern fn c_win64_varargs_f64_u64_f64_u64(...) void;
1727318014
1727418015test "win64 varargs" {
17275 if (builtin.cpu.arch != .x86_64 or builtin.os.tag != .windows) return error.SkipZigTest;
18016 if (std.lang.CallingConvention.c != .x86_64_win) return error.SkipZigTest;
1727618017
1727718018 const Opv = extern struct {};
1727818019 c_win64_varargs_u64_f64_u64_f64(
......@@ -17298,3 +18039,25 @@ test "win64 varargs" {
1729818039 @as(Opv, .{}),
1729918040 );
1730018041}
18042
18043const preserve_none_cc: ?std.lang.CallingConvention = if (builtin.zig_backend != .stage2_llvm)
18044 null
18045else switch (builtin.cpu.arch) {
18046 .x86_64 => .{ .x86_64_preserve_none = .{} },
18047 .aarch64, .aarch64_be => .{ .aarch64_preserve_none = .{} },
18048 else => null,
18049};
18050
18051export fn zig_preserve_none(x: i32) callconv(preserve_none_cc orelse .c) i32 {
18052 return x + 1;
18053}
18054
18055test "preserve_none calling convention" {
18056 if (preserve_none_cc == null) return error.SkipZigTest;
18057 const static = struct {
18058 extern fn c_preserve_none(x: i32) callconv(preserve_none_cc.?) i32;
18059 extern fn c_preserve_none_check() void;
18060 };
18061 try expect(static.c_preserve_none(41) == 42);
18062 static.c_preserve_none_check();
18063}
test/cases/compile_errors/bad_panic_call_signature.zig+1
......@@ -15,6 +15,7 @@ pub const panic = struct {
1515 pub const castToNull = simple_panic.castToNull;
1616 pub const incorrectAlignment = simple_panic.incorrectAlignment;
1717 pub const invalidErrorCode = simple_panic.invalidErrorCode;
18 pub const unexpectedErrorCode = simple_panic.unexpectedErrorCode;
1819 pub const integerOutOfBounds = simple_panic.integerOutOfBounds;
1920 pub const integerOverflow = simple_panic.integerOverflow;
2021 pub const shlOverflow = simple_panic.shlOverflow;
test/cases/compile_errors/bad_panic_generic_signature.zig+1
......@@ -11,6 +11,7 @@ pub const panic = struct {
1111 pub const castToNull = simple_panic.castToNull;
1212 pub const incorrectAlignment = simple_panic.incorrectAlignment;
1313 pub const invalidErrorCode = simple_panic.invalidErrorCode;
14 pub const unexpectedErrorCode = simple_panic.unexpectedErrorCode;
1415 pub const integerOutOfBounds = simple_panic.integerOutOfBounds;
1516 pub const integerOverflow = simple_panic.integerOverflow;
1617 pub const shlOverflow = simple_panic.shlOverflow;
test/cases/compile_errors/callconv_preserve_none_on_unsupported_platform.zig created+16
......@@ -0,0 +1,16 @@
1const F1 = fn () callconv(.{ .x86_64_preserve_none = .{} }) void;
2const F2 = fn () callconv(.{ .aarch64_preserve_none = .{} }) void;
3export fn entry1() void {
4 const a: F1 = undefined;
5 _ = a;
6}
7export fn entry2() void {
8 const a: F2 = undefined;
9 _ = a;
10}
11
12// error
13// target=riscv64-linux-none
14//
15// :1:28: error: calling convention 'x86_64_preserve_none' only available on architectures 'x86_64'
16// :2:28: error: calling convention 'aarch64_preserve_none' only available on architectures 'aarch64', 'aarch64_be'
test/cases/compile_errors/capture_by_ref_discard.zig+5
......@@ -16,9 +16,14 @@ export fn d() void {
1616 while (null) |*_| {}
1717}
1818
19export fn e() void {
20 if (0) |*_| {} else |err| switch (err) {}
21}
22
1923// error
2024//
2125// :2:16: error: pointer modifier invalid on discard
2226// :7:18: error: pointer modifier invalid on discard
2327// :12:16: error: pointer modifier invalid on discard
2428// :16:19: error: pointer modifier invalid on discard
29// :20:13: error: pointer modifier invalid on discard
test/cases/compile_errors/coerce_pointers_with_uncoercable_child_pointers.zig+14
......@@ -28,6 +28,16 @@ export fn entry5() void {
2828 _ = q;
2929}
3030
31export fn entry6(p: **[3]u8) void {
32 const q: *[]u8 = p;
33 _ = q;
34}
35
36export fn entry7(p: *[]u8) void {
37 const q: **[3]u8 = p;
38 _ = q;
39}
40
3141// error
3242//
3343// :3:22: error: expected type '**i32', found '**u32'
......@@ -50,3 +60,7 @@ export fn entry5() void {
5060// :27:24: note: pointer type child '*[1:42]u8' cannot cast into pointer type child '*[1]u8'
5161// :27:24: note: pointer type child '[1:42]u8' cannot cast into pointer type child '[1]u8'
5262// :27:24: note: source array cannot be guaranteed to maintain '42' sentinel
63// :32:22: error: expected type '*[]u8', found '**[3]u8'
64// :32:22: note: pointer type child '*[3]u8' cannot cast into pointer type child '[]u8'
65// :37:24: error: expected type '**[3]u8', found '*[]u8'
66// :37:24: note: pointer type child '[]u8' cannot cast into pointer type child '*[3]u8'
test/cases/compile_errors/coercion_from_vector_element_to_c_ptr.zig created+11
......@@ -0,0 +1,11 @@
1export fn foo() void {
2 var size: @Vector(4, c_int) = undefined;
3 bar(&size[0]);
4}
5extern fn bar([*c]c_int) void;
6
7// error
8//
9// 3:9: error: expected type '[*c]c_int', found '*align(4:0:4:0) c_int'
10// 3:9: note: pointer host size '4' cannot cast into pointer host size '0'
11// 5:15: note: parameter type declared here
test/cases/compile_errors/deref_slice_and_get_len_field.zig+1-1
......@@ -6,4 +6,4 @@ export fn entry() void {
66
77// error
88//
9// :3:10: error: index syntax required for slice type '[]u8'
9// :3:10: error: index syntax required to access runtime-known slice
test/cases/compile_errors/deref_slice_with_undef_len.zig created+23
......@@ -0,0 +1,23 @@
1export fn entry2() void {
2 comptime var slice: []const u16 = &.{ 1, 2, 3 };
3 slice.len = undefined;
4 _ = slice.*;
5}
6
7export fn entry3() void {
8 comptime var slice: []const u16 = &.{ 1, 2, 3 };
9 slice.len = undefined;
10 _ = &slice.*;
11}
12
13export fn entry4() void {
14 comptime var slice: []const u8 = "hello";
15 slice.len = undefined;
16 @compileError(slice);
17}
18
19// error
20//
21// :4:14: error: cannot dereference slice with undefined length
22// :10:15: error: cannot dereference slice with undefined length
23// :16:19: error: use of slice with undefined length here causes illegal behavior
test/cases/compile_errors/dereference_slice.zig+1-1
......@@ -7,4 +7,4 @@ comptime {
77
88// error
99//
10// :2:13: error: index syntax required for slice type '[]i32'
10// :2:13: error: index syntax required to access runtime-known slice
test/cases/compile_errors/duplicate_boolean_switch_value.zig+2-2
......@@ -17,7 +17,7 @@ comptime {
1717
1818// error
1919//
20// :5:9: error: duplicate switch value
20// :5:9: error: duplicate switch value 'true'
2121// :3:9: note: previous value here
22// :13:9: error: duplicate switch value
22// :13:9: error: duplicate switch value 'false'
2323// :11:9: note: previous value here
test/cases/compile_errors/duplicate_error_in_switch.zig+1-1
......@@ -16,5 +16,5 @@ fn foo(x: i32) !void {
1616
1717// error
1818//
19// :5:9: error: duplicate switch value
19// :5:9: error: duplicate switch value 'error.Foo'
2020// :3:9: note: previous value here
test/cases/compile_errors/ignored_deferred_function_call.zig+2-2
......@@ -14,6 +14,6 @@ fn bar2() anyerror {
1414
1515// error
1616//
17// :2:14: error: error union is ignored
17// :2:14: error: error union of type 'anyerror!i32' is ignored
1818// :2:14: note: consider using 'try', 'catch', or 'if'
19// :9:15: error: error set is ignored
19// :9:15: error: error set of type 'anyerror' is ignored
test/cases/compile_errors/ignored_expression_in_while_continuation.zig+4-4
......@@ -24,10 +24,10 @@ fn bad2() anyerror {
2424
2525// error
2626//
27// :2:24: error: error union is ignored
27// :2:24: error: error union of type 'anyerror!void' is ignored
2828// :2:24: note: consider using 'try', 'catch', or 'if'
29// :7:25: error: error union is ignored
29// :7:25: error: error union of type 'anyerror!void' is ignored
3030// :7:25: note: consider using 'try', 'catch', or 'if'
31// :12:25: error: error union is ignored
31// :12:25: error: error union of type 'anyerror!void' is ignored
3232// :12:25: note: consider using 'try', 'catch', or 'if'
33// :19:25: error: error set is ignored
33// :19:25: error: error set of type 'anyerror' is ignored
test/cases/compile_errors/initialize_empty_union.zig-31
......@@ -28,25 +28,6 @@ export fn init5() void {
2828 _ = @as(U5, undefined);
2929}
3030
31export fn deref0(ptr: *const U0) void {
32 _ = ptr.*;
33}
34export fn deref1(ptr: *const U1) void {
35 _ = ptr.*;
36}
37export fn deref2(ptr: *const U2) void {
38 _ = ptr.*;
39}
40export fn deref3(ptr: *const U3) void {
41 _ = ptr.*;
42}
43export fn deref4(ptr: *const U4) void {
44 _ = ptr.*;
45}
46export fn deref5(ptr: *const U5) void {
47 _ = ptr.*;
48}
49
5031// error
5132//
5233// :13:17: error: expected type 'tmp.U0', found '@TypeOf(undefined)'
......@@ -67,15 +48,3 @@ export fn deref5(ptr: *const U5) void {
6748// :28:17: error: expected type 'tmp.U5', found '@TypeOf(undefined)'
6849// :28:17: note: cannot coerce to uninstantiable type 'tmp.U5'
6950// :10:12: note: union declared here
70// :32:12: error: cannot load uninstantiable type 'tmp.U0'
71// :5:12: note: union declared here
72// :35:12: error: cannot load uninstantiable type 'tmp.U1'
73// :6:12: note: union declared here
74// :38:12: error: cannot load uninstantiable type 'tmp.U2'
75// :7:12: note: union declared here
76// :41:12: error: cannot load uninstantiable type 'tmp.U3'
77// :8:12: note: union declared here
78// :44:12: error: cannot load uninstantiable type 'tmp.U4'
79// :9:12: note: union declared here
80// :47:12: error: cannot load uninstantiable type 'tmp.U5'
81// :10:12: note: union declared here
test/cases/compile_errors/invalid_float_casts.zig+1-1
......@@ -22,6 +22,6 @@ export fn qux() void {
2222// error
2323//
2424// :4:40: error: unable to cast runtime value to 'comptime_float'
25// :9:18: error: expected integer type, found 'f32'
25// :9:18: error: expected integer result type, found 'f32'
2626// :14:32: error: expected integer type, found 'f32'
2727// :19:29: error: expected float or vector type, found 'u32'
test/cases/compile_errors/invalid_int_casts.zig+7-3
......@@ -8,6 +8,9 @@ export fn bar() void {
88 _ = &a;
99 _ = @as(u32, @floatFromInt(a));
1010}
11export fn bar2() void {
12 _ = @as(comptime_int, @floatFromInt(2));
13}
1114export fn baz() void {
1215 var a: u32 = 2;
1316 _ = &a;
......@@ -22,6 +25,7 @@ export fn qux() void {
2225// error
2326//
2427// :4:36: error: unable to cast runtime value to 'comptime_int'
25// :9:18: error: expected float type, found 'u32'
26// :14:32: error: expected float type, found 'u32'
27// :19:27: error: expected integer or vector, found 'f32'
28// :9:18: error: expected float result type, found 'u32'
29// :12:27: error: expected float result type, found 'comptime_int'
30// :17:32: error: expected float type, found 'u32'
31// :22:27: error: expected integer or vector, found 'f32'
test/cases/compile_errors/invalid_member_of_builtin_enum.zig+1-1
......@@ -6,5 +6,5 @@ export fn entry() void {
66
77// error
88//
9// :3:35: error: enum 'lang.OptimizeMode' has no member named 'x86'
9// :3:35: error: enum 'lang.Optimize' has no member named 'x86'
1010// : note: enum declared here
test/cases/compile_errors/slice_to_array_pointer.zig created+70
......@@ -0,0 +1,70 @@
1export fn entry1() void {
2 var array: [2]u16 = .{ 1, 2 };
3 const slice: []const u16 = &array;
4 foo(slice);
5}
6
7export fn entry2() void {
8 const slice: []const u16 = undefined;
9 foo(slice);
10}
11
12export fn entry3() void {
13 comptime var slice: []const u16 = &.{ 1, 2 };
14 slice.len = undefined;
15 foo(slice);
16}
17
18export fn entry4() void {
19 const slice: []const u16 = &.{ 1, 2, 3 };
20 foo(slice);
21}
22
23export fn entry5() void {
24 const slice: []const u8 = &.{ 1, 2 };
25 foo(slice);
26}
27
28fn foo(x: *const [2]u16) void {
29 _ = x;
30}
31
32export fn entry6() void {
33 const slice: [:0]const u16 = &.{ 1, 2, 3 };
34 bar(slice);
35}
36
37export fn entry7() void {
38 const slice: [:1]const u16 = &.{ 1, 2 };
39 bar(slice);
40}
41
42export fn entry8() void {
43 const slice: []const u16 = &.{ 1, 2 };
44 bar(slice);
45}
46
47fn bar(x: *const [2:0]u16) void {
48 _ = x;
49}
50
51// error
52//
53// :4:9: error: coercion from slice to array pointer type '*const [2]u16' requires length to be known at compile-time
54// :9:9: error: slice with undefined length cannot cast into array pointer type '*const [2]u16'
55// :9:9: note: length of slice must be defined and match length of array type
56// :15:9: error: slice with undefined length cannot cast into array pointer type '*const [2]u16'
57// :15:9: note: length of slice must be defined and match length of array type
58// :20:9: error: slice of length 3 cannot cast into array pointer type '*const [2]u16'
59// :20:9: note: length of slice must match length of array type
60// :25:9: error: expected type '*const [2]u16', found '[]const u8'
61// :25:9: note: pointer type child 'u8' cannot cast into pointer type child 'u16'
62// :28:11: note: parameter type declared here
63// :34:9: error: slice of length 3 cannot cast into array pointer type '*const [2:0]u16'
64// :34:9: note: length of slice must match length of array type
65// :39:9: error: expected type '*const [2:0]u16', found '[:1]const u16'
66// :39:9: note: pointer sentinel '1' cannot cast into pointer sentinel '0'
67// :47:11: note: parameter type declared here
68// :44:9: error: expected type '*const [2:0]u16', found '[]const u16'
69// :44:9: note: destination pointer requires '0' sentinel
70// :47:11: note: parameter type declared here
test/cases/compile_errors/switch_expression-duplicate_enumeration_prong.zig+2-1
......@@ -20,5 +20,6 @@ export fn entry() usize {
2020
2121// error
2222//
23// :13:15: error: duplicate switch value
23// :13:15: error: duplicate switch value '.Two'
2424// :10:15: note: previous value here
25// :1:16: note: enum declared here
test/cases/compile_errors/switch_expression-duplicate_enumeration_prong_when_else_present.zig+2-1
......@@ -21,5 +21,6 @@ export fn entry() usize {
2121
2222// error
2323//
24// :13:15: error: duplicate switch value
24// :13:15: error: duplicate switch value '.Two'
2525// :10:15: note: previous value here
26// :1:16: note: enum declared here
test/cases/compile_errors/switch_expression-duplicate_error_prong.zig+2-2
......@@ -25,7 +25,7 @@ export fn entry() usize {
2525
2626// error
2727//
28// :8:9: error: duplicate switch value
28// :8:9: error: duplicate switch value 'error.Foo'
2929// :5:9: note: previous value here
30// :16:9: error: duplicate switch value
30// :16:9: error: duplicate switch value 'error.Foo'
3131// :13:9: note: previous value here
test/cases/compile_errors/switch_expression-duplicate_error_prong_when_else_present.zig+2-2
......@@ -27,7 +27,7 @@ export fn entry() usize {
2727
2828// error
2929//
30// :8:9: error: duplicate switch value
30// :8:9: error: duplicate switch value 'error.Foo'
3131// :5:9: note: previous value here
32// :17:9: error: duplicate switch value
32// :17:9: error: duplicate switch value 'error.Foo'
3333// :14:9: note: previous value here
test/cases/compile_errors/switch_expression-duplicate_or_overlapping_integer_value.zig deleted-16
......@@ -1,16 +0,0 @@
1fn foo(x: u8) u8 {
2 return switch (x) {
3 0...100 => @as(u8, 0),
4 101...200 => 1,
5 201, 203...207 => 2,
6 206...255 => 3,
7 };
8}
9export fn entry() usize {
10 return @sizeOf(@TypeOf(&foo));
11}
12
13// error
14//
15// :6:12: error: duplicate switch value
16// :5:17: note: previous value here
test/cases/compile_errors/switch_expression-duplicate_type.zig+1-1
......@@ -13,5 +13,5 @@ export fn entry() usize {
1313
1414// error
1515//
16// :6:9: error: duplicate switch value
16// :6:9: error: duplicate switch value 'u32'
1717// :4:9: note: previous value here
test/cases/compile_errors/switch_expression-duplicate_type_struct_alias.zig+2-1
......@@ -17,5 +17,6 @@ export fn entry() usize {
1717
1818// error
1919//
20// :10:9: error: duplicate switch value
20// :10:9: error: duplicate switch value 'tmp.Test'
2121// :8:9: note: previous value here
22// :1:14: note: struct declared here
test/cases/compile_errors/switch_on_invalid_type.zig created+103
......@@ -0,0 +1,103 @@
1const AutoUnion = union { a: u8 };
2export fn entry1() void {
3 switch (@as(AutoUnion, .{ .a = 123 })) {
4 else => {},
5 }
6}
7
8const ExternUnion = union { a: u8 };
9export fn entry2() void {
10 switch (@as(ExternUnion, .{ .a = 123 })) {
11 else => {},
12 }
13}
14
15const AutoStruct = struct { a: u8 };
16export fn entry3() void {
17 switch (@as(AutoStruct, .{ .a = 123 })) {
18 else => {},
19 }
20}
21
22const ExternStruct = extern struct { a: u8 };
23export fn entry4() void {
24 switch (@as(ExternStruct, .{ .a = 123 })) {
25 else => {},
26 }
27}
28
29export fn entry5() void {
30 switch (@as([]const u16, &.{ 1, 2, 3 })) {
31 else => {},
32 }
33}
34
35export fn entry6() void {
36 switch (@as([3]u16, .{ 1, 2, 3 })) {
37 else => {},
38 }
39}
40
41export fn entry7() void {
42 switch (@as(@Vector(3, u16), .{ 1, 2, 3 })) {
43 else => {},
44 }
45}
46
47export fn entry8() void {
48 switch (@as(?u16, 123)) {
49 else => {},
50 }
51}
52
53export fn entry9() void {
54 switch (@as(anyerror!u16, 123)) {
55 else => {},
56 }
57}
58
59export fn entry10() void {
60 switch (@as(f32, 123)) {
61 else => {},
62 }
63}
64
65export fn entry11() void {
66 switch (@as(comptime_float, 123)) {
67 else => {},
68 }
69}
70
71export fn entry12() void {
72 switch (undefined) {
73 else => {},
74 }
75}
76
77export fn entry13() void {
78 switch (null) {
79 else => {},
80 }
81}
82
83// error
84//
85// :3:13: error: switch on union with no attached enum
86// :1:19: note: consider 'union(enum)' here
87// :10:13: error: switch on union with no attached enum
88// :8:21: note: consider 'union(enum)' here
89// :17:13: error: switch on non-packed struct
90// :15:20: note: struct declared here
91// :24:13: error: switch on non-packed struct
92// :22:29: note: struct declared here
93// :30:13: error: switch on type '[]const u16'
94// :36:13: error: switch on type '[3]u16'
95// :42:13: error: switch on type '@Vector(3, u16)'
96// :48:13: error: switch on optional type '?u16'
97// :48:13: note: consider using '.?', 'orelse', or 'if'
98// :54:13: error: switch on error union type 'anyerror!u16'
99// :54:13: note: consider using 'try', 'catch', or 'if'
100// :60:13: error: switch on type 'f32'
101// :66:13: error: switch on type 'comptime_float'
102// :72:13: error: switch on type '@TypeOf(undefined)'
103// :78:13: error: switch on type '@TypeOf(null)'
test/cases/compile_errors/switch_on_non_packed_struct.zig deleted-25
......@@ -1,25 +0,0 @@
1const Auto = struct {
2 a: u8,
3};
4export fn entry1(a: u8) void {
5 const s: Auto = .{ .a = a };
6 switch (s) {
7 else => {},
8 }
9}
10
11const Extern = extern struct {
12 a: u8,
13};
14export fn entry2(s: Extern) void {
15 switch (s) {
16 else => {},
17 }
18}
19
20// error
21//
22// :6:13: error: switch on struct with auto layout
23// :1:14: note: consider 'packed struct' here
24// :15:13: error: switch on struct with extern layout
25// :11:23: note: consider 'packed struct' here
test/cases/compile_errors/switch_on_union_with_nonexhaustive_tag_is_exhaustive.zig created+56
......@@ -0,0 +1,56 @@
1const E = enum(u8) {
2 a,
3 b,
4 _,
5};
6const U = union(E) {
7 a,
8 b,
9};
10fn foo() U {
11 return undefined;
12}
13
14export fn entry1() void {
15 const u = foo();
16 switch (u) {
17 .a => {},
18 }
19}
20export fn entry2() void {
21 const u = foo();
22 switch (u) {
23 .a => {},
24 .b => {},
25 else => {},
26 }
27}
28export fn entry3() void {
29 const u = foo();
30 switch (u) {
31 .a => {},
32 .b => {},
33 _ => {},
34 }
35}
36export fn entry4() void {
37 const u = foo();
38 switch (u) {
39 .a => {},
40 else => {},
41 _ => {},
42 }
43}
44
45// error
46//
47// :16:5: error: switch must handle all possibilities
48// :3:5: note: unhandled enumeration value: 'b'
49// :1:11: note: enum 'tmp.E' declared here
50// :25:14: error: unreachable else prong; all cases already handled
51// :30:5: error: '_' prong only allowed when switching on non-exhaustive enums
52// :33:9: note: '_' prong here
53// :30:5: note: consider using 'else'
54// :38:5: error: '_' prong only allowed when switching on non-exhaustive enums
55// :41:9: note: '_' prong here
56// :38:5: note: consider using 'else'
test/cases/compile_errors/switch_with_overlapping_case_ranges.zig+36-6
......@@ -28,13 +28,43 @@ export fn entry4(x: u8) void {
2828 }
2929}
3030
31export fn entry5(x: u8) void {
32 switch (x) {
33 0...255 => {},
34 4...120 => {},
35 }
36}
37
38export fn entry6(x: u8) void {
39 switch (x) {
40 0...130 => {},
41 120...255 => {},
42 }
43}
44
45export fn entry7(x: u8) void {
46 switch (x) {
47 2 => {},
48 0...255 => {},
49 }
50}
51
3152// error
3253//
33// :4:10: error: duplicate switch value
34// :3:10: note: previous value here
35// :11:10: error: duplicate switch value
36// :10:13: note: previous value here
37// :17:10: error: duplicate switch value
54// :4:10: error: duplicate switch ranges
55// :3:10: note: overlaps with previous range here
56// :3:10: note: ranges overlap from '1' to '2'
57// :11:10: error: duplicate switch value '5'
58// :10:13: note: previous value inside range here
59// :17:10: error: duplicate switch value '5'
3860// :18:9: note: previous value here
39// :27:10: error: duplicate switch value
61// :27:10: error: duplicate switch value '6'
4062// :26:9: note: previous value here
63// :34:10: error: duplicate switch ranges
64// :33:10: note: overlaps with previous range here
65// :33:10: note: ranges overlap from '4' to '120'
66// :41:12: error: duplicate switch ranges
67// :40:10: note: overlaps with previous range here
68// :40:10: note: ranges overlap from '120' to '130'
69// :48:10: error: duplicate switch value '2'
70// :47:9: note: previous value here
test/cases/safety/@errorCast error not present in destination.zig +1-1
......@@ -2,7 +2,7 @@ const std = @import("std");
22
33pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
44 _ = stack_trace;
5 if (std.mem.eql(u8, message, "invalid error code")) {
5 if (std.mem.eql(u8, message, "unexpected error code, found error.B")) {
66 std.process.exit(0);
77 }
88 std.process.exit(1);
test/cases/safety/@errorCast error union casted to disjoint set.zig +1-1
......@@ -2,7 +2,7 @@ const std = @import("std");
22
33pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
44 _ = stack_trace;
5 if (std.mem.eql(u8, message, "invalid error code")) {
5 if (std.mem.eql(u8, message, "unexpected error code, found error.Bar")) {
66 std.process.exit(0);
77 }
88 std.process.exit(1);
test/cases/safety/load_uninstantiable_enum.zig created+20
......@@ -0,0 +1,20 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "attempt to load uninstantiable type")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10
11const E = enum {};
12pub fn main() error{TestFailed}!void {
13 const bytes: [32]u8 = @splat(0);
14 const ptr: *const E = @ptrCast(&bytes);
15 _ = ptr.*;
16 return error.TestFailed;
17}
18// run
19// backend=selfhosted,llvm
20// target=x86_64-linux,aarch64-linux,wasm32-wasi
test/cases/safety/load_uninstantiable_enum_from_slice.zig created+21
......@@ -0,0 +1,21 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "attempt to load uninstantiable type")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10
11const E = enum {};
12pub fn main() error{TestFailed}!void {
13 const bytes: [32]u8 = @splat(0);
14 const ptr: *const [1]E = @ptrCast(&bytes);
15 const slice: []const E = ptr;
16 _ = slice[0];
17 return error.TestFailed;
18}
19// run
20// backend=selfhosted,llvm
21// target=x86_64-linux,aarch64-linux,wasm32-wasi
test/cases/safety/load_uninstantiable_union.zig created+23
......@@ -0,0 +1,23 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "attempt to load uninstantiable type")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10
11const U = union {
12 foo: struct { a: u8, b: noreturn, },
13 bar: enum {},
14};
15pub fn main() error{TestFailed}!void {
16 const bytes: [32]u8 = @splat(0);
17 const ptr: *const U = @ptrCast(&bytes);
18 _ = ptr.*;
19 return error.TestFailed;
20}
21// run
22// backend=selfhosted,llvm
23// target=x86_64-linux,aarch64-linux,wasm32-wasi
test/cases/safety/load_uninstantiable_union_from_slice.zig created+24
......@@ -0,0 +1,24 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "attempt to load uninstantiable type")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10
11const U = union {
12 foo: struct { a: u8, b: noreturn, },
13 bar: enum {},
14};
15pub fn main() error{TestFailed}!void {
16 const bytes: [32]u8 = @splat(0);
17 const ptr: *const [1]U = @ptrCast(&bytes);
18 const slice: []const U = ptr;
19 _ = slice[0];
20 return error.TestFailed;
21}
22// run
23// backend=selfhosted,llvm
24// target=x86_64-linux,aarch64-linux,wasm32-wasi
test/error_traces.zig+41-2
......@@ -1,7 +1,10 @@
11const std = @import("std");
2const Context = @import("tests.zig").ErrorTracesContext;
23
3pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.Os.Tag) void {
4pub fn addCases(cases: *Context, params: *const Context.CaseParameters, target: *const std.Target) void {
45 cases.addCase(.{
6 .params = params,
7 .target = target,
58 .name = "return",
69 .source =
710 \\pub fn main() !void {
......@@ -17,6 +20,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
1720 });
1821
1922 cases.addCase(.{
23 .params = params,
24 .target = target,
2025 .name = "try return",
2126 .source =
2227 \\fn foo() !void {
......@@ -44,6 +49,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
4449 },
4550 });
4651 cases.addCase(.{
52 .params = params,
53 .target = target,
4754 .name = "non-error return pops error trace",
4855 .source =
4956 \\fn bar() !void {
......@@ -70,6 +77,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
7077 });
7178
7279 cases.addCase(.{
80 .params = params,
81 .target = target,
7382 .name = "continue in while loop",
7483 .source =
7584 \\fn foo() !void {
......@@ -93,6 +102,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
93102 });
94103
95104 cases.addCase(.{
105 .params = params,
106 .target = target,
96107 .name = "for loop pops error return trace",
97108 .source =
98109 \\fn foo() !void { return error.FooError; }
......@@ -123,6 +134,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
123134 });
124135
125136 cases.addCase(.{
137 .params = params,
138 .target = target,
126139 .name = "implicit continue in for loop pops stale error return trace",
127140 .source =
128141 \\fn foo() !void { return error.FooError; }
......@@ -154,6 +167,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
154167 });
155168
156169 cases.addCase(.{
170 .params = params,
171 .target = target,
157172 .name = "while loop pops error return trace",
158173 .source =
159174 \\fn foo() !void { return error.FooError; }
......@@ -186,6 +201,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
186201 });
187202
188203 cases.addCase(.{
204 .params = params,
205 .target = target,
189206 .name = "implicit continue in while loop pops stale error return trace",
190207 .source =
191208 \\fn foo() !void { return error.FooError; }
......@@ -219,6 +236,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
219236 });
220237
221238 cases.addCase(.{
239 .params = params,
240 .target = target,
222241 .name = "try return + handled catch/if-else",
223242 .source =
224243 \\fn foo() !void {
......@@ -251,6 +270,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
251270 });
252271
253272 cases.addCase(.{
273 .params = params,
274 .target = target,
254275 .name = "break from inline loop pops error return trace",
255276 .source =
256277 \\fn foo() !void { return error.FooBar; }
......@@ -276,6 +297,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
276297 });
277298
278299 cases.addCase(.{
300 .params = params,
301 .target = target,
279302 .name = "catch and re-throw error",
280303 .source =
281304 \\fn foo() !void {
......@@ -304,6 +327,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
304327 });
305328
306329 cases.addCase(.{
330 .params = params,
331 .target = target,
307332 .name = "errors stored in var do not contribute to error trace",
308333 .source =
309334 \\fn foo() !void {
......@@ -328,6 +353,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
328353 });
329354
330355 cases.addCase(.{
356 .params = params,
357 .target = target,
331358 .name = "error stored in const has trace preserved for duration of block",
332359 .source =
333360 \\fn foo() !void { return error.TheSkyIsFalling; }
......@@ -376,6 +403,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
376403 });
377404
378405 cases.addCase(.{
406 .params = params,
407 .target = target,
379408 .name = "error passed to function has its trace preserved for duration of the call",
380409 .source =
381410 \\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.
418447 });
419448
420449 cases.addCase(.{
450 .params = params,
451 .target = target,
421452 .name = "try return from within catch",
422453 .source =
423454 \\fn foo() !void {
......@@ -455,6 +486,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
455486 });
456487
457488 cases.addCase(.{
489 .params = params,
490 .target = target,
458491 .name = "try return from within if-else",
459492 .source =
460493 \\fn foo() !void {
......@@ -492,6 +525,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
492525 });
493526
494527 cases.addCase(.{
528 .params = params,
529 .target = target,
495530 .name = "try try return return",
496531 .source =
497532 \\fn foo() !void {
......@@ -534,6 +569,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
534569 });
535570
536571 cases.addCase(.{
572 .params = params,
573 .target = target,
537574 .name = "error union switch with call operand",
538575 .source =
539576 \\pub fn main() !void {
......@@ -579,6 +616,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
579616 });
580617
581618 cases.addCase(.{
619 .params = params,
620 .target = target,
582621 .name = "trace through inline call",
583622 // The main function has two inline calls to ensure
584623 // that inlinees in PDBs are properly deduplicated.
......@@ -595,7 +634,7 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
595634 \\}
596635 ,
597636 .expect_error = "ThisIsSoSad",
598 .expect_trace = switch (os) {
637 .expect_trace = switch (target.os.tag) {
599638 // LLVM doesn't emit column info in the binary annotations for inlinee callees in PDBs,
600639 // so our expected result is slightly different for Windows than on other operating
601640 // systems.
test/incremental/change_panic_handler_explicit+6
......@@ -23,6 +23,7 @@ pub const panic = struct {
2323 pub const castToNull = no_panic.castToNull;
2424 pub const incorrectAlignment = no_panic.incorrectAlignment;
2525 pub const invalidErrorCode = no_panic.invalidErrorCode;
26 pub const unexpectedErrorCode = no_panic.unexpectedErrorCode;
2627 pub const integerOutOfBounds = no_panic.integerOutOfBounds;
2728 pub const shlOverflow = no_panic.shlOverflow;
2829 pub const shrOverflow = no_panic.shrOverflow;
......@@ -36,6 +37,7 @@ pub const panic = struct {
3637 pub const copyLenMismatch = no_panic.copyLenMismatch;
3738 pub const memcpyAlias = no_panic.memcpyAlias;
3839 pub const noreturnReturned = no_panic.noreturnReturned;
40 pub const loadUninstantiableType = no_panic.loadUninstantiableType;
3941};
4042fn myPanic(msg: []const u8, _: ?usize) noreturn {
4143 var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});
......@@ -71,6 +73,7 @@ pub const panic = struct {
7173 pub const castToNull = no_panic.castToNull;
7274 pub const incorrectAlignment = no_panic.incorrectAlignment;
7375 pub const invalidErrorCode = no_panic.invalidErrorCode;
76 pub const unexpectedErrorCode = no_panic.unexpectedErrorCode;
7477 pub const integerOutOfBounds = no_panic.integerOutOfBounds;
7578 pub const shlOverflow = no_panic.shlOverflow;
7679 pub const shrOverflow = no_panic.shrOverflow;
......@@ -84,6 +87,7 @@ pub const panic = struct {
8487 pub const copyLenMismatch = no_panic.copyLenMismatch;
8588 pub const memcpyAlias = no_panic.memcpyAlias;
8689 pub const noreturnReturned = no_panic.noreturnReturned;
90 pub const loadUninstantiableType = no_panic.loadUninstantiableType;
8791};
8892fn myPanic(msg: []const u8, _: ?usize) noreturn {
8993 var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});
......@@ -119,6 +123,7 @@ pub const panic = struct {
119123 pub const castToNull = no_panic.castToNull;
120124 pub const incorrectAlignment = no_panic.incorrectAlignment;
121125 pub const invalidErrorCode = no_panic.invalidErrorCode;
126 pub const unexpectedErrorCode = no_panic.unexpectedErrorCode;
122127 pub const integerOutOfBounds = no_panic.integerOutOfBounds;
123128 pub const shlOverflow = no_panic.shlOverflow;
124129 pub const shrOverflow = no_panic.shrOverflow;
......@@ -132,6 +137,7 @@ pub const panic = struct {
132137 pub const copyLenMismatch = no_panic.copyLenMismatch;
133138 pub const memcpyAlias = no_panic.memcpyAlias;
134139 pub const noreturnReturned = no_panic.noreturnReturned;
140 pub const loadUninstantiableType = no_panic.loadUninstantiableType;
135141};
136142fn myPanicNew(msg: []const u8, _: ?usize) noreturn {
137143 var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});
test/incremental/temporary_analysis_error_in_generic_signature created+46
......@@ -0,0 +1,46 @@
1#update=initial version
2#file=main.zig
3//! The original repro here depends on re-analysis order, which depends on
4//! declaration order, so this exact declaration order must be used.
5const Foo = struct { x: u8 };
6pub fn main(init: std.process.Init) !void {
7 const c = bar('Z').x;
8 try std.Io.File.stdout().writeStreamingAll(init.io, &.{ c, '\n' });
9}
10fn bar(comptime x: u8) @This().Foo {
11 return .{ .x = x };
12}
13const std = @import("std");
14#expect_stdout="Z\n"
15
16#update=change generic signature to use non-existent member
17#file=main.zig
18//! The original repro here depends on re-analysis order, which depends on
19//! declaration order, so this exact declaration order must be used.
20const Foo = struct { x: u8 };
21pub fn main(init: std.process.Init) !void {
22 const c = bar('Z').x;
23 try std.Io.File.stdout().writeStreamingAll(init.io, &.{ c, '\n' });
24}
25fn bar(comptime x: u8) @This().FooAlias {
26 return .{ .x = x };
27}
28const std = @import("std");
29#expect_error=main.zig:8:31: error: root source file struct 'main' has no member named 'FooAlias'
30#expect_error=main.zig:1:1: note: struct declared here
31
32#update=add that member, fixing the error
33#file=main.zig
34//! The original repro here depends on re-analysis order, which depends on
35//! declaration order, so this exact declaration order must be used.
36const Foo = struct { x: u8 };
37const FooAlias = Foo;
38pub fn main(init: std.process.Init) !void {
39 const c = bar('Z').x;
40 try std.Io.File.stdout().writeStreamingAll(init.io, &.{ c, '\n' });
41}
42fn bar(comptime x: u8) @This().FooAlias {
43 return .{ .x = x };
44}
45const std = @import("std");
46#expect_stdout="Z\n"
test/llvm_ir.zig+20
......@@ -116,6 +116,26 @@ pub fn addCases(cases: *tests.LlvmIrContext) void {
116116 "null_pointer_is_valid",
117117 "store i16 42, ptr",
118118 }, .{});
119
120 cases.addMatches("load and store bool",
121 \\export fn foo(a: *bool, b: *align(2) bool) void {
122 \\ const tmp = a.*;
123 \\ a.* = b.*;
124 \\ b.* = tmp;
125 \\}
126 , &.{
127 // TODO: this should all be one multiline string literal, but `-femit-llvm-ir` is currently
128 // emitting CRLF on Windows, which is a pain to handle here. In future that option will emit
129 // unoptimized LLVM IR emitted directly from Zig, so that bug will go away.
130 " %3 = load i8, ptr %0, align 1",
131 " %4 = trunc nuw i8 %3 to i1",
132 " %5 = load i8, ptr %1, align 2",
133 " %6 = trunc nuw i8 %5 to i1",
134 " %7 = zext i1 %6 to i8",
135 " store i8 %7, ptr %0, align 1",
136 " %8 = zext i1 %4 to i8",
137 " store i8 %8, ptr %1, align 2",
138 }, .{ .strip = true });
119139}
120140
121141const std = @import("std");
test/llvm_targets.zig+2-2
......@@ -106,9 +106,9 @@ const targets = [_]std.Target.Query{
106106 .{ .cpu_arch = .lanai, .os_tag = .freestanding, .abi = .none },
107107
108108 .{ .cpu_arch = .loongarch32, .os_tag = .freestanding, .abi = .none },
109 // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .gnu },
109 .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .gnu },
110110 // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .gnuf32 },
111 // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .gnusf },
111 .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .gnusf },
112112 // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .musl },
113113 // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .muslf32 },
114114 // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .muslsf },
test/src/Cases.zig+2-2
......@@ -491,7 +491,7 @@ pub fn lowerToBuildSteps(
491491
492492 for (self.cases.items) |case| {
493493 for (options.test_filters) |test_filter| {
494 if (std.mem.indexOf(u8, case.name, test_filter)) |_| break;
494 if (std.mem.find(u8, case.name, test_filter)) |_| break;
495495 } else if (options.test_filters.len > 0) continue;
496496
497497 if (case.case.? == .Error and options.skip_compile_errors) continue;
......@@ -524,7 +524,7 @@ pub fn lowerToBuildSteps(
524524
525525 if (options.test_target_filters.len > 0) {
526526 for (options.test_target_filters) |filter| {
527 if (std.mem.indexOf(u8, triple_txt, filter) != null) break;
527 if (std.mem.find(u8, triple_txt, filter) != null) break;
528528 } else continue;
529529 }
530530
test/src/Debugger.zig+2-2
......@@ -2384,13 +2384,13 @@ fn addTest(
23842384) void {
23852385 if (db.options.test_filters.len > 0) {
23862386 for (db.options.test_filters) |test_filter| {
2387 if (std.mem.indexOf(u8, name, test_filter) != null) break;
2387 if (std.mem.find(u8, name, test_filter) != null) break;
23882388 } else return;
23892389 }
23902390 if (db.options.test_target_filters.len > 0) {
23912391 const triple_txt = target.resolved.query.zigTriple(db.b.allocator) catch @panic("OOM");
23922392 for (db.options.test_target_filters) |filter| {
2393 if (std.mem.indexOf(u8, triple_txt, filter) != null) break;
2393 if (std.mem.find(u8, triple_txt, filter) != null) break;
23942394 } else return;
23952395 }
23962396 const files_wf = db.b.addWriteFiles();
test/src/ErrorTrace.zig+120-53
......@@ -1,11 +1,81 @@
1const ErrorTrace = @This();
2
3const builtin = @import("builtin");
4
5const std = @import("std");
6const Step = std.Build.Step;
7const OptimizeMode = std.lang.Optimize;
8const mem = std.mem;
9
10const error_traces_cases = @import("../error_traces.zig");
11
112b: *std.Build,
213step: *Step,
314test_filters: []const []const u8,
4targets: []const std.Build.ResolvedTarget,
15skip_non_native: bool,
516optimize_modes: []const OptimizeMode,
617convert_exe: *std.Build.Step.Compile,
718
19pub const CaseParameters = @import("StackTrace.zig").CaseParameters;
20
21const param_sets = [_]CaseParameters{
22 .{},
23 .{
24 .link_libc = true,
25 },
26 .{
27 .use_llvm = true,
28 .use_lld = true,
29 },
30 .{
31 .pie = true,
32 },
33 .{
34 .target = .{
35 .cpu_arch = .aarch64,
36 .os_tag = .windows,
37 .abi = .msvc,
38 },
39 },
40 .{
41 .target = .{
42 .cpu_arch = .x86_64,
43 .os_tag = .windows,
44 .abi = .gnu,
45 },
46 },
47 .{
48 .target = .{
49 .cpu_arch = .x86,
50 .os_tag = .windows,
51 .abi = .msvc,
52 },
53 },
54 .{
55 .target = .{
56 .cpu_arch = .aarch64,
57 .os_tag = .macos,
58 },
59 },
60 .{
61 .target = .{
62 .cpu_arch = .s390x,
63 .os_tag = .linux,
64 .abi = .none,
65 },
66 },
67 .{
68 .target = .{
69 .cpu_arch = .loongarch32,
70 .os_tag = .linux,
71 .abi = .none,
72 },
73 },
74};
75
876pub const Case = struct {
77 params: *const CaseParameters,
78 target: *const std.Target,
979 name: []const u8,
1080 source: []const u8,
1181 expect_error: []const u8,
......@@ -22,50 +92,47 @@ pub const Case = struct {
2292 pub const Backend = enum { llvm, selfhosted };
2393};
2494
25pub fn addCase(self: *ErrorTrace, case: Case) void {
26 for (self.targets) |*target| {
27 const triple: ?[]const u8 = if (target.query.isNative()) null else t: {
28 break :t target.query.zigTriple(self.b.graph.arena) catch @panic("OOM");
29 };
30 for (self.optimize_modes) |optimize| {
31 self.addCaseConfig(case, target, triple, optimize, .llvm);
32 }
33 if (shouldTestNonLlvm(&target.result)) {
34 for (self.optimize_modes) |optimize| {
35 self.addCaseConfig(case, target, triple, optimize, .selfhosted);
36 }
95pub fn addCases(self: *ErrorTrace) void {
96 const b = self.b;
97
98 for (&param_sets) |*params| {
99 const resolved_target = b.resolveTargetQuery(params.target);
100
101 if (self.skip_non_native and !resolved_target.query.isNative()) continue;
102
103 // To avoid redundant testing, skip cross-compilation targets matching the host.
104 if (resolved_target.result.os.tag == builtin.target.os.tag and
105 resolved_target.result.cpu.arch == builtin.target.cpu.arch)
106 {
107 continue;
37108 }
38 }
39}
40109
41fn shouldTestNonLlvm(target: *const std.Target) bool {
42 if (comptime builtin.cpu.arch.endian() == .big) return false; // https://github.com/ziglang/zig/issues/25961
43 return switch (target.cpu.arch) {
44 .x86_64 => switch (target.ofmt) {
45 .elf => !target.os.tag.isBSD() and target.os.tag != .illumos,
46 else => false,
47 },
48 else => false,
49 };
110 for (self.optimize_modes) |optimize| {
111 if (optimize == params.optimize) break;
112 } else return;
113
114 error_traces_cases.addCases(self, params, &resolved_target.result);
115 }
50116}
51117
52fn addCaseConfig(
53 self: *ErrorTrace,
54 case: Case,
55 target: *const std.Build.ResolvedTarget,
56 triple: ?[]const u8,
57 optimize: OptimizeMode,
58 backend: Case.Backend,
59) void {
118/// Called from test/error_traces.zig
119pub fn addCase(self: *ErrorTrace, case: Case) void {
60120 const b = self.b;
121 const params = case.params;
122 const target = case.target;
123 const target_query = params.target;
124
125 const triple: ?[]const u8 = if (target_query.isNative()) null else t: {
126 break :t target_query.zigTriple(self.b.graph.arena) catch @panic("OOM");
127 };
61128
62129 const error_tracing: bool = tracing: {
63 if (optimize == .Debug) break :tracing true;
64 if (backend != .llvm) break :tracing true;
65 if (optimize == .ReleaseSmall) break :tracing false;
130 if (params.optimize == .debug) break :tracing true;
131 if (params.use_llvm == false) break :tracing true;
132 if (params.optimize == .small) break :tracing false;
66133 for (case.disable_trace_optimized) |disable| {
67134 const d_arch, const d_os = disable;
68 if (target.result.cpu.arch == d_arch and target.result.os.tag == d_os) {
135 if (target.cpu.arch == d_arch and target.os.tag == d_os) {
69136 // This particular configuration cannot do error tracing in optimized LLVM builds.
70137 break :tracing false;
71138 }
......@@ -73,16 +140,23 @@ fn addCaseConfig(
73140 break :tracing true;
74141 };
75142
76 const annotated_case_name = b.fmt("check {s} ({s}{s}{s} {s})", .{
143 const backend_string = if (params.use_llvm == true)
144 "-llvm"
145 else if (params.use_llvm == false)
146 "-selfhosted"
147 else
148 "";
149
150 const annotated_case_name = b.fmt("check {s} ({s}{s}{t}{s})", .{
77151 case.name,
78152 triple orelse "",
79153 if (triple != null) " " else "",
80 @tagName(optimize),
81 @tagName(backend),
154 params.optimize,
155 backend_string,
82156 });
83157 if (self.test_filters.len > 0) {
84158 for (self.test_filters) |test_filter| {
85 if (mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
159 if (mem.find(u8, annotated_case_name, test_filter)) |_| break;
86160 } else return;
87161 }
88162
......@@ -92,19 +166,18 @@ fn addCaseConfig(
92166 .name = "test",
93167 .root_module = b.createModule(.{
94168 .root_source_file = source_zig,
95 .optimize = optimize,
96 .target = target.*,
169 .optimize = params.optimize,
170 .target = .{ .result = target.*, .query = target_query },
97171 .error_tracing = error_tracing,
98172 .strip = false,
99173 }),
100 .use_llvm = switch (backend) {
101 .llvm => true,
102 .selfhosted => false,
103 },
174 .use_llvm = params.use_llvm,
175 .use_lld = params.use_lld,
104176 });
105177 exe.bundle_ubsan_rt = false;
106178
107179 const run = b.addRunArtifact(exe);
180 run.skip_foreign_checks = true;
108181 run.removeEnvironmentVariable("CLICOLOR_FORCE");
109182 run.setEnvironmentVariable("NO_COLOR", "1");
110183 run.expectExitCode(1);
......@@ -116,16 +189,10 @@ fn addCaseConfig(
116189 };
117190
118191 const check_run = b.addRunArtifact(self.convert_exe);
192 check_run.skip_foreign_checks = true;
119193 check_run.setName(annotated_case_name);
120194 check_run.addFileArg(run.captureStdErr(.{}));
121195 check_run.expectStdOutEqual(expected_stderr);
122196
123197 self.step.dependOn(&check_run.step);
124198}
125
126const ErrorTrace = @This();
127const std = @import("std");
128const builtin = @import("builtin");
129const Step = std.Build.Step;
130const OptimizeMode = std.builtin.OptimizeMode;
131const mem = std.mem;
test/src/Libc.zig+2-2
......@@ -49,7 +49,7 @@ pub fn addTarget(libc: *const Libc, target: std.Build.ResolvedTarget) void {
4949 if (libc.options.test_target_filters.len > 0) {
5050 const triple_txt = target.query.zigTriple(libc.b.allocator) catch @panic("OOM");
5151 for (libc.options.test_target_filters) |filter| {
52 if (std.mem.indexOf(u8, triple_txt, filter)) |_| break;
52 if (std.mem.find(u8, triple_txt, filter)) |_| break;
5353 } else return;
5454 }
5555
......@@ -82,7 +82,7 @@ pub fn addTarget(libc: *const Libc, target: std.Build.ResolvedTarget) void {
8282
8383 const annotated_case_name = libc.b.fmt("run libc-test {s} ({t})", .{ test_case.name, optimize });
8484 for (libc.options.test_filters) |test_filter| {
85 if (std.mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
85 if (std.mem.find(u8, annotated_case_name, test_filter)) |_| break;
8686 } else if (libc.options.test_filters.len > 0) continue;
8787
8888 const mod = libc.b.createModule(.{
test/src/Link.zig+1-1
......@@ -8,7 +8,7 @@ use_lld: bool,
88link_libc: bool,
99test_filters: []const []const u8,
1010update_step: ?*Step.UpdateSourceFiles,
11updated_snapshots: std.StringArrayHashMapUnmanaged(void),
11updated_snapshots: std.array_hash_map.String(void),
1212max_rss: usize,
1313
1414pub fn includeTest(self: *Link, prefix: []const u8) ?Case {
test/src/LlvmIr.zig+2-2
......@@ -77,14 +77,14 @@ pub fn addCase(self: *LlvmIr, case: TestCase) void {
7777 if (self.options.test_target_filters.len > 0) {
7878 const triple_txt = target.query.zigTriple(self.b.allocator) catch @panic("OOM");
7979 for (self.options.test_target_filters) |filter| {
80 if (std.mem.indexOf(u8, triple_txt, filter) != null) break;
80 if (std.mem.find(u8, triple_txt, filter) != null) break;
8181 } else return;
8282 }
8383
8484 const name = std.fmt.allocPrint(self.b.allocator, "check llvm-ir {s}", .{case.name}) catch @panic("OOM");
8585 if (self.options.test_filters.len > 0) {
8686 for (self.options.test_filters) |filter| {
87 if (std.mem.indexOf(u8, name, filter) != null) break;
87 if (std.mem.find(u8, name, filter) != null) break;
8888 } else return;
8989 }
9090
test/src/RunTranslatedC.zig+1-1
......@@ -68,7 +68,7 @@ pub fn addCase(self: *RunTranslatedCContext, case: *const TestCase) void {
6868
6969 const annotated_case_name = fmt.allocPrint(self.b.allocator, "run-translated-c {s}", .{case.name}) catch unreachable;
7070 for (self.test_filters) |test_filter| {
71 if (mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
71 if (mem.find(u8, annotated_case_name, test_filter)) |_| break;
7272 } else if (self.test_filters.len > 0) return;
7373
7474 const write_src = b.addWriteFiles();
test/src/StackTrace.zig+156-93
......@@ -1,10 +1,91 @@
1const StackTrace = @This();
2
3const builtin = @import("builtin");
4
5const std = @import("std");
6const Step = std.Build.Step;
7const OptimizeMode = std.lang.Optimize;
8const mem = std.mem;
9
10const stack_traces_cases = @import("../stack_traces.zig");
11
112b: *std.Build,
213step: *Step,
314test_filters: []const []const u8,
4targets: []const std.Build.ResolvedTarget,
15skip_non_native: bool,
516convert_exe: *std.Build.Step.Compile,
617
18pub const CaseParameters = struct {
19 target: std.Target.Query = .{},
20 optimize: std.builtin.OptimizeMode = .debug,
21 link_libc: ?bool = null,
22 use_llvm: ?bool = null,
23 use_lld: ?bool = null,
24 pie: ?bool = null,
25 /// To enable this coverage, one of two things needs to happen:
26 /// * The compiler needs to gain the ability to strip only debug info (not symbols)
27 /// * `std.Build.Step.ObjCopy` needs to be un-regressed
28 strip: ?bool = false,
29};
30
31const param_sets = [_]CaseParameters{
32 .{},
33 .{
34 .link_libc = true,
35 },
36 .{
37 .use_llvm = true,
38 .use_lld = true,
39 },
40 .{
41 .pie = true,
42 },
43 .{
44 .target = .{
45 .cpu_arch = .aarch64,
46 .os_tag = .windows,
47 .abi = .msvc,
48 },
49 },
50 .{
51 .target = .{
52 .cpu_arch = .x86_64,
53 .os_tag = .windows,
54 .abi = .gnu,
55 },
56 },
57 .{
58 .target = .{
59 .cpu_arch = .x86,
60 .os_tag = .windows,
61 .abi = .msvc,
62 },
63 },
64 .{
65 .target = .{
66 .cpu_arch = .aarch64,
67 .os_tag = .macos,
68 },
69 },
70 .{
71 .target = .{
72 .cpu_arch = .s390x,
73 .os_tag = .linux,
74 .abi = .none,
75 },
76 },
77 .{
78 .target = .{
79 .cpu_arch = .loongarch32,
80 .os_tag = .linux,
81 .abi = .none,
82 },
83 },
84};
85
786const Config = struct {
87 params: *const CaseParameters,
88 target: *const std.Target,
889 name: []const u8,
990 source: []const u8,
1091 /// Whether this test case expects to have unwind tables / frame pointers.
......@@ -26,42 +107,37 @@ const Config = struct {
26107 expect_strip: []const u8,
27108};
28109
29pub fn addCase(self: *StackTrace, config: Config) void {
30 for (self.targets) |*target| {
31 addCaseTarget(
32 self,
33 config,
34 target,
35 if (target.query.isNative()) null else t: {
36 break :t target.query.zigTriple(self.b.graph.arena) catch @panic("OOM");
37 },
38 );
110pub fn addCases(self: *StackTrace) void {
111 const b = self.b;
112
113 for (&param_sets) |*params| {
114 const resolved_target = b.resolveTargetQuery(params.target);
115
116 if (self.skip_non_native and !resolved_target.query.isNative()) continue;
117
118 // To avoid redundant testing, skip cross-compilation targets matching the host.
119 if (resolved_target.result.os.tag == builtin.target.os.tag and
120 resolved_target.result.cpu.arch == builtin.target.cpu.arch)
121 {
122 continue;
123 }
124
125 stack_traces_cases.addCases(self, params, &resolved_target.result);
39126 }
40127}
41fn addCaseTarget(
42 self: *StackTrace,
43 config: Config,
44 target: *const std.Build.ResolvedTarget,
45 triple: ?[]const u8,
46) void {
47 const both_backends = b: {
48 if (comptime builtin.cpu.arch.endian() == .big) break :b false; // https://github.com/ziglang/zig/issues/25961
49 break :b switch (target.result.cpu.arch) {
50 .x86_64 => switch (target.result.ofmt) {
51 .elf => !target.result.os.tag.isBSD() and target.result.os.tag != .illumos,
52 else => false,
53 },
54 else => false,
55 };
56 };
57 const both_pie = switch (target.result.os.tag) {
58 .fuchsia => false,
59 else => true,
128
129/// Called from test/stack_traces.zig
130pub fn addCase(self: *StackTrace, config: Config) void {
131 const params = config.params;
132 const target = config.target;
133 const target_query = config.params.target;
134
135 const triple: ?[]const u8 = if (target_query.isNative()) null else t: {
136 break :t target_query.zigTriple(self.b.graph.arena) catch @panic("OOM");
60137 };
61 const both_libc = !std.os.targetRequiresLibC(&target.result);
62138
63139 // See `std.debug.StackIterator.fp_usability` logic.
64 const fp_usability: enum { useless, unsafe, safe, ideal } = switch (target.result.cpu.arch) {
140 const fp_usability: enum { useless, unsafe, safe, ideal } = switch (target.cpu.arch) {
65141 .alpha,
66142 .csky,
67143 .microblaze,
......@@ -83,20 +159,15 @@ fn addCaseTarget(
83159 .sparc,
84160 .sparc64,
85161 => .ideal,
86 .aarch64 => if (target.result.os.tag.isDarwin()) .safe else .unsafe,
162 .aarch64 => if (target.os.tag.isDarwin()) .safe else .unsafe,
87163 else => .unsafe,
88164 };
89 const supports_unwind_tables = switch (target.result.os.tag) {
165 const supports_unwind_tables = switch (target.os.tag) {
90166 // x86-windows just has no way to do stack unwinding other then using frame pointers.
91 .windows => target.result.cpu.arch != .x86,
167 .windows => target.cpu.arch != .x86,
92168 else => true,
93169 };
94170
95 const use_llvm_vals: []const bool = if (both_backends) &.{ true, false } else &.{true};
96 const pie_vals: []const ?bool = if (both_pie) &.{ true, false } else &.{null};
97 const link_libc_vals: []const ?bool = if (both_libc) &.{ true, false } else &.{null};
98 const strip_debug_vals: []const bool = &.{ true, false };
99
100171 const UnwindInfo = packed struct(u2) {
101172 tables: bool,
102173 fp: bool,
......@@ -126,43 +197,33 @@ fn addCaseTarget(
126197 },
127198 };
128199
129 for (use_llvm_vals) |use_llvm| {
130 for (pie_vals) |pie| {
131 for (link_libc_vals) |link_libc| {
132 for (strip_debug_vals) |strip_debug| {
133 for (unwind_info_vals) |unwind_info| {
134 if (unwind_info.tables and !supports_unwind_tables) continue;
135 self.addCaseInstance(
136 target,
137 triple,
138 config.name,
139 config.source,
140 use_llvm,
141 pie,
142 link_libc,
143 strip_debug,
144 !unwind_info.tables and supports_unwind_tables,
145 !unwind_info.fp,
146 config.expect_panic,
147 if (strip_debug) config.expect_strip else config.expect,
148 );
149 }
150 }
151 }
152 }
200 for (unwind_info_vals) |unwind_info| {
201 if (unwind_info.tables and !supports_unwind_tables) continue;
202 const strip = params.strip orelse switch (params.optimize) {
203 .debug, .fast, .safe => false,
204 .small => true,
205 };
206 self.addCaseInstance(
207 .{ .result = target.*, .query = target_query },
208 triple,
209 config.name,
210 config.source,
211 params,
212 !unwind_info.tables and supports_unwind_tables,
213 !unwind_info.fp,
214 config.expect_panic,
215 if (strip) config.expect_strip else config.expect,
216 );
153217 }
154218}
155219
156220fn addCaseInstance(
157221 self: *StackTrace,
158 target: *const std.Build.ResolvedTarget,
222 resolved_target: std.Build.ResolvedTarget,
159223 triple: ?[]const u8,
160224 name: []const u8,
161225 source: []const u8,
162 use_llvm: bool,
163 pie: ?bool,
164 link_libc: ?bool,
165 strip_debug: bool,
226 params: *const CaseParameters,
166227 strip_unwind: bool,
167228 omit_frame_pointer: bool,
168229 expect_panic: bool,
......@@ -170,13 +231,6 @@ fn addCaseInstance(
170231) void {
171232 const b = self.b;
172233
173 if (strip_debug) {
174 // To enable this coverage, one of two things needs to happen:
175 // * The compiler needs to gain the ability to strip only debug info (not symbols)
176 // * `std.Build.Step.ObjCopy` needs to be un-regressed
177 return;
178 }
179
180234 if (strip_unwind) {
181235 // To enable this coverage, `std.Build.Step.ObjCopy` needs to be un-regressed and gain the
182236 // ability to remove individual sections. `-fno-unwind-tables` is insufficient because it
......@@ -187,20 +241,34 @@ fn addCaseInstance(
187241 return;
188242 }
189243
244 const backend_string = if (params.use_llvm == true)
245 " llvm"
246 else if (params.use_llvm == false)
247 " selfhosted"
248 else
249 "";
250
251 const strip_string = if (params.strip == true)
252 " strip"
253 else if (params.strip == false)
254 " unstripped"
255 else
256 "";
257
190258 const annotated_case_name = b.fmt("check {s} ({s}{s}{s}{s}{s}{s}{s}{s})", .{
191259 name,
192260 triple orelse "",
193261 if (triple != null) " " else "",
194 if (use_llvm) "llvm" else "selfhosted",
195 if (pie == true) " pie" else "",
196 if (link_libc == true) " libc" else "",
197 if (strip_debug) " strip" else "",
262 backend_string,
263 if (params.pie == true) " pie" else "",
264 if (params.link_libc == true) " libc" else "",
265 strip_string,
198266 if (strip_unwind) " no_unwind" else "",
199267 if (omit_frame_pointer) " no_fp" else "",
200268 });
201269 if (self.test_filters.len > 0) {
202270 for (self.test_filters) |test_filter| {
203 if (mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
271 if (mem.find(u8, annotated_case_name, test_filter)) |_| break;
204272 } else return;
205273 }
206274
......@@ -211,24 +279,26 @@ fn addCaseInstance(
211279 .root_module = b.createModule(.{
212280 .root_source_file = source_zig,
213281 .optimize = .Debug,
214 .target = target.*,
282 .target = resolved_target,
215283 .omit_frame_pointer = omit_frame_pointer,
216 .link_libc = link_libc,
284 .link_libc = params.link_libc,
217285 .unwind_tables = if (strip_unwind) .none else null,
218286 // make panics single-threaded so that they don't include a thread ID
219287 .single_threaded = expect_panic,
220288 }),
221 .use_llvm = use_llvm,
289 .use_llvm = params.use_llvm,
290 .use_lld = params.use_lld,
222291 });
223 exe.pie = pie;
292 exe.pie = params.pie;
224293 exe.bundle_ubsan_rt = false;
225294
226295 const run = b.addRunArtifact(exe);
296 run.skip_foreign_checks = true;
227297 run.removeEnvironmentVariable("CLICOLOR_FORCE");
228298 run.setEnvironmentVariable("NO_COLOR", "1");
229299 run.addCheck(.{ .expect_term = term: {
230300 if (!expect_panic) break :term .{ .exited = 0 };
231 if (target.result.os.tag == .windows) break :term .{ .exited = 3 };
301 if (resolved_target.result.os.tag == .windows) break :term .{ .exited = 3 };
232302 break :term .{ .signal = @fromBackingInt(@intCast(6)) };
233303 } });
234304 run.expectStdOutEqual("");
......@@ -241,10 +311,3 @@ fn addCaseInstance(
241311
242312 self.step.dependOn(&check_run.step);
243313}
244
245const StackTrace = @This();
246const std = @import("std");
247const builtin = @import("builtin");
248const Step = std.Build.Step;
249const OptimizeMode = std.builtin.OptimizeMode;
250const mem = std.mem;
test/src/TranslateC.zig+2-2
......@@ -90,7 +90,7 @@ pub fn addCase(self: *TranslateCContext, case: *const TestCase) void {
9090 const translate_c_cmd = "translate-c";
9191 const annotated_case_name = fmt.allocPrint(self.b.allocator, "{s} {s}", .{ translate_c_cmd, case.name }) catch unreachable;
9292 for (self.test_filters) |test_filter| {
93 if (mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
93 if (mem.find(u8, annotated_case_name, test_filter)) |_| break;
9494 } else if (self.test_filters.len > 0) return;
9595
9696 const target = b.resolveTargetQuery(case.target);
......@@ -99,7 +99,7 @@ pub fn addCase(self: *TranslateCContext, case: *const TestCase) void {
9999 const triple_txt = target.query.zigTriple(b.allocator) catch @panic("OOM");
100100
101101 for (self.test_target_filters) |filter| {
102 if (std.mem.indexOf(u8, triple_txt, filter) != null) break;
102 if (std.mem.find(u8, triple_txt, filter) != null) break;
103103 } else return;
104104 }
105105
test/src/convert-stack-trace.zig+3-3
......@@ -52,13 +52,13 @@ pub fn main(init: std.process.Init) !void {
5252 continue;
5353 }
5454
55 const src_pos_end = std.mem.indexOf(u8, in_line, ": 0x") orelse {
55 const src_pos_end = std.mem.find(u8, in_line, ": 0x") orelse {
5656 try w.writeAll(in_line);
5757 continue;
5858 };
5959 const src_pos_start = b: {
6060 const postfix = ".zig:";
61 const postfix_index = std.mem.lastIndexOf(u8, in_line[0..src_pos_end], postfix) orelse {
61 const postfix_index = std.mem.findLast(u8, in_line[0..src_pos_end], postfix) orelse {
6262 try w.writeAll(in_line);
6363 continue;
6464 };
......@@ -89,7 +89,7 @@ pub fn main(init: std.process.Init) !void {
8989 // ...with that first '_' being replaced by its basename.
9090
9191 const src_path = in_line[0..src_pos_start];
92 const basename_start = if (std.mem.lastIndexOfAny(u8, src_path, "/\\")) |i| i + 1 else 0;
92 const basename_start = if (std.mem.findLastAny(u8, src_path, "/\\")) |i| i + 1 else 0;
9393 const symbol_start = addr_end + " in ".len;
9494 try w.writeAll(in_line[basename_start..src_pos_end]);
9595 try w.writeAll(": [address] in ");
test/stack_traces.zig+24-5
......@@ -1,7 +1,10 @@
11const std = @import("std");
2const Context = @import("tests.zig").StackTracesContext;
23
3pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.Os.Tag) void {
4pub fn addCases(cases: *Context, params: *const Context.CaseParameters, target: *const std.Target) void {
45 cases.addCase(.{
6 .params = params,
7 .target = target,
58 .name = "simple panic",
69 .source =
710 \\pub fn main() void {
......@@ -33,6 +36,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
3336 });
3437
3538 cases.addCase(.{
39 .params = params,
40 .target = target,
3641 .name = "simple panic with no unwind strategy",
3742 .source =
3843 \\pub fn main() void {
......@@ -50,6 +55,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
5055 });
5156
5257 cases.addCase(.{
58 .params = params,
59 .target = target,
5360 .name = "dump current trace",
5461 .source =
5562 \\pub fn main() void {
......@@ -89,6 +96,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
8996 });
9097
9198 cases.addCase(.{
99 .params = params,
100 .target = target,
92101 .name = "dump current trace with no unwind strategy",
93102 .source =
94103 \\pub fn main() void {
......@@ -114,6 +123,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
114123 });
115124
116125 cases.addCase(.{
126 .params = params,
127 .target = target,
117128 .name = "dump captured trace",
118129 .source =
119130 \\pub fn main() void {
......@@ -155,6 +166,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
155166 });
156167
157168 cases.addCase(.{
169 .params = params,
170 .target = target,
158171 .name = "dump captured trace with no unwind strategy",
159172 .source =
160173 \\pub fn main() void {
......@@ -180,6 +193,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
180193 });
181194
182195 cases.addCase(.{
196 .params = params,
197 .target = target,
183198 .name = "dump captured trace on thread",
184199 .source =
185200 \\pub fn main() !void {
......@@ -225,6 +240,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
225240 });
226241
227242 cases.addCase(.{
243 .params = params,
244 .target = target,
228245 .name = "simple inline panic",
229246 // The main function has two inline calls to ensure
230247 // that inlinees in PDBs are properly deduplicated.
......@@ -240,7 +257,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
240257 ,
241258 .unwind = .any,
242259 .expect_panic = true,
243 .expect = switch (os) {
260 .expect = switch (target.os.tag) {
244261 // LLVM doesn't emit column info in the binary annotations for inlinee callees in PDBs,
245262 // so the first location has only a row.
246263 .windows =>
......@@ -262,7 +279,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
262279 \\ ^
263280 ,
264281 },
265 .expect_strip = switch (os) {
282 .expect_strip = switch (target.os.tag) {
266283 .windows =>
267284 \\panic: oh no
268285 \\???:?:?: [address] in source.foo
......@@ -279,6 +296,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
279296
280297 // Make sure all inline calls are resolved and in the right order!
281298 cases.addCase(.{
299 .params = params,
300 .target = target,
282301 .name = "nested inline panic",
283302 .source =
284303 \\pub fn main() void {
......@@ -298,7 +317,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
298317 .unwind = .any,
299318 .expect_panic = true,
300319 // This switch serves a similar purpose as in "inline panic".
301 .expect = switch (os) {
320 .expect = switch (target.os.tag) {
302321 .windows =>
303322 \\panic: oh no
304323 \\source.zig:11: [address] in baz
......@@ -322,7 +341,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
322341 \\ ^
323342 ,
324343 },
325 .expect_strip = switch (os) {
344 .expect_strip = switch (target.os.tag) {
326345 .windows =>
327346 \\panic: oh no
328347 \\???:?:?: [address] in baz
test/standalone/build.zig+1-1
......@@ -31,6 +31,7 @@ pub fn build(b: *std.Build) void {
3131 const tools_target = b.resolveTargetQuery(.{});
3232 for ([_][]const u8{
3333 // Alphabetically sorted. No need to build `tools/spirv/grammar.zig`.
34 "../../tools/bsp.zig",
3435 "../../tools/check_mingw.zig",
3536 "../../tools/dump-cov.zig",
3637 "../../tools/fetch_them_macos_headers.zig",
......@@ -39,7 +40,6 @@ pub fn build(b: *std.Build) void {
3940 "../../tools/gen_parser_oracle.zig",
4041 "../../tools/gen_spirv_spec.zig",
4142 "../../tools/gen_stubs.zig",
42 "../../tools/generate_c_size_and_align_checks.zig",
4343 "../../tools/generate_JSONTestSuite.zig",
4444 "../../tools/generate_linux_syscalls.zig",
4545 "../../tools/process_headers.zig",
test/standalone/build.zig.zon-3
......@@ -187,9 +187,6 @@
187187 .posix = .{
188188 .path = "posix",
189189 },
190 .debug_io_color = .{
191 .path = "debug_io_color",
192 },
193190 .elf2 = .{
194191 .path = "elf2",
195192 },
test/standalone/compiler_rt_panic/main.c+2-2
......@@ -1,11 +1,11 @@
11#include <stddef.h>
22
3void* __memset(void* dest, char c, size_t n, size_t dest_n);
3void *__memset_chk(void *dest, int c, size_t n, size_t dest_n);
44
55char foo[128];
66
77int main() {
8 __memset(&foo[0], 0xff, 128, 128);
8 __memset_chk(&foo[0], 0xff, 128, 128);
99 return foo[64];
1010}
1111
test/standalone/config_header/build.zig+21
......@@ -51,6 +51,27 @@ pub fn build(b: *std.Build) void {
5151 });
5252 test_step.dependOn(&check_config_header_autoconf_at.step);
5353
54 const config_header_meson = b.addConfigHeader(
55 .{ .style = .{
56 .meson = b.path("meson/mesondefine.h.in"),
57 } },
58 .{
59 .version = "1.2.3",
60 .boolean_true = true,
61 .boolean_false = false,
62 .uint_64 = 42,
63 .int_64 = -42,
64 .string = "meson",
65 .ident = .meson,
66 .not_defined = null,
67 .is_defined = {},
68 },
69 );
70 const check_config_header_meson = b.addCheckFile(config_header_meson.getOutputFile(), .{
71 .expected_exact = @embedFile("meson/mesondefine.h"),
72 });
73 test_step.dependOn(&check_config_header_meson.step);
74
5475 const config_header_blank = b.addConfigHeader(
5576 .{
5677 .style = .blank,
test/standalone/config_header/meson/mesondefine.h created+22
......@@ -0,0 +1,22 @@
1/* This file was generated by ConfigHeader using the Zig Build System. */
2// comments are preserved
3
4// empty lines are preserved
5
6#define VERSION_STR "1.2.3"
7
8#define boolean_true /* comment after define is okay */
9
10#undef boolean_false // same for line comment
11
12#define uint_64 42
13
14#define int_64 -42
15
16#define string "meson"
17
18#define ident meson
19
20/* #undef not_defined */
21
22#define is_defined
test/standalone/config_header/meson/mesondefine.h.in created+21
......@@ -0,0 +1,21 @@
1// comments are preserved
2
3// empty lines are preserved
4
5#define VERSION_STR "@version@"
6
7#mesondefine boolean_true /* comment after define is okay */
8
9#mesondefine boolean_false // same for line comment
10
11#mesondefine uint_64
12
13#mesondefine int_64
14
15#mesondefine string
16
17#mesondefine ident
18
19#mesondefine not_defined
20
21#mesondefine is_defined
test/standalone/debug_io_color/build.zig deleted-95
......@@ -1,95 +0,0 @@
1const std = @import("std");
2
3pub fn build(b: *std.Build) void {
4 const test_step = b.step("test", "Test");
5 b.default_step = test_step;
6
7 // Most targets handle color the same way, regardless of whether libc is linked.
8 const native_target = b.graph.host;
9 addTestCases(test_step, native_target, false);
10 addTestCases(test_step, native_target, true);
11
12 // WASI behaves differently depending on whether libc is linked.
13 if (b.enable_wasmtime) {
14 const wasi_target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .wasi });
15 addTestCases(test_step, wasi_target, false);
16 addTestCases(test_step, wasi_target, true);
17 }
18}
19
20fn addTestCases(
21 test_step: *std.Build.Step,
22 target: std.Build.ResolvedTarget,
23 link_libc: bool,
24) void {
25 const b = test_step.owner;
26 const exe = b.addExecutable(.{
27 .name = b.fmt("{s}{s}", .{ @tagName(target.result.os.tag), if (link_libc) "-libc" else "" }),
28 .root_module = b.createModule(.{
29 .root_source_file = b.path("main.zig"),
30 .target = target,
31 .link_libc = link_libc,
32 }),
33 });
34
35 // Should reflect 'std.process.Environ.Block' and 'std.Io.Threaded.init_single_threaded'.
36 const debug_io_can_read_environ = switch (target.result.os.tag) {
37 .windows => true,
38 .wasi, .emscripten => link_libc,
39 .freestanding, .other => false,
40 else => true,
41 };
42
43 // Don't forget to account for whether the build process's stderr supports color.
44 const parent_stderr_color_enabled = (std.Io.Terminal.Mode.detect(b.graph.io, .stderr(), false, false) catch unreachable) != .no_color;
45
46 _ = addTestCase(test_step, exe, "neither", .inherit, .manual, parent_stderr_color_enabled);
47 _ = addTestCase(test_step, exe, "neither", .redirect, .manual, false);
48 _ = addTestCase(test_step, exe, "no_color", .inherit, .disable, if (debug_io_can_read_environ) false else parent_stderr_color_enabled);
49 _ = addTestCase(test_step, exe, "no_color", .redirect, .disable, false);
50 _ = addTestCase(test_step, exe, "clicolor_force", .inherit, .enable, if (debug_io_can_read_environ) true else parent_stderr_color_enabled);
51 _ = addTestCase(test_step, exe, "clicolor_force", .redirect, .enable, debug_io_can_read_environ);
52
53 const both = addTestCase(test_step, exe, "both", .inherit, .manual, if (debug_io_can_read_environ) false else parent_stderr_color_enabled);
54 both.setEnvironmentVariable("NO_COLOR", "1");
55 both.setEnvironmentVariable("CLICOLOR_FORCE", "1");
56
57 const both_redirected = addTestCase(test_step, exe, "both", .redirect, .manual, false);
58 both_redirected.setEnvironmentVariable("NO_COLOR", "1");
59 both_redirected.setEnvironmentVariable("CLICOLOR_FORCE", "1");
60}
61
62fn addTestCase(
63 test_step: *std.Build.Step,
64 exe: *std.Build.Step.Compile,
65 test_case_name: []const u8,
66 stderr: enum { inherit, redirect },
67 run_step_color: std.Build.Step.Run.Color,
68 expected_color_enabled: bool,
69) *std.Build.Step.Run {
70 const b = test_step.owner;
71 const step_name = b.fmt("{s} {s}{s}", .{
72 exe.name,
73 test_case_name,
74 if (stderr == .redirect) "-redirect" else "",
75 });
76 const run_exe = b.addRunArtifact(exe);
77 run_exe.setName(b.fmt("run {s}", .{step_name}));
78
79 run_exe.failing_to_execute_foreign_is_an_error = false;
80 if (stderr == .redirect) run_exe.expectStdErrMatch("");
81
82 run_exe.clearEnvironment();
83 run_exe.color = run_step_color;
84
85 // Build system quirk: Currently, Run step stdout checks will also redirect stderr, so as a
86 // workaround we use a CheckFile step instead. We must also mark the Run step as having side
87 // effects, to ensure the parent stderr is inherited when not explicitly redirected.
88 run_exe.has_side_effects = true;
89 const stdout = run_exe.captureStdOut(.{});
90 const check_file = b.addCheckFile(stdout, .{ .expected_exact = if (expected_color_enabled) "true" else "false" });
91 check_file.setName(b.fmt("check {s}", .{step_name}));
92 test_step.dependOn(&check_file.step);
93
94 return run_exe;
95}
test/standalone/debug_io_color/main.zig deleted-7
......@@ -1,7 +0,0 @@
1const std = @import("std");
2
3pub fn main() !void {
4 const stderr = std.debug.lockStderr(&.{});
5 defer std.debug.unlockStderr();
6 try std.Io.File.stdout().writeStreamingAll(std.Options.debug_io, if (stderr.terminal_mode != .no_color) "true" else "false");
7}
test/standalone/dependency_options/build.zig+9-9
......@@ -11,11 +11,11 @@ pub fn build(b: *std.Build) !void {
1111 const none_specified_mod = none_specified.module("dummy");
1212 if (!none_specified_mod.resolved_target.?.query.eql(b.graph.host.query)) return error.TestFailed;
1313 const expected_optimize: std.builtin.OptimizeMode = switch (b.graph.release_mode) {
14 .off => .Debug,
14 .off => .debug,
1515 .any => unreachable,
16 .fast => .ReleaseFast,
17 .safe => .ReleaseSafe,
18 .small => .ReleaseSmall,
16 .fast => .fast,
17 .safe => .safe,
18 .small => .small,
1919 };
2020 if (none_specified_mod.optimize.? != expected_optimize) return error.TestFailed;
2121
......@@ -44,7 +44,7 @@ pub fn build(b: *std.Build) !void {
4444
4545 const all_specified = b.dependency("other", .{
4646 .target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu }),
47 .optimize = @as(std.builtin.OptimizeMode, .ReleaseSafe),
47 .optimize = @as(std.builtin.OptimizeMode, .safe),
4848 .bool = @as(bool, true),
4949 .int = @as(i64, 123),
5050 .float = @as(f64, 0.5),
......@@ -66,11 +66,11 @@ pub fn build(b: *std.Build) !void {
6666 if (all_specified_mod.resolved_target.?.result.cpu.arch != .x86_64) return error.TestFailed;
6767 if (all_specified_mod.resolved_target.?.result.os.tag != .windows) return error.TestFailed;
6868 if (all_specified_mod.resolved_target.?.result.abi != .gnu) return error.TestFailed;
69 if (all_specified_mod.optimize.? != .ReleaseSafe) return error.TestFailed;
69 if (all_specified_mod.optimize.? != .safe) return error.TestFailed;
7070
7171 const all_specified_optional = b.dependency("other", .{
7272 .target = @as(?std.Build.ResolvedTarget, b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu })),
73 .optimize = @as(?std.builtin.OptimizeMode, .ReleaseSafe),
73 .optimize = @as(?std.builtin.OptimizeMode, .safe),
7474 .bool = @as(?bool, true),
7575 .int = @as(?i64, 123),
7676 .float = @as(?f64, 0.5),
......@@ -92,7 +92,7 @@ pub fn build(b: *std.Build) !void {
9292
9393 const all_specified_literal = b.dependency("other", .{
9494 .target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu }),
95 .optimize = .ReleaseSafe,
95 .optimize = .safe,
9696 .bool = true,
9797 .int = 123,
9898 .float = 0.5,
......@@ -130,7 +130,7 @@ pub fn build(b: *std.Build) !void {
130130 // to the same cached dependency instance.
131131 const all_specified_alt = b.dependency("other", .{
132132 .target = @as(std.Target.Query, .{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu }),
133 .optimize = "ReleaseSafe",
133 .optimize = "safe",
134134 .bool = .true,
135135 .int = "123",
136136 .float = @as(f16, 0.5),
test/standalone/glibc_compat/build.zig+2
......@@ -103,6 +103,8 @@ pub fn build(b: *std.Build) void {
103103 .{ .arch_os_abi = t },
104104 ) catch unreachable);
105105
106 if (target.result.cpu.arch.isLoongArch()) continue; // https://github.com/Vexu/arocc/issues/1096
107
106108 const glibc_ver = target.result.os.version_range.linux.glibc;
107109
108110 // only build test if glibc version supports the architecture
test/standalone/simple/build.zig+5-5
......@@ -13,26 +13,26 @@ pub fn build(b: *std.Build) void {
1313 var optimize_modes_buf: [4]std.builtin.OptimizeMode = undefined;
1414 var optimize_modes_len: usize = 0;
1515 if (!skip_debug) {
16 optimize_modes_buf[optimize_modes_len] = .Debug;
16 optimize_modes_buf[optimize_modes_len] = .debug;
1717 optimize_modes_len += 1;
1818 }
1919 if (!skip_release_safe) {
20 optimize_modes_buf[optimize_modes_len] = .ReleaseSafe;
20 optimize_modes_buf[optimize_modes_len] = .safe;
2121 optimize_modes_len += 1;
2222 }
2323 if (!skip_release_fast) {
24 optimize_modes_buf[optimize_modes_len] = .ReleaseFast;
24 optimize_modes_buf[optimize_modes_len] = .fast;
2525 optimize_modes_len += 1;
2626 }
2727 if (!skip_release_small) {
28 optimize_modes_buf[optimize_modes_len] = .ReleaseSmall;
28 optimize_modes_buf[optimize_modes_len] = .small;
2929 optimize_modes_len += 1;
3030 }
3131 const optimize_modes = optimize_modes_buf[0..optimize_modes_len];
3232
3333 for (cases) |case| {
3434 for (optimize_modes) |optimize| {
35 if (!case.all_modes and optimize != .Debug) continue;
35 if (!case.all_modes and optimize != .debug) continue;
3636 if (case.os_filter) |os_tag| {
3737 if (os_tag != builtin.os.tag) continue;
3838 }
test/standalone/windows_argv/fuzz.zig+1-2
......@@ -147,8 +147,7 @@ fn spawnVerify(verify_path: [:0]const u16, cmd_line: [:0]const u16) !windows.DWO
147147 break :spawn proc_info.hProcess;
148148 };
149149 defer windows.CloseHandle(child_proc);
150 const infinite_timeout: windows.LARGE_INTEGER = std.math.minInt(windows.LARGE_INTEGER);
151 switch (windows.ntdll.NtWaitForSingleObject(child_proc, .FALSE, &infinite_timeout)) {
150 switch (windows.ntdll.NtWaitForSingleObject(child_proc, .FALSE, null)) {
152151 windows.NTSTATUS.WAIT_0 => {},
153152 .TIMEOUT => return error.WaitTimeOut,
154153 else => |status| return windows.unexpectedStatus(status),
test/tests.zig+129-177
......@@ -6,8 +6,6 @@ const OptimizeMode = std.builtin.OptimizeMode;
66const Step = std.Build.Step;
77
88// Cases
9const error_traces = @import("error_traces.zig");
10const stack_traces = @import("stack_traces.zig");
119const llvm_ir = @import("llvm_ir.zig");
1210const libc = @import("libc.zig");
1311const link = @import("link.zig");
......@@ -23,7 +21,7 @@ pub const LinkContext = @import("src/Link.zig");
2321const ModuleTestTarget = struct {
2422 linkage: ?std.builtin.LinkMode = null,
2523 target: std.Target.Query = .{},
26 optimize_mode: std.builtin.OptimizeMode = .Debug,
24 optimize_mode: std.builtin.OptimizeMode = .debug,
2725 link_libc: ?bool = null,
2826 single_threaded: ?bool = null,
2927 use_llvm: ?bool = null,
......@@ -57,38 +55,38 @@ const module_test_targets = blk: {
5755 },
5856
5957 .{
60 .optimize_mode = .ReleaseFast,
58 .optimize_mode = .fast,
6159 },
6260 .{
6361 .link_libc = true,
64 .optimize_mode = .ReleaseFast,
62 .optimize_mode = .fast,
6563 },
6664 .{
67 .optimize_mode = .ReleaseFast,
65 .optimize_mode = .fast,
6866 .single_threaded = true,
6967 },
7068
7169 .{
72 .optimize_mode = .ReleaseSafe,
70 .optimize_mode = .safe,
7371 },
7472 .{
7573 .link_libc = true,
76 .optimize_mode = .ReleaseSafe,
74 .optimize_mode = .safe,
7775 },
7876 .{
79 .optimize_mode = .ReleaseSafe,
77 .optimize_mode = .safe,
8078 .single_threaded = true,
8179 },
8280
8381 .{
84 .optimize_mode = .ReleaseSmall,
82 .optimize_mode = .small,
8583 },
8684 .{
8785 .link_libc = true,
88 .optimize_mode = .ReleaseSmall,
86 .optimize_mode = .small,
8987 },
9088 .{
91 .optimize_mode = .ReleaseSmall,
89 .optimize_mode = .small,
9290 .single_threaded = true,
9391 },
9492
......@@ -200,7 +198,7 @@ const module_test_targets = blk: {
200198 // },
201199 // .use_llvm = false,
202200 // .use_lld = false,
203 // .optimize_mode = .ReleaseFast,
201 // .optimize_mode = .fast,
204202 // .strip = true,
205203 // .skip_modules = &.{"std"}, // TODO get these passing
206204 //},
......@@ -213,7 +211,7 @@ const module_test_targets = blk: {
213211 // },
214212 // .use_llvm = false,
215213 // .use_lld = false,
216 // .optimize_mode = .ReleaseFast,
214 // .optimize_mode = .fast,
217215 // .strip = true,
218216 // .skip_modules = &.{"std"}, // TODO get these passing
219217 //},
......@@ -274,6 +272,15 @@ const module_test_targets = blk: {
274272 },
275273 .link_libc = true,
276274 },
275 .{
276 .target = .{
277 .cpu_arch = .arm,
278 .os_tag = .linux,
279 .abi = .musleabi,
280 .ofmt = .c,
281 },
282 .link_libc = true,
283 },
277284 .{
278285 .target = .{
279286 .cpu_arch = .arm,
......@@ -292,6 +299,15 @@ const module_test_targets = blk: {
292299 },
293300 .link_libc = true,
294301 },
302 .{
303 .target = .{
304 .cpu_arch = .arm,
305 .os_tag = .linux,
306 .abi = .musleabihf,
307 .ofmt = .c,
308 },
309 .link_libc = true,
310 },
295311 .{
296312 .target = .{
297313 .cpu_arch = .arm,
......@@ -341,6 +357,15 @@ const module_test_targets = blk: {
341357 },
342358 .link_libc = true,
343359 },
360 .{
361 .target = .{
362 .cpu_arch = .armeb,
363 .os_tag = .linux,
364 .abi = .musleabi,
365 .ofmt = .c,
366 },
367 .link_libc = true,
368 },
344369 // Crashes in weird ways when applying relocations.
345370 // .{
346371 // .target = .{
......@@ -360,6 +385,15 @@ const module_test_targets = blk: {
360385 },
361386 .link_libc = true,
362387 },
388 .{
389 .target = .{
390 .cpu_arch = .armeb,
391 .os_tag = .linux,
392 .abi = .musleabihf,
393 .ofmt = .c,
394 },
395 .link_libc = true,
396 },
363397 // Crashes in weird ways when applying relocations.
364398 // .{
365399 // .target = .{
......@@ -419,6 +453,23 @@ const module_test_targets = blk: {
419453 .abi = .none,
420454 },
421455 },
456 .{
457 .target = .{
458 .cpu_arch = .loongarch32,
459 .os_tag = .linux,
460 .abi = .gnu,
461 },
462 .link_libc = true,
463 },
464 .{
465 .target = .{
466 .cpu_arch = .loongarch32,
467 .os_tag = .linux,
468 .abi = .gnusf,
469 },
470 .link_libc = true,
471 .extra_target = true,
472 },
422473
423474 .{
424475 .target = .{
......@@ -1107,6 +1158,15 @@ const module_test_targets = blk: {
11071158 },
11081159 .link_libc = true,
11091160 },
1161 .{
1162 .target = .{
1163 .cpu_arch = .x86,
1164 .os_tag = .linux,
1165 .abi = .musl,
1166 .ofmt = .c,
1167 },
1168 .link_libc = true,
1169 },
11101170 .{
11111171 .target = .{
11121172 .cpu_arch = .x86,
......@@ -1257,7 +1317,7 @@ const module_test_targets = blk: {
12571317 // },
12581318 // .use_llvm = false,
12591319 // .use_lld = false,
1260 // .optimize_mode = .ReleaseFast,
1320 // .optimize_mode = .fast,
12611321 // .strip = true,
12621322 //},
12631323
......@@ -1523,7 +1583,6 @@ const module_test_targets = blk: {
15231583 .os_tag = .wasi,
15241584 .abi = .none,
15251585 },
1526 .skip_modules = &.{"compiler-rt"},
15271586 .use_llvm = false,
15281587 .use_lld = false,
15291588 },
......@@ -1645,6 +1704,15 @@ const module_test_targets = blk: {
16451704 },
16461705 .link_libc = true,
16471706 },
1707 .{
1708 .target = .{
1709 .cpu_arch = .x86,
1710 .os_tag = .windows,
1711 .abi = .gnu,
1712 .ofmt = .c,
1713 },
1714 .link_libc = true,
1715 },
16481716
16491717 .{
16501718 .target = .{
......@@ -1961,7 +2029,6 @@ const c_abi_targets = blk: {
19612029 .abi = .musl,
19622030 },
19632031 .use_llvm = false,
1964 .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
19652032 },
19662033 .{
19672034 .target = .{
......@@ -1972,7 +2039,6 @@ const c_abi_targets = blk: {
19722039 },
19732040 .use_llvm = false,
19742041 .strip = true,
1975 .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
19762042 },
19772043 .{
19782044 .target = .{
......@@ -1983,7 +2049,6 @@ const c_abi_targets = blk: {
19832049 },
19842050 .use_llvm = false,
19852051 .pic = true,
1986 .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
19872052 },
19882053 .{
19892054 .target = .{
......@@ -2010,6 +2075,15 @@ const c_abi_targets = blk: {
20102075 .abi = .musl,
20112076 },
20122077 },
2078 .{
2079 .target = .{
2080 .cpu_arch = .wasm32,
2081 .os_tag = .wasi,
2082 .abi = .musl,
2083 },
2084 .use_llvm = false,
2085 .use_lld = false,
2086 },
20132087
20142088 // Windows Targets
20152089
......@@ -2028,7 +2102,6 @@ const c_abi_targets = blk: {
20282102 .abi = .gnu,
20292103 },
20302104 .use_llvm = false,
2031 .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
20322105 },
20332106 .{
20342107 .target = .{
......@@ -2038,7 +2111,6 @@ const c_abi_targets = blk: {
20382111 .abi = .gnu,
20392112 },
20402113 .use_llvm = false,
2041 .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
20422114 },
20432115 .{
20442116 .target = .{
......@@ -2048,7 +2120,6 @@ const c_abi_targets = blk: {
20482120 .abi = .gnu,
20492121 },
20502122 .use_llvm = false,
2051 .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
20522123 },
20532124 .{
20542125 .target = .{
......@@ -2063,7 +2134,7 @@ const c_abi_targets = blk: {
20632134
20642135const LinkTarget = struct {
20652136 target: std.Target.Query = .{},
2066 optimize_mode: std.builtin.OptimizeMode = .Debug,
2137 optimize_mode: std.builtin.OptimizeMode = .debug,
20672138 link_libc: bool = false,
20682139 use_llvm: bool = false,
20692140 use_lld: bool = false,
......@@ -2308,59 +2379,7 @@ pub fn isNative(actual_target: *const std.Build.ResolvedTarget, host: *const std
23082379 return true;
23092380}
23102381
2311/// For stack trace tests, we only test native by default, because external executors are pretty
2312/// unreliable at stack tracing. However, if there's a 32-bit equivalent target which the host can
2313/// trivially run, we may as well at least test that!
2314fn nativeAndCompatible32bit(b: *std.Build, skip_non_native: bool) []const std.Build.ResolvedTarget {
2315 const host = b.graph.host.result;
2316 const only_native = (&b.graph.host)[0..1];
2317 if (skip_non_native) return only_native;
2318 const arch32 = compatible32bitArch(&b.graph.host.result) orelse return only_native;
2319 return b.graph.arena.dupe(std.Build.ResolvedTarget, &.{
2320 b.graph.host,
2321 b.resolveTargetQuery(.{ .cpu_arch = arch32, .os_tag = host.os.tag }),
2322 }) catch @panic("OOM");
2323}
2324
2325fn wineAndCompatible32bit(b: *std.Build, skip_non_native: bool) []const std.Build.ResolvedTarget {
2326 var targets: std.ArrayList(std.Build.ResolvedTarget) = .empty;
2327
2328 const host = b.graph.host.result;
2329
2330 targets.append(b.graph.arena, b.resolveTargetQuery(.{
2331 .cpu_arch = host.cpu.arch,
2332 .os_tag = .windows,
2333 })) catch @panic("OOM");
2334 if (!skip_non_native) {
2335 if (compatible32bitArch(&b.graph.host.result)) |arch| {
2336 targets.append(b.graph.arena, b.resolveTargetQuery(.{
2337 .cpu_arch = arch,
2338 .os_tag = .windows,
2339 })) catch @panic("OOM");
2340 }
2341 }
2342
2343 return targets.toOwnedSlice(b.graph.arena) catch @panic("OOM");
2344}
2345
2346fn darlingTargets(b: *std.Build) []const std.Build.ResolvedTarget {
2347 var targets: std.ArrayList(std.Build.ResolvedTarget) = .empty;
2348
2349 const host = b.graph.host.result;
2350
2351 targets.append(b.graph.arena, b.resolveTargetQuery(.{
2352 .cpu_arch = host.cpu.arch,
2353 .os_tag = .macos,
2354 })) catch @panic("OOM");
2355
2356 return targets.toOwnedSlice(b.graph.arena) catch @panic("OOM");
2357}
2358
2359pub fn addStackTraceTests(
2360 b: *std.Build,
2361 test_filters: []const []const u8,
2362 skip_non_native: bool,
2363) *Step {
2382pub fn addStackTraceTests(b: *std.Build, test_filters: []const []const u8, skip_non_native: bool) *Step {
23642383 const step = b.step("test-stack-traces", "Run the stack trace tests");
23652384
23662385 const convert_exe = b.addExecutable(.{
......@@ -2368,43 +2387,19 @@ pub fn addStackTraceTests(
23682387 .root_module = b.createModule(.{
23692388 .root_source_file = b.path("test/src/convert-stack-trace.zig"),
23702389 .target = b.graph.host,
2371 .optimize = .Debug,
2390 .optimize = .debug,
23722391 }),
23732392 });
23742393
2375 const host_cases = b.allocator.create(StackTracesContext) catch @panic("OOM");
2376 host_cases.* = .{
2394 const stack_traces_context = b.allocator.create(StackTracesContext) catch @panic("OOM");
2395 stack_traces_context.* = .{
23772396 .b = b,
23782397 .step = step,
23792398 .test_filters = test_filters,
2380 .targets = nativeAndCompatible32bit(b, skip_non_native),
2399 .skip_non_native = skip_non_native,
23812400 .convert_exe = convert_exe,
23822401 };
2383 stack_traces.addCases(host_cases, b.graph.host.result.os.tag);
2384
2385 if (b.enable_wine) {
2386 const wine_cases = b.allocator.create(StackTracesContext) catch @panic("OOM");
2387 wine_cases.* = .{
2388 .b = b,
2389 .step = step,
2390 .test_filters = test_filters,
2391 .targets = wineAndCompatible32bit(b, skip_non_native),
2392 .convert_exe = convert_exe,
2393 };
2394 stack_traces.addCases(wine_cases, .windows);
2395 }
2396
2397 if (b.enable_darling) {
2398 const darling_cases = b.allocator.create(StackTracesContext) catch @panic("OOM");
2399 darling_cases.* = .{
2400 .b = b,
2401 .step = step,
2402 .test_filters = test_filters,
2403 .targets = darlingTargets(b),
2404 .convert_exe = convert_exe,
2405 };
2406 stack_traces.addCases(darling_cases, .macos);
2407 }
2402 stack_traces_context.addCases();
24082403
24092404 return step;
24102405}
......@@ -2422,56 +2417,24 @@ pub fn addErrorTraceTests(
24222417 .root_module = b.createModule(.{
24232418 .root_source_file = b.path("test/src/convert-stack-trace.zig"),
24242419 .target = b.graph.host,
2425 .optimize = .Debug,
2420 .optimize = .debug,
24262421 }),
24272422 });
24282423
2429 const host_cases = b.allocator.create(ErrorTracesContext) catch @panic("OOM");
2430 host_cases.* = .{
2424 const error_traces_context = b.allocator.create(ErrorTracesContext) catch @panic("OOM");
2425 error_traces_context.* = .{
24312426 .b = b,
24322427 .step = step,
24332428 .test_filters = test_filters,
2434 .targets = nativeAndCompatible32bit(b, skip_non_native),
2429 .skip_non_native = skip_non_native,
24352430 .optimize_modes = optimize_modes,
24362431 .convert_exe = convert_exe,
24372432 };
2438 error_traces.addCases(host_cases, b.graph.host.result.os.tag);
2439
2440 if (b.enable_wine) {
2441 const wine_cases = b.allocator.create(ErrorTracesContext) catch @panic("OOM");
2442 wine_cases.* = .{
2443 .b = b,
2444 .step = step,
2445 .test_filters = test_filters,
2446 .targets = wineAndCompatible32bit(b, skip_non_native),
2447 .optimize_modes = optimize_modes,
2448 .convert_exe = convert_exe,
2449 };
2450 error_traces.addCases(wine_cases, .windows);
2451 }
2452
2453 if (b.enable_darling) {
2454 const darling_cases = b.allocator.create(ErrorTracesContext) catch @panic("OOM");
2455 darling_cases.* = .{
2456 .b = b,
2457 .step = step,
2458 .test_filters = test_filters,
2459 .targets = darlingTargets(b),
2460 .optimize_modes = optimize_modes,
2461 .convert_exe = convert_exe,
2462 };
2463 error_traces.addCases(darling_cases, .macos);
2464 }
2433 error_traces_context.addCases();
24652434
24662435 return step;
24672436}
24682437
2469fn compilerHasPackageManager(b: *std.Build) bool {
2470 // We can only use dependencies if the compiler was built with support for package management.
2471 // (zig2 doesn't support it, but we still need to construct a build graph to build stage3.)
2472 return b.available_deps.len != 0;
2473}
2474
24752438pub fn addStandaloneTests(
24762439 b: *std.Build,
24772440 optimize_modes: []const OptimizeMode,
......@@ -2480,21 +2443,19 @@ pub fn addStandaloneTests(
24802443 enable_symlinks_windows: bool,
24812444) *Step {
24822445 const step = b.step("test-standalone", "Run the standalone tests");
2483 if (compilerHasPackageManager(b)) {
2484 const test_cases_dep_name = "standalone_test_cases";
2485 const test_cases_dep = b.dependency(test_cases_dep_name, .{
2486 .enable_ios_sdk = enable_ios_sdk,
2487 .enable_macos_sdk = enable_macos_sdk,
2488 .enable_symlinks_windows = enable_symlinks_windows,
2489 .simple_skip_debug = mem.indexOfScalar(OptimizeMode, optimize_modes, .Debug) == null,
2490 .simple_skip_release_safe = mem.indexOfScalar(OptimizeMode, optimize_modes, .ReleaseSafe) == null,
2491 .simple_skip_release_fast = mem.indexOfScalar(OptimizeMode, optimize_modes, .ReleaseFast) == null,
2492 .simple_skip_release_small = mem.indexOfScalar(OptimizeMode, optimize_modes, .ReleaseSmall) == null,
2493 });
2494 const test_cases_dep_step = test_cases_dep.builder.default_step;
2495 test_cases_dep_step.name = b.dupe(test_cases_dep_name);
2496 step.dependOn(test_cases_dep.builder.default_step);
2497 }
2446 const test_cases_dep_name = "standalone_test_cases";
2447 const test_cases_dep = b.dependency(test_cases_dep_name, .{
2448 .enable_ios_sdk = enable_ios_sdk,
2449 .enable_macos_sdk = enable_macos_sdk,
2450 .enable_symlinks_windows = enable_symlinks_windows,
2451 .simple_skip_debug = mem.findScalar(OptimizeMode, optimize_modes, .debug) == null,
2452 .simple_skip_release_safe = mem.findScalar(OptimizeMode, optimize_modes, .safe) == null,
2453 .simple_skip_release_fast = mem.findScalar(OptimizeMode, optimize_modes, .fast) == null,
2454 .simple_skip_release_small = mem.findScalar(OptimizeMode, optimize_modes, .small) == null,
2455 });
2456 const test_cases_dep_step = test_cases_dep.builder.default_step;
2457 test_cases_dep_step.name = b.graph.dupeString(test_cases_dep_name);
2458 step.dependOn(test_cases_dep.builder.default_step);
24982459 return step;
24992460}
25002461
......@@ -2782,16 +2743,6 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
27822743
27832744 const target = &resolved_target.result;
27842745
2785 if (target.cpu.arch == .s390x and target.ofmt == .c) {
2786 // https://codeberg.org/ziglang/zig/issues/35523
2787 continue;
2788 }
2789
2790 if (target.cpu.arch == .riscv64 and target.ofmt == .c) {
2791 // https://codeberg.org/ziglang/zig/issues/30930
2792 continue;
2793 }
2794
27952746 if (std.mem.eql(u8, options.name, "libc")) {
27962747 // The libc API tests obviously need to link libc. So for test
27972748 // target entries where we wouldn't link libc by default, skip the
......@@ -2816,7 +2767,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
28162767
28172768 if (options.test_target_filters.len > 0) {
28182769 for (options.test_target_filters) |filter| {
2819 if (std.mem.indexOf(u8, triple_txt, filter) != null) break;
2770 if (std.mem.find(u8, triple_txt, filter) != null) break;
28202771 } else continue;
28212772 }
28222773
......@@ -3057,7 +3008,7 @@ pub fn wouldUseLlvm(use_llvm: ?bool, query: std.Target.Query, optimize_mode: Opt
30573008 if (use_llvm) |x| return x;
30583009 if (query.ofmt == .c) return false;
30593010 switch (optimize_mode) {
3060 .Debug => {},
3011 .debug => {},
30613012 else => return true,
30623013 }
30633014 const cpu_arch = query.cpu_arch orelse builtin.cpu.arch;
......@@ -3114,7 +3065,7 @@ pub fn addCAbiTests(b: *std.Build, options: CAbiTestOptions) *Step {
31143065
31153066 if (options.test_target_filters.len > 0) {
31163067 for (options.test_target_filters) |filter| {
3117 if (std.mem.indexOf(u8, triple_txt, filter) != null) break;
3068 if (std.mem.find(u8, triple_txt, filter) != null) break;
31183069 } else continue;
31193070 }
31203071
......@@ -3203,7 +3154,7 @@ pub fn addLinkTests(b: *std.Build, options: LinkTestOptions) *Step {
32033154
32043155 if (options.test_target_filters.len > 0) {
32053156 for (options.test_target_filters) |filter| {
3206 if (std.mem.indexOf(u8, triple_txt, filter) != null) break;
3157 if (std.mem.find(u8, triple_txt, filter) != null) break;
32073158 } else continue;
32083159 }
32093160
......@@ -3314,7 +3265,7 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step, test_filters: []cons
33143265 .root_module = b.createModule(.{
33153266 .root_source_file = b.path("tools/incr-check.zig"),
33163267 .target = b.graph.host,
3317 .optimize = .Debug,
3268 .optimize = .debug,
33183269 }),
33193270 });
33203271
......@@ -3328,7 +3279,7 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step, test_filters: []cons
33283279 if (std.mem.endsWith(u8, entry.basename, ".swp")) continue;
33293280
33303281 for (test_filters) |test_filter| {
3331 if (std.mem.indexOf(u8, entry.path, test_filter)) |_| break;
3282 if (std.mem.find(u8, entry.path, test_filter)) |_| break;
33323283 } else if (test_filters.len > 0) continue;
33333284
33343285 switch (entry.kind) {
......@@ -3354,10 +3305,11 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step, test_filters: []cons
33543305
33553306 run.addArg("--quiet"); // don't fill stderr telling us about skipped tests etc
33563307
3357 if (b.enable_qemu) run.addArg("-fqemu");
3358 if (b.enable_wine) run.addArg("-fwine");
3359 if (b.enable_wasmtime) run.addArg("-fwasmtime");
3360 if (b.enable_darling) run.addArg("-fdarling");
3308 run.addThirdPartyEnabledArgDarling(.{ .enabled = "-fdarling" });
3309 run.addThirdPartyEnabledArgQemu(.{ .enabled = "-fqemu" });
3310 run.addThirdPartyEnabledArgRosetta(.{ .enabled = "-frosetta" });
3311 run.addThirdPartyEnabledArgWasmtime(.{ .enabled = "-fwasmtime" });
3312 run.addThirdPartyEnabledArgWine(.{ .enabled = "-fwine" });
33613313
33623314 run.addCheck(.{ .expect_term = .{ .exited = 0 } });
33633315 test_step.dependOn(&run.step);
tools/bsp.zig created+242
......@@ -0,0 +1,242 @@
1//! CLI tool to interface with the build system protocol (zig build --listen=-)
2
3const std = @import("std");
4const Io = std.Io;
5const Allocator = std.mem.Allocator;
6const Configuration = std.Build.Configuration;
7const Client = std.zig.Client;
8const Server = std.zig.Server;
9const log = std.log.scoped(.bsp);
10
11pub fn main(init: std.process.Init) !void {
12 const io = init.io;
13 const gpa = init.gpa;
14 const arena = init.arena.allocator();
15
16 var maker_args: std.ArrayList([]const u8) = .empty;
17
18 const args = try init.minimal.args.toSlice(arena);
19 for (args[1..]) |arg| {
20 try maker_args.append(arena, try arena.dupe(u8, arg));
21 }
22 if (maker_args.items.len < 1) try maker_args.append(arena, "zig");
23 if (maker_args.items.len < 2) try maker_args.append(arena, "build");
24 if (!std.mem.eql(u8, maker_args.last().?, "--listen=-")) try maker_args.append(arena, "--listen=-");
25
26 log.debug("cmd: {f}", .{std.zig.SubprocessCommand{
27 .argv = maker_args.items,
28 }});
29
30 var child_process = std.process.spawn(io, .{
31 .argv = maker_args.items,
32 .stdin = .pipe,
33 .stdout = .pipe,
34 .stderr = .pipe,
35 }) catch |err| std.debug.panic("failed to spawn process: {}", .{err});
36 errdefer child_process.kill(io);
37
38 var multi_reader_buffer: Io.File.MultiReader.Buffer(2) = undefined;
39 var multi_reader: Io.File.MultiReader = undefined;
40 defer multi_reader.deinit();
41 multi_reader.init(
42 gpa,
43 io,
44 multi_reader_buffer.toStreams(),
45 &.{ child_process.stdout.?, child_process.stderr.? },
46 );
47 const client_stdout = multi_reader.reader(0);
48 const client_stderr = multi_reader.reader(1);
49
50 var client_stdout_buffer: [256]u8 = undefined;
51 var client_stdout_writer = child_process.stdin.?.writerStreaming(io, &client_stdout_buffer);
52
53 var client: Client = .{
54 .in = client_stdout,
55 .out = &client_stdout_writer.interface,
56 };
57
58 const err = blk: {
59 const handshake: Server.Message.Handshake = handshake: {
60 const header = client.receiveMessageWithMultiReader(&multi_reader, .none) catch |err| switch (err) {
61 error.Canceled, error.ConcurrencyUnavailable => |e| return e,
62 error.Timeout => unreachable,
63 else => |e| {
64 log.err("failed to receive message: {t}", .{err});
65 break :blk e;
66 },
67 };
68 const body = client_stdout.take(header.bytes_len) catch unreachable;
69 log.debug("received {f} ({d} bytes)", .{ fmtEnum(header.tag), body.len });
70
71 if (header.tag != .bsp_handshake) {
72 log.err("received unexpected message: {f}", .{fmtEnum(header.tag)});
73 return error.UnexpectedMessage;
74 }
75
76 var r: Io.Reader = .fixed(body);
77 break :handshake try r.takeStruct(Server.Message.Handshake, .little);
78 };
79 _ = handshake;
80
81 var conf_arena_allocator: std.heap.ArenaAllocator = .init(gpa);
82 defer conf_arena_allocator.deinit();
83 const conf_arena = conf_arena_allocator.allocator();
84
85 const configuration = configuration: {
86 const header = client.receiveMessageWithMultiReader(&multi_reader, .none) catch |err| switch (err) {
87 error.Canceled, error.ConcurrencyUnavailable => |e| return e,
88 error.Timeout => unreachable,
89 else => |e| {
90 log.err("failed to receive message: {t}", .{err});
91 break :blk e;
92 },
93 };
94 const body = client_stdout.take(header.bytes_len) catch unreachable;
95 log.debug("received {t} ({d} bytes)", .{ header.tag, body.len });
96
97 if (header.tag != .bsp_configuration) {
98 log.err("received unexpected message: {f}", .{fmtEnum(header.tag)});
99 return error.UnexpectedMessage;
100 }
101
102 const configuration_path = body;
103 var file = Io.Dir.cwd().openFile(io, configuration_path, .{}) catch |err|
104 std.debug.panic("failed to open configuration file {q}: {t}", .{ configuration_path, err });
105 defer file.close(io);
106 break :configuration Configuration.loadFile(conf_arena, io, file) catch |err|
107 std.debug.panic("failed to load configuration file {q}: {t}", .{ configuration_path, err });
108 };
109 const c = &configuration;
110
111 var top_level_steps: std.array_hash_map.String(Configuration.Step.Index) = .empty;
112 defer top_level_steps.deinit(gpa);
113
114 for (c.steps, 0..) |*conf_step, step_index_usize| {
115 if (conf_step.owner != .root) continue;
116 const step_index: Configuration.Step.Index = @fromBackingInt(@intCast(step_index_usize));
117 const flags = conf_step.flags(c);
118 if (flags.tag != .top_level) continue;
119 const name = step_index.ptr(c).name.slice(c);
120 try top_level_steps.putNoClobber(gpa, name, step_index);
121 }
122
123 std.debug.print("Steps:\n", .{});
124 for (top_level_steps.keys()) |name| {
125 std.debug.print(" - {q}\n", .{name});
126 }
127 std.debug.print(
128 \\Available Commands:
129 \\ - build [step names / step indices]
130 \\ - watch [step names / step indices]
131 \\ - exit
132 \\
133 , .{});
134
135 var stdin_reader_buffer: [256]u8 = undefined;
136 var stdin_reader = Io.File.stdin().reader(io, &stdin_reader_buffer);
137 const stdin = &stdin_reader.interface;
138
139 while (true) {
140 try Io.File.stdout().writeStreamingAll(io, "> ");
141 const command = try stdin.takeDelimiterExclusive('\n');
142 stdin.toss(1);
143 if (std.mem.startsWith(u8, command, "build") or
144 std.mem.startsWith(u8, command, "watch"))
145 {
146 var steps: std.ArrayList(Configuration.Step.Index) = .empty;
147 defer steps.deinit(gpa);
148
149 const watch = std.mem.startsWith(u8, command, "watch");
150
151 if (std.mem.cutPrefix(u8, command, "build ") orelse
152 std.mem.cutPrefix(u8, command, "watch ")) |command_args|
153 {
154 var it = std.mem.tokenizeScalar(u8, command_args, ' ');
155 while (it.next()) |arg| {
156 const step: Configuration.Step.Index =
157 if (std.fmt.parseInt(u32, arg, 10)) |i|
158 @fromBackingInt(i)
159 else |_|
160 top_level_steps.get(arg) orelse std.debug.panic("unexpected step name or index", .{});
161 try steps.append(gpa, step);
162 }
163 }
164
165 if (steps.items.len < 1) {
166 try steps.append(gpa, c.default_step);
167 }
168
169 try client.serveBuildSteps(steps.items, .{ .watch = watch });
170
171 while (true) {
172 const header: Server.Message.Header = client.receiveMessageWithMultiReader(&multi_reader, .none) catch |err| switch (err) {
173 error.Canceled, error.ConcurrencyUnavailable => |e| return e,
174 error.Timeout => unreachable,
175 else => |e| {
176 log.err("failed to receive message: {t}", .{err});
177 break :blk e;
178 },
179 };
180 const body = client_stdout.take(header.bytes_len) catch unreachable;
181 log.debug("received {f} ({d} bytes)", .{ fmtEnum(header.tag), body.len });
182
183 switch (header.tag) {
184 .bsp_build_started => {},
185 .bsp_build_completed => if (!watch) break,
186 .bsp_step_started => {},
187 .bsp_step_completed => {},
188 .bsp_configuration => @panic("TODO"),
189 else => std.debug.panic("received unexpected message: {f}", .{fmtEnum(header.tag)}),
190 }
191 }
192 continue;
193 } else if (std.mem.eql(u8, command, "exit")) {
194 try client.serveBodylessMessage(.exit);
195 break;
196 } else {
197 log.err("unknown command: {q}", .{command});
198 continue;
199 }
200 }
201 };
202
203 try multi_reader.fillRemaining(.none);
204
205 if (client_stderr.bufferedLen() > 0) {
206 log.err("stderr:\n{s}\n", .{client_stderr.buffered()});
207 }
208
209 try err;
210
211 const term = try child_process.wait(io);
212
213 if (!term.success()) {
214 log.err("maker {f}", .{term});
215 }
216}
217
218const FormatEnum = union(enum) {
219 named: []const u8,
220 unnamed: usize,
221
222 pub fn format(
223 e: FormatEnum,
224 writer: *std.Io.Writer,
225 ) std.Io.Writer.Error!void {
226 switch (e) {
227 .named => |name| {
228 try writer.writeByte('.');
229 try writer.writeAll(name);
230 },
231 .unnamed => |number| try writer.print("0x{x}", .{number}),
232 }
233 }
234};
235
236fn fmtEnum(e: anytype) FormatEnum {
237 if (std.enums.tagName(@TypeOf(e), e)) |name| {
238 return .{ .named = name };
239 } else {
240 return .{ .unnamed = @backingInt(e) };
241 }
242}
tools/docgen.zig+2-2
......@@ -712,10 +712,10 @@ fn tokenizeAndPrintRaw(
712712 next_tok_is_fn = false;
713713
714714 const token = tokenizer.next();
715 if (mem.indexOf(u8, src[index..token.loc.start], "//")) |comment_start_off| {
715 if (mem.find(u8, src[index..token.loc.start], "//")) |comment_start_off| {
716716 // render one comment
717717 const comment_start = index + comment_start_off;
718 const comment_end_off = mem.indexOf(u8, src[comment_start..token.loc.start], "\n");
718 const comment_end_off = mem.find(u8, src[comment_start..token.loc.start], "\n");
719719 const comment_end = if (comment_end_off) |o| comment_start + o else token.loc.start;
720720
721721 try writeEscapedLines(out, src[index..comment_start]);
tools/doctest.zig+11-11
......@@ -383,7 +383,7 @@ fn printOutput(
383383 fatal("example compile crashed", .{});
384384 },
385385 }
386 if (mem.indexOf(u8, result.stderr, error_match) == null) {
386 if (mem.find(u8, result.stderr, error_match) == null) {
387387 print("{s}\nExpected to find '{s}' in stderr\n", .{ result.stderr, error_match });
388388 fatal("example did not have expected compile error", .{});
389389 }
......@@ -438,7 +438,7 @@ fn printOutput(
438438 fatal("example compile crashed", .{});
439439 },
440440 }
441 if (mem.indexOf(u8, result.stderr, error_match) == null) {
441 if (mem.find(u8, result.stderr, error_match) == null) {
442442 print("{s}\nExpected to find '{s}' in stderr\n", .{ result.stderr, error_match });
443443 fatal("example did not have expected runtime safety error message", .{});
444444 }
......@@ -513,7 +513,7 @@ fn printOutput(
513513 fatal("example compile crashed", .{});
514514 },
515515 }
516 if (mem.indexOf(u8, result.stderr, error_match) == null) {
516 if (mem.find(u8, result.stderr, error_match) == null) {
517517 print("{s}\nExpected to find '{s}' in stderr\n", .{ result.stderr, error_match });
518518 fatal("example did not have expected compile error message", .{});
519519 }
......@@ -623,10 +623,10 @@ fn tokenizeAndPrint(arena: Allocator, out: *Writer, raw_src: []const u8) !void {
623623 next_tok_is_fn = false;
624624
625625 const token = tokenizer.next();
626 if (mem.indexOf(u8, src[index..token.loc.start], "//")) |comment_start_off| {
626 if (mem.find(u8, src[index..token.loc.start], "//")) |comment_start_off| {
627627 // render one comment
628628 const comment_start = index + comment_start_off;
629 const comment_end_off = mem.indexOf(u8, src[comment_start..token.loc.start], "\n");
629 const comment_end_off = mem.find(u8, src[comment_start..token.loc.start], "\n");
630630 const comment_end = if (comment_end_off) |o| comment_start + o else token.loc.start;
631631
632632 try writeEscapedLines(out, src[index..comment_start]);
......@@ -870,13 +870,13 @@ const Code = struct {
870870};
871871
872872fn stripManifest(source_bytes: []const u8) []const u8 {
873 const manifest_start = mem.lastIndexOf(u8, source_bytes, "\n\n// ") orelse
873 const manifest_start = mem.findLast(u8, source_bytes, "\n\n// ") orelse
874874 fatal("missing manifest comment", .{});
875875 return source_bytes[0 .. manifest_start + 1];
876876}
877877
878878fn parseManifest(arena: Allocator, source_bytes: []const u8) !Code {
879 const manifest_start = mem.lastIndexOf(u8, source_bytes, "\n\n// ") orelse
879 const manifest_start = mem.findLast(u8, source_bytes, "\n\n// ") orelse
880880 fatal("missing manifest comment", .{});
881881 var it = mem.tokenizeScalar(u8, source_bytes[manifest_start..], '\n');
882882 const first_line = skipPrefix(it.next().?);
......@@ -915,11 +915,11 @@ fn parseManifest(arena: Allocator, source_bytes: []const u8) !Code {
915915 while (it.next()) |prefixed_line| {
916916 const line = skipPrefix(prefixed_line);
917917 if (mem.startsWith(u8, line, "optimize=")) {
918 mode = std.meta.stringToEnum(std.builtin.OptimizeMode, line["optimize=".len..]) orelse
919 fatal("bad optimization mode line: '{s}'", .{line});
918 mode = std.builtin.Optimize.fromString(line["optimize=".len..]) orelse
919 fatal("bad optimization mode line: {q}", .{line});
920920 } else if (mem.startsWith(u8, line, "link_mode=")) {
921921 link_mode = std.meta.stringToEnum(std.builtin.LinkMode, line["link_mode=".len..]) orelse
922 fatal("bad link mode line: '{s}'", .{line});
922 fatal("bad link mode line: {q}", .{line});
923923 } else if (mem.startsWith(u8, line, "link_object=")) {
924924 try link_objects.append(arena, line["link_object=".len..]);
925925 } else if (mem.startsWith(u8, line, "additional_option=")) {
......@@ -1104,7 +1104,7 @@ fn termColor(allocator: Allocator, input: []const u8) ![]u8 {
11041104
11051105// Returns true if number is in slice.
11061106fn in(slice: []const u8, number: u8) bool {
1107 return mem.indexOfScalar(u8, slice, number) != null;
1107 return mem.findScalar(u8, slice, number) != null;
11081108}
11091109
11101110fn run(
tools/fetch_them_macos_headers.zig+2-2
......@@ -187,8 +187,8 @@ fn fetchTarget(
187187
188188 var it = mem.splitScalar(u8, headers_list_str, '\n');
189189 while (it.next()) |line| {
190 if (mem.lastIndexOf(u8, line, "clang") != null) continue;
191 if (mem.lastIndexOf(u8, line, prefix[0..])) |idx| {
190 if (mem.findLast(u8, line, "clang") != null) continue;
191 if (mem.findLast(u8, line, prefix[0..])) |idx| {
192192 const out_rel_path = line[idx + prefix.len + 1 ..];
193193 const out_rel_path_stripped = mem.trim(u8, out_rel_path, " \\");
194194 const dirname = Dir.path.dirname(out_rel_path_stripped) orelse ".";
tools/generate_c_size_and_align_checks.zig deleted-62
......@@ -1,62 +0,0 @@
1//! Usage: zig run tools/generate_c_size_and_align_checks.zig -- [target_triple]
2//! e.g. zig run tools/generate_c_size_and_align_checks.zig -- x86_64-linux-gnu
3//!
4//! Prints _Static_asserts for the size and alignment of all the basic built-in C
5//! types. The output can be run through a compiler for the specified target to
6//! verify that Zig's values are the same as those used by a C compiler for the
7//! target.
8
9const std = @import("std");
10const Io = std.Io;
11
12fn cName(ty: std.Target.CType) []const u8 {
13 return switch (ty) {
14 .char => "char",
15 .short => "short",
16 .ushort => "unsigned short",
17 .int => "int",
18 .uint => "unsigned int",
19 .long => "long",
20 .ulong => "unsigned long",
21 .longlong => "long long",
22 .ulonglong => "unsigned long long",
23 .float => "float",
24 .double => "double",
25 .longdouble => "long double",
26 };
27}
28
29var general_purpose_allocator: std.heap.DebugAllocator(.{}) = .init;
30
31pub fn main(init: std.process.Init) !void {
32 const args = try init.minimal.args.toSlice(init.arena.allocator());
33 const io = init.io;
34
35 if (args.len != 2) {
36 std.debug.print("Usage: {s} [target_triple]\n", .{args[0]});
37 std.process.exit(1);
38 }
39
40 const query = try std.Target.Query.parse(.{ .arch_os_abi = args[1] });
41 const target = try std.zig.system.resolveTargetQuery(io, query);
42
43 var buffer: [2000]u8 = undefined;
44 var stdout_writer = Io.File.stdout().writerStreaming(io, &buffer);
45 const w = &stdout_writer.interface;
46 inline for (@typeInfo(std.Target.CType).@"enum".field_values) |field_value| {
47 const c_type: std.Target.CType = @fromBackingInt(@intCast(field_value));
48 try w.print("_Static_assert(sizeof({0s}) == {1d}, \"sizeof({0s}) == {1d}\");\n", .{
49 cName(c_type),
50 target.cTypeByteSize(c_type),
51 });
52 try w.print("_Static_assert(_Alignof({0s}) == {1d}, \"_Alignof({0s}) == {1d}\");\n", .{
53 cName(c_type),
54 target.cTypeAlignment(c_type),
55 });
56 try w.print("_Static_assert(__alignof({0s}) == {1d}, \"__alignof({0s}) == {1d}\");\n\n", .{
57 cName(c_type),
58 target.cTypePreferredAlignment(c_type),
59 });
60 }
61 try w.flush();
62}
tools/incr-check.zig+37-33
......@@ -305,21 +305,23 @@ const Eval = struct {
305305
306306 fn check(eval: *Eval, mr: *Io.File.MultiReader, update: Case.Update, prog_node: std.Progress.Node) !void {
307307 const arena = eval.arena;
308 const stdout = mr.fileReader(0);
309 const stderr = &mr.fileReader(1).interface;
310 const Header = std.zig.Server.Message.Header;
308 const stdout = mr.reader(0);
309 const stderr = mr.reader(1);
310
311 var client: std.zig.Client = .{
312 .in = stdout,
313 .out = undefined,
314 };
311315
312316 while (true) {
313 const header = stdout.interface.takeStruct(Header, .little) catch |err| switch (err) {
314 error.EndOfStream => break,
315 error.ReadFailed => return stdout.err.?,
316 };
317 const body = stdout.interface.take(header.bytes_len) catch |err| switch (err) {
317 const header = client.receiveMessageWithMultiReader(mr, .none) catch |err| switch (err) {
318 error.Timeout => unreachable,
318319 // If this panic triggers it might be helpful to rework this
319320 // code to print the stderr from the abnormally terminated child.
320321 error.EndOfStream => @panic("unexpected mid-message end of stream"),
321 error.ReadFailed => return stdout.err.?,
322 else => |e| return e,
322323 };
324 const body = client.in.take(header.bytes_len) catch unreachable;
323325
324326 switch (header.tag) {
325327 .error_bundle => {
......@@ -448,7 +450,7 @@ const Eval = struct {
448450 const raw_filename = eb.nullTerminatedString(src.src_path);
449451 // We need to replace backslashes for consistency between platforms.
450452 const filename = name: {
451 if (std.mem.indexOfScalar(u8, raw_filename, '\\') == null) break :name raw_filename;
453 if (std.mem.findScalar(u8, raw_filename, '\\') == null) break :name raw_filename;
452454 const copied = try eval.arena.dupe(u8, raw_filename);
453455 std.mem.replaceScalar(u8, copied, '\\', '/');
454456 break :name copied;
......@@ -605,12 +607,13 @@ const Eval = struct {
605607
606608 fn requestUpdate(eval: *Eval) !void {
607609 const io = eval.io;
608 const header: std.zig.Client.Message.Header = .{
609 .tag = .update,
610 .bytes_len = 0,
610
611 var w = eval.child.stdin.?.writerStreaming(io, &.{});
612 var client: std.zig.Client = .{
613 .in = undefined,
614 .out = &w.interface,
611615 };
612 var w = eval.child.stdin.?.writer(io, &.{});
613 w.interface.writeStruct(header, .little) catch |err| switch (err) {
616 client.serveBodylessMessage(.update) catch |err| switch (err) {
614617 error.WriteFailed => return w.err.?,
615618 };
616619 }
......@@ -618,22 +621,23 @@ const Eval = struct {
618621 fn end(eval: *Eval, mr: *Io.File.MultiReader) !void {
619622 requestExit(eval.child, eval);
620623
621 const stdout = mr.fileReader(0);
622 const Header = std.zig.Server.Message.Header;
624 var client: std.zig.Client = .{
625 .in = mr.reader(0),
626 .out = undefined,
627 };
623628
624629 while (true) {
625 const header = stdout.interface.takeStruct(Header, .little) catch |err| switch (err) {
626 error.EndOfStream => break,
627 error.ReadFailed => return stdout.err.?,
628 };
629 stdout.interface.discardAll(header.bytes_len) catch |err| switch (err) {
630 error.ReadFailed => return stdout.err.?,
631 error.EndOfStream => |e| return e,
630 const header = client.receiveMessageWithMultiReader(mr, .none) catch |err| switch (err) {
631 error.Timeout => unreachable,
632 error.EndOfStream => |e| {
633 if (client.in.bufferedLen() == 0) break;
634 return e;
635 },
636 else => |e| return e,
632637 };
638 try client.in.discardAll(header.bytes_len);
633639 }
634640
635 try mr.fillRemaining(.none);
636
637641 const stderr = mr.reader(1).buffered();
638642 if (stderr.len > 0) eval.fatal("unexpected stderr:\n{s}", .{stderr});
639643 }
......@@ -773,7 +777,7 @@ const Case = struct {
773777 .backend = backend,
774778 });
775779 } else if (std.mem.eql(u8, key, "module")) {
776 const split_idx = std.mem.indexOfScalar(u8, val, '=') orelse
780 const split_idx = std.mem.findScalar(u8, val, '=') orelse
777781 fatal("line {d}: module does not include file", .{line_n});
778782 const name = val[0..split_idx];
779783 const file = val[split_idx + 1 ..];
......@@ -899,12 +903,12 @@ fn requestExit(child: *std.process.Child, eval: *Eval) void {
899903 if (child.stdin == null) return;
900904 const io = eval.io;
901905
902 const header: std.zig.Client.Message.Header = .{
903 .tag = .exit,
904 .bytes_len = 0,
906 var w = eval.child.stdin.?.writerStreaming(io, &.{});
907 var client: std.zig.Client = .{
908 .in = undefined,
909 .out = &w.interface,
905910 };
906 var w = eval.child.stdin.?.writer(io, &.{});
907 w.interface.writeStruct(header, .little) catch |err| switch (err) {
911 client.serveBodylessMessage(.exit) catch |err| switch (err) {
908912 error.WriteFailed => switch (w.err.?) {
909913 error.BrokenPipe => {},
910914 else => |e| eval.fatal("failed to send exit: {t}", .{e}),
......@@ -979,7 +983,7 @@ fn rand64(io: Io) u64 {
979983fn parseTargetQueryAndBackend(input_str: []const u8, err_prefix: []const u8) struct { std.Target.Query, Backend } {
980984 const fatal = std.process.fatal;
981985
982 const split_idx = std.mem.lastIndexOfScalar(u8, input_str, '-') orelse
986 const split_idx = std.mem.findScalarLast(u8, input_str, '-') orelse
983987 fatal("{s}target does not include backend", .{err_prefix});
984988
985989 const query = input_str[0..split_idx];
tools/migrate_langref.zig+2-2
......@@ -319,7 +319,7 @@ fn walk(arena: Allocator, io: Io, tokenizer: *Tokenizer, out_dir: Dir, w: anytyp
319319 return parseError(tokenizer, code_kind_tok, "unrecognized code kind: {s}", .{code_kind_str});
320320 }
321321
322 var mode: std.builtin.OptimizeMode = .Debug;
322 var mode: std.builtin.OptimizeMode = .debug;
323323 var link_objects = std.array_list.Managed([]const u8).init(arena);
324324 var target_str: ?[]const u8 = null;
325325 var link_libc = false;
......@@ -403,7 +403,7 @@ fn walk(arena: Allocator, io: Io, tokenizer: *Tokenizer, out_dir: Dir, w: anytyp
403403 },
404404 }
405405
406 if (mode != .Debug)
406 if (mode != .debug)
407407 try code.print("// optimize={s}\n", .{@tagName(mode)});
408408
409409 for (link_objects.items) |link_object| {
tools/process_headers.zig+2
......@@ -36,6 +36,8 @@ const glibc_targets = [_]LibCTarget{
3636 .{ .arch = .aarch64_be, .abi = .gnu, .dest = "aarch64-linux-gnu" },
3737 .{ .arch = .csky, .abi = .gnueabi, .dest = "csky-linux-gnu" },
3838 .{ .arch = .csky, .abi = .gnueabihf, .dest = "csky-linux-gnu" },
39 .{ .arch = .loongarch32, .abi = .gnu, .dest = "loongarch-linux-gnu" },
40 .{ .arch = .loongarch32, .abi = .gnusf, .dest = "loongarch-linux-gnu" },
3941 .{ .arch = .loongarch64, .abi = .gnu, .dest = "loongarch-linux-gnu" },
4042 .{ .arch = .loongarch64, .abi = .gnusf, .dest = "loongarch-linux-gnu" },
4143 .{ .arch = .m68k, .abi = .gnu },
tools/update_clang_options.zig+1-1
......@@ -599,7 +599,7 @@ const known_options = [_]KnownOpt{
599599const blacklisted_options = [_][]const u8{};
600600
601601fn knownOption(name: []const u8) ?[]const u8 {
602 const chopped_name = if (std.mem.indexOfScalar(u8, name, '=')) |idx| name[0..idx] else name;
602 const chopped_name = if (std.mem.findScalar(u8, name, '=')) |idx| name[0..idx] else name;
603603 for (known_options) |item| {
604604 if (std.mem.eql(u8, chopped_name, item.name)) {
605605 return item.ident;
tools/update_crc_catalog.zig+1-1
......@@ -99,7 +99,7 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8)
9999
100100 var it = mem.splitSequence(u8, line, " ");
101101 while (it.next()) |property| {
102 const i = mem.indexOf(u8, property, "=").?;
102 const i = mem.find(u8, property, "=").?;
103103 const key = property[0..i];
104104 const value = property[i + 1 ..];
105105 if (mem.eql(u8, key, "width")) {
tools/update_glibc.zig+1
......@@ -36,6 +36,7 @@ const exempt_extensions = [_][]const u8{
3636 // These are the start files we use when targeting glibc <= 2.33.
3737 "-2.33.S",
3838 "-2.33.c",
39 "-2.32.c",
3940};
4041
4142pub fn main(init: std.process.Init) !void {