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:...@@ -153,7 +153,7 @@ jobs:
153 fetch-depth: 0153 fetch-depth: 0
154 - name: Build and Test154 - name: Build and Test
155 run: sh ci/s390x-linux-debug.sh155 run: sh ci/s390x-linux-debug.sh
156 timeout-minutes: 420156 timeout-minutes: 480
157 s390x-linux-release:157 s390x-linux-release:
158 runs-on: [self-hosted, s390x-linux]158 runs-on: [self-hosted, s390x-linux]
159 steps:159 steps:
...@@ -174,7 +174,7 @@ jobs:...@@ -174,7 +174,7 @@ jobs:
174 fetch-depth: 0174 fetch-depth: 0
175 - name: Build and Test175 - name: Build and Test
176 run: sh ci/x86_64-freebsd-debug.sh176 run: sh ci/x86_64-freebsd-debug.sh
177 timeout-minutes: 120177 timeout-minutes: 1440
178 x86_64-freebsd-release:178 x86_64-freebsd-release:
179 runs-on: [self-hosted, x86_64-freebsd]179 runs-on: [self-hosted, x86_64-freebsd]
180 steps:180 steps:
...@@ -184,7 +184,7 @@ jobs:...@@ -184,7 +184,7 @@ jobs:
184 fetch-depth: 0184 fetch-depth: 0
185 - name: Build and Test185 - name: Build and Test
186 run: sh ci/x86_64-freebsd-release.sh186 run: sh ci/x86_64-freebsd-release.sh
187 timeout-minutes: 120187 timeout-minutes: 1440
188188
189 x86_64-linux-debug:189 x86_64-linux-debug:
190 runs-on: [self-hosted, x86_64-linux]190 runs-on: [self-hosted, x86_64-linux]
CMakeLists.txt+8-13
...@@ -358,6 +358,8 @@ set(ZIG_STAGE2_SOURCES...@@ -358,6 +358,8 @@ set(ZIG_STAGE2_SOURCES
358 src/codegen/c/type/render_defs.zig358 src/codegen/c/type/render_defs.zig
359 src/codegen/llvm.zig359 src/codegen/llvm.zig
360 src/codegen/llvm/bindings.zig360 src/codegen/llvm/bindings.zig
361 src/codegen/loongarch/abi.zig
362 src/codegen/s390x/abi.zig
361 src/crash_report.zig363 src/crash_report.zig
362 src/dev.zig364 src/dev.zig
363 src/libs/freebsd.zig365 src/libs/freebsd.zig
...@@ -600,24 +602,17 @@ if(MSVC)...@@ -600,24 +602,17 @@ if(MSVC)
600 set(ZIG2_COMPILE_FLAGS "/Od")602 set(ZIG2_COMPILE_FLAGS "/Od")
601 set(ZIG2_LINK_FLAGS "/STACK:16777216 /FORCE:MULTIPLE")603 set(ZIG2_LINK_FLAGS "/STACK:16777216 /FORCE:MULTIPLE")
602else()604else()
603 set(ZIG_WASM2C_COMPILE_FLAGS "-std=c99 -O2")605 set(ZIG_WASM2C_COMPILE_FLAGS "-std=c99")
604 set(ZIG1_COMPILE_FLAGS "-std=c99 -Os -fno-strict-aliasing")606 set(ZIG1_COMPILE_FLAGS "-std=c99 -Oz -fno-strict-aliasing")
605 set(ZIG2_COMPILE_FLAGS "-std=c99 -O0 -fno-sanitize=undefined -fno-stack-protector -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()
606 # Must match the condition in build.zig.611 # Must match the condition in build.zig.
607 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)?$")612 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)?$")
608 set(ZIG1_COMPILE_FLAGS "${ZIG1_COMPILE_FLAGS} -ffunction-sections -fdata-sections")613 set(ZIG1_COMPILE_FLAGS "${ZIG1_COMPILE_FLAGS} -ffunction-sections -fdata-sections")
609 set(ZIG2_COMPILE_FLAGS "${ZIG2_COMPILE_FLAGS} -ffunction-sections -fdata-sections")614 set(ZIG2_COMPILE_FLAGS "${ZIG2_COMPILE_FLAGS} -ffunction-sections -fdata-sections")
610 endif()615 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()
621 if (CMAKE_C_COMPILER_ID STREQUAL "GNU")616 if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
622 # Prevent GCC from miscompiling 'zig2.c'. See also 'GCC_BUG_119085_PRESENT' workaround details in 'bootstrap.c'.617 # Prevent GCC from miscompiling 'zig2.c'. See also 'GCC_BUG_119085_PRESENT' workaround details in 'bootstrap.c'.
623 if (618 if (
bootstrap.c+2-2
...@@ -56,7 +56,7 @@ static void panic(const char *reason) {...@@ -56,7 +56,7 @@ static void panic(const char *reason) {
56 #define GCC_BUG_119085_PRESENT 056 #define GCC_BUG_119085_PRESENT 0
57#endif57#endif
5858
59#if defined(__WIN32__)59#if defined(_WIN32)
60#error TODO write the functionality for executing child process into this build script60#error TODO write the functionality for executing child process into this build script
61#else61#else
6262
...@@ -99,7 +99,7 @@ static void print_and_run(const char **argv) {...@@ -99,7 +99,7 @@ static void print_and_run(const char **argv) {
99static const char *get_host_os(void) {99static const char *get_host_os(void) {
100 const char *host_os = getenv("ZIG_HOST_TARGET_OS");100 const char *host_os = getenv("ZIG_HOST_TARGET_OS");
101 if (host_os != NULL) return host_os;101 if (host_os != NULL) return host_os;
102#if defined(__WIN32__)102#if defined(_WIN32)
103 return "windows";103 return "windows";
104#elif defined(__APPLE__)104#elif defined(__APPLE__)
105 return "macos";105 return "macos";
build.zig+11-11
...@@ -207,7 +207,7 @@ pub fn build(b: *std.Build) !void {...@@ -207,7 +207,7 @@ pub fn build(b: *std.Build) !void {
207207
208 const mem_leak_frames: u32 = b.option(u32, "mem-leak-frames", "How many stack frames to print when a memory leak occurs. Tests get 2x this amount.") orelse blk: {208 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: {
209 if (strip == true) break :blk @as(u32, 0);209 if (strip == true) break :blk @as(u32, 0);
210 if (optimize != .Debug) break :blk 0;210 if (optimize != .debug) break :blk 0;
211 break :blk 4;211 break :blk 4;
212 };212 };
213213
...@@ -256,7 +256,7 @@ pub fn build(b: *std.Build) !void {...@@ -256,7 +256,7 @@ pub fn build(b: *std.Build) !void {
256 exe.root_module.link_libc = true;256 exe.root_module.link_libc = true;
257 }257 }
258258
259 const is_debug = optimize == .Debug;259 const is_debug = optimize == .debug;
260 const enable_debug_extensions = b.option(bool, "debug-extensions", "Enable commands and options useful for debugging the compiler") orelse is_debug;260 const enable_debug_extensions = b.option(bool, "debug-extensions", "Enable commands and options useful for debugging the compiler") orelse is_debug;
261 const enable_logging = b.option(bool, "log", "Enable debug logging with --debug-log") orelse is_debug;261 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 {...@@ -403,8 +403,8 @@ pub fn build(b: *std.Build) !void {
403 if (tracy) |tracy_dir| {403 if (tracy) |tracy_dir| {
404 const tracy_mod = b.createModule(.{404 const tracy_mod = b.createModule(.{
405 .target = target,405 .target = target,
406 // Always build Tracy in ReleaseFast so that it doesn't make Debug compiler builds unusable.406 // Always build Tracy in ReleaseFast so that it doesn't make -Odebug compiler builds unusable.
407 .optimize = .ReleaseFast,407 .optimize = .fast,
408 .root_source_file = null,408 .root_source_file = null,
409 .link_libc = true,409 .link_libc = true,
410 .link_libcpp = true,410 .link_libcpp = true,
...@@ -434,19 +434,19 @@ pub fn build(b: *std.Build) !void {...@@ -434,19 +434,19 @@ pub fn build(b: *std.Build) !void {
434 var chosen_opt_modes_buf: [4]std.lang.OptimizeMode = undefined;434 var chosen_opt_modes_buf: [4]std.lang.OptimizeMode = undefined;
435 var chosen_mode_index: usize = 0;435 var chosen_mode_index: usize = 0;
436 if (!skip_debug) {436 if (!skip_debug) {
437 chosen_opt_modes_buf[chosen_mode_index] = .Debug;437 chosen_opt_modes_buf[chosen_mode_index] = .debug;
438 chosen_mode_index += 1;438 chosen_mode_index += 1;
439 }439 }
440 if (!skip_release_safe) {440 if (!skip_release_safe) {
441 chosen_opt_modes_buf[chosen_mode_index] = .ReleaseSafe;441 chosen_opt_modes_buf[chosen_mode_index] = .safe;
442 chosen_mode_index += 1;442 chosen_mode_index += 1;
443 }443 }
444 if (!skip_release_fast) {444 if (!skip_release_fast) {
445 chosen_opt_modes_buf[chosen_mode_index] = .ReleaseFast;445 chosen_opt_modes_buf[chosen_mode_index] = .fast;
446 chosen_mode_index += 1;446 chosen_mode_index += 1;
447 }447 }
448 if (!skip_release_small) {448 if (!skip_release_small) {
449 chosen_opt_modes_buf[chosen_mode_index] = .ReleaseSmall;449 chosen_opt_modes_buf[chosen_mode_index] = .small;
450 chosen_mode_index += 1;450 chosen_mode_index += 1;
451 }451 }
452 const optimize_modes = chosen_opt_modes_buf[0..chosen_mode_index];452 const optimize_modes = chosen_opt_modes_buf[0..chosen_mode_index];
...@@ -622,7 +622,7 @@ pub fn build(b: *std.Build) !void {...@@ -622,7 +622,7 @@ pub fn build(b: *std.Build) !void {
622 .use_llvm = use_llvm,622 .use_llvm = use_llvm,
623 .use_lld = use_llvm,623 .use_lld = use_llvm,
624 .zig_lib_dir = b.path("lib"),624 .zig_lib_dir = b.path("lib"),
625 .max_rss = 2_700_000_000,625 .max_rss = 3_000_000_000,
626 });626 });
627 if (link_libc) {627 if (link_libc) {
628 unit_tests.root_module.link_libc = true;628 unit_tests.root_module.link_libc = true;
...@@ -763,9 +763,8 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {...@@ -763,9 +763,8 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
763 .optimize = .ReleaseSmall,763 .optimize = .ReleaseSmall,
764 .target = b.resolveTargetQuery(std.Target.Query.parse(.{764 .target = b.resolveTargetQuery(std.Target.Query.parse(.{
765 .arch_os_abi = "wasm32-wasi",765 .arch_os_abi = "wasm32-wasi",
766 // * `extended_const` is not supported by the `wasm-opt` version in CI.
767 // * `nontrapping_bulk_memory_len0` is supported by `wasm2c`.766 // * `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",
769 }) catch unreachable),768 }) catch unreachable),
770 });769 });
771770
...@@ -809,6 +808,7 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {...@@ -809,6 +808,7 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
809 "-Oz",808 "-Oz",
810 "--enable-bulk-memory",809 "--enable-bulk-memory",
811 "--enable-mutable-globals",810 "--enable-mutable-globals",
811 "--enable-extended-const",
812 "--enable-nontrapping-float-to-int",812 "--enable-nontrapping-float-to-int",
813 "--enable-sign-ext",813 "--enable-sign-ext",
814 });814 });
ci/x86_64-freebsd-debug.sh+1-7
...@@ -46,13 +46,7 @@ export ZIG_LIB_DIR="$PWD/../lib"...@@ -46,13 +46,7 @@ export ZIG_LIB_DIR="$PWD/../lib"
46stage3-debug/bin/zig build test docs \46stage3-debug/bin/zig build test docs \
47 --maxrss ${ZSF_MAX_RSS:-0} \47 --maxrss ${ZSF_MAX_RSS:-0} \
48 -Dstatic-llvm \48 -Dstatic-llvm \
49 -Dskip-spirv \49 -Dskip-non-native \
50 -Dskip-wasm \
51 -Dskip-linux \
52 -Dskip-netbsd \
53 -Dskip-openbsd \
54 -Dskip-windows \
55 -Dskip-darwin \
56 --search-prefix "$PREFIX" \50 --search-prefix "$PREFIX" \
57 --test-timeout 2m51 --test-timeout 2m
5852
ci/x86_64-freebsd-release.sh+1-7
...@@ -46,13 +46,7 @@ export ZIG_LIB_DIR="$PWD/../lib"...@@ -46,13 +46,7 @@ export ZIG_LIB_DIR="$PWD/../lib"
46stage3-release/bin/zig build test docs \46stage3-release/bin/zig build test docs \
47 --maxrss ${ZSF_MAX_RSS:-0} \47 --maxrss ${ZSF_MAX_RSS:-0} \
48 -Dstatic-llvm \48 -Dstatic-llvm \
49 -Dskip-spirv \49 -Dskip-non-native \
50 -Dskip-wasm \
51 -Dskip-linux \
52 -Dskip-netbsd \
53 -Dskip-openbsd \
54 -Dskip-windows \
55 -Dskip-darwin \
56 --search-prefix "$PREFIX" \50 --search-prefix "$PREFIX" \
57 --test-timeout 2m51 --test-timeout 2m
5852
ci/x86_64-linux-debug.sh+1-1
...@@ -44,7 +44,7 @@ ninja install...@@ -44,7 +44,7 @@ ninja install
4444
45# Must be done after zig cc is finished.45# Must be done after zig cc is finished.
46export ZIG_LIB_DIR="$PWD/../lib"46export ZIG_LIB_DIR="$PWD/../lib"
47export ZIG_DEBUG_MAKER=147export ZIG_DEBUG_CMD=1
4848
49# simultaneously test building self-hosted without LLVM and with 32-bit arm49# simultaneously test building self-hosted without LLVM and with 32-bit arm
50stage3-debug/bin/zig build \50stage3-debug/bin/zig build \
doc/langref.html.in+6-2
...@@ -1119,6 +1119,10 @@...@@ -1119,6 +1119,10 @@
1119 otherwise the optimizer figures out all the values at compile-time,1119 otherwise the optimizer figures out all the values at compile-time,
1120 which operates in strict mode.</p>1120 which operates in strict mode.</p>
1121 {#code|float_mode_exe.zig#}1121 {#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
1123 {#see_also|@setFloatMode|Division by Zero#}1127 {#see_also|@setFloatMode|Division by Zero#}
1124 {#header_close#}1128 {#header_close#}
...@@ -5848,7 +5852,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val...@@ -5848,7 +5852,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
5848 {#header_open|@Union#}5852 {#header_open|@Union#}
5849 <pre>{#syntax#}@Union(5853 <pre>{#syntax#}@Union(
5850 comptime layout: std.lang.Type.ContainerLayout,5854 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`.
5852 comptime ArgType: ?type,5856 comptime ArgType: ?type,
5853 comptime field_names: []const []const u8,5857 comptime field_names: []const []const u8,
5854 comptime field_types: *const [field_names.len]type,5858 comptime field_types: *const [field_names.len]type,
...@@ -7499,7 +7503,7 @@ fn readU32Be() u32 {}...@@ -7499,7 +7503,7 @@ fn readU32Be() u32 {}
7499 <pre>{#syntax#}errdefer{#endsyntax#}</pre>7503 <pre>{#syntax#}errdefer{#endsyntax#}</pre>
7500 </th>7504 </th>
7501 <td>7505 <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.
7503 <ul>7507 <ul>
7504 <li>See also {#link|errdefer#}</li>7508 <li>See also {#link|errdefer#}</li>
7505 </ul>7509 </ul>
doc/langref/test_packed_structs.zig-1
...@@ -1,5 +1,4 @@...@@ -1,5 +1,4 @@
1const std = @import("std");1const std = @import("std");
2const native_endian = @import("builtin").target.cpu.arch.endian();
3const expectEqual = std.testing.expectEqual;2const expectEqual = std.testing.expectEqual;
43
5const Full = packed struct {4const 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...@@ -84,7 +84,7 @@ pub fn compileResultMessage(msg_bytes: []u8) error{ OutOfMemory, WriteFailed }!v
84 defer gpa.free(slowest_decls);84 defer gpa.free(slowest_decls);
8585
86 for (slowest_files) |*file_out| {86 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");
88 file_out.* = .{88 file_out.* = .{
89 .name = trailing[0..i],89 .name = trailing[0..i],
90 .ns_sema = 0,90 .ns_sema = 0,
...@@ -95,7 +95,7 @@ pub fn compileResultMessage(msg_bytes: []u8) error{ OutOfMemory, WriteFailed }!v...@@ -95,7 +95,7 @@ pub fn compileResultMessage(msg_bytes: []u8) error{ OutOfMemory, WriteFailed }!v
95 }95 }
9696
97 for (slowest_decls) |*decl_out| {97 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");
99 const file_idx = std.mem.readInt(u32, trailing[i..][1..5], .little);99 const file_idx = std.mem.readInt(u32, trailing[i..][1..5], .little);
100 const sema_count = std.mem.readInt(u32, trailing[i..][5..9], .little);100 const sema_count = std.mem.readInt(u32, trailing[i..][5..9], .little);
101 const sema_ns = std.mem.readInt(u64, trailing[i..][9..17], .little);101 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 {...@@ -258,7 +258,7 @@ pub fn runTestResultMessage(msg_bytes: []u8) error{OutOfMemory}!void {
258 defer table_html.deinit(gpa);258 defer table_html.deinit(gpa);
259259
260 for (durations) |test_ns| {260 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");
262 const test_name = trailing[offset..][0..test_name_len];262 const test_name = trailing[offset..][0..test_name_len];
263 offset += test_name_len + 1;263 offset += test_name_len + 1;
264 try table_html.print(gpa, "<tr><th scope=\"row\"><code>{f}</code></th>", .{fmtEscapeHtml(test_name)});264 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) {...@@ -59,8 +59,8 @@ const Header = packed struct(u64) {
59 }59 }
6060
61 const safety = switch (builtin.mode) {61 const safety = switch (builtin.mode) {
62 .Debug, .ReleaseSafe => true,62 .debug, .safe => true,
63 .ReleaseFast, .ReleaseSmall => false,63 .fast, .small => false,
64 };64 };
65 const max_addr_bits = switch (safety) {65 const max_addr_bits = switch (safety) {
66 true => 48, // Ensures space for Canary bits.66 true => 48, // Ensures space for Canary bits.
lib/compiler/Maker.zig+339-78
...@@ -11,6 +11,7 @@ const File = std.Io.File;...@@ -11,6 +11,7 @@ const File = std.Io.File;
11const Io = std.Io;11const Io = std.Io;
12const Dir = std.Io.Dir;12const Dir = std.Io.Dir;
13const Path = std.Build.Cache.Path;13const Path = std.Build.Cache.Path;
14const Reader = std.Io.Reader;
14const Writer = std.Io.Writer;15const Writer = std.Io.Writer;
15const assert = std.debug.assert;16const assert = std.debug.assert;
16const fatal = std.process.fatal;17const fatal = std.process.fatal;
...@@ -19,6 +20,8 @@ const log = std.log;...@@ -19,6 +20,8 @@ const log = std.log;
19const mem = std.mem;20const mem = std.mem;
20const process = std.process;21const process = std.process;
21const Color = std.zig.Color;22const Color = std.zig.Color;
23const Client = std.zig.Client;
24const Server = std.zig.Server;
22const EnvVar = std.zig.EnvVar;25const EnvVar = std.zig.EnvVar;
23const default_local_zig_cache_basename = std.zig.default_local_zig_cache_basename;26const default_local_zig_cache_basename = std.zig.default_local_zig_cache_basename;
24const stringToEnum = std.meta.stringToEnum;27const stringToEnum = std.meta.stringToEnum;
...@@ -51,10 +54,14 @@ max_rss_mutex: Io.Mutex,...@@ -51,10 +54,14 @@ max_rss_mutex: Io.Mutex,
51skip_oom_steps: bool,54skip_oom_steps: bool,
52unit_test_timeout_ns: ?u64,55unit_test_timeout_ns: ?u64,
53watch: bool,56watch: bool,
57protocol_server: ?*AvoidableServer,
58protocol_server_mutex: Io.Mutex,
54web_server: ?*AvoidableWebServer,59web_server: ?*AvoidableWebServer,
55/// Allocated into `gpa`.60/// Allocated into `gpa`.
56memory_blocked_steps: std.ArrayList(Configuration.Step.Index),61memory_blocked_steps: std.ArrayList(Configuration.Step.Index),
57/// Allocated into `gpa`.62/// Allocated into `gpa`.
63initial_steps: std.array_hash_map.Auto(Configuration.Step.Index, void),
64/// Allocated into `gpa`.
58step_stack: std.array_hash_map.Auto(Configuration.Step.Index, void),65step_stack: std.array_hash_map.Auto(Configuration.Step.Index, void),
59pkg_config: PkgConfig,66pkg_config: PkgConfig,
6067
...@@ -67,12 +74,13 @@ var stdio_buffer_allocation: [256]u8 = undefined;...@@ -67,12 +74,13 @@ var stdio_buffer_allocation: [256]u8 = undefined;
67var stdout_writer_allocation: Io.File.Writer = undefined;74var stdout_writer_allocation: Io.File.Writer = undefined;
68var debug_maker_leaks: bool = false;75var debug_maker_leaks: bool = false;
6976
77const AvoidableServer = if (builtin.single_threaded) void else Server;
70const AvoidableWebServer = if (builtin.single_threaded) void else WebServer;78const AvoidableWebServer = if (builtin.single_threaded) void else WebServer;
7179
72const is_debug_mode = builtin.mode == .Debug;80const is_debug_mode = builtin.mode == .debug;
73const use_safe_allocator = switch (builtin.mode) {81const use_safe_allocator = switch (builtin.mode) {
74 .Debug, .ReleaseSafe => true,82 .debug, .safe => true,
75 .ReleaseFast, .ReleaseSmall => false,83 .fast, .small => false,
76};84};
7785
78const InstallPaths = struct {86const InstallPaths = struct {
...@@ -216,6 +224,7 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -216,6 +224,7 @@ pub fn main(init: process.Init.Minimal) !void {
216 var watch = false;224 var watch = false;
217 var fuzz: ?Fuzz.Mode = null;225 var fuzz: ?Fuzz.Mode = null;
218 var debounce_interval_ms: u16 = 50;226 var debounce_interval_ms: u16 = 50;
227 var listen: bool = false;
219 var webui_listen: ?Io.net.IpAddress = null;228 var webui_listen: ?Io.net.IpAddress = null;
220 var debug_pkg_config = false;229 var debug_pkg_config = false;
221 var run_args: ?[]const []const u8 = null;230 var run_args: ?[]const []const u8 = null;
...@@ -242,6 +251,12 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -242,6 +251,12 @@ pub fn main(init: process.Init.Minimal) !void {
242 }251 }
243 }252 }
244253
254 if (EnvVar.ZIG_BUILD_SUMMARY.get(&graph.environ_map)) |str| {
255 if (stringToEnum(Summary, str)) |value| {
256 summary = value;
257 }
258 }
259
245 try configure_argv.ensureUnusedCapacity(arena, 16);260 try configure_argv.ensureUnusedCapacity(arena, 16);
246 try cached_passthru_configure.ensureUnusedCapacity(arena, 16);261 try cached_passthru_configure.ensureUnusedCapacity(arena, 16);
247262
...@@ -416,6 +431,8 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -416,6 +431,8 @@ pub fn main(init: process.Init.Minimal) !void {
416 next_arg, err,431 next_arg, err,
417 });432 });
418 };433 };
434 } else if (mem.eql(u8, arg, "--listen=-")) {
435 listen = true;
419 } else if (mem.eql(u8, arg, "--webui")) {436 } else if (mem.eql(u8, arg, "--webui")) {
420 if (webui_listen == null) webui_listen = .{ .ip6 = .loopback(0) };437 if (webui_listen == null) webui_listen = .{ .ip6 = .loopback(0) };
421 } else if (mem.startsWith(u8, arg, "--webui=")) {438 } else if (mem.startsWith(u8, arg, "--webui=")) {
...@@ -553,7 +570,7 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -553,7 +570,7 @@ pub fn main(init: process.Init.Minimal) !void {
553 }570 }
554571
555 const early_exit_mode = fetch_only or help_menu or steps_menu or print_configuration != .none;572 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
558 process.raiseFileDescriptorLimit();575 process.raiseFileDescriptorLimit();
559576
...@@ -631,20 +648,31 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -631,20 +648,31 @@ pub fn main(init: process.Init.Minimal) !void {
631 .sub_path = "zig-out",648 .sub_path = "zig-out",
632 };649 };
633650
634 const install_lib_path: Path = if (override_lib_dir) |cwd_relative| .{651 // These three overrides are meant to be relative to the install prefix,
635 .root_dir = .cwd(),652 // not current working directory, unless absolute paths are used.
636 .sub_path = cwd_relative,653 const install_lib_path: Path = if (override_lib_dir) |lib_dir|
637 } else try install_prefix_path.join(arena, "lib");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| .{661 const install_bin_path: Path = if (override_bin_dir) |bin_dir|
640 .root_dir = .cwd(),662 if (Dir.path.isAbsolute(bin_dir)) .{
641 .sub_path = cwd_relative,663 .root_dir = .cwd(),
642 } else try install_prefix_path.join(arena, "bin");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| .{669 const install_include_path: Path = if (override_include_dir) |include_dir|
645 .root_dir = .cwd(),670 if (Dir.path.isAbsolute(include_dir)) .{
646 .sub_path = cwd_relative,671 .root_dir = .cwd(),
647 } else try install_prefix_path.join(arena, "include");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
649 const now = Io.Clock.Timestamp.now(io, .awake);677 const now = Io.Clock.Timestamp.now(io, .awake);
650678
...@@ -661,6 +689,25 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -661,6 +689,25 @@ pub fn main(init: process.Init.Minimal) !void {
661 break :ws &web_server_allocation;689 break :ws &web_server_allocation;
662 } else null;690 } 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
664 while (true) {711 while (true) {
665 // If this fails, we can still start the server and wait for user712 // If this fails, we can still start the server and wait for user
666 // to request a rebuild. If it returns error.FailedButCacheIntact713 // to request a rebuild. If it returns error.FailedButCacheIntact
...@@ -731,16 +778,25 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -731,16 +778,25 @@ pub fn main(init: process.Init.Minimal) !void {
731778
732 .watch = watch,779 .watch = watch,
733 .web_server = web_server,780 .web_server = web_server,
781 .protocol_server = protocol_server,
782 .protocol_server_mutex = .init,
734 .memory_blocked_steps = .empty,783 .memory_blocked_steps = .empty,
784 .initial_steps = .empty,
735 .step_stack = .empty,785 .step_stack = .empty,
736 .pkg_config = .{ .debug = debug_pkg_config },786 .pkg_config = .{ .debug = debug_pkg_config },
737787
738 .error_style = error_style,788 .error_style = error_style,
739 .multiline_errors = multiline_errors,789 .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,
741 };796 };
742 defer {797 defer {
743 maker.memory_blocked_steps.deinit(gpa);798 maker.memory_blocked_steps.deinit(gpa);
799 maker.initial_steps.deinit(gpa);
744 maker.step_stack.deinit(gpa);800 maker.step_stack.deinit(gpa);
745 }801 }
746802
...@@ -749,7 +805,91 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -749,7 +805,91 @@ pub fn main(init: process.Init.Minimal) !void {
749 maker.max_rss_is_default = true;805 maker.max_rss_is_default = true;
750 }806 }
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) {
753 error.DependencyLoopDetected, error.InsufficientMemory => {893 error.DependencyLoopDetected, error.InsufficientMemory => {
754 // TODO handle DependencyLoopDetected as error.FailedButCacheIntact894 // TODO handle DependencyLoopDetected as error.FailedButCacheIntact
755 // and handle InsufficientMemory as error.AlreadyReported895 // and handle InsufficientMemory as error.AlreadyReported
...@@ -774,18 +914,7 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -774,18 +914,7 @@ pub fn main(init: process.Init.Minimal) !void {
774 error.WriteFailed => return stderr.file_writer.err.?,914 error.WriteFailed => return stderr.file_writer.err.?,
775 };915 };
776 }) {916 }) {
777 if (web_server) |ws| ws.startBuild();917 try maker.makeSteps(main_progress_node, fuzz);
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 }
789918
790 if (web_server) |ws| {919 if (web_server) |ws| {
791 const c = &scanned_config.configuration;920 const c = &scanned_config.configuration;
...@@ -850,6 +979,9 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -850,6 +979,9 @@ pub fn main(init: process.Init.Minimal) !void {
850 _ = io.lockStderr(&.{}, graph.stderr_mode) catch {};979 _ = io.lockStderr(&.{}, graph.stderr_mode) catch {};
851 process.exit(1);980 process.exit(1);
852 }981 }
982 if (protocol_server != null) {
983 fatal("(zig build system) TODO send error messages to client when build.zig compilation fails", .{});
984 }
853 if (watch and can_fs_watch) {985 if (watch and can_fs_watch) {
854 fatal("(zig build system) TODO set up fs watching even when build.zig compilation fails", .{});986 fatal("(zig build system) TODO set up fs watching even when build.zig compilation fails", .{});
855 } else {987 } else {
...@@ -1330,7 +1462,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {...@@ -1330,7 +1462,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {
1330 if (config_man) |man| for (configuration.path_deps) |path_dep| {1462 if (config_man) |man| for (configuration.path_deps) |path_dep| {
1331 switch (path_dep.flags.mode) {1463 switch (path_dep.flags.mode) {
1332 .directory => {}, // TODO1464 .directory => {}, // TODO
1333 .contents => try man.addPathPost(confPathDepToCachePath(graph, &configuration, path_dep)),1465 .contents => try man.addPathPost(try confPathDepToCachePath(arena, graph, &configuration, path_dep)),
1334 .metadata => {}, // TODO1466 .metadata => {}, // TODO
1335 }1467 }
1336 };1468 };
...@@ -1433,7 +1565,6 @@ fn cmdFetch(gpa: Allocator, graph: *Graph, args: []const []const u8) !void {...@@ -1433,7 +1565,6 @@ fn cmdFetch(gpa: Allocator, graph: *Graph, args: []const []const u8) !void {
14331565
1434 const color: Color = Color.settingFromEnvironment(environ_map);1566 const color: Color = Color.settingFromEnvironment(environ_map);
1435 var opt_path_or_url: ?[]const u8 = null;1567 var opt_path_or_url: ?[]const u8 = null;
1436 var override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map);
1437 var override_local_cache_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_CACHE_DIR.get(environ_map);1568 var override_local_cache_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_CACHE_DIR.get(environ_map);
1438 var override_pkg_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_PKG_DIR.get(environ_map);1569 var override_pkg_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_PKG_DIR.get(environ_map);
1439 var debug_hash: bool = false;1570 var debug_hash: bool = false;
...@@ -1449,8 +1580,6 @@ fn cmdFetch(gpa: Allocator, graph: *Graph, args: []const []const u8) !void {...@@ -1449,8 +1580,6 @@ fn cmdFetch(gpa: Allocator, graph: *Graph, args: []const []const u8) !void {
1449 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {1580 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
1450 try Io.File.stdout().writeStreamingAll(io, usage_fetch);1581 try Io.File.stdout().writeStreamingAll(io, usage_fetch);
1451 return process.cleanExit(io);1582 return process.cleanExit(io);
1452 } else if (mem.eql(u8, arg, "--global-cache-dir")) {
1453 override_global_cache_dir = nextArgOrFatal(args, &arg_i);
1454 } else if (mem.eql(u8, arg, "--cache-dir")) {1583 } else if (mem.eql(u8, arg, "--cache-dir")) {
1455 override_local_cache_dir = nextArgOrFatal(args, &arg_i);1584 override_local_cache_dir = nextArgOrFatal(args, &arg_i);
1456 } else if (mem.eql(u8, arg, "--pkg-dir")) {1585 } else if (mem.eql(u8, arg, "--pkg-dir")) {
...@@ -1730,7 +1859,6 @@ const usage_fetch =...@@ -1730,7 +1859,6 @@ const usage_fetch =
1730 \\1859 \\
1731 \\Options:1860 \\Options:
1732 \\ -h, --help Print this help and exit1861 \\ -h, --help Print this help and exit
1733 \\ --global-cache-dir [path] Override path to global Zig cache directory
1734 \\ --cache-dir [path] Override path to local cache directory1862 \\ --cache-dir [path] Override path to local cache directory
1735 \\ --pkg-dir [path] Override path to local package directory1863 \\ --pkg-dir [path] Override path to local package directory
1736 \\ --debug-hash Print verbose hash information to stdout1864 \\ --debug-hash Print verbose hash information to stdout
...@@ -1991,7 +2119,7 @@ fn markFailedStepsDirty(maker: *Maker) void {...@@ -1991,7 +2119,7 @@ fn markFailedStepsDirty(maker: *Maker) void {
1991 for (all_steps) |step_index| {2119 for (all_steps) |step_index| {
1992 const step = maker.stepByIndex(step_index);2120 const step = maker.stepByIndex(step_index);
1993 switch (step.state) {2121 switch (step.state) {
1994 .dependency_failure, .failure, .skipped => _ = maker.invalidateResult(step),2122 .dependency_failure, .dependency_skipped, .failure, .skipped => _ = maker.invalidateResult(step),
1995 else => continue,2123 else => continue,
1996 }2124 }
1997 }2125 }
...@@ -2020,11 +2148,37 @@ pub fn stepByIndex(maker: *const Maker, i: Configuration.Step.Index) *Step {...@@ -2020,11 +2148,37 @@ pub fn stepByIndex(maker: *const Maker, i: Configuration.Step.Index) *Step {
2020 return &maker.steps[@backingInt(i)];2148 return &maker.steps[@backingInt(i)];
2021}2149}
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 {
2024 const gpa = maker.gpa;2177 const gpa = maker.gpa;
2025 const graph = maker.graph;2178 const graph = maker.graph;
2026 const arena = graph.arena;2179 const arena = graph.arena;
2027 const seed: u32 = graph.random_seed;2180 const seed: u32 = graph.random_seed;
2181 const initial_steps = &maker.initial_steps;
2028 const step_stack = &maker.step_stack;2182 const step_stack = &maker.step_stack;
2029 const c = &maker.scanned_config.configuration;2183 const c = &maker.scanned_config.configuration;
20302184
...@@ -2033,18 +2187,15 @@ fn prepare(maker: *Maker, step_names: []const []const u8) !void {...@@ -2033,18 +2187,15 @@ fn prepare(maker: *Maker, step_names: []const []const u8) !void {
2033 step.* = .{ .extended = .init(step_index.ptr(c).flags(c).tag) };2187 step.* = .{ .extended = .init(step_index.ptr(c).flags(c).tag) };
2034 }2188 }
20352189
2036 if (step_names.len == 0) {2190 try initial_steps.ensureUnusedCapacity(gpa, step_indices.len);
2037 try step_stack.put(gpa, c.default_step, {});2191 try step_stack.ensureUnusedCapacity(gpa, step_indices.len);
2038 } else {2192
2039 try step_stack.ensureUnusedCapacity(gpa, step_names.len);2193 initial_steps.clearRetainingCapacity();
2040 for (0..step_names.len) |i| {2194 step_stack.clearRetainingCapacity();
2041 const step_name = step_names[step_names.len - i - 1];2195
2042 const s = maker.scanned_config.top_level_steps.get(step_name) orelse {2196 for (step_indices) |step| {
2043 log.info("to list available steps: zig build -l", .{});2197 initial_steps.putAssumeCapacity(step, {});
2044 fatal("no such step: {s}", .{step_name});2198 step_stack.putAssumeCapacity(step, {});
2045 };
2046 step_stack.putAssumeCapacity(s, {});
2047 }
2048 }2199 }
20492200
2050 const starting_steps = try arena.dupe(Configuration.Step.Index, step_stack.keys());2201 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 {...@@ -2085,6 +2236,7 @@ fn prepare(maker: *Maker, step_names: []const []const u8) !void {
2085 }2236 }
2086 }2237 }
2087 if (any_problems) {2238 if (any_problems) {
2239 log.info("use --skip-oom-steps to proceed, skipping memory limited steps", .{});
2088 if (maker.max_rss_is_default) {2240 if (maker.max_rss_is_default) {
2089 log.info("use --maxrss {d} to proceed, risking system memory exhaustion", .{max_needed});2241 log.info("use --maxrss {d} to proceed, risking system memory exhaustion", .{max_needed});
2090 }2242 }
...@@ -2093,9 +2245,8 @@ fn prepare(maker: *Maker, step_names: []const []const u8) !void {...@@ -2093,9 +2245,8 @@ fn prepare(maker: *Maker, step_names: []const []const u8) !void {
2093 }2245 }
2094}2246}
20952247
2096fn makeStepNames(2248fn makeSteps(
2097 maker: *Maker,2249 maker: *Maker,
2098 step_names: []const []const u8,
2099 parent_progress_node: std.Progress.Node,2250 parent_progress_node: std.Progress.Node,
2100 fuzz: ?Fuzz.Mode,2251 fuzz: ?Fuzz.Mode,
2101) !void {2252) !void {
...@@ -2106,6 +2257,12 @@ fn makeStepNames(...@@ -2106,6 +2257,12 @@ fn makeStepNames(
2106 const top_level_steps = &maker.scanned_config.top_level_steps;2257 const top_level_steps = &maker.scanned_config.top_level_steps;
2107 const c = &maker.scanned_config.configuration;2258 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
2109 {2266 {
2110 // Collect the initial set of tasks (those with no outstanding dependencies) into a buffer,2267 // Collect the initial set of tasks (those with no outstanding dependencies) into a buffer,
2111 // then spawn them. The buffer is so that we don't race with `makeStep` and end up thinking2268 // then spawn them. The buffer is so that we don't race with `makeStep` and end up thinking
...@@ -2131,6 +2288,19 @@ fn makeStepNames(...@@ -2131,6 +2288,19 @@ fn makeStepNames(
2131 try group.await(io);2288 try group.await(io);
2132 }2289 }
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
2134 assert(maker.memory_blocked_steps.items.len == 0);2304 assert(maker.memory_blocked_steps.items.len == 0);
21352305
2136 var test_pass_count: usize = 0;2306 var test_pass_count: usize = 0;
...@@ -2164,7 +2334,7 @@ fn makeStepNames(...@@ -2164,7 +2334,7 @@ fn makeStepNames(
2164 .precheck_unstarted => unreachable,2334 .precheck_unstarted => unreachable,
2165 .precheck_started => unreachable,2335 .precheck_started => unreachable,
2166 .precheck_done => unreachable,2336 .precheck_done => unreachable,
2167 .dependency_failure => pending_count += 1,2337 .dependency_failure, .dependency_skipped => pending_count += 1,
2168 .success => success_count += 1,2338 .success => success_count += 1,
2169 .skipped, .skipped_oom => skipped_count += 1,2339 .skipped, .skipped_oom => skipped_count += 1,
2170 .failure => {2340 .failure => {
...@@ -2283,7 +2453,7 @@ fn makeStepNames(...@@ -2283,7 +2453,7 @@ fn makeStepNames(
2283 defer step_stack_copy.deinit(gpa);2453 defer step_stack_copy.deinit(gpa);
22842454
2285 var print_node: PrintNode = .{ .parent = null };2455 var print_node: PrintNode = .{ .parent = null };
2286 if (step_names.len == 0) {2456 if (maker.initial_steps.count() == 0) {
2287 print_node.last = true;2457 print_node.last = true;
2288 printTreeStep(maker, c.default_step, t, &print_node, &step_stack_copy) catch |err| switch (err) {2458 printTreeStep(maker, c.default_step, t, &print_node, &step_stack_copy) catch |err| switch (err) {
2289 error.Canceled => |e| return e,2459 error.Canceled => |e| return e,
...@@ -2291,10 +2461,10 @@ fn makeStepNames(...@@ -2291,10 +2461,10 @@ fn makeStepNames(
2291 };2461 };
2292 } else {2462 } else {
2293 const last_index = if (maker.summary == .all) top_level_steps.count() else blk: {2463 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();
2295 while (i > 0) {2465 while (i > 0) {
2296 i -= 1;2466 i -= 1;
2297 const step_index = top_level_steps.get(step_names[i]).?;2467 const step_index = maker.initial_steps.keys()[i];
2298 const step = maker.stepByIndex(step_index);2468 const step = maker.stepByIndex(step_index);
2299 const found = switch (maker.summary) {2469 const found = switch (maker.summary) {
2300 .all, .line, .none => unreachable,2470 .all, .line, .none => unreachable,
...@@ -2305,8 +2475,7 @@ fn makeStepNames(...@@ -2305,8 +2475,7 @@ fn makeStepNames(
2305 }2475 }
2306 break :blk top_level_steps.count();2476 break :blk top_level_steps.count();
2307 };2477 };
2308 for (step_names, 0..) |step_name, i| {2478 for (maker.initial_steps.keys(), 0..) |step_index, i| {
2309 const step_index = top_level_steps.get(step_name).?;
2310 print_node.last = i + 1 == last_index;2479 print_node.last = i + 1 == last_index;
2311 printTreeStep(maker, step_index, t, &print_node, &step_stack_copy) catch |err| switch (err) {2480 printTreeStep(maker, step_index, t, &print_node, &step_stack_copy) catch |err| switch (err) {
2312 error.Canceled => |e| return e,2481 error.Canceled => |e| return e,
...@@ -2317,7 +2486,7 @@ fn makeStepNames(...@@ -2317,7 +2486,7 @@ fn makeStepNames(
2317 w.writeByte('\n') catch {};2486 w.writeByte('\n') catch {};
2318 }2487 }
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
2322 const code: u8 = code: {2491 const code: u8 = code: {
2323 if (failure_count == 0) break :code 0; // success2492 if (failure_count == 0) break :code 0; // success
...@@ -2392,6 +2561,15 @@ fn makeStep(...@@ -2392,6 +2561,15 @@ fn makeStep(
2392 defer step_prog_node.end();2561 defer step_prog_node.end();
23932562
2394 if (maker.web_server) |ws| ws.updateStepStatus(step_index, .wip);2563 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
2396 const new_state: Step.State = for (deps) |dep_index| {2574 const new_state: Step.State = for (deps) |dep_index| {
2397 const dep_make_step = maker.stepByIndex(dep_index);2575 const dep_make_step = maker.stepByIndex(dep_index);
...@@ -2402,10 +2580,14 @@ fn makeStep(...@@ -2402,10 +2580,14 @@ fn makeStep(
24022580
2403 .failure,2581 .failure,
2404 .dependency_failure,2582 .dependency_failure,
2405 .skipped_oom,
2406 => break .dependency_failure,2583 => break .dependency_failure,
24072584
2408 .success, .skipped => {},2585 .dependency_skipped,
2586 .skipped_oom,
2587 .skipped,
2588 => break .dependency_skipped,
2589
2590 .success => {},
2409 }2591 }
2410 } else if (Step.make(step_index, maker, step_prog_node)) state: {2592 } else if (Step.make(step_index, maker, step_prog_node)) state: {
2411 break :state .success;2593 break :state .success;
...@@ -2417,25 +2599,46 @@ fn makeStep(...@@ -2417,25 +2599,46 @@ fn makeStep(
24172599
2418 @atomicStore(Step.State, &make_step.state, new_state, .monotonic);2600 @atomicStore(Step.State, &make_step.state, new_state, .monotonic);
24192601
2420 switch (new_state) {2602 const success = switch (new_state) {
2421 .precheck_unstarted => unreachable,2603 .precheck_unstarted => unreachable,
2422 .precheck_started => unreachable,2604 .precheck_started => unreachable,
2423 .precheck_done => unreachable,2605 .precheck_done => unreachable,
24242606
2425 .failure,2607 .failure,
2426 .dependency_failure,2608 .dependency_failure,
2609 .dependency_skipped,
2427 .skipped_oom,2610 .skipped_oom,
2428 => {2611 .skipped,
2429 if (maker.web_server) |ws| ws.updateStepStatus(step_index, .failure);2612 => false,
2430 std.Progress.setStatus(.failure_working);
2431 },
24322613
2433 .success,2614 .success,
2434 .skipped,2615 => true,
2435 => {2616 };
2436 if (maker.web_server) |ws| ws.updateStepStatus(step_index, .success);2617
2437 },2618 if (maker.web_server) |ws| {
2619 ws.updateStepStatus(step_index, if (success) .success else .failure);
2438 }2620 }
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);
2439 }2642 }
24402643
2441 // No matter the result, we want to display error/warning messages.2644 // No matter the result, we want to display error/warning messages.
...@@ -2468,7 +2671,7 @@ fn makeStep(...@@ -2468,7 +2671,7 @@ fn makeStep(
2468 maker.available_rss += max_rss;2671 maker.available_rss += max_rss;
2469 dispatch_set.ensureUnusedCapacity(gpa, maker.memory_blocked_steps.items.len) catch2672 dispatch_set.ensureUnusedCapacity(gpa, maker.memory_blocked_steps.items.len) catch
2470 @panic("TODO eliminate memory allocation here");2673 @panic("TODO eliminate memory allocation here");
2471 while (maker.memory_blocked_steps.getLast()) |candidate_index| {2674 while (maker.memory_blocked_steps.last()) |candidate_index| {
2472 const candidate_max_rss = candidate_index.ptr(c).max_rss.toBytes();2675 const candidate_max_rss = candidate_index.ptr(c).max_rss.toBytes();
2473 if (maker.available_rss < candidate_max_rss) break;2676 if (maker.available_rss < candidate_max_rss) break;
2474 assert(maker.memory_blocked_steps.pop() == candidate_index);2677 assert(maker.memory_blocked_steps.pop() == candidate_index);
...@@ -2579,6 +2782,12 @@ fn printStepStatus(maker: *Maker, step_index: Configuration.Step.Index, stderr:...@@ -2579,6 +2782,12 @@ fn printStepStatus(maker: *Maker, step_index: Configuration.Step.Index, stderr:
2579 try stderr.setColor(.reset);2782 try stderr.setColor(.reset);
2580 },2783 },
25812784
2785 .dependency_skipped => {
2786 try stderr.setColor(.dim);
2787 try writer.writeAll(" transitive skip\n");
2788 try stderr.setColor(.reset);
2789 },
2790
2582 .success => {2791 .success => {
2583 try stderr.setColor(.green);2792 try stderr.setColor(.green);
2584 if (s.result_cached) {2793 if (s.result_cached) {
...@@ -2825,6 +3034,7 @@ fn constructGraphAndCheckForDependencyLoop(...@@ -2825,6 +3034,7 @@ fn constructGraphAndCheckForDependencyLoop(
28253034
2826 // These don't happen until we actually run the step graph.3035 // These don't happen until we actually run the step graph.
2827 .dependency_failure => unreachable,3036 .dependency_failure => unreachable,
3037 .dependency_skipped => unreachable,
2828 .success => unreachable,3038 .success => unreachable,
2829 .failure => unreachable,3039 .failure => unreachable,
2830 .skipped => unreachable,3040 .skipped => unreachable,
...@@ -2912,7 +3122,7 @@ pub fn printErrorMessages(...@@ -2912,7 +3122,7 @@ pub fn printErrorMessages(
2912 try stderr.setColor(.red);3122 try stderr.setColor(.red);
2913 try writer.writeAll("error:");3123 try writer.writeAll("error:");
2914 try stderr.setColor(.reset);3124 try stderr.setColor(.reset);
2915 if (std.mem.indexOfScalar(u8, msg, '\n') == null) {3125 if (std.mem.findScalar(u8, msg, '\n') == null) {
2916 try writer.print(" {s}\n", .{msg});3126 try writer.print(" {s}\n", .{msg});
2917 } else switch (multiline_errors) {3127 } else switch (multiline_errors) {
2918 .indent => {3128 .indent => {
...@@ -2990,6 +3200,50 @@ fn cleanTmpFiles(maker: *Maker, steps: []const Configuration.Step.Index) void {...@@ -2990,6 +3200,50 @@ fn cleanTmpFiles(maker: *Maker, steps: []const Configuration.Step.Index) void {
2990 }3200 }
2991}3201}
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
2993fn initStdoutWriter(io: Io) *Writer {3247fn initStdoutWriter(io: Io) *Writer {
2994 stdout_writer_allocation = Io.File.stdout().writerStreaming(io, &stdio_buffer_allocation);3248 stdout_writer_allocation = Io.File.stdout().writerStreaming(io, &stdio_buffer_allocation);
2995 return &stdout_writer_allocation.interface;3249 return &stdout_writer_allocation.interface;
...@@ -3071,17 +3325,19 @@ pub fn packagePath(...@@ -3071,17 +3325,19 @@ pub fn packagePath(
3071) Allocator.Error!Path {3325) Allocator.Error!Path {
3072 const c = &maker.scanned_config.configuration;3326 const c = &maker.scanned_config.configuration;
3073 const graph = maker.graph;3327 const graph = maker.graph;
3074 const package = package_index.get(c) orelse return .{3328
3329 if (package_index == .root) return .{
3075 .root_dir = graph.build_root_directory,3330 .root_dir = graph.build_root_directory,
3076 .sub_path = sub_path,3331 .sub_path = sub_path,
3077 };3332 };
3333
3078 // Currently, neither configurer nor Maker is aware of the standard zig3334 // Currently, neither configurer nor Maker is aware of the standard zig
3079 // package path, and the root path is stored as a bare string rather than3335 // package path, and the root path is stored as a bare string rather than
3080 // relative to a known base directory. Without changing that, we must3336 // relative to a known base directory. Without changing that, we must
3081 // construct a cwd relative path here.3337 // construct a cwd relative path here.
3082 return .{3338 return .{
3083 .root_dir = .cwd(),3339 .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 }),
3085 };3341 };
3086}3342}
30873343
...@@ -3687,7 +3943,12 @@ const Templates = struct {...@@ -3687,7 +3943,12 @@ const Templates = struct {
3687 }3943 }
3688};3944};
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 {
3691 const sub_path = path_dep.sub.slice(c);3952 const sub_path = path_dep.sub.slice(c);
3692 return switch (path_dep.flags.base) {3953 return switch (path_dep.flags.base) {
3693 .cwd => .{3954 .cwd => .{
...@@ -3703,11 +3964,11 @@ fn confPathDepToCachePath(graph: *const Graph, c: *const Configuration, path_dep...@@ -3703,11 +3964,11 @@ fn confPathDepToCachePath(graph: *const Graph, c: *const Configuration, path_dep
3703 .sub_path = sub_path,3964 .sub_path = sub_path,
3704 },3965 },
3705 .build_root => .{3966 .build_root => .{
3706 .root_dir = switch (path_dep.pkg.unwrap().?) {3967 .root_dir = graph.build_root_directory,
3707 .root => graph.build_root_directory,3968 .sub_path = switch (path_dep.pkg.unwrap().?) {
3708 _ => @panic("TODO"),3969 .root => sub_path,
3970 else => |index| try Dir.path.join(arena, &.{ index.ptr(c).root_path.slice(c), sub_path }),
3709 },3971 },
3710 .sub_path = sub_path,
3711 },3972 },
3712 .zig_lib => .{3973 .zig_lib => .{
3713 .root_dir = graph.zig_lib_directory,3974 .root_dir = graph.zig_lib_directory,
lib/compiler/Maker/Fetch.zig+3-3
...@@ -1164,7 +1164,7 @@ const FileType = enum {...@@ -1164,7 +1164,7 @@ const FileType = enum {
1164 if (cd_header[value_start] != '=') return null;1164 if (cd_header[value_start] != '=') return null;
1165 value_start += 1;1165 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;
1168 if (cd_header[value_end - 1] == '\"') {1168 if (cd_header[value_end - 1] == '\"') {
1169 value_end -= 1;1169 value_end -= 1;
1170 }1170 }
...@@ -1344,7 +1344,7 @@ fn unpackResource(...@@ -1344,7 +1344,7 @@ fn unpackResource(
1344 return f.fail(f.location_tok, try eb.addString("missing 'Content-Type' header"));1344 return f.fail(f.location_tok, try eb.addString("missing 'Content-Type' header"));
13451345
1346 // Extract the MIME type, ignoring charset and boundary directives1346 // 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;
1348 const mime_type = content_type[0..mime_type_end];1348 const mime_type = content_type[0..mime_type_end];
13491349
1350 if (ascii.eqlIgnoreCase(mime_type, "application/x-tar"))1350 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...@@ -1455,7 +1455,7 @@ fn unpackTarball(f: *Fetch, out_dir: Io.Dir, reader: *Io.Reader) RunError!Unpack
14551455
1456 var diagnostics: std.tar.Diagnostics = .{ .allocator = arena };1456 var diagnostics: std.tar.Diagnostics = .{ .allocator = arena };
14571457
1458 std.tar.pipeToFileSystem(io, out_dir, reader, .{1458 std.tar.extract(io, out_dir, reader, .{
1459 .diagnostics = &diagnostics,1459 .diagnostics = &diagnostics,
1460 .strip_components = 0,1460 .strip_components = 0,
1461 .mode_mode = .ignore,1461 .mode_mode = .ignore,
lib/compiler/Maker/Fetch/git.zig+6-6
...@@ -336,7 +336,7 @@ pub const Repository = struct {...@@ -336,7 +336,7 @@ pub const Repository = struct {
336 fn next(iterator: *TreeIterator) !?Entry {336 fn next(iterator: *TreeIterator) !?Entry {
337 if (iterator.pos == iterator.data.len) return null;337 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;
340 const mode: packed struct {340 const mode: packed struct {
341 permission: u9,341 permission: u9,
342 unused: u3,342 unused: u3,
...@@ -351,7 +351,7 @@ pub const Repository = struct {...@@ -351,7 +351,7 @@ pub const Repository = struct {
351 };351 };
352 iterator.pos = mode_end + 1;352 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;
355 const name = iterator.data[iterator.pos..name_end :0];355 const name = iterator.data[iterator.pos..name_end :0];
356 iterator.pos = name_end + 1;356 iterator.pos = name_end + 1;
357357
...@@ -823,7 +823,7 @@ pub const Session = struct {...@@ -823,7 +823,7 @@ pub const Session = struct {
823 value: ?[]const u8 = null,823 value: ?[]const u8 = null,
824824
825 fn parse(data: []const u8) Capability {825 fn parse(data: []const u8) Capability {
826 return if (mem.indexOfScalar(u8, data, '=')) |separator_pos|826 return if (mem.findScalar(u8, data, '=')) |separator_pos|
827 .{ .key = data[0..separator_pos], .value = data[separator_pos + 1 ..] }827 .{ .key = data[0..separator_pos], .value = data[separator_pos + 1 ..] }
828 else828 else
829 .{ .key = data };829 .{ .key = data };
...@@ -941,17 +941,17 @@ pub const Session = struct {...@@ -941,17 +941,17 @@ pub const Session = struct {
941 .flush => return null,941 .flush => return null,
942 .data => |data| {942 .data => |data| {
943 const ref_data = Packet.normalizeText(data);943 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;
945 const oid = Oid.parse(it.format, data[0..oid_sep_pos]) catch return error.InvalidRefPacket;945 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;
948 const name = ref_data[oid_sep_pos + 1 .. name_sep_pos];948 const name = ref_data[oid_sep_pos + 1 .. name_sep_pos];
949949
950 var symref_target: ?[]const u8 = null;950 var symref_target: ?[]const u8 = null;
951 var peeled: ?Oid = null;951 var peeled: ?Oid = null;
952 var last_sep_pos = name_sep_pos;952 var last_sep_pos = name_sep_pos;
953 while (last_sep_pos < ref_data.len) {953 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;
955 const attribute = ref_data[last_sep_pos + 1 .. next_sep_pos];955 const attribute = ref_data[last_sep_pos + 1 .. next_sep_pos];
956 if (mem.startsWith(u8, attribute, "symref-target:")) {956 if (mem.startsWith(u8, attribute, "symref-target:")) {
957 symref_target = attribute["symref-target:".len..];957 symref_target = attribute["symref-target:".len..];
lib/compiler/Maker/PkgConfig.zig+2
...@@ -63,6 +63,8 @@ pub fn run(...@@ -63,6 +63,8 @@ pub fn run(
63 }63 }
64 }64 }
6565
66 step.clearFailedCommand(maker.gpa);
67
66 return parsed;68 return parsed;
67}69}
6870
lib/compiler/Maker/ScannedConfig.zig+63-5
...@@ -12,10 +12,6 @@ top_level_steps: std.array_hash_map.String(Configuration.Step.Index),...@@ -12,10 +12,6 @@ top_level_steps: std.array_hash_map.String(Configuration.Step.Index),
12path: std.Build.Cache.Path,12path: std.Build.Cache.Path,
1313
14pub fn print(sc: *const ScannedConfig, w: *Writer) Writer.Error!void {14pub 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", .{});
19 const c = &sc.configuration;15 const c = &sc.configuration;
20 var serializer: Serializer = .{ .writer = w };16 var serializer: Serializer = .{ .writer = w };
21 var s = try serializer.beginStruct(.{});17 var s = try serializer.beginStruct(.{});
...@@ -45,6 +41,69 @@ pub fn print(sc: *const ScannedConfig, w: *Writer) Writer.Error!void {...@@ -45,6 +41,69 @@ pub fn print(sc: *const ScannedConfig, w: *Writer) Writer.Error!void {
45 try tf.end();41 try tf.end();
46 }42 }
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
48 try s.end();107 try s.end();
49}108}
50109
...@@ -341,7 +400,6 @@ pub fn printUsage(sc: *const ScannedConfig, graph: *Graph, w: *Writer) !void {...@@ -341,7 +400,6 @@ pub fn printUsage(sc: *const ScannedConfig, graph: *Graph, w: *Writer) !void {
341 \\ --error-limit [num] Set the maximum amount of distinct error values400 \\ --error-limit [num] Set the maximum amount of distinct error values
342 \\ --build-file [file] Override path to build.zig401 \\ --build-file [file] Override path to build.zig
343 \\ --cache-dir [path] Override path to local Zig cache directory402 \\ --cache-dir [path] Override path to local Zig cache directory
344 \\ --global-cache-dir [path] Override path to global Zig cache directory
345 \\ --zig-lib=[arg] Override path to Zig lib directory403 \\ --zig-lib=[arg] Override path to Zig lib directory
346 \\ --seed [integer] For shuffling dependency traversal order (default: random)404 \\ --seed [integer] For shuffling dependency traversal order (default: random)
347 \\ --cache-poison[=mode] Override configuration caching behavior405 \\ --cache-poison[=mode] Override configuration caching behavior
lib/compiler/Maker/Step.zig+13-8
...@@ -163,6 +163,9 @@ pub const State = enum {...@@ -163,6 +163,9 @@ pub const State = enum {
163 /// be re-evaluated.163 /// be re-evaluated.
164 precheck_done,164 precheck_done,
165 dependency_failure,165 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,
166 success,169 success,
167 failure,170 failure,
168 /// This state indicates that the step did not complete, however, it also did not fail,171 /// 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...@@ -561,24 +564,26 @@ fn zigProcessUpdate(step_index: Configuration.Step.Index, maker: *Maker, zp: *Zi
561 var result: ?Path = null;564 var result: ?Path = null;
562 var eos_err: error{EndOfStream}!void = {};565 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
566 while (true) {572 while (true) {
567 const Header = std.zig.Server.Message.Header;573 const header = client.receiveMessageWithMultiReader(&zp.multi_reader, .none) catch |err| switch (err) {
568 const header = stdout.interface.takeStruct(Header, .little) catch |err| switch (err) {574 error.Timeout => unreachable,
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 error.EndOfStream => |e| {575 error.EndOfStream => |e| {
576 if (client.in.bufferedLen() == 0) break;
574 // Better to report the crash with stderr below, but we set577 // Better to report the crash with stderr below, but we set
575 // this in case the child exits successfully while violating578 // this in case the child exits successfully while violating
576 // this protocol.579 // this protocol.
577 eos_err = e;580 eos_err = e;
578 break;581 break;
579 },582 },
580 error.ReadFailed => return stdout.err.?,583 else => |e| return e,
581 };584 };
585 const body = client.in.take(header.bytes_len) catch unreachable;
586
582 switch (header.tag) {587 switch (header.tag) {
583 .zig_version => {588 .zig_version => {
584 if (!std.mem.eql(u8, builtin.zig_version_string, body)) {589 if (!std.mem.eql(u8, builtin.zig_version_string, body)) {
lib/compiler/Maker/Step/Compile.zig+2-2
...@@ -215,8 +215,8 @@ fn lowerZigArgs(...@@ -215,8 +215,8 @@ fn lowerZigArgs(
215 try addBool(gpa, zig_args, "-ffuzz", fuzz);215 try addBool(gpa, zig_args, "-ffuzz", fuzz);
216216
217 {217 {
218 var is_linking_libc = conf_comp.flags3.is_linking_libc;218 var is_linking_libc = false;
219 var is_linking_libcpp = conf_comp.flags3.is_linking_libcpp;219 var is_linking_libcpp = false;
220220
221 // Stores system libraries that have already been seen for at least one221 // Stores system libraries that have already been seen for at least one
222 // module, along with any C compiler arguments that need to be passed222 // 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(...@@ -93,6 +93,32 @@ pub fn make(
93 else => |e| return e,93 else => |e| return e,
94 };94 };
95 },95 },
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 },
96 .blank => {122 .blank => {
97 renderBlank(conf, &aw.writer, value_pairs, &value_map, include_path, include_guard_override) catch |err| switch (err) {123 renderBlank(conf, &aw.writer, value_pairs, &value_map, include_path, include_guard_override) catch |err| switch (err) {
98 error.WriteFailed => return error.OutOfMemory,124 error.WriteFailed => return error.OutOfMemory,
...@@ -370,6 +396,62 @@ fn renderCmake(...@@ -370,6 +396,62 @@ fn renderCmake(
370 if (any_errors) return error.MakeFailed;396 if (any_errors) return error.MakeFailed;
371}397}
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
373fn renderBlank(455fn renderBlank(
374 conf: *const Configuration,456 conf: *const Configuration,
375 w: *Writer,457 w: *Writer,
...@@ -432,6 +514,28 @@ fn renderValueC(conf: *const Configuration, w: *Writer, newline: []const u8, nam...@@ -432,6 +514,28 @@ fn renderValueC(conf: *const Configuration, w: *Writer, newline: []const u8, nam
432 }514 }
433}515}
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
435fn renderValueCIdent(w: *Writer, newline: []const u8, name: []const u8, ident: []const u8) Writer.Error!void {539fn renderValueCIdent(w: *Writer, newline: []const u8, name: []const u8, ident: []const u8) Writer.Error!void {
436 try w.print("#define {s}", .{name});540 try w.print("#define {s}", .{name});
437 if (ident.len > 0) {541 if (ident.len > 0) {
...@@ -628,3 +732,36 @@ fn expandVariablesCmake(...@@ -628,3 +732,36 @@ fn expandVariablesCmake(
628732
629 return result.toOwnedSliceAssert();733 return result.toOwnedSliceAssert();
630}734}
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(...@@ -64,9 +64,9 @@ pub fn make(
64 }64 }
65 }65 }
6666
67 for (conf_run.preopen_names.slice, conf_run.preopen_paths.slice) |name, path| {67 for (conf_run.preopens.slice) |preopen| {
68 man.hash.addBytesZ(name.slice(conf));68 man.hash.addBytesZ(preopen.name.slice(conf));
69 const cwd_path = try maker.resolveLazyPathIndex(arena, path, run_index);69 const cwd_path = try maker.resolveLazyPathIndex(arena, preopen.path, run_index);
70 man.hash.addBytes(try cwd_path.toString(arena));70 man.hash.addBytes(try cwd_path.toString(arena));
71 }71 }
7272
...@@ -187,6 +187,11 @@ pub fn make(...@@ -187,6 +187,11 @@ pub fn make(
187 man.hash.addListOfBytes(run_args);187 man.hash.addListOfBytes(run_args);
188 }188 }
189 },189 },
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),
190 }195 }
191 }196 }
192197
...@@ -351,6 +356,29 @@ pub fn make(...@@ -351,6 +356,29 @@ pub fn make(
351 step.clearFailedCommand(gpa);356 step.clearFailedCommand(gpa);
352}357}
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
354/// Reads stdout of a Zig test process until a termination condition is reached:382/// Reads stdout of a Zig test process until a termination condition is reached:
355/// * A write fails, indicating the child unexpectedly closed stdin383/// * A write fails, indicating the child unexpectedly closed stdin
356/// * A test (or a response from the test runner) times out384/// * A test (or a response from the test runner) times out
...@@ -384,13 +412,23 @@ fn waitZigTest(...@@ -384,13 +412,23 @@ fn waitZigTest(
384 var sub_prog_node: ?std.Progress.Node = null;412 var sub_prog_node: ?std.Progress.Node = null;
385 defer if (sub_prog_node) |n| n.end();413 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
387 if (opt_metadata.*) |*md| {425 if (opt_metadata.*) |*md| {
388 // Previous unit test process died or was killed; we're continuing where it left off426 // 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 };
390 } else {428 } else {
391 // Running unit tests normally429 // Running unit tests normally
392 run.fuzz_tests.clearRetainingCapacity();430 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 };
394 }432 }
395433
396 var active_test_index: ?u32 = null;434 var active_test_index: ?u32 = null;
...@@ -410,10 +448,6 @@ fn waitZigTest(...@@ -410,10 +448,6 @@ fn waitZigTest(
410 .raw = .fromNanoseconds(ns),448 .raw = .fromNanoseconds(ns),
411 } else null;449 } 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
417 while (true) {451 while (true) {
418 const timeout: Io.Timeout = t: {452 const timeout: Io.Timeout = t: {
419 const opt_duration = if (active_test_index == null) response_timeout else test_timeout;453 const opt_duration = if (active_test_index == null) response_timeout else test_timeout;
...@@ -421,46 +455,20 @@ fn waitZigTest(...@@ -421,46 +455,20 @@ fn waitZigTest(
421 break :t .{ .deadline = last_update.addDuration(duration) };455 break :t .{ .deadline = last_update.addDuration(duration) };
422 };456 };
423457
424 // This block is exited when `stdout` contains enough bytes for a `Header`.458 const header = client.receiveMessageWithMultiReader(multi_reader, timeout) catch |err| switch (err) {
425 header_ready: {459 error.Timeout => return .{ .timeout = .{
426 if (stdout.buffered().len >= @sizeOf(Header)) {460 .active_test_index = active_test_index,
427 // We already have one, no need to poll!461 .ns_elapsed = @intCast(last_update.untilNow(io).raw.nanoseconds),
428 break :header_ready;462 } },
429 }463 error.EndOfStream => return .{ .no_poll = .{
430464 .active_test_index = active_test_index,
431 multi_reader.fill(64, timeout) catch |err| switch (err) {465 .ns_elapsed = @intCast(last_update.untilNow(io).raw.nanoseconds),
432 error.Timeout => return .{ .timeout = .{466 } },
433 .active_test_index = active_test_index,467 else => |e| return e,
434 .ns_elapsed = @intCast(last_update.untilNow(io).raw.nanoseconds),468 };
435 } },469 const body = client.in.take(header.bytes_len) catch unreachable;
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;
463 var body_r: std.Io.Reader = .fixed(body);470 var body_r: std.Io.Reader = .fixed(body);
471
464 switch (header.tag) {472 switch (header.tag) {
465 .zig_version => {473 .zig_version => {
466 if (!std.mem.eql(u8, builtin.zig_version_string, body)) return step.fail(474 if (!std.mem.eql(u8, builtin.zig_version_string, body)) return step.fail(
...@@ -500,7 +508,7 @@ fn waitZigTest(...@@ -500,7 +508,7 @@ fn waitZigTest(
500 active_test_index = null;508 active_test_index = null;
501 last_update = .now(io, .awake);509 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 };
504 },512 },
505 .test_started => {513 .test_started => {
506 active_test_index = opt_metadata.*.?.next_index - 1;514 active_test_index = opt_metadata.*.?.next_index - 1;
...@@ -551,7 +559,7 @@ fn waitZigTest(...@@ -551,7 +559,7 @@ fn waitZigTest(
551 md.ns_per_test[tr_hdr.index] = @intCast(last_update.durationTo(now).raw.nanoseconds);559 md.ns_per_test[tr_hdr.index] = @intCast(last_update.durationTo(now).raw.nanoseconds);
552 last_update = now;560 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 };
555 },563 },
556 else => {}, // ignore other messages564 else => {}, // ignore other messages
557 }565 }
...@@ -575,7 +583,7 @@ const FuzzTestRunner = struct {...@@ -575,7 +583,7 @@ const FuzzTestRunner = struct {
575583
576 const Instance = struct {584 const Instance = struct {
577 child: process.Child,585 child: process.Child,
578 message: std.ArrayListAligned(u8, .@"4"),586 message: std.array_list.Aligned(u8, .@"4"),
579 broadcast_written: usize,587 broadcast_written: usize,
580 stderr: std.ArrayList(u8),588 stderr: std.ArrayList(u8),
581 stdin_vec: [1][]u8,589 stdin_vec: [1][]u8,
...@@ -697,17 +705,18 @@ const FuzzTestRunner = struct {...@@ -697,17 +705,18 @@ const FuzzTestRunner = struct {
697705
698 for (0.., f.instances) |id, *instance| {706 for (0.., f.instances) |id, *instance| {
699 const id32: u32 = @intCast(id);707 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 };
700 (switch (f.ctx.fuzz.mode) {713 (switch (f.ctx.fuzz.mode) {
701 .forever => sendRunFuzzTestMessage(714 .forever => client.serveRunFuzzTestMessage(
702 io,
703 instance.child.stdin.?,
704 run.fuzz_tests.items,715 run.fuzz_tests.items,
705 .forever,716 .forever,
706 id32,717 id32,
707 ),718 ),
708 .limit => |limit| sendRunFuzzTestMessage(719 .limit => |limit| client.serveRunFuzzTestMessage(
709 io,
710 instance.child.stdin.?,
711 run.fuzz_tests.items,720 run.fuzz_tests.items,
712 .iterations,721 .iterations,
713 limit.amount,722 limit.amount,
...@@ -1315,7 +1324,7 @@ pub const CachedTestMetadata = struct {...@@ -1315,7 +1324,7 @@ pub const CachedTestMetadata = struct {
1315 }1324 }
1316};1325};
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 {
1319 while (metadata.next_index < metadata.names.len) {1328 while (metadata.next_index < metadata.names.len) {
1320 const i = metadata.next_index;1329 const i = metadata.next_index;
1321 metadata.next_index += 1;1330 metadata.next_index += 1;
...@@ -1326,76 +1335,11 @@ fn requestNextTest(io: Io, in: Io.File, metadata: *TestMetadata, sub_prog_node:...@@ -1326,76 +1335,11 @@ fn requestNextTest(io: Io, in: Io.File, metadata: *TestMetadata, sub_prog_node:
1326 if (sub_prog_node.*) |n| n.end();1335 if (sub_prog_node.*) |n| n.end();
1327 sub_prog_node.* = metadata.prog_node.start(name, 0);1336 sub_prog_node.* = metadata.prog_node.start(name, 0);
13281337
1329 try sendRunTestMessage(io, in, .run_test, i);1338 try client.serveRunTest(i);
1330 return;1339 return;
1331 } else {1340 } else {
1332 metadata.next_index = std.math.maxInt(u32); // indicate that all tests are done1341 metadata.next_index = std.math.maxInt(u32); // indicate that all tests are done
1333 try sendMessage(io, in, .exit);1342 try client.serveBodylessMessage(.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 };
1399 }1343 }
1400}1344}
14011345
...@@ -1619,6 +1563,11 @@ pub fn rerunInFuzzMode(...@@ -1619,6 +1563,11 @@ pub fn rerunInFuzzMode(
1619 .output_file => unreachable,1563 .output_file => unreachable,
1620 .output_directory => unreachable,1564 .output_directory => unreachable,
1621 .passthru => unreachable,1565 .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),
1622 }1571 }
1623 }1572 }
16241573
...@@ -1917,14 +1866,14 @@ fn runCommand(...@@ -1917,14 +1866,14 @@ fn runCommand(
1917 },1866 },
1918 .wasmtime => |bin_name| {1867 .wasmtime => |bin_name| {
1919 if (graph.enable_wasmtime) {1868 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);
1921 interp_argv.appendAssumeCapacity(bin_name);1870 interp_argv.appendAssumeCapacity(bin_name);
1922 interp_argv.appendAssumeCapacity("--dir=.");1871 interp_argv.appendAssumeCapacity("--dir=.");
1923 for (conf_run.preopen_names.slice, conf_run.preopen_paths.slice) |name, lazy_path| {1872 for (conf_run.preopens.slice) |preopen| {
1924 const path = try maker.resolveLazyPath(arena, lazy_path.get(conf), run_index);1873 const path = try maker.resolveLazyPath(arena, preopen.path.get(conf), run_index);
1925 path.root_dir.handle.createDirPath(io, path.subPathOrDot()) catch |e|1874 path.root_dir.handle.createDirPath(io, path.subPathOrDot()) catch |e|
1926 return step.fail(maker, "failed creating directory {f}: {t}", .{ path, e });1875 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) }));
1928 }1877 }
1929 // Wasmtime doeesn't inherit environment variables from the parent process1878 // Wasmtime doeesn't inherit environment variables from the parent process
1930 // by default. '-S inherit-env' was added in Wasmtime version 20.1879 // 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(...@@ -2204,7 +2153,7 @@ fn fmtSnapshotIndicatorLine(buf: []const u8, index: usize) std.fmt.Alt(
2204}2153}
22052154
2206fn snapshotIndicatorLine(line: FmtIndicatorLine, w: *std.Io.Writer) std.Io.Writer.Error!void {2155fn 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|
2208 line_begin + 12157 line_begin + 1
2209 else2158 else
2210 0;2159 0;
...@@ -2285,25 +2234,35 @@ fn spawnChildAndCollect(...@@ -2285,25 +2234,35 @@ fn spawnChildAndCollect(
2285 assert(conf_run.flags.stdio != .inherit);2234 assert(conf_run.flags.stdio != .inherit);
2286 break :s .pipe;2235 break :s .pipe;
2287 } else switch (conf_run.flags.stdio) {2236 } 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,
2289 .inherit => .inherit,2238 .inherit => .inherit,
2290 .check => .ignore,2239 .check => .ignore,
2291 .zig_test => .pipe,2240 .zig_test => .pipe,
2292 },2241 },
2293 .stdout = if (conf_run.captured_stdout.value != null) .pipe else switch (conf_run.flags.stdio) {2242 .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,
2295 .inherit => .inherit,2244 .inherit => .inherit,
2296 .check => if (checksContainStdout(&conf_run)) .pipe else .ignore,2245 .check => if (checksContainStdout(&conf_run)) .pipe else .ignore,
2297 .zig_test => .pipe,2246 .zig_test => .pipe,
2298 },2247 },
2299 .stderr = if (conf_run.captured_stderr.value != null) .pipe else switch (conf_run.flags.stdio) {2248 .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,2249 .infer_from_args => if (maker.protocol_server == null and has_side_effects) .inherit else .pipe,
2301 .inherit => .inherit,2250 .inherit => if (maker.protocol_server == null) .inherit else .pipe,
2302 .check => .pipe,2251 .check => .pipe,
2303 .zig_test => .pipe,2252 .zig_test => .pipe,
2304 },2253 },
2305 };2254 };
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
2307 if (conf_run.flags.stdio == .zig_test) {2266 if (conf_run.flags.stdio == .zig_test) {
2308 try setColorEnvironmentVariables(&conf_run, environ_map, graph.stderr_mode.?);2267 try setColorEnvironmentVariables(&conf_run, environ_map, graph.stderr_mode.?);
2309 const started: Io.Clock.Timestamp = .now(io, .awake);2268 const started: Io.Clock.Timestamp = .now(io, .awake);
lib/compiler/Maker/Step/TranslateC.zig+3-3
...@@ -49,9 +49,9 @@ pub fn make(...@@ -49,9 +49,9 @@ pub fn make(
4949
50 const opt: ?OptimizeMode = switch (conf_tc.flags.optimize) {50 const opt: ?OptimizeMode = switch (conf_tc.flags.optimize) {
51 .debug, .default => null, // Skip since it's the default51 .debug, .default => null, // Skip since it's the default
52 .safe => .ReleaseSafe,52 .safe => .safe,
53 .fast => .ReleaseFast,53 .fast => .fast,
54 .small => .ReleaseSmall,54 .small => .small,
55 };55 };
56 if (opt) |o| argv.appendAssumeCapacity(try arena.print("-O{t}", .{o}));56 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 {...@@ -501,7 +501,7 @@ fn serveRequest(ws: *WebServer, req: *http.Server.Request) !void {
501 if (mem.eql(u8, target, "/main.js")) return serveLibFile(ws, req, "build-web/main.js", "application/javascript");501 if (mem.eql(u8, target, "/main.js")) return serveLibFile(ws, req, "build-web/main.js", "application/javascript");
502 if (mem.eql(u8, target, "/style.css")) return serveLibFile(ws, req, "build-web/style.css", "text/css");502 if (mem.eql(u8, target, "/style.css")) return serveLibFile(ws, req, "build-web/style.css", "text/css");
503 if (mem.eql(u8, target, "/time_report.css")) return serveLibFile(ws, req, "build-web/time_report.css", "text/css");503 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
506 if (ws.fuzz) |*fuzz| {506 if (ws.fuzz) |*fuzz| {
507 if (mem.eql(u8, target, "/sources.tar")) return fuzz.serveSourcesTar(req);507 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,...@@ -1601,6 +1601,7 @@ pub fn addSourceFromOwnedBuffer(comp: *Compilation, path: []const u8, buf: []u8,
1601 var list: std.ArrayList(u8) = .{1601 var list: std.ArrayList(u8) = .{
1602 .items = contents[0..i],1602 .items = contents[0..i],
1603 .capacity = contents.len,1603 .capacity = contents.len,
1604 .pointer_stability = .{},
1604 };1605 };
1605 contents = try list.toOwnedSlice(comp.gpa);1606 contents = try list.toOwnedSlice(comp.gpa);
1606 }1607 }
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...@@ -510,7 +510,7 @@ pub fn formatArgs(w: *std.Io.Writer, fmt: []const u8, args: anytype) std.Io.Writ
510510
511pub fn templateIndex(w: *std.Io.Writer, fmt: []const u8, template: []const u8) std.Io.Writer.Error!usize {511pub fn templateIndex(w: *std.Io.Writer, fmt: []const u8, template: []const u8) std.Io.Writer.Error!usize {
512 const i = std.mem.indexOf(u8, fmt, template) orelse {512 const i = std.mem.indexOf(u8, fmt, template) orelse {
513 if (@import("builtin").mode == .Debug) {513 if (@import("builtin").mode == .debug) {
514 std.debug.panic("template `{s}` not found in format string `{s}`", .{ template, fmt });514 std.debug.panic("template `{s}` not found in format string `{s}`", .{ template, fmt });
515 }515 }
516 try w.print("template `{s}` not found in format string `{s}` (this is a bug in arocc)", .{ template, fmt });516 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 {...@@ -1559,15 +1559,15 @@ pub fn ptrBitWidth(target: *const Target) u16 {
1559}1559}
15601560
1561pub fn cCharSignedness(target: *const Target) std.builtin.Signedness {1561pub fn cCharSignedness(target: *const Target) std.builtin.Signedness {
1562 return target.toZigTarget().cCharSignedness();1562 return target.toZigTarget().cCharSignedness().?;
1563}1563}
15641564
1565pub fn cTypeBitSize(target: *const Target, c_type: std.Target.CType) u16 {1565pub 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).?;
1567}1567}
15681568
1569pub fn cTypeAlignment(target: *const Target, c_type: std.Target.CType) u16 {1569pub 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).?;
1571}1571}
15721572
1573pub fn standardDynamicLinkerPath(target: *const Target) std.Target.DynamicLinker {1573pub 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 {...@@ -40,7 +40,7 @@ pub fn main(init: process.Init.Minimal) u8 {
40 defer threaded.deinit();40 defer threaded.deinit();
41 const io = threaded.io();41 const io = threaded.io();
4242
43 const fast_exit = @import("builtin").mode != .Debug;43 const fast_exit = @import("builtin").mode != .debug;
4444
45 const args = init.args.toSlice(arena) catch {45 const args = init.args.toSlice(arena) catch {
46 std.debug.print("out of memory\n", .{});46 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 {...@@ -83,7 +83,7 @@ pub fn main(init: process.Init.Minimal) !void {
83 if (mem.cutPrefix(u8, arg, "-D")) |option_contents| {83 if (mem.cutPrefix(u8, arg, "-D")) |option_contents| {
84 if (option_contents.len == 0)84 if (option_contents.len == 0)
85 fatalWithHint("expected option name after '-D'", .{});85 fatalWithHint("expected option name after '-D'", .{});
86 if (mem.indexOfScalar(u8, option_contents, '=')) |name_end| {86 if (mem.findScalar(u8, option_contents, '=')) |name_end| {
87 const option_name = option_contents[0..name_end];87 const option_name = option_contents[0..name_end];
88 const option_value = option_contents[name_end + 1 ..];88 const option_value = option_contents[name_end + 1 ..];
89 if (try builder.addUserInputOption(option_name, option_value))89 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 {...@@ -214,11 +214,11 @@ fn cmdObjCopy(arena: Allocator, io: Io, args: []const []const u8) !void {
214 if (listen) {214 if (listen) {
215 var stdin_reader = Io.File.stdin().reader(io, &stdin_buffer);215 var stdin_reader = Io.File.stdin().reader(io, &stdin_buffer);
216 var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer);216 var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer);
217 var server = try Server.init(.{217 var server: Server = .{
218 .in = &stdin_reader.interface,218 .in = &stdin_reader.interface,
219 .out = &stdout_writer.interface,219 .out = &stdout_writer.interface,
220 .zig_version = builtin.zig_version_string,220 };
221 });221 try server.serveStringMessage(.zig_version, builtin.zig_version_string);
222222
223 var seen_update = false;223 var seen_update = false;
224 while (true) {224 while (true) {
...@@ -435,13 +435,13 @@ const BinaryElfOutput = struct {...@@ -435,13 +435,13 @@ const BinaryElfOutput = struct {
435435
436 var program_headers = elf_hdr.iterateProgramHeaders(in);436 var program_headers = elf_hdr.iterateProgramHeaders(in);
437 while (try program_headers.next()) |phdr| {437 while (try program_headers.next()) |phdr| {
438 if (phdr.p_type == elf.PT_LOAD) {438 if (phdr.type == .LOAD) {
439 const newSegment = try allocator.create(BinaryElfSegment);439 const newSegment = try allocator.create(BinaryElfSegment);
440440
441 newSegment.physicalAddress = phdr.p_paddr;441 newSegment.physicalAddress = phdr.paddr;
442 newSegment.virtualAddress = phdr.p_vaddr;442 newSegment.virtualAddress = phdr.vaddr;
443 newSegment.fileSize = @intCast(phdr.p_filesz);443 newSegment.fileSize = @intCast(phdr.filesz);
444 newSegment.elfOffset = phdr.p_offset;444 newSegment.elfOffset = phdr.offset;
445 newSegment.binaryOffset = 0;445 newSegment.binaryOffset = 0;
446 newSegment.firstSection = null;446 newSegment.firstSection = null;
447447
...@@ -495,8 +495,8 @@ const BinaryElfOutput = struct {...@@ -495,8 +495,8 @@ const BinaryElfOutput = struct {
495 return self;495 return self;
496 }496 }
497497
498 fn sectionWithinSegment(section: *BinaryElfSection, segment: elf.Elf64_Phdr) bool {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);499 return segment.offset <= section.elfOffset and (segment.offset + segment.filesz) >= (section.elfOffset + section.fileSize);
500 }500 }
501501
502 fn sectionValidForOutput(shdr: anytype) bool {502 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 {...@@ -400,7 +400,7 @@ fn parse(gpa: Allocator, io: Io, file_path: []const u8) !Ast {
400 file_path,400 file_path,
401 gpa,401 gpa,
402 .limited(std.math.maxInt(u32)),402 .limited(std.math.maxInt(u32)),
403 .fromByteUnits(1),403 .@"1",
404 0,404 0,
405 ) catch |err| {405 ) catch |err| {
406 fatal("unable to open '{s}': {s}", .{ file_path, @errorName(err) });406 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 {...@@ -540,7 +540,7 @@ pub const Compiler = struct {
540 // This currently only checks for NUL bytes, but it should probably also check for540 // This currently only checks for NUL bytes, but it should probably also check for
541 // platform-specific invalid characters like '*', '?', '"', '<', '>', '|' (Windows)541 // platform-specific invalid characters like '*', '?', '"', '<', '>', '|' (Windows)
542 // Related: https://github.com/ziglang/zig/pull/14533#issuecomment-1416888193542 // 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) {
544 return self.addErrorDetailsAndFail(.{544 return self.addErrorDetailsAndFail(.{
545 .err = .invalid_filename,545 .err = .invalid_filename,
546 .token = node.filename.getFirstToken(),546 .token = node.filename.getFirstToken(),
...@@ -2919,11 +2919,11 @@ fn validateSearchPath(path: []const u8) error{BadPathName}!void {...@@ -2919,11 +2919,11 @@ fn validateSearchPath(path: []const u8) error{BadPathName}!void {
2919 var component_iterator = std.fs.path.componentIterator(path);2919 var component_iterator = std.fs.path.componentIterator(path);
2920 while (component_iterator.next()) |component| {2920 while (component_iterator.next()) |component| {
2921 // https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file2921 // 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;
2923 }2923 }
2924 },2924 },
2925 else => {2925 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;
2927 },2927 },
2928 }2928 }
2929}2929}
lib/compiler/resinator/cvtres.zig+1-1
...@@ -1056,7 +1056,7 @@ pub const supported_targets = struct {...@@ -1056,7 +1056,7 @@ pub const supported_targets = struct {
1056 comptime {1056 comptime {
1057 const info = @typeInfo(Arch).@"enum";1057 const info = @typeInfo(Arch).@"enum";
1058 for (info.field_names, info.field_values) |field_name, field_value| {1058 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 {
1060 @compileError(std.fmt.comptimePrint("'{s}' missing from ordered_for_display", .{field_name}));1060 @compileError(std.fmt.comptimePrint("'{s}' missing from ordered_for_display", .{field_name}));
1061 };1061 };
1062 }1062 }
lib/compiler/resinator/errors.zig+1-1
...@@ -506,7 +506,7 @@ pub const ErrorDetails = struct {...@@ -506,7 +506,7 @@ pub const ErrorDetails = struct {
506 // We know that the token slice is a well-formed #pragma code_page(N), so506 // We know that the token slice is a well-formed #pragma code_page(N), so
507 // we can skip to the first ( and then get the number that follows507 // we can skip to the first ( and then get the number that follows
508 const token_slice = self.token.slice(source);508 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;
510 while (std.ascii.isWhitespace(token_slice[number_start])) {510 while (std.ascii.isWhitespace(token_slice[number_start])) {
511 number_start += 1;511 number_start += 1;
512 }512 }
lib/compiler/resinator/parse.zig+1-1
...@@ -1277,7 +1277,7 @@ pub const Parser = struct {...@@ -1277,7 +1277,7 @@ pub const Parser = struct {
1277 },1277 },
1278 else => unreachable,1278 else => unreachable,
1279 }1279 }
1280 @compileError("unreachable");1280 comptime unreachable;
1281 }1281 }
12821282
1283 pub const OptionalParamParser = struct {1283 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...@@ -538,7 +538,7 @@ pub fn handleLineCommand(allocator: Allocator, line_command: []const u8, current
538 defer allocator.free(filename);538 defer allocator.free(filename);
539539
540 // \x00 bytes in the filename is incompatible with how StringTable works540 // \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
543 current_mapping.line_num = linenum;543 current_mapping.line_num = linenum;
544 current_mapping.filename.clearRetainingCapacity();544 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 {...@@ -142,9 +142,9 @@ fn serveRequest(request: *std.http.Server.Request, context: *Context) !void {
142 {142 {
143 try serveDocsFile(request, context, "docs/main.js", "application/javascript");143 try serveDocsFile(request, context, "docs/main.js", "application/javascript");
144 } else if (std.mem.eql(u8, request.head.target, "/main.wasm")) {144 } else if (std.mem.eql(u8, request.head.target, "/main.wasm")) {
145 try serveWasm(request, context, .ReleaseFast);145 try serveWasm(request, context, .fast);
146 } else if (std.mem.eql(u8, request.head.target, "/debug/main.wasm")) {146 } else if (std.mem.eql(u8, request.head.target, "/debug/main.wasm")) {
147 try serveWasm(request, context, .Debug);147 try serveWasm(request, context, .debug);
148 } else if (std.mem.eql(u8, request.head.target, "/sources.tar") or148 } else if (std.mem.eql(u8, request.head.target, "/sources.tar") or
149 std.mem.eql(u8, request.head.target, "/debug/sources.tar"))149 std.mem.eql(u8, request.head.target, "/debug/sources.tar"))
150 {150 {
...@@ -346,29 +346,39 @@ fn buildWasmBinary(...@@ -346,29 +346,39 @@ fn buildWasmBinary(
346 multi_reader.init(gpa, io, multi_reader_buffer.toStreams(), &.{ child.stdout.?, child.stderr.? });346 multi_reader.init(gpa, io, multi_reader_buffer.toStreams(), &.{ child.stdout.?, child.stderr.? });
347 defer multi_reader.deinit();347 defer multi_reader.deinit();
348348
349 try sendMessage(io, child.stdin.?, .update);349 const stdout = multi_reader.reader(0);
350 try sendMessage(io, child.stdin.?, .exit);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
352 var result: ?Cache.Path = null;363 var result: ?Cache.Path = null;
353 var result_error_bundle = std.zig.ErrorBundle.empty;364 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
358 var eos_err: error{EndOfStream}!void = {};366 var eos_err: error{EndOfStream}!void = {};
359367
360 while (true) {368 while (true) {
361 const header = stdout.interface.takeStruct(MessageHeader, .little) catch |err| switch (err) {369 const header = client.receiveMessageWithMultiReader(&multi_reader, .none) catch |err| switch (err) {
362 error.EndOfStream => break,370 error.Timeout => unreachable,
363 error.ReadFailed => return stdout.err.?,
364 };
365 const body = stdout.interface.take(header.bytes_len) catch |err| switch (err) {
366 error.EndOfStream => |e| {371 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.
367 eos_err = e;376 eos_err = e;
368 break;377 break;
369 },378 },
370 error.ReadFailed => return stdout.err.?,379 else => |e| return e,
371 };380 };
381 const body = client.in.take(header.bytes_len) catch unreachable;
372382
373 switch (header.tag) {383 switch (header.tag) {
374 .zig_version => {384 .zig_version => {
...@@ -435,17 +445,6 @@ fn buildWasmBinary(...@@ -435,17 +445,6 @@ fn buildWasmBinary(
435 };445 };
436}446}
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
449fn openBrowserTab(io: Io, url: []const u8) !void {448fn openBrowserTab(io: Io, url: []const u8) !void {
450 // Until https://github.com/ziglang/zig/issues/19205 is implemented, we449 // Until https://github.com/ziglang/zig/issues/19205 is implemented, we
451 // spawn and then leak a concurrent task for this child process.450 // 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 {...@@ -78,11 +78,11 @@ fn mainServer(init: std.process.Init.Minimal) !void {
78 @disableInstrumentation();78 @disableInstrumentation();
79 stdin_reader = .initStreaming(.stdin(), runner_threaded_io, &stdin_buffer);79 stdin_reader = .initStreaming(.stdin(), runner_threaded_io, &stdin_buffer);
80 stdout_writer = .initStreaming(.stdout(), runner_threaded_io, &stdout_buffer);80 stdout_writer = .initStreaming(.stdout(), runner_threaded_io, &stdout_buffer);
81 var server = try std.zig.Server.init(.{81 var server: std.zig.Server = .{
82 .in = &stdin_reader.interface,82 .in = &stdin_reader.interface,
83 .out = &stdout_writer.interface,83 .out = &stdout_writer.interface,
84 .zig_version = builtin.zig_version_string,84 };
85 });85 try server.serveStringMessage(.zig_version, builtin.zig_version_string);
8686
87 while (true) {87 while (true) {
88 const hdr = try server.receiveMessage();88 const hdr = try server.receiveMessage();
...@@ -91,24 +91,23 @@ fn mainServer(init: std.process.Init.Minimal) !void {...@@ -91,24 +91,23 @@ fn mainServer(init: std.process.Init.Minimal) !void {
91 return std.process.exit(0);91 return std.process.exit(0);
92 },92 },
93 .query_test_metadata => {93 .query_test_metadata => {
94 testing.allocator_instance = .init(std.heap.page_allocator, .{});94 var sa: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{});
95 defer if (testing.allocator_instance.deinit() != 0) {95 defer if (sa.deinit() != 0) @panic("internal test runner memory leak");
96 @panic("internal test runner memory leak");96 const gpa = sa.allocator();
97 };
9897
99 var string_bytes: std.ArrayList(u8) = .empty;98 var string_bytes: std.ArrayList(u8) = .empty;
100 defer string_bytes.deinit(testing.allocator);99 defer string_bytes.deinit(gpa);
101 try string_bytes.append(testing.allocator, 0); // Reserve 0 for null.100 try string_bytes.append(gpa, 0); // Reserve 0 for null.
102101
103 const test_fns = builtin.test_functions;102 const test_fns = builtin.test_functions;
104 const names = try testing.allocator.alloc(u32, test_fns.len);103 const names = try gpa.alloc(u32, test_fns.len);
105 defer testing.allocator.free(names);104 defer gpa.free(names);
106 const expected_panic_msgs = try testing.allocator.alloc(u32, test_fns.len);105 const expected_panic_msgs = try gpa.alloc(u32, test_fns.len);
107 defer testing.allocator.free(expected_panic_msgs);106 defer gpa.free(expected_panic_msgs);
108107
109 for (test_fns, names, expected_panic_msgs) |test_fn, *name, *expected_panic_msg| {108 for (test_fns, names, expected_panic_msgs) |test_fn, *name, *expected_panic_msg| {
110 name.* = @intCast(string_bytes.items.len);109 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);
112 string_bytes.appendSliceAssumeCapacity(test_fn.name);111 string_bytes.appendSliceAssumeCapacity(test_fn.name);
113 string_bytes.appendAssumeCapacity(0);112 string_bytes.appendAssumeCapacity(0);
114 expected_panic_msg.* = 0;113 expected_panic_msg.* = 0;
...@@ -377,6 +376,7 @@ pub fn mainSimple() anyerror!void {...@@ -377,6 +376,7 @@ pub fn mainSimple() anyerror!void {
377 else => false,376 else => false,
378 };377 };
379378
379 testing.allocator_instance = .init(std.heap.page_allocator, .{});
380 testing.io_instance = .init(testing.allocator, .{});380 testing.io_instance = .init(testing.allocator, .{});
381381
382 var passed: u64 = 0;382 var passed: u64 = 0;
lib/compiler/translate-c/MacroTranslator.zig+1-1
...@@ -361,7 +361,7 @@ fn parseCNumLit(mt: *MacroTranslator) ParseError!ZigNode {...@@ -361,7 +361,7 @@ fn parseCNumLit(mt: *MacroTranslator) ParseError!ZigNode {
361 return error.ParseError;361 return error.ParseError;
362 },362 },
363 });363 });
364 if (bytes.getLast().? == '.') {364 if (bytes.last().? == '.') {
365 bytes.appendAssumeCapacity('0');365 bytes.appendAssumeCapacity('0');
366 } else if (mem.findAny(u8, bytes.items, ".eEpP") == null) {366 } else if (mem.findAny(u8, bytes.items, ".eEpP") == null) {
367 bytes.appendSliceAssumeCapacity(".0");367 bytes.appendSliceAssumeCapacity(".0");
lib/compiler/translate-c/main.zig+1-1
...@@ -9,7 +9,7 @@ const compiler_util = @import("../util.zig");...@@ -9,7 +9,7 @@ const compiler_util = @import("../util.zig");
99
10const Translator = @import("Translator.zig");10const Translator = @import("Translator.zig");
1111
12const fast_exit = @import("builtin").mode != .Debug;12const fast_exit = @import("builtin").mode != .debug;
1313
14pub fn main(init: process.Init) u8 {14pub fn main(init: process.Init) u8 {
15 const gpa = init.gpa;15 const gpa = init.gpa;
lib/compiler_rt.zig+193-177
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
2const compiler_rt = @This();
2const ofmt_c = builtin.object_format == .c;3const ofmt_c = builtin.object_format == .c;
3const native_endian = builtin.cpu.arch.endian();4const native_endian = builtin.cpu.arch.endian();
45
...@@ -84,144 +85,17 @@ comptime {...@@ -84,144 +85,17 @@ comptime {
84 // Float routines85 // Float routines
85 // conversion86 // conversion
86 _ = @import("compiler_rt/extendf.zig");87 _ = @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
98 _ = @import("compiler_rt/truncf.zig");88 _ = @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
110 _ = @import("compiler_rt/int_from_float.zig");89 _ = @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
149 _ = @import("compiler_rt/float_from_int.zig");90 _ = @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
191 // comparison92 // comparison
192 _ = @import("compiler_rt/comparef.zig");93 _ = @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
203 // arithmetic95 // arithmetic
204 _ = @import("compiler_rt/addf3.zig");96 _ = @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
217 _ = @import("compiler_rt/mulf3.zig");97 _ = @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");
225 _ = @import("compiler_rt/divsf3.zig");99 _ = @import("compiler_rt/divsf3.zig");
226 _ = @import("compiler_rt/divdf3.zig");100 _ = @import("compiler_rt/divdf3.zig");
227 _ = @import("compiler_rt/divxf3.zig");101 _ = @import("compiler_rt/divxf3.zig");
...@@ -235,25 +109,17 @@ comptime {...@@ -235,25 +109,17 @@ comptime {
235 symbol(&__negsf2, "__negsf2");109 symbol(&__negsf2, "__negsf2");
236 symbol(&__negdf2, "__negdf2");110 symbol(&__negdf2, "__negdf2");
237 }111 }
238 if (want_ppc_abi) symbol(&__negtf2, "__negkf2");112 if (want_ppc_abi) {
239 symbol(&__negtf2, "__negtf2");113 symbol(&__negtf2, "__negkf2");
114 } else {
115 symbol(&__negtf2, "__negtf2");
116 }
240 symbol(&__negxf2, "__negxf2");117 symbol(&__negxf2, "__negxf2");
241118
242 // other119 // other
243 _ = @import("compiler_rt/powiXf2.zig");120 _ = @import("compiler_rt/powiXf2.zig");
244 _ = @import("compiler_rt/mulc3.zig");121 _ = @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
251 _ = @import("compiler_rt/divc3.zig");122 _ = @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
258 // Math routines. Alphabetically sorted.124 // Math routines. Alphabetically sorted.
259 _ = @import("compiler_rt/cos.zig");125 _ = @import("compiler_rt/cos.zig");
...@@ -279,7 +145,7 @@ comptime {...@@ -279,7 +145,7 @@ comptime {
279 _ = @import("compiler_rt/divmodei4.zig");145 _ = @import("compiler_rt/divmodei4.zig");
280 _ = @import("compiler_rt/udivmodei4.zig");146 _ = @import("compiler_rt/udivmodei4.zig");
281147
282 _ = @import("compiler_rt/limb64.zig");148 if (builtin.cpu.arch.isWasm()) _ = @import("compiler_rt/limb64.zig");
283149
284 // extra150 // extra
285 _ = @import("compiler_rt/os_version_check.zig");151 _ = @import("compiler_rt/os_version_check.zig");
...@@ -290,7 +156,7 @@ comptime {...@@ -290,7 +156,7 @@ comptime {
290 _ = @import("compiler_rt/clear_cache.zig");156 _ = @import("compiler_rt/clear_cache.zig");
291 _ = @import("compiler_rt/hexagon.zig");157 _ = @import("compiler_rt/hexagon.zig");
292158
293 if (@import("builtin").object_format != .c) {159 if (builtin.object_format != .c) {
294 if (builtin.zig_backend != .stage2_aarch64) _ = @import("compiler_rt/atomics.zig");160 if (builtin.zig_backend != .stage2_aarch64) _ = @import("compiler_rt/atomics.zig");
295 _ = @import("compiler_rt/stack_probe.zig");161 _ = @import("compiler_rt/stack_probe.zig");
296162
...@@ -302,7 +168,6 @@ comptime {...@@ -302,7 +168,6 @@ comptime {
302 _ = @import("compiler_rt/memcpy.zig");168 _ = @import("compiler_rt/memcpy.zig");
303 if (!ofmt_c) {169 if (!ofmt_c) {
304 symbol(&memset, "memset");170 symbol(&memset, "memset");
305 symbol(&__memset, "__memset");
306 }171 }
307 _ = @import("compiler_rt/memmove.zig");172 _ = @import("compiler_rt/memmove.zig");
308 symbol(&memcmp, "memcmp");173 symbol(&memcmp, "memcmp");
...@@ -367,10 +232,7 @@ pub const want_aeabi = switch (builtin.abi) {...@@ -367,10 +232,7 @@ pub const want_aeabi = switch (builtin.abi) {
367 .gnueabihf,232 .gnueabihf,
368 .android,233 .android,
369 .androideabi,234 .androideabi,
370 => switch (builtin.cpu.arch) {235 => builtin.cpu.arch.isArm(),
371 .arm, .armeb, .thumb, .thumbeb => true,
372 else => false,
373 },
374 else => false,236 else => false,
375};237};
376238
...@@ -444,19 +306,108 @@ pub const gnu_f16_abi = switch (builtin.cpu.arch) {...@@ -444,19 +306,108 @@ pub const gnu_f16_abi = switch (builtin.cpu.arch) {
444pub const want_sparc64_abi = builtin.cpu.arch == .sparc64;306pub const want_sparc64_abi = builtin.cpu.arch == .sparc64;
445pub const want_sparc32_abi = builtin.cpu.arch == .sparc;307pub const want_sparc32_abi = builtin.cpu.arch == .sparc;
446308
447pub fn F16T(comptime OtherType: type) type {309/// For operations converting between `f16` and another floating point type.
448 return switch (builtin.cpu.arch) {310pub fn f16Conv(comptime OtherType: type) type {
449 .x86, .x86_64 => if (builtin.target.os.tag.isDarwin()) switch (OtherType) {311 switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 16)) {
450 // Starting with LLVM 16, Darwin uses different abi for f16312 .hard => {},
451 // depending on the type of the other return/argument..???313 .soft => return softFloatAbi(f16),
452 f32, f64 => u16,314 }
453 f80, f128 => f16,315 if (builtin.cpu.arch.isX86() and builtin.os.tag.isDarwin()) switch (OtherType) {
454 else => unreachable,316 else => unreachable,
455 } else f16,317 // Starting with LLVM 16, Darwin uses different abi for f16
456 else => 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 }
457 };404 };
458}405}
459406
407pub fn Complex(comptime Float: type) type {
408 return struct { real: Float, imag: Float };
409}
410
460pub fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void {411pub fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void {
461 switch (Z) {412 switch (Z) {
462 u16 => {413 u16 => {
...@@ -589,31 +540,31 @@ pub inline fn fneg(a: anytype) @TypeOf(a) {...@@ -589,31 +540,31 @@ pub inline fn fneg(a: anytype) @TypeOf(a) {
589 return @bitCast(negated);540 return @bitCast(negated);
590}541}
591542
592fn __negxf2(a: f80) callconv(.c) f80 {543fn __neghf2(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
593 return fneg(a);544 return compiler_rt.f16.toAbi(fneg(compiler_rt.f16.fromAbi(a)));
594}545}
595546
596fn __neghf2(a: f16) callconv(.c) f16 {547fn __negsf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
597 return fneg(a);548 return compiler_rt.f32.toAbi(fneg(compiler_rt.f32.fromAbi(a)));
598}549}
599550
600fn __negdf2(a: f64) callconv(.c) f64 {551fn __negdf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
601 return fneg(a);552 return compiler_rt.f64.toAbi(fneg(compiler_rt.f64.fromAbi(a)));
602}553}
603554
604fn __aeabi_dneg(a: f64) callconv(.{ .arm_aapcs = .{} }) f64 {555fn __negxf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
605 return fneg(a);556 return compiler_rt.f80.toAbi(fneg(compiler_rt.f80.fromAbi(a)));
606}557}
607558
608fn __negtf2(a: f128) callconv(.c) f128 {559fn __negtf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
609 return fneg(a);560 return compiler_rt.f128.toAbi(fneg(compiler_rt.f128.fromAbi(a)));
610}561}
611562
612fn __negsf2(a: f32) callconv(.c) f32 {563fn __aeabi_fneg(a: f32) callconv(.{ .arm_aapcs = .{} }) f32 {
613 return fneg(a);564 return fneg(a);
614}565}
615566
616fn __aeabi_fneg(a: f32) callconv(.{ .arm_aapcs = .{} }) f32 {567fn __aeabi_dneg(a: f64) callconv(.{ .arm_aapcs = .{} }) f64 {
617 return fneg(a);568 return fneg(a);
618}569}
619570
...@@ -650,14 +601,80 @@ inline fn negXi2(comptime T: type, a: T) T {...@@ -650,14 +601,80 @@ inline fn negXi2(comptime T: type, a: T) T {
650 return -a;601 return -a;
651}602}
652603
653pub fn memset(dest: ?[*]u8, c: u8, len: usize) callconv(.c) ?[*]u8 {604fn memsetSmallPowerOf2(d: [*]u8, b: u8, comptime size: usize) void {
654 @setRuntimeSafety(false);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
656 if (len != 0) {673 if (len != 0) {
657 var d = dest.?;674 var d = dest.?;
658 var n = len;675 var n = len;
659 while (true) {676 while (true) {
660 d[0] = c;677 d[0] = b;
661 n -= 1;678 n -= 1;
662 if (n == 0) break;679 if (n == 0) break;
663 d += 1;680 d += 1;
...@@ -667,11 +684,10 @@ pub fn memset(dest: ?[*]u8, c: u8, len: usize) callconv(.c) ?[*]u8 {...@@ -667,11 +684,10 @@ pub fn memset(dest: ?[*]u8, c: u8, len: usize) callconv(.c) ?[*]u8 {
667 return dest;684 return dest;
668}685}
669686
670pub fn __memset(dest: ?[*]u8, c: u8, n: usize, dest_n: usize) callconv(.c) ?[*]u8 {687pub const memset = if (builtin.optimize == .small)
671 if (dest_n < n)688 smallMemset
672 @panic("buffer overflow");689else
673 return memset(dest, c, n);690 fastMemset;
674}
675691
676pub fn bcmp(vl: [*]allowzero const u8, vr: [*]allowzero const u8, n: usize) callconv(.c) c_int {692pub fn bcmp(vl: [*]allowzero const u8, vr: [*]allowzero const u8, n: usize) callconv(.c) c_int {
677 @setRuntimeSafety(false);693 @setRuntimeSafety(false);
lib/compiler_rt/absv.zig+1-2
...@@ -14,8 +14,7 @@ pub inline fn absv(comptime ST: type, a: ST) ST {...@@ -14,8 +14,7 @@ pub inline fn absv(comptime ST: type, a: ST) ST {
14 const sign: ST = a >> N - 1;14 const sign: ST = a >> N - 1;
15 x +%= sign;15 x +%= sign;
16 x ^= sign;16 x ^= sign;
17 if (x < 0)17 if (x < 0) @panic("integer overflow");
18 @panic("compiler_rt absv: overflow");
19 return x;18 return x;
20}19}
2120
lib/compiler_rt/absvdi2.zig+3-2
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1const symbol = @import("../compiler_rt.zig").symbol;1const compiler_rt = @import("../compiler_rt.zig");
2const absv = @import("./absv.zig").absv;2const symbol = compiler_rt.symbol;
3const absv = @import("absv.zig").absv;
34
4comptime {5comptime {
5 symbol(&__absvdi2, "__absvdi2");6 symbol(&__absvdi2, "__absvdi2");
lib/compiler_rt/absvsi2.zig+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const compiler_rt = @import("../compiler_rt.zig");1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;2const symbol = compiler_rt.symbol;
3const absv = @import("./absv.zig").absv;3const absv = @import("absv.zig").absv;
44
5comptime {5comptime {
6 symbol(&__absvsi2, "__absvsi2");6 symbol(&__absvsi2, "__absvsi2");
lib/compiler_rt/absvti2.zig+3-2
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1const symbol = @import("../compiler_rt.zig").symbol;1const compiler_rt = @import("../compiler_rt.zig");
2const absv = @import("./absv.zig").absv;2const symbol = compiler_rt.symbol;
3const absv = @import("absv.zig").absv;
34
4comptime {5comptime {
5 symbol(&__absvti2, "__absvti2");6 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 @@...@@ -1,12 +1,143 @@
1const std = @import("std");1const std = @import("std");
2const math = std.math;2const math = std.math;
3const compiler_rt = @import("../compiler_rt.zig");3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
4const normalize = compiler_rt.normalize;5const 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
6/// Ported from:137/// Ported from:
7///138///
8/// https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/lib/builtins/fp_add_impl.inc139/// 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 {
10 const bits = @typeInfo(T).float.bits;141 const bits = @typeInfo(T).float.bits;
11 const Z = @Int(.unsigned, bits);142 const Z = @Int(.unsigned, bits);
12143
lib/compiler_rt/addf3_test.zig+7-6
...@@ -8,12 +8,13 @@ const builtin = @import("builtin");...@@ -8,12 +8,13 @@ const builtin = @import("builtin");
8const math = std.math;8const math = std.math;
9const qnan128: f128 = @bitCast(@as(u128, 0x7fff800000000000) << 64);9const qnan128: f128 = @bitCast(@as(u128, 0x7fff800000000000) << 64);
1010
11const __addtf3 = @import("addtf3.zig").__addtf3;11const impl = @import("addf3.zig");
12const __addxf3 = @import("addxf3.zig").__addxf3;12const add_f128 = impl.add_f128;
13const __subtf3 = @import("subtf3.zig").__subtf3;13const add_f80 = impl.add_f80;
14const sub_f128 = impl.sub_f128;
1415
15fn test__addtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void {16fn 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
18 const rep: u128 = @bitCast(x);19 const rep: u128 = @bitCast(x);
19 const hi: u64 = @intCast(rep >> 64);20 const hi: u64 = @intCast(rep >> 64);
...@@ -52,7 +53,7 @@ test "addtf3" {...@@ -52,7 +53,7 @@ test "addtf3" {
52}53}
5354
54fn test__subtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void {55fn 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
57 const rep: u128 = @bitCast(x);58 const rep: u128 = @bitCast(x);
58 const hi: u64 = @intCast(rep >> 64);59 const hi: u64 = @intCast(rep >> 64);
...@@ -91,7 +92,7 @@ test "subtf3" {...@@ -91,7 +92,7 @@ test "subtf3" {
91const qnan80: f80 = @bitCast(@as(u80, @bitCast(math.nan(f80))) | (1 << (math.floatFractionalBits(f80) - 1)));92const qnan80: f80 = @bitCast(@as(u80, @bitCast(math.nan(f80))) | (1 << (math.floatFractionalBits(f80) - 1)));
9293
93fn test__addxf3(a: f80, b: f80, expected: u80) !void {94fn test__addxf3(a: f80, b: f80, expected: u80) !void {
94 const x = __addxf3(a, b);95 const x = add_f80(a, b);
95 const rep: u80 = @bitCast(x);96 const rep: u80 = @bitCast(x);
9697
97 if (rep == expected)98 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 @@...@@ -1,4 +1,5 @@
1const symbol = @import("../compiler_rt.zig").symbol;1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
2const testing = @import("std").testing;3const testing = @import("std").testing;
34
4comptime {5comptime {
...@@ -9,7 +10,7 @@ pub fn __addvdi3(a: i64, b: i64) callconv(.c) i64 {...@@ -9,7 +10,7 @@ pub fn __addvdi3(a: i64, b: i64) callconv(.c) i64 {
9 const sum = a +% b;10 const sum = a +% b;
10 // Overflow occurred iff both operands have the same sign, and the sign of the sum does11 // Overflow occurred iff both operands have the same sign, and the sign of the sum does
11 // not match it. In other words, iff the sum sign is not the sign of either operand.12 // 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");
13 return sum;14 return sum;
14}15}
1516
lib/compiler_rt/addvsi3.zig+1-1
...@@ -10,7 +10,7 @@ pub fn __addvsi3(a: i32, b: i32) callconv(.c) i32 {...@@ -10,7 +10,7 @@ pub fn __addvsi3(a: i32, b: i32) callconv(.c) i32 {
10 const sum = a +% b;10 const sum = a +% b;
11 // Overflow occurred iff both operands have the same sign, and the sign of the sum does11 // Overflow occurred iff both operands have the same sign, and the sign of the sum does
12 // not match it. In other words, iff the sum sign is not the sign of either operand.12 // 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");
14 return sum;14 return sum;
15}15}
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;...@@ -5,7 +5,7 @@ const arch = cpu.arch;
5const std = @import("std");5const std = @import("std");
66
7const compiler_rt = @import("../compiler_rt.zig");7const compiler_rt = @import("../compiler_rt.zig");
8const symbol = @import("../compiler_rt.zig").symbol;8const symbol = compiler_rt.symbol;
99
10// This parameter is true iff the target architecture supports the bare minimum10// This parameter is true iff the target architecture supports the bare minimum
11// to implement the atomic load/store intrinsics.11// to implement the atomic load/store intrinsics.
lib/compiler_rt/aulldiv.zig+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
22
3const compiler_rt = @import("../compiler_rt.zig");3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = @import("../compiler_rt.zig").symbol;4const symbol = compiler_rt.symbol;
55
6comptime {6comptime {
7 if (compiler_rt.want_windows_x86_msvc_abi) {7 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 @@...@@ -5,52 +5,12 @@
5const std = @import("std");5const std = @import("std");
6const builtin = @import("builtin");6const builtin = @import("builtin");
77
8const __eqdf2 = @import("./cmpdf2.zig").__eqdf2;8const compiler_rt = @import("../compiler_rt.zig");
9const __ledf2 = @import("./cmpdf2.zig").__ledf2;
10const __ltdf2 = @import("./cmpdf2.zig").__ltdf2;
11const __nedf2 = @import("./cmpdf2.zig").__nedf2;
129
13const __gedf2 = @import("./gedf2.zig").__gedf2;10const impl = @import("comparef.zig");
14const __gtdf2 = @import("./gedf2.zig").__gtdf2;11const Order = impl.Order;
1512const cmp_f64 = impl.cmp_f64;
16const __unorddf2 = @import("./unorddf2.zig").__unorddf2;13const unord_f64 = impl.unord_f64;
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}
5414
55const arguments = [_]f64{15const arguments = [_]f64{
56 std.math.nan(f64),16 std.math.nan(f64),
...@@ -73,36 +33,20 @@ const arguments = [_]f64{...@@ -73,36 +33,20 @@ const arguments = [_]f64{
73 std.math.inf(f64),33 std.math.inf(f64),
74};34};
7535
76fn generateVector(comptime a: f64, comptime b: f64) TestVector {36test "compare f64" {
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;
96 for (arguments[0..], 0..) |arg_i, i| {37 for (arguments[0..], 0..) |arg_i, i| {
97 for (arguments[0..], 0..) |arg_j, j| {38 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));
99 }50 }
100 }51 }
101 break :init vectors;
102};
103
104test "compare f64" {
105 for (test_vectors) |vector| {
106 try std.testing.expect(test__cmpdf2(vector));
107 }
108}52}
lib/compiler_rt/comparef.zig+274-167
...@@ -1,163 +1,309 @@...@@ -1,163 +1,309 @@
1const builtin = @import("builtin");
1const std = @import("std");2const std = @import("std");
23
3const compiler_rt = @import("../compiler_rt.zig");4const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;5const symbol = compiler_rt.symbol;
56
6comptime {7const Unordered = if (builtin.cpu.arch == .avr)
7 if (compiler_rt.want_aeabi) {8 i8
8 symbol(&__aeabi_fcmpun, "__aeabi_fcmpun");9else if (builtin.cpu.arch.isAARCH64())
9 } else {10 i32
10 symbol(&__unordsf2, "__unordsf2");11else if (builtin.target.cTypeBitSize(.long).? >= builtin.target.ptrBitWidth())
11 }12 c_long
1213else
13 symbol(&__unordxf2, "__unordxf2");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");18comptime {
16 symbol(&__nehf2, "__nehf2");
17 symbol(&__lehf2, "__lehf2");
18 symbol(&__cmphf2, "__cmphf2");19 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
21 if (compiler_rt.want_aeabi) {28 if (compiler_rt.want_aeabi) {
22 symbol(&__aeabi_fcmpeq, "__aeabi_fcmpeq");29 symbol(&__aeabi_fcmpeq, "__aeabi_fcmpeq");
23 symbol(&__aeabi_fcmplt, "__aeabi_fcmplt");30 symbol(&__aeabi_fcmplt, "__aeabi_fcmplt");
24 symbol(&__aeabi_fcmple, "__aeabi_fcmple");31 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");
25 } else {42 } else {
26 symbol(&__eqsf2, "__eqsf2");
27 symbol(&__nesf2, "__nesf2");
28 symbol(&__lesf2, "__lesf2");
29 symbol(&__cmpsf2, "__cmpsf2");43 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");
31 }60 }
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
33 if (compiler_rt.want_ppc_abi) {71 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");
34 symbol(&__unordtf2, "__unordkf2");78 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");
35 }104 }
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);
42}105}
43106
44pub fn __unordtf2(a: f128, b: f128) callconv(.c) i32 {107fn __cmphf2(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) Order {
45 return unordcmp(f128, a, b);108 return cmp_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)) orelse .gt;
46}109}
47110fn __gehf2(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) Order {
48/// "These functions calculate a <=> b. That is, if a is less than b, they return -1;111 return cmp_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)) orelse .lt;
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));
56}112}
57113fn __unordhf2(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) Unordered {
58/// "These functions return a value less than or equal to zero if neither argument is NaN,114 return @intFromBool(unord_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)));
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);
62}115}
63116pub fn cmp_f16(a: f16, b: f16) ?Order {
64/// "These functions return zero if neither argument is NaN, and a and b are equal."117 return cmpf2(f16, a, b);
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);
69}118}
70119pub fn unord_f16(a: f16, b: f16) bool {
71/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal."120 return unord(f16, a, b);
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);
76}121}
77122
78/// "These functions return a value less than zero if neither argument is NaN, and a123fn __cmpsf2(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) Order {
79/// is strictly less than b."124 return cmp_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)) orelse .gt;
80pub fn __ltsf2(a: f32, b: f32) callconv(.c) i32 {
81 return __cmpsf2(a, b);
82}125}
83
84fn __aeabi_fcmpeq(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {126fn __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);
86}128}
87
88fn __aeabi_fcmplt(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {129fn __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);
90}131}
91
92fn __aeabi_fcmple(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {132fn __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);
94}134}
95135fn __gesf2(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) Order {
96/// "These functions calculate a <=> b. That is, if a is less than b, they return -1;136 return cmp_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)) orelse .lt;
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));
104}137}
105138fn __aeabi_fcmpge(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
106/// "These functions return a value less than or equal to zero if neither argument is NaN,139 return @intFromBool(cmp_f32(a, b) orelse .lt != .lt);
107/// and a is less than or equal to b."
108fn __lehf2(a: f16, b: f16) callconv(.c) i32 {
109 return __cmphf2(a, b);
110}140}
111141fn __aeabi_fcmpgt(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
112/// "These functions return zero if neither argument is NaN, and a and b are equal."142 return @intFromBool(cmp_f32(a, b) == .gt);
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);
117}143}
118144fn __unordsf2(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) Unordered {
119/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal."145 return @intFromBool(unord_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)));
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);
124}146}
125147fn __aeabi_fcmpun(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
126/// "These functions return a value less than zero if neither argument is NaN, and a148 return @intFromBool(unord_f32(a, b));
127/// is strictly less than b."
128fn __lthf2(a: f16, b: f16) callconv(.c) i32 {
129 return __cmphf2(a, b);
130}149}
131150pub fn cmp_f32(a: f32, b: f32) ?Order {
132fn __unordxf2(a: f80, b: f80) callconv(.c) i32 {151 return cmpf2(f32, a, b);
133 return unordcmp(f80, a, b);152}
153pub fn unord_f32(a: f32, b: f32) bool {
154 return unord(f32, a, b);
134}155}
135156
136pub fn __unordsf2(a: f32, b: f32) callconv(.c) i32 {157fn __cmpdf2(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) Order {
137 return unordcmp(f32, a, b);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);
138}189}
139190
140fn __aeabi_fcmpun(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {191fn __cmpxf2(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) Order {
141 return unordcmp(f32, a, b);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;
142}196}
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) {208 // If either a or b is NaN, they are unordered.
145 Less = -1,209 if ((a_rep.exp & special_exp == special_exp and a_rep.fraction ^ int_bit != 0) or
146 Equal = 0,210 (b_rep.exp & special_exp == special_exp and b_rep.fraction ^ int_bit != 0))
147 Greater = 1,211 return null;
148212
149 const Unordered: LE = .Greater;213 // If a and b are both zeros, they are equal.
150};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) {217 if (@intFromBool(a_rep.exp == b_rep.exp) & @intFromBool(a_rep.fraction == b_rep.fraction) != 0) {
153 Less = -1,218 return .eq;
154 Equal = 0,219 } else if (a_rep.exp & sign_bit != b_rep.exp & sign_bit) {
155 Greater = 1,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;240fn __cmptf2(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) Order {
158};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 {
161 const bits = @typeInfo(T).float.bits;307 const bits = @typeInfo(T).float.bits;
162 const srep_t = @Int(.signed, bits);308 const srep_t = @Int(.signed, bits);
163 const rep_t = @Int(.unsigned, bits);309 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 {...@@ -175,81 +321,42 @@ pub inline fn cmpf2(comptime T: type, comptime RT: type, a: T, b: T) RT {
175 const bAbs = @as(rep_t, @bitCast(bInt)) & absMask;321 const bAbs = @as(rep_t, @bitCast(bInt)) & absMask;
176322
177 // If either a or b is NaN, they are unordered.323 // 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
180 // If a and b are both zeros, they are equal.326 // 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
183 // If at least one of a and b is positive, we get the same result comparing329 // If at least one of a and b is positive, we get the same result comparing
184 // a and b as signed integers as we would with a floating-point compare.330 // a and b as signed integers as we would with a floating-point compare.
185 if ((aInt & bInt) >= 0) {331 if ((aInt & bInt) >= 0) {
186 if (aInt < bInt) {332 if (aInt < bInt) {
187 return .Less;333 return .lt;
188 } else if (aInt == bInt) {334 } else if (aInt == bInt) {
189 return .Equal;335 return .eq;
190 } else return .Greater;336 } else return .gt;
191 } else {337 } else {
192 // Otherwise, both are negative, so we need to flip the sense of the338 // Otherwise, both are negative, so we need to flip the sense of the
193 // comparison to get the correct result. (This assumes a twos- or ones-339 // comparison to get the correct result. (This assumes a twos- or ones-
194 // complement integer representation; if integers are represented in a340 // complement integer representation; if integers are represented in a
195 // sign-magnitude representation, then this flip is incorrect).341 // sign-magnitude representation, then this flip is incorrect).
196 if (aInt > bInt) {342 if (aInt > bInt) {
197 return .Less;343 return .lt;
198 } else if (aInt == bInt) {344 } else if (aInt == bInt) {
199 return .Equal;345 return .eq;
200 } else return .Greater;346 } else return .gt;
201 }347 }
202}348}
203349
204pub inline fn cmp_f80(comptime RT: type, a: f80, b: f80) RT {350test cmp_f80 {
205 const a_rep = std.math.F80.fromFloat(a);351 try std.testing.expect(cmp_f80(1.0, 1.0) == .eq);
206 const b_rep = std.math.F80.fromFloat(b);352 try std.testing.expect(cmp_f80(0.0, -0.0) == .eq);
207 const sig_bits = std.math.floatMantissaBits(f80);353 try std.testing.expect(cmp_f80(2.0, 4.0) == .lt);
208 const int_bit = 0x8000000000000000;354 try std.testing.expect(cmp_f80(2.0, -4.0) == .gt);
209 const sign_bit = 0x8000;355 try std.testing.expect(cmp_f80(-2.0, -4.0) == .gt);
210 const special_exp = 0x7FFF;356 try std.testing.expect(cmp_f80(-2.0, 4.0) == .lt);
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 }
250}357}
251358
252pub inline fn unordcmp(comptime T: type, a: T, b: T) i32 {359inline fn unord(comptime T: type, a: T, b: T) bool {
253 const rep_t = @Int(.unsigned, @typeInfo(T).float.bits);360 const rep_t = @Int(.unsigned, @typeInfo(T).float.bits);
254361
255 const significandBits = std.math.floatMantissaBits(T);362 const significandBits = std.math.floatMantissaBits(T);
...@@ -261,7 +368,7 @@ pub inline fn unordcmp(comptime T: type, a: T, b: T) i32 {...@@ -261,7 +368,7 @@ pub inline fn unordcmp(comptime T: type, a: T, b: T) i32 {
261 const aAbs: rep_t = @as(rep_t, @bitCast(a)) & absMask;368 const aAbs: rep_t = @as(rep_t, @bitCast(a)) & absMask;
262 const bAbs: rep_t = @as(rep_t, @bitCast(b)) & absMask;369 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;
265}372}
266373
267test {374test {
lib/compiler_rt/comparesf2_test.zig+17-73
...@@ -5,52 +5,12 @@...@@ -5,52 +5,12 @@
5const std = @import("std");5const std = @import("std");
6const builtin = @import("builtin");6const builtin = @import("builtin");
77
8const __eqsf2 = @import("./comparef.zig").__eqsf2;8const compiler_rt = @import("../compiler_rt.zig");
9const __lesf2 = @import("./comparef.zig").__lesf2;
10const __ltsf2 = @import("./comparef.zig").__ltsf2;
11const __nesf2 = @import("./comparef.zig").__nesf2;
129
13const __gesf2 = @import("./gesf2.zig").__gesf2;10const impl = @import("comparef.zig");
14const __gtsf2 = @import("./gesf2.zig").__gtsf2;11const Order = impl.Order;
1512const cmp_f32 = impl.cmp_f32;
16const __unordsf2 = @import("./comparef.zig").__unordsf2;13const unord_f32 = impl.unord_f32;
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}
5414
55const arguments = [_]f32{15const arguments = [_]f32{
56 std.math.nan(f32),16 std.math.nan(f32),
...@@ -73,36 +33,20 @@ const arguments = [_]f32{...@@ -73,36 +33,20 @@ const arguments = [_]f32{
73 std.math.inf(f32),33 std.math.inf(f32),
74};34};
7535
76fn generateVector(comptime a: f32, comptime b: f32) TestVector {36test "compare f32" {
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;
96 for (arguments[0..], 0..) |arg_i, i| {37 for (arguments[0..], 0..) |arg_i, i| {
97 for (arguments[0..], 0..) |arg_j, j| {38 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));
99 }50 }
100 }51 }
101 break :init vectors;
102};
103
104test "compare f32" {
105 for (test_vectors) |vector| {
106 try std.testing.expect(test__cmpsf2(vector));
107 }
108}52}
lib/compiler_rt/cos.zig+64-51
...@@ -13,31 +13,34 @@ const expect = std.testing.expect;...@@ -13,31 +13,34 @@ const expect = std.testing.expect;
13const expectApproxEqAbs = std.testing.expectApproxEqAbs;13const expectApproxEqAbs = std.testing.expectApproxEqAbs;
1414
15const compiler_rt = @import("../compiler_rt.zig");15const compiler_rt = @import("../compiler_rt.zig");
16const symbol = @import("../compiler_rt.zig").symbol;16const symbol = compiler_rt.symbol;
17const trig = @import("trig.zig");17const trig = @import("trig.zig");
18const rem_pio2 = @import("rem_pio2.zig").rem_pio2;18const rem_pio2 = @import("rem_pio2.zig").rem_pio2;
19const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f;19const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f;
20const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l;20const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l;
2121
22comptime {22comptime {
23 symbol(&cosh, "__cosh");23 symbol(&__cosh, "__cosh");
24 symbol(&cosl, "__cosl");
25 symbol(&cosf, "cosf");24 symbol(&cosf, "cosf");
26 symbol(&cos, "cos");25 symbol(&cos, "cos");
27 symbol(&cosx, "__cosx");26 symbol(&__cosx, "__cosx");
28 if (compiler_rt.want_ppc_abi) {27 symbol(&cosq, "cosf128");
29 symbol(&cosq, "cosf128");
30 }
31 symbol(&cosq, "cosq");
32 symbol(&cosl, "cosl");28 symbol(&cosl, "cosl");
29 symbol(&cosl, "__cosl"); // required by musl
33}30}
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 {
36 // TODO: more efficient implementation36 // TODO: more efficient implementation
37 return @floatCast(cosf(a));37 return @floatCast(cos_f32(x));
38}38}
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 {
41 // Small multiples of pi/2 rounded to double precision.44 // Small multiples of pi/2 rounded to double precision.
42 const c1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D1845 const c1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18
43 const c2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D1846 const c2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18
...@@ -94,7 +97,10 @@ pub fn cosf(x: f32) callconv(.c) f32 {...@@ -94,7 +97,10 @@ pub fn cosf(x: f32) callconv(.c) f32 {
94 };97 };
95}98}
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 {
98 var ix = @as(u64, @bitCast(x)) >> 32;104 var ix = @as(u64, @bitCast(x)) >> 32;
99 ix &= 0x7fffffff;105 ix &= 0x7fffffff;
100106
...@@ -123,7 +129,10 @@ pub fn cos(x: f64) callconv(.c) f64 {...@@ -123,7 +129,10 @@ pub fn cos(x: f64) callconv(.c) f64 {
123 };129 };
124}130}
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 {
127 const se = ld.signExponent(x) & 0x7fff;136 const se = ld.signExponent(x) & 0x7fff;
128 if (se == 0x7fff) {137 if (se == 0x7fff) {
129 return x - x;138 return x - x;
...@@ -147,7 +156,10 @@ pub fn cosx(x: f80) callconv(.c) f80 {...@@ -147,7 +156,10 @@ pub fn cosx(x: f80) callconv(.c) f80 {
147 };156 };
148}157}
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 {
151 const se = ld.signExponent(x) & 0x7fff;163 const se = ld.signExponent(x) & 0x7fff;
152 if (se == 0x7fff) {164 if (se == 0x7fff) {
153 return x - x;165 return x - x;
...@@ -173,20 +185,21 @@ pub fn cosq(x: f128) callconv(.c) f128 {...@@ -173,20 +185,21 @@ pub fn cosq(x: f128) callconv(.c) f128 {
173185
174pub fn cosl(x: c_longdouble) callconv(.c) c_longdouble {186pub fn cosl(x: c_longdouble) callconv(.c) c_longdouble {
175 switch (@typeInfo(c_longdouble).float.bits) {187 switch (@typeInfo(c_longdouble).float.bits) {
176 64 => return cos(x),188 64 => return cos_f64(x),
177 80 => return cosx(x),189 80 => return cos_f80(x),
178 128 => return cosq(x),190 128 => return cos_f128(x),
179 else => @compileError("unreachable"),191 else => comptime unreachable,
180 }192 }
181}193}
182194
183fn testCosSpecial(comptime T: type) !void {195fn testCosSpecial(comptime T: type) !void {
184 const f = switch (T) {196 const f = switch (T) {
185 f32 => cosf,197 f16 => cos_f16,
186 f64 => cos,198 f32 => cos_f32,
187 f80 => cosx,199 f64 => cos_f64,
188 f128 => cosq,200 f80 => cos_f80,
189 else => @compileError("unimplemented"),201 f128 => cos_f128,
202 else => comptime unreachable,
190 };203 };
191204
192 try expect(f(0.0) == 1.0);205 try expect(f(0.0) == 1.0);
...@@ -198,13 +211,13 @@ fn testCosSpecial(comptime T: type) !void {...@@ -198,13 +211,13 @@ fn testCosSpecial(comptime T: type) !void {
198211
199test "cos32.normal" {212test "cos32.normal" {
200 const epsilon = math.floatEps(f32);213 const epsilon = math.floatEps(f32);
201 try expectApproxEqAbs(@as(f32, 1.0), cosf(0.0), epsilon);214 try expectApproxEqAbs(@as(f32, 1.0), cos_f32(0.0), epsilon);
202 try expectApproxEqAbs(@as(f32, 0.9800666), cosf(0.2), epsilon);215 try expectApproxEqAbs(@as(f32, 0.9800666), cos_f32(0.2), epsilon);
203 try expectApproxEqAbs(@as(f32, 0.6276231), cosf(0.8923), epsilon);216 try expectApproxEqAbs(@as(f32, 0.6276231), cos_f32(0.8923), epsilon);
204 try expectApproxEqAbs(@as(f32, 0.0707372), cosf(1.5), epsilon);217 try expectApproxEqAbs(@as(f32, 0.0707372), cos_f32(1.5), epsilon);
205 try expectApproxEqAbs(@as(f32, 0.0707372), cosf(-1.5), epsilon);218 try expectApproxEqAbs(@as(f32, 0.0707372), cos_f32(-1.5), epsilon);
206 try expectApproxEqAbs(@as(f32, 0.96913195), cosf(37.45), epsilon);219 try expectApproxEqAbs(@as(f32, 0.96913195), cos_f32(37.45), epsilon);
207 try expectApproxEqAbs(@as(f32, 0.40079966), cosf(89.123), epsilon);220 try expectApproxEqAbs(@as(f32, 0.40079966), cos_f32(89.123), epsilon);
208}221}
209222
210test "cos32.special" {223test "cos32.special" {
...@@ -213,13 +226,13 @@ test "cos32.special" {...@@ -213,13 +226,13 @@ test "cos32.special" {
213226
214test "cos64.normal" {227test "cos64.normal" {
215 const epsilon = math.floatEps(f64);228 const epsilon = math.floatEps(f64);
216 try expectApproxEqAbs(@as(f64, 1.0), cos(0.0), epsilon);229 try expectApproxEqAbs(@as(f64, 1.0), cos_f64(0.0), epsilon);
217 try expectApproxEqAbs(@as(f64, 0.9800665778412416), cos(0.2), epsilon);230 try expectApproxEqAbs(@as(f64, 0.9800665778412416), cos_f64(0.2), epsilon);
218 try expectApproxEqAbs(@as(f64, 0.6276230983360804), cos(0.8923), epsilon);231 try expectApproxEqAbs(@as(f64, 0.6276230983360804), cos_f64(0.8923), epsilon);
219 try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos(1.5), epsilon);232 try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos_f64(1.5), epsilon);
220 try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos(-1.5), epsilon);233 try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos_f64(-1.5), epsilon);
221 try expectApproxEqAbs(@as(f64, 0.9691317730707778), cos(37.45), epsilon);234 try expectApproxEqAbs(@as(f64, 0.9691317730707778), cos_f64(37.45), epsilon);
222 try expectApproxEqAbs(@as(f64, 0.4008006809354791), cos(89.123), epsilon);235 try expectApproxEqAbs(@as(f64, 0.4008006809354791), cos_f64(89.123), epsilon);
223}236}
224237
225test "cos64.special" {238test "cos64.special" {
...@@ -228,13 +241,13 @@ test "cos64.special" {...@@ -228,13 +241,13 @@ test "cos64.special" {
228241
229test "cos80.normal" {242test "cos80.normal" {
230 const epsilon = math.floatEps(f80);243 const epsilon = math.floatEps(f80);
231 try expectApproxEqAbs(@as(f80, 1.0), cosx(0.0), epsilon);244 try expectApproxEqAbs(@as(f80, 1.0), cos_f80(0.0), epsilon);
232 try expectApproxEqAbs(@as(f80, 0.98006657784124163112419651674816888), cosx(0.2), epsilon);245 try expectApproxEqAbs(@as(f80, 0.98006657784124163112419651674816888), cos_f80(0.2), epsilon);
233 try expectApproxEqAbs(@as(f80, 0.62762309833608037003563995939286067), cosx(0.8923), epsilon);246 try expectApproxEqAbs(@as(f80, 0.62762309833608037003563995939286067), cos_f80(0.8923), epsilon);
234 try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cosx(1.5), epsilon);247 try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cos_f80(1.5), epsilon);
235 try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cosx(-1.5), epsilon);248 try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cos_f80(-1.5), epsilon);
236 try expectApproxEqAbs(@as(f80, 0.9691317730707771246), cosx(37.45), epsilon);249 try expectApproxEqAbs(@as(f80, 0.9691317730707771246), cos_f80(37.45), epsilon);
237 try expectApproxEqAbs(@as(f80, 0.4008006809354834001), cosx(89.123), epsilon);250 try expectApproxEqAbs(@as(f80, 0.4008006809354834001), cos_f80(89.123), epsilon);
238}251}
239252
240test "cos80.special" {253test "cos80.special" {
...@@ -243,13 +256,13 @@ test "cos80.special" {...@@ -243,13 +256,13 @@ test "cos80.special" {
243256
244test "cos128.normal" {257test "cos128.normal" {
245 const epsilon = math.floatEps(f128);258 const epsilon = math.floatEps(f128);
246 try expectApproxEqAbs(@as(f128, 1.0), cosq(0.0), epsilon);259 try expectApproxEqAbs(@as(f128, 1.0), cos_f128(0.0), epsilon);
247 try expectApproxEqAbs(@as(f128, 0.98006657784124163112419651674816888), cosq(0.2), epsilon);260 try expectApproxEqAbs(@as(f128, 0.98006657784124163112419651674816888), cos_f128(0.2), epsilon);
248 try expectApproxEqAbs(@as(f128, 0.62762309833608037003563995939286067), cosq(0.8923), epsilon);261 try expectApproxEqAbs(@as(f128, 0.62762309833608037003563995939286067), cos_f128(0.8923), epsilon);
249 try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cosq(1.5), epsilon);262 try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cos_f128(1.5), epsilon);
250 try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cosq(-1.5), epsilon);263 try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cos_f128(-1.5), epsilon);
251 try expectApproxEqAbs(@as(f128, 0.96913177307077712443149563847233230), cosq(37.45), epsilon);264 try expectApproxEqAbs(@as(f128, 0.96913177307077712443149563847233230), cos_f128(37.45), epsilon);
252 try expectApproxEqAbs(@as(f128, 0.40080068093548339848199454493704702), cosq(89.123), epsilon);265 try expectApproxEqAbs(@as(f128, 0.40080068093548339848199454493704702), cos_f128(89.123), epsilon);
253}266}
254267
255test "cos128.special" {268test "cos128.special" {
lib/compiler_rt/count0bits.zig+2-1
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
2const std = @import("std");2const std = @import("std");
3const symbol = @import("../compiler_rt.zig").symbol;3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
45
5comptime {6comptime {
6 symbol(&__clzsi2, "__clzsi2");7 symbol(&__clzsi2, "__clzsi2");
lib/compiler_rt/divc3.zig+78-5
...@@ -7,12 +7,81 @@ const maxInt = std.math.maxInt;...@@ -7,12 +7,81 @@ const maxInt = std.math.maxInt;
7const minInt = std.math.minInt;7const minInt = std.math.minInt;
8const isFinite = std.math.isFinite;8const isFinite = std.math.isFinite;
9const copysign = std.math.copysign;9const 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
12/// Implementation based on Annex G of C17 Standard (N2176)79/// 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) {80inline fn divc3(comptime T: type, lhs: Complex(T), rhs: Complex(T)) Complex(T) {
14 var c = c_in;81 const a = lhs.real;
15 var d = d_in;82 const b = lhs.imag;
83 var c = rhs.real;
84 var d = rhs.imag;
1685
17 // logbw used to prevent under/over-flow86 // logbw used to prevent under/over-flow
18 const logbw = ilogb(@max(@abs(c), @abs(d)));87 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) {...@@ -23,7 +92,7 @@ pub inline fn divc3(comptime T: type, a: T, b: T, c_in: T, d_in: T) Complex(T) {
23 break :b logbw;92 break :b logbw;
24 } else 0;93 } else 0;
25 const denom = c * c + d * d;94 const denom = c * c + d * d;
26 const result = Complex(T){95 const result: Complex(T) = .{
27 .real = scalbn((a * c + b * d) / denom, -ilogbw),96 .real = scalbn((a * c + b * d) / denom, -ilogbw),
28 .imag = scalbn((b * c - a * d) / denom, -ilogbw),97 .imag = scalbn((b * c - a * d) / denom, -ilogbw),
29 };98 };
...@@ -58,3 +127,7 @@ pub inline fn divc3(comptime T: type, a: T, b: T, c_in: T, d_in: T) Complex(T) {...@@ -58,3 +127,7 @@ pub inline fn divc3(comptime T: type, a: T, b: T, c_in: T, d_in: T) Complex(T) {
58127
59 return result;128 return result;
60}129}
130
131test {
132 _ = @import("divc3_test.zig");
133}
lib/compiler_rt/divc3_test.zig+28-51
...@@ -2,76 +2,53 @@ const std = @import("std");...@@ -2,76 +2,53 @@ const std = @import("std");
2const math = std.math;2const math = std.math;
3const expect = std.testing.expect;3const expect = std.testing.expect;
44
5const Complex = @import("./mulc3.zig").Complex;5const Complex = @import("../compiler_rt.zig").Complex;
6const __divhc3 = @import("./divhc3.zig").__divhc3;6
7const __divsc3 = @import("./divsc3.zig").__divsc3;7const impl = @import("divc3.zig");
8const __divdc3 = @import("./divdc3.zig").__divdc3;8const div_cf16 = impl.div_cf16;
9const __divxc3 = @import("./divxc3.zig").__divxc3;9const div_cf32 = impl.div_cf32;
10const __divtc3 = @import("./divtc3.zig").__divtc3;10const div_cf64 = impl.div_cf64;
11const div_cf80 = impl.div_cf80;
12const div_cf128 = impl.div_cf128;
1113
12test "divc3" {14test "divc3" {
13 try testDiv(f16, __divhc3);15 try testDiv(f16, div_cf16);
14 try testDiv(f32, __divsc3);16 try testDiv(f32, div_cf32);
15 try testDiv(f64, __divdc3);17 try testDiv(f64, div_cf64);
16 try testDiv(f80, __divxc3);18 try testDiv(f80, div_cf80);
17 try testDiv(f128, __divtc3);19 try testDiv(f128, div_cf128);
18}20}
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 {
21 {23 {
22 const a: T = 1.0;24 const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -1.0, .imag = 0.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);
28 try expect(result.real == -1.0);25 try expect(result.real == -1.0);
29 try expect(result.imag == 0.0);26 try expect(math.isNegativeZero(result.imag));
30 }27 }
31 {28 {
32 const a: T = 1.0;29 const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -4.0, .imag = 0.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);
38 try expect(result.real == -0.25);30 try expect(result.real == -0.25);
39 try expect(result.imag == 0.0);31 try expect(math.isNegativeZero(result.imag));
40 }32 }
41 {33 {
42 // if the first operand is an infinity and the second operand is a finite number, then the34 // 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;35 // resultult of the / operator is an infinity;
44 const a: T = -math.inf(T);36 const result = f(.{ .real = -math.inf(T), .imag = 0.0 }, .{ .real = -4.0, .imag = 1.0 });
45 const b: T = 0.0;37 try expect(math.isPositiveInf(result.real));
46 const c: T = -4.0;38 try expect(math.isPositiveInf(result.imag));
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));
52 }39 }
53 {40 {
54 // if the first operand is a finite number and the second operand is an infinity, then the41 // if the first operand is a finite number and the second operand is an infinity, then the
55 // result of the / operator is a zero;42 // result of the / operator is a zero;
56 const a: T = 17.2;43 const result = f(.{ .real = 17.2, .imag = 0.0 }, .{ .real = -math.inf(T), .imag = 0.0 });
57 const b: T = 0.0;44 try expect(math.isNegativeZero(result.real));
58 const c: T = -math.inf(T);45 try expect(math.isNegativeZero(result.imag));
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);
64 }46 }
65 {47 {
66 // if the first operand is a nonzero finite number or an infinity and the second operand is48 // if the first operand is a nonzero finite number or an infinity and the second operand is
67 // a zero, then the result of the / operator is an infinity49 // a zero, then the result of the / operator is an infinity
68 const a: T = 1.1;50 const result = f(.{ .real = 1.1, .imag = 0.1 }, .{ .real = 0.0, .imag = 0.0 });
69 const b: T = 0.1;51 try expect(math.isPositiveInf(result.real));
70 const c: T = 0.0;52 try expect(math.isPositiveInf(result.imag));
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));
76 }53 }
77}54}
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 {...@@ -17,15 +17,15 @@ comptime {
17 }17 }
18}18}
1919
20pub fn __divdf3(a: f64, b: f64) callconv(.c) f64 {20fn __divdf3(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
21 return div(a, b);21 return compiler_rt.f64.toAbi(div_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)));
22}22}
2323
24fn __aeabi_ddiv(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 {24fn __aeabi_ddiv(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 {
25 return div(a, b);25 return div_f64(a, b);
26}26}
2727
28inline fn div(a: f64, b: f64) f64 {28pub fn div_f64(a: f64, b: f64) f64 {
29 const Z = @Int(.unsigned, 64);29 const Z = @Int(.unsigned, 64);
30 const SignedZ = @Int(.signed, 64);30 const SignedZ = @Int(.signed, 64);
3131
lib/compiler_rt/divdf3_test.zig+2-2
...@@ -6,7 +6,7 @@ const std = @import("std");...@@ -6,7 +6,7 @@ const std = @import("std");
6const math = std.math;6const math = std.math;
7const testing = std.testing;7const testing = std.testing;
88
9const __divdf3 = @import("divdf3.zig").__divdf3;9const div_f64 = @import("divdf3.zig").div_f64;
1010
11const nanRep: u64 = @as(u64, @bitCast(math.nan(f64)));11const nanRep: u64 = @as(u64, @bitCast(math.nan(f64)));
12const infRep: u64 = @as(u64, @bitCast(math.inf(f64)));12const infRep: u64 = @as(u64, @bitCast(math.inf(f64)));
...@@ -30,7 +30,7 @@ fn compareResultD(result: f64, expected: u64) bool {...@@ -30,7 +30,7 @@ fn compareResultD(result: f64, expected: u64) bool {
30}30}
3131
32fn test__divdf3(a: f64, b: f64, expected: u64) !void {32fn test__divdf3(a: f64, b: f64, expected: u64) !void {
33 const x = __divdf3(a, b);33 const x = div_f64(a, b);
34 const ret = compareResultD(x, expected);34 const ret = compareResultD(x, expected);
35 try testing.expect(ret == true);35 try testing.expect(ret == true);
36}36}
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");...@@ -5,7 +5,7 @@ const std = @import("std");
55
6const compiler_rt = @import("../compiler_rt.zig");6const compiler_rt = @import("../compiler_rt.zig");
7const udivmod = @import("udivmodei4.zig").divmod;7const udivmod = @import("udivmodei4.zig").divmod;
8const symbol = @import("../compiler_rt.zig").symbol;8const symbol = compiler_rt.symbol;
99
10comptime {10comptime {
11 symbol(&__divei4, "__divei4");11 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;...@@ -9,6 +9,7 @@ const symbol = compiler_rt.symbol;
9const normalize = compiler_rt.normalize;9const normalize = compiler_rt.normalize;
1010
11comptime {11comptime {
12 symbol(&__divhf3, "__divhf3");
12 if (compiler_rt.want_aeabi) {13 if (compiler_rt.want_aeabi) {
13 symbol(&__aeabi_fdiv, "__aeabi_fdiv");14 symbol(&__aeabi_fdiv, "__aeabi_fdiv");
14 } else {15 } else {
...@@ -16,15 +17,23 @@ comptime {...@@ -16,15 +17,23 @@ comptime {
16 }17 }
17}18}
1819
19pub fn __divsf3(a: f32, b: f32) callconv(.c) f32 {20fn __divhf3(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
20 return div(a, b);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)));
21}30}
2231
23fn __aeabi_fdiv(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 {32fn __aeabi_fdiv(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 {
24 return div(a, b);33 return div_f32(a, b);
25}34}
2635
27inline fn div(a: f32, b: f32) f32 {36pub fn div_f32(a: f32, b: f32) f32 {
28 const Z = @Int(.unsigned, 32);37 const Z = @Int(.unsigned, 32);
2938
30 const significandBits = std.math.floatMantissaBits(f32);39 const significandBits = std.math.floatMantissaBits(f32);
lib/compiler_rt/divsf3_test.zig+2-2
...@@ -6,7 +6,7 @@ const std = @import("std");...@@ -6,7 +6,7 @@ const std = @import("std");
6const math = std.math;6const math = std.math;
7const testing = std.testing;7const testing = std.testing;
88
9const __divsf3 = @import("divsf3.zig").__divsf3;9const div_f32 = @import("divsf3.zig").div_f32;
1010
11const nanRep: u32 = @as(u32, @bitCast(math.nan(f32)));11const nanRep: u32 = @as(u32, @bitCast(math.nan(f32)));
12const infRep: u32 = @as(u32, @bitCast(math.inf(f32)));12const infRep: u32 = @as(u32, @bitCast(math.inf(f32)));
...@@ -30,7 +30,7 @@ fn compareResultF(result: f32, expected: u32) bool {...@@ -30,7 +30,7 @@ fn compareResultF(result: f32, expected: u32) bool {
30}30}
3131
32fn test__divsf3(a: f32, b: f32, expected: u32) !void {32fn test__divsf3(a: f32, b: f32, expected: u32) !void {
33 const x = __divsf3(a, b);33 const x = div_f32(a, b);
34 const ret = compareResultF(x, expected);34 const ret = compareResultF(x, expected);
35 try testing.expect(ret == true);35 try testing.expect(ret == true);
36}36}
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 {...@@ -13,19 +13,20 @@ comptime {
13 symbol(&_Qp_div, "_Qp_div");13 symbol(&_Qp_div, "_Qp_div");
14 } else if (compiler_rt.want_sparc32_abi) {14 } else if (compiler_rt.want_sparc32_abi) {
15 symbol(&__divtf3, "_Q_div");15 symbol(&__divtf3, "_Q_div");
16 } else {
17 symbol(&__divtf3, "__divtf3");
16 }18 }
17 symbol(&__divtf3, "__divtf3");
18}19}
1920
20pub fn __divtf3(a: f128, b: f128) callconv(.c) f128 {21fn __divtf3(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
21 return div(a, b);22 return compiler_rt.f128.toAbi(div_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)));
22}23}
2324
24fn _Qp_div(c: *f128, a: *const f128, b: *const f128) callconv(.c) void {25fn _Qp_div(c: *f128, a: *const f128, b: *const f128) callconv(.c) void {
25 c.* = div(a.*, b.*);26 c.* = div_f128(a.*, b.*);
26}27}
2728
28inline fn div(a: f128, b: f128) f128 {29pub fn div_f128(a: f128, b: f128) f128 {
29 const Z = @Int(.unsigned, 128);30 const Z = @Int(.unsigned, 128);
3031
31 const significandBits = std.math.floatMantissaBits(f128);32 const significandBits = std.math.floatMantissaBits(f128);
lib/compiler_rt/divtf3_test.zig+2-2
...@@ -2,7 +2,7 @@ const std = @import("std");...@@ -2,7 +2,7 @@ const std = @import("std");
2const math = std.math;2const math = std.math;
3const testing = std.testing;3const testing = std.testing;
44
5const __divtf3 = @import("divtf3.zig").__divtf3;5const div_f128 = @import("divtf3.zig").div_f128;
66
7fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool {7fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool {
8 const rep: u128 = @bitCast(result);8 const rep: u128 = @bitCast(result);
...@@ -24,7 +24,7 @@ fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool {...@@ -24,7 +24,7 @@ fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool {
24}24}
2525
26fn test__divtf3(a: f128, b: f128, expectedHi: u64, expectedLo: u64) !void {26fn test__divtf3(a: f128, b: f128, expectedHi: u64, expectedLo: u64) !void {
27 const x = __divtf3(a, b);27 const x = div_f128(a, b);
28 const ret = compareResultLD(x, expectedHi, expectedLo);28 const ret = compareResultLD(x, expectedHi, expectedLo);
29 try testing.expect(ret == true);29 try testing.expect(ret == true);
30}30}
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 {...@@ -11,7 +11,10 @@ comptime {
11 symbol(&__divxf3, "__divxf3");11 symbol(&__divxf3, "__divxf3");
12}12}
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 {
15 const T = f80;18 const T = f80;
16 const Z = @Int(.unsigned, @bitSizeOf(T));19 const Z = @Int(.unsigned, @bitSizeOf(T));
1720
lib/compiler_rt/divxf3_test.zig+3-3
...@@ -2,7 +2,7 @@ const std = @import("std");...@@ -2,7 +2,7 @@ const std = @import("std");
2const math = std.math;2const math = std.math;
3const testing = std.testing;3const testing = std.testing;
44
5const __divxf3 = @import("divxf3.zig").__divxf3;5const div_f80 = @import("divxf3.zig").div_f80;
66
7const nanRep: u80 = @as(u80, @bitCast(math.nan(f80)));7const nanRep: u80 = @as(u80, @bitCast(math.nan(f80)));
8const infRep: u80 = @as(u80, @bitCast(math.inf(f80)));8const infRep: u80 = @as(u80, @bitCast(math.inf(f80)));
...@@ -19,14 +19,14 @@ fn compareResult(result: f80, expected: u80) bool {...@@ -19,14 +19,14 @@ fn compareResult(result: f80, expected: u80) bool {
19}19}
2020
21fn expect__divxf3_result(a: f80, b: f80, expected: u80) !void {21fn expect__divxf3_result(a: f80, b: f80, expected: u80) !void {
22 const x = __divxf3(a, b);22 const x = div_f80(a, b);
23 const ret = compareResult(x, expected);23 const ret = compareResult(x, expected);
24 try testing.expect(ret == true);24 try testing.expect(ret == true);
25}25}
2626
27fn test__divxf3(a: f80, b: f80) !void {27fn test__divxf3(a: f80, b: f80) !void {
28 const integerBit = 1 << math.floatFractionalBits(f80);28 const integerBit = 1 << math.floatFractionalBits(f80);
29 const x = __divxf3(a, b);29 const x = div_f80(a, b);
3030
31 // Next float (assuming normal, non-zero result)31 // Next float (assuming normal, non-zero result)
32 const x_plus_eps: f80 = @bitCast((@as(u80, @bitCast(x)) + 1) | integerBit);32 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;...@@ -14,26 +14,29 @@ const expect = std.testing.expect;
14const expectEqual = std.testing.expectEqual;14const expectEqual = std.testing.expectEqual;
1515
16const compiler_rt = @import("../compiler_rt.zig");16const compiler_rt = @import("../compiler_rt.zig");
17const symbol = @import("../compiler_rt.zig").symbol;17const symbol = compiler_rt.symbol;
1818
19comptime {19comptime {
20 symbol(&__exph, "__exph");20 symbol(&__exph, "__exph");
21 symbol(&expf, "expf");21 symbol(&expf, "expf");
22 symbol(&exp, "exp");22 symbol(&exp, "exp");
23 symbol(&__expx, "__expx");23 symbol(&__expx, "__expx");
24 if (compiler_rt.want_ppc_abi) {24 symbol(&expq, "expf128");
25 symbol(&expq, "expf128");
26 }
27 symbol(&expq, "expq");
28 symbol(&expl, "expl");25 symbol(&expl, "expl");
29}26}
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 {
32 // TODO: more efficient implementation32 // TODO: more efficient implementation
33 return @floatCast(expf(a));33 return @floatCast(exp_f32(x));
34}34}
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 {
37 const half = [_]f32{ 0.5, -0.5 };40 const half = [_]f32{ 0.5, -0.5 };
38 const ln2hi = 6.9314575195e-1;41 const ln2hi = 6.9314575195e-1;
39 const ln2lo = 1.4286067653e-6;42 const ln2lo = 1.4286067653e-6;
...@@ -108,7 +111,10 @@ pub fn expf(x_: f32) callconv(.c) f32 {...@@ -108,7 +111,10 @@ pub fn expf(x_: f32) callconv(.c) f32 {
108 }111 }
109}112}
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 {
112 const half = [_]f64{ 0.5, -0.5 };118 const half = [_]f64{ 0.5, -0.5 };
113 const ln2hi: f64 = 6.93147180369123816490e-01;119 const ln2hi: f64 = 6.93147180369123816490e-01;
114 const ln2lo: f64 = 1.90821492927058770002e-10;120 const ln2lo: f64 = 1.90821492927058770002e-10;
...@@ -189,116 +195,121 @@ pub fn exp(x_: f64) callconv(.c) f64 {...@@ -189,116 +195,121 @@ pub fn exp(x_: f64) callconv(.c) f64 {
189 }195 }
190}196}
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 {
193 // TODO: more efficient implementation202 // TODO: more efficient implementation
194 return @floatCast(expq(a));203 return @floatCast(exp_f128(x));
195}204}
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
199pub fn expl(x: c_longdouble) callconv(.c) c_longdouble {211pub fn expl(x: c_longdouble) callconv(.c) c_longdouble {
200 switch (@typeInfo(c_longdouble).float.bits) {212 switch (@typeInfo(c_longdouble).float.bits) {
201 64 => return exp(x),213 64 => return exp_f64(x),
202 80 => return __expx(x),214 80 => return exp_f80(x),
203 128 => return expq(x),215 128 => return exp_f128(x),
204 else => @compileError("unreachable"),216 else => comptime unreachable,
205 }217 }
206}218}
207219
208test "expf() special" {220test "expf() special" {
209 try expectEqual(expf(0.0), 1.0);221 try expectEqual(exp_f32(0.0), 1.0);
210 try expectEqual(expf(-0.0), 1.0);222 try expectEqual(exp_f32(-0.0), 1.0);
211 try expectEqual(expf(1.0), math.e);223 try expectEqual(exp_f32(1.0), math.e);
212 try expectEqual(expf(math.ln2), 2.0);224 try expectEqual(exp_f32(math.ln2), 2.0);
213 try expectEqual(expf(math.inf(f32)), math.inf(f32));225 try expectEqual(exp_f32(math.inf(f32)), math.inf(f32));
214 try expect(math.isPositiveZero(expf(-math.inf(f32))));226 try expect(math.isPositiveZero(exp_f32(-math.inf(f32))));
215 try expect(math.isNan(expf(math.nan(f32))));227 try expect(math.isNan(exp_f32(math.nan(f32))));
216 try expect(math.isNan(expf(math.snan(f32))));228 try expect(math.isNan(exp_f32(math.snan(f32))));
217}229}
218230
219test "expf() sanity" {231test "expf() sanity" {
220 try expectEqual(expf(-0x1.0223a0p+3), 0x1.490320p-12);232 try expectEqual(exp_f32(-0x1.0223a0p+3), 0x1.490320p-12);
221 try expectEqual(expf(0x1.161868p+2), 0x1.34712ap+6);233 try expectEqual(exp_f32(0x1.161868p+2), 0x1.34712ap+6);
222 try expectEqual(expf(-0x1.0c34b4p+3), 0x1.e06b1ap-13);234 try expectEqual(exp_f32(-0x1.0c34b4p+3), 0x1.e06b1ap-13);
223 try expectEqual(expf(-0x1.a206f0p+2), 0x1.7dd484p-10);235 try expectEqual(exp_f32(-0x1.a206f0p+2), 0x1.7dd484p-10);
224 try expectEqual(expf(0x1.288bbcp+3), 0x1.4abc80p+13);236 try expectEqual(exp_f32(0x1.288bbcp+3), 0x1.4abc80p+13);
225 try expectEqual(expf(0x1.52efd0p-1), 0x1.f04a9cp+0);237 try expectEqual(exp_f32(0x1.52efd0p-1), 0x1.f04a9cp+0);
226 try expectEqual(expf(-0x1.a05cc8p-2), 0x1.54f1e0p-1);238 try expectEqual(exp_f32(-0x1.a05cc8p-2), 0x1.54f1e0p-1);
227 try expectEqual(expf(0x1.1f9efap-1), 0x1.c0f628p+0);239 try expectEqual(exp_f32(0x1.1f9efap-1), 0x1.c0f628p+0);
228 try expectEqual(expf(0x1.8c5db0p-1), 0x1.1599b2p+1);240 try expectEqual(exp_f32(0x1.8c5db0p-1), 0x1.1599b2p+1);
229 try expectEqual(expf(-0x1.5b86eap-1), 0x1.03b572p-1);241 try expectEqual(exp_f32(-0x1.5b86eap-1), 0x1.03b572p-1);
230 try expectEqual(expf(-0x1.57f25cp+2), 0x1.2fbea2p-8);242 try expectEqual(exp_f32(-0x1.57f25cp+2), 0x1.2fbea2p-8);
231 try expectEqual(expf(0x1.c7d310p+3), 0x1.76eefp+20);243 try expectEqual(exp_f32(0x1.c7d310p+3), 0x1.76eefp+20);
232 try expectEqual(expf(0x1.19be70p+4), 0x1.52d3dep+25);244 try expectEqual(exp_f32(0x1.19be70p+4), 0x1.52d3dep+25);
233 try expectEqual(expf(-0x1.ab6d70p+3), 0x1.a88adep-20);245 try expectEqual(exp_f32(-0x1.ab6d70p+3), 0x1.a88adep-20);
234 try expectEqual(expf(-0x1.5ac18ep+2), 0x1.22b328p-8);246 try expectEqual(exp_f32(-0x1.5ac18ep+2), 0x1.22b328p-8);
235 try expectEqual(expf(-0x1.925982p-1), 0x1.d2acc0p-2);247 try expectEqual(exp_f32(-0x1.925982p-1), 0x1.d2acc0p-2);
236 try expectEqual(expf(0x1.7221cep+3), 0x1.9c2ceap+16);248 try expectEqual(exp_f32(0x1.7221cep+3), 0x1.9c2ceap+16);
237 try expectEqual(expf(0x1.11a0d4p+4), 0x1.980ee6p+24);249 try expectEqual(exp_f32(0x1.11a0d4p+4), 0x1.980ee6p+24);
238 try expectEqual(expf(-0x1.ae41a2p+1), 0x1.1c28d0p-5);250 try expectEqual(exp_f32(-0x1.ae41a2p+1), 0x1.1c28d0p-5);
239 try expectEqual(expf(-0x1.329154p+4), 0x1.47ef94p-28);251 try expectEqual(exp_f32(-0x1.329154p+4), 0x1.47ef94p-28);
240}252}
241253
242test "expf() boundary" {254test "expf() boundary" {
243 try expectEqual(expf(0x1.62e42ep+6), 0x1.ffff08p+127); // The last value before the result gets infinite255 try expectEqual(exp_f32(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 inf256 try expectEqual(exp_f32(0x1.62e430p+6), math.inf(f32)); // The first value that gives inf
245 try expectEqual(expf(0x1.fffffep+127), math.inf(f32)); // Max input value257 try expectEqual(exp_f32(0x1.fffffep+127), math.inf(f32)); // Max input value
246 try expectEqual(expf(0x1p-149), 1.0); // Min positive input value258 try expectEqual(exp_f32(0x1p-149), 1.0); // Min positive input value
247 try expectEqual(expf(-0x1p-149), 1.0); // Min negative input value259 try expectEqual(exp_f32(-0x1p-149), 1.0); // Min negative input value
248 try expectEqual(expf(0x1p-126), 1.0); // First positive subnormal input260 try expectEqual(exp_f32(0x1p-126), 1.0); // First positive subnormal input
249 try expectEqual(expf(-0x1p-126), 1.0); // First negative subnormal input261 try expectEqual(exp_f32(-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 zero262 try expectEqual(exp_f32(-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 zero263 try expectEqual(exp_f32(-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 subnormal264 try expectEqual(exp_f32(-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 subnormal265 try expectEqual(exp_f32(-0x1.5d58a0p+6), 0x1.ffff98p-127); // The first value for which the result flushes to subnormal
254
255}266}
256267
257test "exp() special" {268test "exp() special" {
258 try expectEqual(exp(0.0), 1.0);269 try expectEqual(exp_f64(0.0), 1.0);
259 try expectEqual(exp(-0.0), 1.0);270 try expectEqual(exp_f64(-0.0), 1.0);
260 // TODO: Accuracy error - off in the last bit in 64-bit, disagreeing with GCC271 // TODO: Accuracy error - off in the last bit in 64-bit, disagreeing with GCC
261 // try expectEqual(exp(1.0), math.e);272 // try expectEqual(exp(1.0), math.e);
262 try expectEqual(exp(math.ln2), 2.0);273 try expectEqual(exp_f64(math.ln2), 2.0);
263 try expectEqual(exp(math.inf(f64)), math.inf(f64));274 try expectEqual(exp_f64(math.inf(f64)), math.inf(f64));
264 try expect(math.isPositiveZero(exp(-math.inf(f64))));275 try expect(math.isPositiveZero(exp_f64(-math.inf(f64))));
265 try expect(math.isNan(exp(math.nan(f64))));276 try expect(math.isNan(exp_f64(math.nan(f64))));
266 try expect(math.isNan(exp(math.snan(f64))));277 try expect(math.isNan(exp_f64(math.snan(f64))));
267}278}
268279
269test "exp() sanity" {280test "exp() sanity" {
270 try expectEqual(exp(-0x1.02239f3c6a8f1p+3), 0x1.490327ea61235p-12);281 try expectEqual(exp_f64(-0x1.02239f3c6a8f1p+3), 0x1.490327ea61235p-12);
271 try expectEqual(exp(0x1.161868e18bc67p+2), 0x1.34712ed238c04p+6);282 try expectEqual(exp_f64(0x1.161868e18bc67p+2), 0x1.34712ed238c04p+6);
272 try expectEqual(exp(-0x1.0c34b3e01e6e7p+3), 0x1.e06b1b6c18e64p-13);283 try expectEqual(exp_f64(-0x1.0c34b3e01e6e7p+3), 0x1.e06b1b6c18e64p-13);
273 try expectEqual(exp(-0x1.a206f0a19dcc4p+2), 0x1.7dd47f810e68cp-10);284 try expectEqual(exp_f64(-0x1.a206f0a19dcc4p+2), 0x1.7dd47f810e68cp-10);
274 try expectEqual(exp(0x1.288bbb0d6a1e6p+3), 0x1.4abc77496e07ep+13);285 try expectEqual(exp_f64(0x1.288bbb0d6a1e6p+3), 0x1.4abc77496e07ep+13);
275 try expectEqual(exp(0x1.52efd0cd80497p-1), 0x1.f04a9c1080500p+0);286 try expectEqual(exp_f64(0x1.52efd0cd80497p-1), 0x1.f04a9c1080500p+0);
276 try expectEqual(exp(-0x1.a05cc754481d1p-2), 0x1.54f1e0fd3ea0dp-1);287 try expectEqual(exp_f64(-0x1.a05cc754481d1p-2), 0x1.54f1e0fd3ea0dp-1);
277 try expectEqual(exp(0x1.1f9ef934745cbp-1), 0x1.c0f6266a6a547p+0);288 try expectEqual(exp_f64(0x1.1f9ef934745cbp-1), 0x1.c0f6266a6a547p+0);
278 try expectEqual(exp(0x1.8c5db097f7442p-1), 0x1.1599b1d4a25fbp+1);289 try expectEqual(exp_f64(0x1.8c5db097f7442p-1), 0x1.1599b1d4a25fbp+1);
279 try expectEqual(exp(-0x1.5b86ea8118a0ep-1), 0x1.03b5728a00229p-1);290 try expectEqual(exp_f64(-0x1.5b86ea8118a0ep-1), 0x1.03b5728a00229p-1);
280 try expectEqual(exp(-0x1.57f25b2b5006dp+2), 0x1.2fbea6a01cab9p-8);291 try expectEqual(exp_f64(-0x1.57f25b2b5006dp+2), 0x1.2fbea6a01cab9p-8);
281 try expectEqual(exp(0x1.c7d30fb825911p+3), 0x1.76eeed45a0634p+20);292 try expectEqual(exp_f64(0x1.c7d30fb825911p+3), 0x1.76eeed45a0634p+20);
282 try expectEqual(exp(0x1.19be709de7505p+4), 0x1.52d3eb7be6844p+25);293 try expectEqual(exp_f64(0x1.19be709de7505p+4), 0x1.52d3eb7be6844p+25);
283 try expectEqual(exp(-0x1.ab6d6fba96889p+3), 0x1.a88ae12f985d6p-20);294 try expectEqual(exp_f64(-0x1.ab6d6fba96889p+3), 0x1.a88ae12f985d6p-20);
284 try expectEqual(exp(-0x1.5ac18e27084ddp+2), 0x1.22b327da9cca6p-8);295 try expectEqual(exp_f64(-0x1.5ac18e27084ddp+2), 0x1.22b327da9cca6p-8);
285 try expectEqual(exp(-0x1.925981b093c41p-1), 0x1.d2acc046b55f7p-2);296 try expectEqual(exp_f64(-0x1.925981b093c41p-1), 0x1.d2acc046b55f7p-2);
286 try expectEqual(exp(0x1.7221cd18455f5p+3), 0x1.9c2cde8699cfbp+16);297 try expectEqual(exp_f64(0x1.7221cd18455f5p+3), 0x1.9c2cde8699cfbp+16);
287 try expectEqual(exp(0x1.11a0d4a51b239p+4), 0x1.980ef612ff182p+24);298 try expectEqual(exp_f64(0x1.11a0d4a51b239p+4), 0x1.980ef612ff182p+24);
288 try expectEqual(exp(-0x1.ae41a1079de4dp+1), 0x1.1c28d16bb3222p-5);299 try expectEqual(exp_f64(-0x1.ae41a1079de4dp+1), 0x1.1c28d16bb3222p-5);
289 try expectEqual(exp(-0x1.329153103b871p+4), 0x1.47efa6ddd0d22p-28);300 try expectEqual(exp_f64(-0x1.329153103b871p+4), 0x1.47efa6ddd0d22p-28);
290}301}
291302
292test "exp() boundary" {303test "exp() boundary" {
293 try expectEqual(exp(0x1.62e42fefa39efp+9), 0x1.fffffffffff2ap+1023); // The last value before the result gets infinite304 try expectEqual(exp_f64(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 inf305 try expectEqual(exp_f64(0x1.62e42fefa39f0p+9), math.inf(f64)); // The first value that gives inf
295 try expectEqual(exp(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value306 try expectEqual(exp_f64(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value
296 try expectEqual(exp(0x1p-1074), 1.0); // Min positive input value307 try expectEqual(exp_f64(0x1p-1074), 1.0); // Min positive input value
297 try expectEqual(exp(-0x1p-1074), 1.0); // Min negative input value308 try expectEqual(exp_f64(-0x1p-1074), 1.0); // Min negative input value
298 try expectEqual(exp(0x1p-1022), 1.0); // First positive subnormal input309 try expectEqual(exp_f64(0x1p-1022), 1.0); // First positive subnormal input
299 try expectEqual(exp(-0x1p-1022), 1.0); // First negative subnormal input310 try expectEqual(exp_f64(-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 zero311 try expectEqual(exp_f64(-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 zero312 try expectEqual(exp_f64(-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 subnormal313 try expectEqual(exp_f64(-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 subnormal314 try expectEqual(exp_f64(-0x1.6232bdd7abcd3p+9), 0x1.ffffffffffcf8p-1023); // The first value for which the result flushes to subnormal
304}315}
lib/compiler_rt/exp2.zig+85-73
...@@ -19,19 +19,22 @@ comptime {...@@ -19,19 +19,22 @@ comptime {
19 symbol(&exp2f, "exp2f");19 symbol(&exp2f, "exp2f");
20 symbol(&exp2, "exp2");20 symbol(&exp2, "exp2");
21 symbol(&__exp2x, "__exp2x");21 symbol(&__exp2x, "__exp2x");
22 if (compiler_rt.want_ppc_abi) {22 symbol(&exp2q, "exp2f128");
23 symbol(&exp2q, "exp2f128");
24 }
25 symbol(&exp2q, "exp2q");
26 symbol(&exp2l, "exp2l");23 symbol(&exp2l, "exp2l");
27}24}
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 {
30 // TODO: more efficient implementation30 // TODO: more efficient implementation
31 return @floatCast(exp2f(x));31 return @floatCast(exp2_f32(x));
32}32}
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 {
35 const tblsiz: u32 = @intCast(exp2ft.len);38 const tblsiz: u32 = @intCast(exp2ft.len);
36 const redux: f32 = 0x1.8p23 / @as(f32, @floatFromInt(tblsiz));39 const redux: f32 = 0x1.8p23 / @as(f32, @floatFromInt(tblsiz));
37 const P1: f32 = 0x1.62e430p-1;40 const P1: f32 = 0x1.62e430p-1;
...@@ -88,7 +91,10 @@ pub fn exp2f(x: f32) callconv(.c) f32 {...@@ -88,7 +91,10 @@ pub fn exp2f(x: f32) callconv(.c) f32 {
88 return @floatCast(r * uk);91 return @floatCast(r * uk);
89}92}
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 {
92 const tblsiz: u32 = @intCast(exp2dt.len / 2);98 const tblsiz: u32 = @intCast(exp2dt.len / 2);
93 const redux: f64 = 0x1.8p52 / @as(f64, @floatFromInt(tblsiz));99 const redux: f64 = 0x1.8p52 / @as(f64, @floatFromInt(tblsiz));
94 const P1: f64 = 0x1.62e42fefa39efp-1;100 const P1: f64 = 0x1.62e42fefa39efp-1;
...@@ -156,19 +162,25 @@ pub fn exp2(x: f64) callconv(.c) f64 {...@@ -156,19 +162,25 @@ pub fn exp2(x: f64) callconv(.c) f64 {
156 return math.scalbn(r, ik);162 return math.scalbn(r, ik);
157}163}
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 {
160 // TODO: more efficient implementation169 // TODO: more efficient implementation
161 return @floatCast(exp2q(x));170 return @floatCast(exp2_f128(x));
162}171}
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
166pub fn exp2l(x: c_longdouble) callconv(.c) c_longdouble {178pub fn exp2l(x: c_longdouble) callconv(.c) c_longdouble {
167 switch (@typeInfo(c_longdouble).float.bits) {179 switch (@typeInfo(c_longdouble).float.bits) {
168 64 => return exp2(x),180 64 => return exp2_f64(x),
169 80 => return __exp2x(x),181 80 => return exp2_f80(x),
170 128 => return exp2q(x),182 128 => return exp2_f128(x),
171 else => @compileError("unreachable"),183 else => comptime unreachable,
172 }184 }
173}185}
174186
...@@ -452,77 +464,77 @@ const exp2dt = [_]f64{...@@ -452,77 +464,77 @@ const exp2dt = [_]f64{
452};464};
453465
454test "exp2f() special" {466test "exp2f() special" {
455 try expectEqual(exp2f(0.0), 1.0);467 try expectEqual(exp2_f32(0.0), 1.0);
456 try expectEqual(exp2f(-0.0), 1.0);468 try expectEqual(exp2_f32(-0.0), 1.0);
457 try expectEqual(exp2f(1.0), 2.0);469 try expectEqual(exp2_f32(1.0), 2.0);
458 try expectEqual(exp2f(-1.0), 0.5);470 try expectEqual(exp2_f32(-1.0), 0.5);
459 try expectEqual(exp2f(math.inf(f32)), math.inf(f32));471 try expectEqual(exp2_f32(math.inf(f32)), math.inf(f32));
460 try expect(math.isPositiveZero(exp2f(-math.inf(f32))));472 try expect(math.isPositiveZero(exp2_f32(-math.inf(f32))));
461 try expect(math.isNan(exp2f(math.nan(f32))));473 try expect(math.isNan(exp2_f32(math.nan(f32))));
462 try expect(math.isNan(exp2f(math.snan(f32))));474 try expect(math.isNan(exp2_f32(math.snan(f32))));
463}475}
464476
465test "exp2f() sanity" {477test "exp2f() sanity" {
466 try expectEqual(exp2f(-0x1.0223a0p+3), 0x1.e8d134p-9);478 try expectEqual(exp2_f32(-0x1.0223a0p+3), 0x1.e8d134p-9);
467 try expectEqual(exp2f(0x1.161868p+2), 0x1.453672p+4);479 try expectEqual(exp2_f32(0x1.161868p+2), 0x1.453672p+4);
468 try expectEqual(exp2f(-0x1.0c34b4p+3), 0x1.890ca0p-9);480 try expectEqual(exp2_f32(-0x1.0c34b4p+3), 0x1.890ca0p-9);
469 try expectEqual(exp2f(-0x1.a206f0p+2), 0x1.622d4ep-7);481 try expectEqual(exp2_f32(-0x1.a206f0p+2), 0x1.622d4ep-7);
470 try expectEqual(exp2f(0x1.288bbcp+3), 0x1.340ecep+9);482 try expectEqual(exp2_f32(0x1.288bbcp+3), 0x1.340ecep+9);
471 try expectEqual(exp2f(0x1.52efd0p-1), 0x1.950eeep+0);483 try expectEqual(exp2_f32(0x1.52efd0p-1), 0x1.950eeep+0);
472 try expectEqual(exp2f(-0x1.a05cc8p-2), 0x1.824056p-1);484 try expectEqual(exp2_f32(-0x1.a05cc8p-2), 0x1.824056p-1);
473 try expectEqual(exp2f(0x1.1f9efap-1), 0x1.79dfa2p+0);485 try expectEqual(exp2_f32(0x1.1f9efap-1), 0x1.79dfa2p+0);
474 try expectEqual(exp2f(0x1.8c5db0p-1), 0x1.b5ceacp+0);486 try expectEqual(exp2_f32(0x1.8c5db0p-1), 0x1.b5ceacp+0);
475 try expectEqual(exp2f(-0x1.5b86eap-1), 0x1.3fd8bap-1);487 try expectEqual(exp2_f32(-0x1.5b86eap-1), 0x1.3fd8bap-1);
476}488}
477489
478test "exp2f() boundary" {490test "exp2f() boundary" {
479 try expectEqual(exp2f(0x1.fffffep+6), 0x1.ffff4ep+127); // The last value before the result gets infinite491 try expectEqual(exp2_f32(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 result492 try expectEqual(exp2_f32(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 zero493 try expectEqual(exp2_f32(-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 zero494 try expectEqual(exp2_f32(-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 subnormal495 try expectEqual(exp2_f32(-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 subnormal496 try expectEqual(exp2_f32(-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 value497 try expectEqual(exp2_f32(0x1.fffffep+127), math.inf(f32)); // Max input value
486 try expectEqual(exp2f(0x1p-149), 1); // Min positive input value498 try expectEqual(exp2_f32(0x1p-149), 1); // Min positive input value
487 try expectEqual(exp2f(-0x1p-149), 1); // Min negative input value499 try expectEqual(exp2_f32(-0x1p-149), 1); // Min negative input value
488 try expectEqual(exp2f(0x1p-126), 1); // First positive subnormal input500 try expectEqual(exp2_f32(0x1p-126), 1); // First positive subnormal input
489 try expectEqual(exp2f(-0x1p-126), 1); // First negative subnormal input501 try expectEqual(exp2_f32(-0x1p-126), 1); // First negative subnormal input
490}502}
491503
492test "exp2() special" {504test "exp2() special" {
493 try expectEqual(exp2(0.0), 1.0);505 try expectEqual(exp2_f64(0.0), 1.0);
494 try expectEqual(exp2(-0.0), 1.0);506 try expectEqual(exp2_f64(-0.0), 1.0);
495 try expectEqual(exp2(1.0), 2.0);507 try expectEqual(exp2_f64(1.0), 2.0);
496 try expectEqual(exp2(-1.0), 0.5);508 try expectEqual(exp2_f64(-1.0), 0.5);
497 try expectEqual(exp2(math.inf(f64)), math.inf(f64));509 try expectEqual(exp2_f64(math.inf(f64)), math.inf(f64));
498 try expect(math.isPositiveZero(exp2(-math.inf(f64))));510 try expect(math.isPositiveZero(exp2_f64(-math.inf(f64))));
499 try expect(math.isNan(exp2(math.nan(f64))));511 try expect(math.isNan(exp2_f64(math.nan(f64))));
500 try expect(math.isNan(exp2(math.snan(f64))));512 try expect(math.isNan(exp2_f64(math.snan(f64))));
501}513}
502514
503test "exp2() sanity" {515test "exp2() sanity" {
504 try expectEqual(exp2(-0x1.02239f3c6a8f1p+3), 0x1.e8d13c396f452p-9);516 try expectEqual(exp2_f64(-0x1.02239f3c6a8f1p+3), 0x1.e8d13c396f452p-9);
505 try expectEqual(exp2(0x1.161868e18bc67p+2), 0x1.4536746bb6f12p+4);517 try expectEqual(exp2_f64(0x1.161868e18bc67p+2), 0x1.4536746bb6f12p+4);
506 try expectEqual(exp2(-0x1.0c34b3e01e6e7p+3), 0x1.890ca0c00b9a2p-9);518 try expectEqual(exp2_f64(-0x1.0c34b3e01e6e7p+3), 0x1.890ca0c00b9a2p-9);
507 try expectEqual(exp2(-0x1.a206f0a19dcc4p+2), 0x1.622d4b0ebc6c1p-7);519 try expectEqual(exp2_f64(-0x1.a206f0a19dcc4p+2), 0x1.622d4b0ebc6c1p-7);
508 try expectEqual(exp2(0x1.288bbb0d6a1e6p+3), 0x1.340ec7f3e607ep+9);520 try expectEqual(exp2_f64(0x1.288bbb0d6a1e6p+3), 0x1.340ec7f3e607ep+9);
509 try expectEqual(exp2(0x1.52efd0cd80497p-1), 0x1.950eef4bc5451p+0);521 try expectEqual(exp2_f64(0x1.52efd0cd80497p-1), 0x1.950eef4bc5451p+0);
510 try expectEqual(exp2(-0x1.a05cc754481d1p-2), 0x1.824056efc687cp-1);522 try expectEqual(exp2_f64(-0x1.a05cc754481d1p-2), 0x1.824056efc687cp-1);
511 try expectEqual(exp2(0x1.1f9ef934745cbp-1), 0x1.79dfa14ab121ep+0);523 try expectEqual(exp2_f64(0x1.1f9ef934745cbp-1), 0x1.79dfa14ab121ep+0);
512 try expectEqual(exp2(0x1.8c5db097f7442p-1), 0x1.b5cead2247372p+0);524 try expectEqual(exp2_f64(0x1.8c5db097f7442p-1), 0x1.b5cead2247372p+0);
513 try expectEqual(exp2(-0x1.5b86ea8118a0ep-1), 0x1.3fd8ba33216b9p-1);525 try expectEqual(exp2_f64(-0x1.5b86ea8118a0ep-1), 0x1.3fd8ba33216b9p-1);
514}526}
515527
516test "exp2() boundary" {528test "exp2() boundary" {
517 try expectEqual(exp2(0x1.fffffffffffffp+9), 0x1.ffffffffffd3ap+1023); // The last value before the result gets infinite529 try expectEqual(exp2_f64(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 result530 try expectEqual(exp2_f64(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 zero531 try expectEqual(exp2_f64(-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 zero532 try expectEqual(exp2_f64(-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 subnormal533 try expectEqual(exp2_f64(-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 subnormal534 try expectEqual(exp2_f64(-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 value535 try expectEqual(exp2_f64(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value
524 try expectEqual(exp2(0x1p-1074), 1); // Min positive input value536 try expectEqual(exp2_f64(0x1p-1074), 1); // Min positive input value
525 try expectEqual(exp2(-0x1p-1074), 1); // Min negative input value537 try expectEqual(exp2_f64(-0x1p-1074), 1); // Min negative input value
526 try expectEqual(exp2(0x1p-1022), 1); // First positive subnormal input538 try expectEqual(exp2_f64(0x1p-1022), 1); // First positive subnormal input
527 try expectEqual(exp2(-0x1p-1022), 1); // First negative subnormal input539 try expectEqual(exp2_f64(-0x1p-1022), 1); // First negative subnormal input
528}540}
lib/compiler_rt/exp_f128.zig+2-2
...@@ -26,7 +26,7 @@ const exp_f128 = @This();...@@ -26,7 +26,7 @@ const exp_f128 = @This();
26const std = @import("std");26const std = @import("std");
27const math = std.math;27const math = std.math;
2828
29pub fn exp(x: f128) callconv(.c) f128 {29pub fn exp(x: f128) f128 {
30 if (!math.isFinite(x)) {30 if (!math.isFinite(x)) {
31 if (math.isNan(x)) {31 if (math.isNan(x)) {
32 if (math.isSignalNan(x)) math.raiseInvalid();32 if (math.isSignalNan(x)) math.raiseInvalid();
...@@ -91,7 +91,7 @@ fn expPoly(r_hi: f128, r_lo: f128) f128 {...@@ -91,7 +91,7 @@ fn expPoly(r_hi: f128, r_lo: f128) f128 {
91}91}
9292
93/// Computes 2^x93/// Computes 2^x
94pub fn exp2(x: f128) callconv(.c) f128 {94pub fn exp2(x: f128) f128 {
95 if (!math.isFinite(x)) {95 if (!math.isFinite(x)) {
96 if (math.isNan(x)) {96 if (math.isNan(x)) {
97 if (math.isSignalNan(x)) math.raiseInvalid();97 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 @@...@@ -1,10 +1,175 @@
1const std = @import("std");1const std = @import("std");
22
3pub inline fn extendf(3const compiler_rt = @import("../compiler_rt.zig");
4 comptime dst_t: type,4const symbol = compiler_rt.symbol;
5 comptime src_t: type,5
6 a: @Int(.unsigned, @typeInfo(src_t).float.bits),6comptime {
7) dst_t {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 {
8 const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits);173 const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits);
9 const dst_rep_t = @Int(.unsigned, @typeInfo(dst_t).float.bits);174 const dst_rep_t = @Int(.unsigned, @typeInfo(dst_t).float.bits);
10 const srcSigBits = std.math.floatMantissaBits(src_t);175 const srcSigBits = std.math.floatMantissaBits(src_t);
...@@ -31,6 +196,7 @@ pub inline fn extendf(...@@ -31,6 +196,7 @@ pub inline fn extendf(
31196
32 const dstMinNormal: dst_rep_t = @as(dst_rep_t, 1) << dstSigBits;197 const dstMinNormal: dst_rep_t = @as(dst_rep_t, 1) << dstSigBits;
33198
199 const a: src_rep_t = @bitCast(f);
34 // Break a into a sign and representation of the absolute value200 // Break a into a sign and representation of the absolute value
35 const aRep: src_rep_t = @bitCast(a);201 const aRep: src_rep_t = @bitCast(a);
36 const aAbs: src_rep_t = aRep & srcAbsMask;202 const aAbs: src_rep_t = aRep & srcAbsMask;
...@@ -66,11 +232,11 @@ pub inline fn extendf(...@@ -66,11 +232,11 @@ pub inline fn extendf(
66 }232 }
67233
68 // Apply the signbit to (dst_t)abs(a).234 // 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);
70 return @bitCast(result);236 return @bitCast(result);
71}237}
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 {
74 const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits);240 const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits);
75 const src_sig_bits = std.math.floatMantissaBits(src_t);241 const src_sig_bits = std.math.floatMantissaBits(src_t);
76 const dst_int_bit = 0x8000000000000000;242 const dst_int_bit = 0x8000000000000000;
...@@ -92,6 +258,7 @@ pub inline fn extend_f80(comptime src_t: type, a: @Int(.unsigned, @typeInfo(src_...@@ -92,6 +258,7 @@ pub inline fn extend_f80(comptime src_t: type, a: @Int(.unsigned, @typeInfo(src_
92258
93 var dst: std.math.F80 = undefined;259 var dst: std.math.F80 = undefined;
94260
261 const a: src_rep_t = @bitCast(f);
95 // Break a into a sign and representation of the absolute value262 // Break a into a sign and representation of the absolute value
96 const a_abs = a & src_abs_mask;263 const a_abs = a & src_abs_mask;
97 const sign: u16 = if (a & src_sign_mask != 0) 0x8000 else 0;264 const sign: u16 = if (a & src_sign_mask != 0) 0x8000 else 0;
lib/compiler_rt/extendf_test.zig+94-95
...@@ -1,31 +1,37 @@...@@ -1,31 +1,37 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
2
3const std = @import("std");2const 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;16const f80_floatCast_f64 = impl.f80_floatCast_f64;
7const __extendhftf2 = @import("extendhftf2.zig").__extendhftf2;17const f128_floatCast_f64 = impl.f128_floatCast_f64;
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;
1218
13fn test__extenddfxf2(a: f64, expected: u80) !void {19const f128_floatCast_f80 = impl.f128_floatCast_f80;
14 const x = __extenddfxf2(a);20
21fn test_f80_floatCast_f64(a: f64, expected: u80) !void {
22 const x = f80_floatCast_f64(a);
1523
16 const rep: u80 = @bitCast(x);24 const rep: u80 = @bitCast(x);
17 if (rep == expected)25 if (rep == expected)
18 return;26 return;
19
20 // test other possible NaN representation(signal NaN)27 // 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))
22 return;29 return;
2330 return error.TestFailure;
24 @panic("__extenddfxf2 test failure");
25}31}
2632
27fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void {33fn test_f128_floatCast_f64(a: f64, expected_hi: u64, expected_lo: u64) !void {
28 const x = __extenddftf2(a);34 const x = f128_floatCast_f64(a);
2935
30 const rep: u128 = @bitCast(x);36 const rep: u128 = @bitCast(x);
31 const hi: u64 = @intCast(rep >> 64);37 const hi: u64 = @intCast(rep >> 64);
...@@ -33,7 +39,6 @@ fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void {...@@ -33,7 +39,6 @@ fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void {
3339
34 if (hi == expected_hi and lo == expected_lo)40 if (hi == expected_hi and lo == expected_lo)
35 return;41 return;
36
37 // test other possible NaN representation(signal NaN)42 // test other possible NaN representation(signal NaN)
38 if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) {43 if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) {
39 if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and44 if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and
...@@ -42,12 +47,11 @@ fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void {...@@ -42,12 +47,11 @@ fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void {
42 return;47 return;
43 }48 }
44 }49 }
4550 return error.TestFailure;
46 @panic("__extenddftf2 test failure");
47}51}
4852
49fn test__extendhfsf2(a: u16, expected: u32) !void {53fn test_f32_floatCast_f16(a: u16, expected: u32) !void {
50 const x = __extendhfsf2(@as(F16T(f32), @bitCast(a)));54 const x = f32_floatCast_f16(@bitCast(a));
51 const rep: u32 = @bitCast(x);55 const rep: u32 = @bitCast(x);
5256
53 if (rep == expected) {57 if (rep == expected) {
...@@ -58,12 +62,11 @@ fn test__extendhfsf2(a: u16, expected: u32) !void {...@@ -58,12 +62,11 @@ fn test__extendhfsf2(a: u16, expected: u32) !void {
58 return;62 return;
59 }63 }
60 }64 }
61
62 return error.TestFailure;65 return error.TestFailure;
63}66}
6467
65fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void {68fn test_f128_floatCast_f32(a: f32, expected_hi: u64, expected_lo: u64) !void {
66 const x = __extendsftf2(a);69 const x = f128_floatCast_f32(a);
6770
68 const rep: u128 = @bitCast(x);71 const rep: u128 = @bitCast(x);
69 const hi: u64 = @intCast(rep >> 64);72 const hi: u64 = @intCast(rep >> 64);
...@@ -71,7 +74,6 @@ fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void {...@@ -71,7 +74,6 @@ fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void {
7174
72 if (hi == expected_hi and lo == expected_lo)75 if (hi == expected_hi and lo == expected_lo)
73 return;76 return;
74
75 // test other possible NaN representation(signal NaN)77 // test other possible NaN representation(signal NaN)
76 if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) {78 if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) {
77 if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and79 if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and
...@@ -80,111 +82,108 @@ fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void {...@@ -80,111 +82,108 @@ fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void {
80 return;82 return;
81 }83 }
82 }84 }
83
84 return error.TestFailure;85 return error.TestFailure;
85}86}
8687
87test "extenddfxf2" {88test f80_floatCast_f64 {
88 // qNaN89 // qNaN
89 try test__extenddfxf2(makeQNaN64(), 0x7fffc000000000000000);90 try test_f80_floatCast_f64(makeQNaN64(), 0x7fffc000000000000000);
9091
91 // NaN92 // NaN
92 try test__extenddfxf2(makeNaN64(0x7100000000000), 0x7fffe080000000000000);93 try test_f80_floatCast_f64(makeNaN64(0x7100000000000), 0x7fffe080000000000000);
93 // This is bad?94 // This is bad?
9495
95 // inf96 // inf
96 try test__extenddfxf2(makeInf64(), 0x7fff8000000000000000);97 try test_f80_floatCast_f64(makeInf64(), 0x7fff8000000000000000);
9798
98 // zero99 // 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
109 // subnormal110 // subnormal
110 try test__extenddfxf2(0x1.8000000000001p-1022, 0x3c01c000000000000800);111 try test_f80_floatCast_f64(0x1.8000000000001p-1022, 0x3c01c000000000000800);
111 try test__extenddfxf2(0x1.8000000000002p-1023, 0x3c00c000000000001000);112 try test_f80_floatCast_f64(0x1.8000000000002p-1023, 0x3c00c000000000001000);
112}113}
113114
114test "extenddftf2" {115test f128_floatCast_f64 {
115 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
116
117 // qNaN116 // qNaN
118 try test__extenddftf2(makeQNaN64(), 0x7fff800000000000, 0x0);117 try test_f128_floatCast_f64(makeQNaN64(), 0x7fff800000000000, 0x0);
119118
120 // NaN119 // NaN
121 try test__extenddftf2(makeNaN64(0x7100000000000), 0x7fff710000000000, 0x0);120 try test_f128_floatCast_f64(makeNaN64(0x7100000000000), 0x7fff710000000000, 0x0);
122121
123 // inf122 // inf
124 try test__extenddftf2(makeInf64(), 0x7fff000000000000, 0x0);123 try test_f128_floatCast_f64(makeInf64(), 0x7fff000000000000, 0x0);
125124
126 // zero125 // 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
137 // subnormal136 // subnormal
138 try test__extenddftf2(0x1.8p-1022, 0x3c01800000000000, 0x0);137 try test_f128_floatCast_f64(0x1.8p-1022, 0x3c01800000000000, 0x0);
139 try test__extenddftf2(0x1.8p-1023, 0x3c00800000000000, 0x0);138 try test_f128_floatCast_f64(0x1.8p-1023, 0x3c00800000000000, 0x0);
140}139}
141140
142test "extendhfsf2" {141test f32_floatCast_f16 {
143 try test__extendhfsf2(0x7e00, 0x7fc00000); // qNaN142 try test_f32_floatCast_f16(0x7e00, 0x7fc00000); // qNaN
144 try test__extendhfsf2(0x7f00, 0x7fe00000); // sNaN143 try test_f32_floatCast_f16(0x7f00, 0x7fe00000); // sNaN
145 // On x86 the NaN becomes quiet because the return is pushed on the x87144 // On x86 the NaN becomes quiet because the return is pushed on the x87
146 // stack due to ABI requirements145 // stack due to ABI requirements
147 if (builtin.target.cpu.arch != .x86 and builtin.target.os.tag == .windows)146 if (builtin.target.cpu.arch != .x86 and builtin.target.os.tag == .windows)
148 try test__extendhfsf2(0x7c01, 0x7f802000); // sNaN147 try test_f32_floatCast_f16(0x7c01, 0x7f802000); // sNaN
149148
150 try test__extendhfsf2(0, 0); // 0149 try test_f32_floatCast_f16(0, 0); // 0
151 try test__extendhfsf2(0x8000, 0x80000000); // -0150 try test_f32_floatCast_f16(0x8000, 0x80000000); // -0
152151
153 try test__extendhfsf2(0x7c00, 0x7f800000); // inf152 try test_f32_floatCast_f16(0x7c00, 0x7f800000); // inf
154 try test__extendhfsf2(0xfc00, 0xff800000); // -inf153 try test_f32_floatCast_f16(0xfc00, 0xff800000); // -inf
155154
156 try test__extendhfsf2(0x0001, 0x33800000); // denormal (min), 2**-24155 try test_f32_floatCast_f16(0x0001, 0x33800000); // denormal (min), 2**-24
157 try test__extendhfsf2(0x8001, 0xb3800000); // denormal (min), -2**-24156 try test_f32_floatCast_f16(0x8001, 0xb3800000); // denormal (min), -2**-24
158157
159 try test__extendhfsf2(0x03ff, 0x387fc000); // denormal (max), 2**-14 - 2**-24158 try test_f32_floatCast_f16(0x03ff, 0x387fc000); // denormal (max), 2**-14 - 2**-24
160 try test__extendhfsf2(0x83ff, 0xb87fc000); // denormal (max), -2**-14 + 2**-24159 try test_f32_floatCast_f16(0x83ff, 0xb87fc000); // denormal (max), -2**-14 + 2**-24
161160
162 try test__extendhfsf2(0x0400, 0x38800000); // normal (min), 2**-14161 try test_f32_floatCast_f16(0x0400, 0x38800000); // normal (min), 2**-14
163 try test__extendhfsf2(0x8400, 0xb8800000); // normal (min), -2**-14162 try test_f32_floatCast_f16(0x8400, 0xb8800000); // normal (min), -2**-14
164163
165 try test__extendhfsf2(0x7bff, 0x477fe000); // normal (max), 65504164 try test_f32_floatCast_f16(0x7bff, 0x477fe000); // normal (max), 65504
166 try test__extendhfsf2(0xfbff, 0xc77fe000); // normal (max), -65504165 try test_f32_floatCast_f16(0xfbff, 0xc77fe000); // normal (max), -65504
167166
168 try test__extendhfsf2(0x3c01, 0x3f802000); // normal, 1 + 2**-10167 try test_f32_floatCast_f16(0x3c01, 0x3f802000); // normal, 1 + 2**-10
169 try test__extendhfsf2(0xbc01, 0xbf802000); // normal, -1 - 2**-10168 try test_f32_floatCast_f16(0xbc01, 0xbf802000); // normal, -1 - 2**-10
170169
171 try test__extendhfsf2(0x3555, 0x3eaaa000); // normal, approx. 1/3170 try test_f32_floatCast_f16(0x3555, 0x3eaaa000); // normal, approx. 1/3
172 try test__extendhfsf2(0xb555, 0xbeaaa000); // normal, approx. -1/3171 try test_f32_floatCast_f16(0xb555, 0xbeaaa000); // normal, approx. -1/3
173}172}
174173
175test "extendsftf2" {174test f128_floatCast_f32 {
176 // qNaN175 // qNaN
177 try test__extendsftf2(makeQNaN32(), 0x7fff800000000000, 0x0);176 try test_f128_floatCast_f32(makeQNaN32(), 0x7fff800000000000, 0x0);
178 // NaN177 // NaN
179 try test__extendsftf2(makeNaN32(0x410000), 0x7fff820000000000, 0x0);178 try test_f128_floatCast_f32(makeNaN32(0x410000), 0x7fff820000000000, 0x0);
180 // inf179 // inf
181 try test__extendsftf2(makeInf32(), 0x7fff000000000000, 0x0);180 try test_f128_floatCast_f32(makeInf32(), 0x7fff000000000000, 0x0);
182 // zero181 // zero
183 try test__extendsftf2(0.0, 0x0, 0x0);182 try test_f128_floatCast_f32(0.0, 0x0, 0x0);
184 try test__extendsftf2(0x1.23456p+5, 0x4004234560000000, 0x0);183 try test_f128_floatCast_f32(0x1.23456p+5, 0x4004234560000000, 0x0);
185 try test__extendsftf2(0x1.edcbap-9, 0x3ff6edcba0000000, 0x0);184 try test_f128_floatCast_f32(0x1.edcbap-9, 0x3ff6edcba0000000, 0x0);
186 try test__extendsftf2(0x1.23456p+45, 0x402c234560000000, 0x0);185 try test_f128_floatCast_f32(0x1.23456p+45, 0x402c234560000000, 0x0);
187 try test__extendsftf2(0x1.edcbap-45, 0x3fd2edcba0000000, 0x0);186 try test_f128_floatCast_f32(0x1.edcbap-45, 0x3fd2edcba0000000, 0x0);
188}187}
189188
190fn makeQNaN64() f64 {189fn makeQNaN64() f64 {
...@@ -211,8 +210,8 @@ fn makeInf32() f32 {...@@ -211,8 +210,8 @@ fn makeInf32() f32 {
211 return @bitCast(@as(u32, 0x7f800000));210 return @bitCast(@as(u32, 0x7f800000));
212}211}
213212
214fn test__extendhftf2(a: u16, expected_hi: u64, expected_lo: u64) !void {213fn test_f128_floatCast_f16(a: u16, expected_hi: u64, expected_lo: u64) !void {
215 const x = __extendhftf2(@as(F16T(f128), @bitCast(a)));214 const x = f128_floatCast_f16(@bitCast(a));
216215
217 const rep: u128 = @bitCast(x);216 const rep: u128 = @bitCast(x);
218 const hi: u64 = @intCast(rep >> 64);217 const hi: u64 = @intCast(rep >> 64);
...@@ -233,26 +232,26 @@ fn test__extendhftf2(a: u16, expected_hi: u64, expected_lo: u64) !void {...@@ -233,26 +232,26 @@ fn test__extendhftf2(a: u16, expected_hi: u64, expected_lo: u64) !void {
233 return error.TestFailure;232 return error.TestFailure;
234}233}
235234
236test "extendhftf2" {235test f128_floatCast_f16 {
237 // qNaN236 // qNaN
238 try test__extendhftf2(0x7e00, 0x7fff800000000000, 0x0);237 try test_f128_floatCast_f16(0x7e00, 0x7fff800000000000, 0x0);
239 // NaN238 // NaN
240 try test__extendhftf2(0x7d00, 0x7fff400000000000, 0x0);239 try test_f128_floatCast_f16(0x7d00, 0x7fff400000000000, 0x0);
241 // inf240 // inf
242 try test__extendhftf2(0x7c00, 0x7fff000000000000, 0x0);241 try test_f128_floatCast_f16(0x7c00, 0x7fff000000000000, 0x0);
243 try test__extendhftf2(0xfc00, 0xffff000000000000, 0x0);242 try test_f128_floatCast_f16(0xfc00, 0xffff000000000000, 0x0);
244 // zero243 // zero
245 try test__extendhftf2(0x0000, 0x0000000000000000, 0x0);244 try test_f128_floatCast_f16(0x0000, 0x0000000000000000, 0x0);
246 try test__extendhftf2(0x8000, 0x8000000000000000, 0x0);245 try test_f128_floatCast_f16(0x8000, 0x8000000000000000, 0x0);
247 // denormal246 // denormal
248 try test__extendhftf2(0x0010, 0x3feb000000000000, 0x0);247 try test_f128_floatCast_f16(0x0010, 0x3feb000000000000, 0x0);
249 try test__extendhftf2(0x0001, 0x3fe7000000000000, 0x0);248 try test_f128_floatCast_f16(0x0001, 0x3fe7000000000000, 0x0);
250 try test__extendhftf2(0x8001, 0xbfe7000000000000, 0x0);249 try test_f128_floatCast_f16(0x8001, 0xbfe7000000000000, 0x0);
251250
252 // pi251 // pi
253 try test__extendhftf2(0x4248, 0x4000920000000000, 0x0);252 try test_f128_floatCast_f16(0x4248, 0x4000920000000000, 0x0);
254 try test__extendhftf2(0xc248, 0xc000920000000000, 0x0);253 try test_f128_floatCast_f16(0xc248, 0xc000920000000000, 0x0);
255254
256 try test__extendhftf2(0x508c, 0x4004230000000000, 0x0);255 try test_f128_floatCast_f16(0x508c, 0x4004230000000000, 0x0);
257 try test__extendhftf2(0x1bb7, 0x3ff6edc000000000, 0x0);256 try test_f128_floatCast_f16(0x1bb7, 0x3ff6edc000000000, 0x0);
258}257}
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 {...@@ -9,39 +9,51 @@ comptime {
9 symbol(&fabsf, "fabsf");9 symbol(&fabsf, "fabsf");
10 symbol(&fabs, "fabs");10 symbol(&fabs, "fabs");
11 symbol(&__fabsx, "__fabsx");11 symbol(&__fabsx, "__fabsx");
12 if (compiler_rt.want_ppc_abi) {12 symbol(&fabsq, "fabsf128");
13 symbol(&fabsq, "fabsf128");
14 }
15 symbol(&fabsq, "fabsq");
16 symbol(&fabsl, "fabsl");13 symbol(&fabsl, "fabsl");
17}14}
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 {
20 return generic_fabs(a);20 return generic_fabs(a);
21}21}
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 {
24 return generic_fabs(a);27 return generic_fabs(a);
25}28}
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 {
28 return generic_fabs(a);34 return generic_fabs(a);
29}35}
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 {
32 return generic_fabs(a);41 return generic_fabs(a);
33}42}
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 {
36 return generic_fabs(a);48 return generic_fabs(a);
37}49}
3850
39pub fn fabsl(x: c_longdouble) callconv(.c) c_longdouble {51pub fn fabsl(x: c_longdouble) callconv(.c) c_longdouble {
40 switch (@typeInfo(c_longdouble).float.bits) {52 switch (@typeInfo(c_longdouble).float.bits) {
41 64 => return fabs(x),53 64 => return fabs_f64(x),
42 80 => return __fabsx(x),54 80 => return fabs_f80(x),
43 128 => return fabsq(x),55 128 => return fabs_f128(x),
44 else => @compileError("unreachable"),56 else => comptime unreachable,
45 }57 }
46}58}
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 @@...@@ -1,7 +1,475 @@
1const builtin = @import("builtin");
1const std = @import("std");2const std = @import("std");
2const math = std.math;3const 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 {
5 if (x == 0) return 0;473 if (x == 0) return 0;
6474
7 // Various constants whose values follow from the type parameters.475 // Various constants whose values follow from the type parameters.
...@@ -53,7 +521,7 @@ pub fn floatFromInt(comptime T: type, x: anytype) T {...@@ -53,7 +521,7 @@ pub fn floatFromInt(comptime T: type, x: anytype) T {
53 return @bitCast(sign_bit | result);521 return @bitCast(sign_bit | result);
54}522}
55523
56const endian = @import("builtin").cpu.arch.endian();524const endian = builtin.cpu.arch.endian();
57inline fn limb(limbs: []const u32, index: usize) u32 {525inline fn limb(limbs: []const u32, index: usize) u32 {
58 return switch (endian) {526 return switch (endian) {
59 .little => limbs[index],527 .little => limbs[index],
...@@ -61,11 +529,11 @@ inline fn limb(limbs: []const u32, index: usize) u32 {...@@ -61,11 +529,11 @@ inline fn limb(limbs: []const u32, index: usize) u32 {
61 };529 };
62}530}
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 {
65 switch (x.len) {533 switch (x.len) {
66 0 => return 0,534 0 => return 0,
67 inline 1...4 => |limbs_len| {535 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) {
69 .little => x[0..limbs_len].*,537 .little => x[0..limbs_len].*,
70 .big => switch (limbs_len) {538 .big => switch (limbs_len) {
71 1 => .{x[0]},539 1 => .{x[0]},
lib/compiler_rt/float_from_int_test.zig+757-733
...@@ -2,571 +2,593 @@ const std = @import("std");...@@ -2,571 +2,593 @@ const std = @import("std");
2const testing = std.testing;2const testing = std.testing;
3const math = std.math;3const math = std.math;
44
5const __floatunsihf = @import("floatunsihf.zig").__floatunsihf;5const impl = @import("float_from_int.zig");
66
7// Conversion to f327const f16_floatFromInt_i32 = impl.f16_floatFromInt_i32;
8const __floatsisf = @import("floatsisf.zig").__floatsisf;8const f16_floatFromInt_u32 = impl.f16_floatFromInt_u32;
9const __floatunsisf = @import("floatunsisf.zig").__floatunsisf;9const f16_floatFromInt_i64 = impl.f16_floatFromInt_i64;
10const __floatdisf = @import("floatdisf.zig").__floatdisf;10const f16_floatFromInt_u64 = impl.f16_floatFromInt_u64;
11const __floatundisf = @import("floatundisf.zig").__floatundisf;11const f16_floatFromInt_i128 = impl.f16_floatFromInt_i128;
12const __floattisf = @import("floattisf.zig").__floattisf;12const f16_floatFromInt_u128 = impl.f16_floatFromInt_u128;
13const __floatuntisf = @import("floatuntisf.zig").__floatuntisf;13const f16_floatFromInt_signed = impl.f16_floatFromInt_signed;
14const __floateisf = @import("floateisf.zig").__floateisf;14const f16_floatFromInt_unsigned = impl.f16_floatFromInt_unsigned;
15const __floatuneisf = @import("floatuneisf.zig").__floatuneisf;15
1616const f32_floatFromInt_i32 = impl.f32_floatFromInt_i32;
17// Conversion to f6417const f32_floatFromInt_u32 = impl.f32_floatFromInt_u32;
18const __floatsidf = @import("floatsidf.zig").__floatsidf;18const f32_floatFromInt_i64 = impl.f32_floatFromInt_i64;
19const __floatunsidf = @import("floatunsidf.zig").__floatunsidf;19const f32_floatFromInt_u64 = impl.f32_floatFromInt_u64;
20const __floatdidf = @import("floatdidf.zig").__floatdidf;20const f32_floatFromInt_i128 = impl.f32_floatFromInt_i128;
21const __floatundidf = @import("floatundidf.zig").__floatundidf;21const f32_floatFromInt_u128 = impl.f32_floatFromInt_u128;
22const __floattidf = @import("floattidf.zig").__floattidf;22const f32_floatFromInt_signed = impl.f32_floatFromInt_signed;
23const __floatuntidf = @import("floatuntidf.zig").__floatuntidf;23const f32_floatFromInt_unsigned = impl.f32_floatFromInt_unsigned;
2424
25// Conversion to f12825const f64_floatFromInt_i32 = impl.f64_floatFromInt_i32;
26const __floatsitf = @import("floatsitf.zig").__floatsitf;26const f64_floatFromInt_u32 = impl.f64_floatFromInt_u32;
27const __floatunsitf = @import("floatunsitf.zig").__floatunsitf;27const f64_floatFromInt_i64 = impl.f64_floatFromInt_i64;
28const __floatditf = @import("floatditf.zig").__floatditf;28const f64_floatFromInt_u64 = impl.f64_floatFromInt_u64;
29const __floatunditf = @import("floatunditf.zig").__floatunditf;29const f64_floatFromInt_i128 = impl.f64_floatFromInt_i128;
30const __floattitf = @import("floattitf.zig").__floattitf;30const f64_floatFromInt_u128 = impl.f64_floatFromInt_u128;
31const __floatuntitf = @import("floatuntitf.zig").__floatuntitf;31const f64_floatFromInt_signed = impl.f64_floatFromInt_signed;
3232const f64_floatFromInt_unsigned = impl.f64_floatFromInt_unsigned;
33fn test__floatsisf(a: i32, expected: u32) !void {33
34 const r = __floatsisf(a);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);
35 try std.testing.expect(@as(u32, @bitCast(r)) == expected);54 try std.testing.expect(@as(u32, @bitCast(r)) == expected);
36}55}
3756
38fn test_one_floatunsisf(a: u32, expected: u32) !void {57fn test_f32_floatFromInt_u32(a: u32, expected: u32) !void {
39 const r = __floatunsisf(a);58 const r = f32_floatFromInt_u32(a);
40 try std.testing.expect(@as(u32, @bitCast(r)) == expected);59 try std.testing.expect(@as(u32, @bitCast(r)) == expected);
41}60}
4261
43test "floatsisf" {62test f32_floatFromInt_i32 {
44 try test__floatsisf(0, 0x00000000);63 try test_f32_floatFromInt_i32(0, 0x00000000);
45 try test__floatsisf(1, 0x3f800000);64 try test_f32_floatFromInt_i32(1, 0x3f800000);
46 try test__floatsisf(-1, 0xbf800000);65 try test_f32_floatFromInt_i32(-1, 0xbf800000);
47 try test__floatsisf(0x7FFFFFFF, 0x4f000000);66 try test_f32_floatFromInt_i32(0x7FFFFFFF, 0x4f000000);
48 try test__floatsisf(@bitCast(@as(u32, @intCast(0x80000000))), 0xcf000000);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));
49}70}
5071
51test "floatunsisf" {72test f32_floatFromInt_u32 {
52 // Test the produced bit pattern73 // Test the produced bit pattern
53 try test_one_floatunsisf(0, 0);74 try test_f32_floatFromInt_u32(0, 0);
54 try test_one_floatunsisf(1, 0x3f800000);75 try test_f32_floatFromInt_u32(1, 0x3f800000);
55 try test_one_floatunsisf(0x7FFFFFFF, 0x4f000000);76 try test_f32_floatFromInt_u32(0x7FFFFFFF, 0x4f000000);
56 try test_one_floatunsisf(0x80000000, 0x4f000000);77 try test_f32_floatFromInt_u32(0x80000000, 0x4f000000);
57 try test_one_floatunsisf(0xFFFFFFFF, 0x4f800000);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);
58}93}
5994
60fn test__floatdisf(a: i64, expected: f32) !void {95fn test_f32_floatFromInt_u64(a: u64, expected: f32) !void {
61 const x = __floatdisf(a);96 const x = f32_floatFromInt_u64(a);
62 try testing.expect(x == expected);97 try testing.expect(x == expected);
63}98}
6499
65fn test__floatundisf(a: u64, expected: f32) !void {100test f32_floatFromInt_i64 {
66 try std.testing.expectEqual(expected, __floatundisf(a));101 try test_f32_floatFromInt_i64(0, 0.0);
67}102 try test_f32_floatFromInt_i64(1, 1.0);
68103 try test_f32_floatFromInt_i64(2, 2.0);
69test "floatdisf" {104 try test_f32_floatFromInt_i64(-1, -1.0);
70 try test__floatdisf(0, 0.0);105 try test_f32_floatFromInt_i64(-2, -2.0);
71 try test__floatdisf(1, 1.0);106 try test_f32_floatFromInt_i64(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
72 try test__floatdisf(2, 2.0);107 try test_f32_floatFromInt_i64(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
73 try test__floatdisf(-1, -1.0);108 try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000008000000000)), -0x1.FFFFFEp+62);
74 try test__floatdisf(-2, -2.0);109 try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000010000000000)), -0x1.FFFFFCp+62);
75 try test__floatdisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);110 try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000000000000000)), -0x1.000000p+63);
76 try test__floatdisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);111 try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000000000000001)), -0x1.000000p+63);
77 try test__floatdisf(@bitCast(@as(u64, 0x8000008000000000)), -0x1.FFFFFEp+62);112 try test_f32_floatFromInt_i64(0x0007FB72E8000000, 0x1.FEDCBAp+50);
78 try test__floatdisf(@bitCast(@as(u64, 0x8000010000000000)), -0x1.FFFFFCp+62);113 try test_f32_floatFromInt_i64(0x0007FB72EA000000, 0x1.FEDCBAp+50);
79 try test__floatdisf(@bitCast(@as(u64, 0x8000000000000000)), -0x1.000000p+63);114 try test_f32_floatFromInt_i64(0x0007FB72EB000000, 0x1.FEDCBAp+50);
80 try test__floatdisf(@bitCast(@as(u64, 0x8000000000000001)), -0x1.000000p+63);115 try test_f32_floatFromInt_i64(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
81 try test__floatdisf(0x0007FB72E8000000, 0x1.FEDCBAp+50);116 try test_f32_floatFromInt_i64(0x0007FB72EC000000, 0x1.FEDCBCp+50);
82 try test__floatdisf(0x0007FB72EA000000, 0x1.FEDCBAp+50);117 try test_f32_floatFromInt_i64(0x0007FB72E8000001, 0x1.FEDCBAp+50);
83 try test__floatdisf(0x0007FB72EB000000, 0x1.FEDCBAp+50);118 try test_f32_floatFromInt_i64(0x0007FB72E6000000, 0x1.FEDCBAp+50);
84 try test__floatdisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);119 try test_f32_floatFromInt_i64(0x0007FB72E7000000, 0x1.FEDCBAp+50);
85 try test__floatdisf(0x0007FB72EC000000, 0x1.FEDCBCp+50);120 try test_f32_floatFromInt_i64(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
86 try test__floatdisf(0x0007FB72E8000001, 0x1.FEDCBAp+50);121 try test_f32_floatFromInt_i64(0x0007FB72E4000001, 0x1.FEDCBAp+50);
87 try test__floatdisf(0x0007FB72E6000000, 0x1.FEDCBAp+50);122 try test_f32_floatFromInt_i64(0x0007FB72E4000000, 0x1.FEDCB8p+50);
88 try test__floatdisf(0x0007FB72E7000000, 0x1.FEDCBAp+50);123}
89 try test__floatdisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);124
90 try test__floatdisf(0x0007FB72E4000001, 0x1.FEDCBAp+50);125test f32_floatFromInt_u64 {
91 try test__floatdisf(0x0007FB72E4000000, 0x1.FEDCB8p+50);126 try test_f32_floatFromInt_u64(0, 0.0);
92}127 try test_f32_floatFromInt_u64(1, 1.0);
93128 try test_f32_floatFromInt_u64(2, 2.0);
94test "floatundisf" {129 try test_f32_floatFromInt_u64(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
95 try test__floatundisf(0, 0.0);130 try test_f32_floatFromInt_u64(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
96 try test__floatundisf(1, 1.0);131 try test_f32_floatFromInt_u64(0x8000008000000000, 0x1p+63);
97 try test__floatundisf(2, 2.0);132 try test_f32_floatFromInt_u64(0x8000010000000000, 0x1.000002p+63);
98 try test__floatundisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);133 try test_f32_floatFromInt_u64(0x8000000000000000, 0x1p+63);
99 try test__floatundisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);134 try test_f32_floatFromInt_u64(0x8000000000000001, 0x1p+63);
100 try test__floatundisf(0x8000008000000000, 0x1p+63);135 try test_f32_floatFromInt_u64(0xFFFFFFFFFFFFFFFE, 0x1p+64);
101 try test__floatundisf(0x8000010000000000, 0x1.000002p+63);136 try test_f32_floatFromInt_u64(0xFFFFFFFFFFFFFFFF, 0x1p+64);
102 try test__floatundisf(0x8000000000000000, 0x1p+63);137 try test_f32_floatFromInt_u64(0x0007FB72E8000000, 0x1.FEDCBAp+50);
103 try test__floatundisf(0x8000000000000001, 0x1p+63);138 try test_f32_floatFromInt_u64(0x0007FB72EA000000, 0x1.FEDCBAp+50);
104 try test__floatundisf(0xFFFFFFFFFFFFFFFE, 0x1p+64);139 try test_f32_floatFromInt_u64(0x0007FB72EB000000, 0x1.FEDCBAp+50);
105 try test__floatundisf(0xFFFFFFFFFFFFFFFF, 0x1p+64);140 try test_f32_floatFromInt_u64(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
106 try test__floatundisf(0x0007FB72E8000000, 0x1.FEDCBAp+50);141 try test_f32_floatFromInt_u64(0x0007FB72EC000000, 0x1.FEDCBCp+50);
107 try test__floatundisf(0x0007FB72EA000000, 0x1.FEDCBAp+50);142 try test_f32_floatFromInt_u64(0x0007FB72E8000001, 0x1.FEDCBAp+50);
108 try test__floatundisf(0x0007FB72EB000000, 0x1.FEDCBAp+50);143 try test_f32_floatFromInt_u64(0x0007FB72E6000000, 0x1.FEDCBAp+50);
109 try test__floatundisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);144 try test_f32_floatFromInt_u64(0x0007FB72E7000000, 0x1.FEDCBAp+50);
110 try test__floatundisf(0x0007FB72EC000000, 0x1.FEDCBCp+50);145 try test_f32_floatFromInt_u64(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
111 try test__floatundisf(0x0007FB72E8000001, 0x1.FEDCBAp+50);146 try test_f32_floatFromInt_u64(0x0007FB72E4000001, 0x1.FEDCBAp+50);
112 try test__floatundisf(0x0007FB72E6000000, 0x1.FEDCBAp+50);147 try test_f32_floatFromInt_u64(0x0007FB72E4000000, 0x1.FEDCB8p+50);
113 try test__floatundisf(0x0007FB72E7000000, 0x1.FEDCBAp+50);148}
114 try test__floatundisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);149
115 try test__floatundisf(0x0007FB72E4000001, 0x1.FEDCBAp+50);150fn test_f32_floatFromInt_i128(a: i128, expected: f32) !void {
116 try test__floatundisf(0x0007FB72E4000000, 0x1.FEDCB8p+50);151 const x = f32_floatFromInt_i128(a);
117}
118
119fn test__floattisf(a: i128, expected: f32) !void {
120 const x = __floattisf(a);
121 try testing.expect(x == expected);152 try testing.expect(x == expected);
122}153}
123154
124fn test__floatuntisf(a: u128, expected: f32) !void {155fn test_f32_floatFromInt_u128(a: u128, expected: f32) !void {
125 const x = __floatuntisf(a);156 const x = f32_floatFromInt_u128(a);
126 try testing.expect(x == expected);157 try testing.expect(x == expected);
127}158}
128159
129test "floattisf" {160test f32_floatFromInt_i128 {
130 try test__floattisf(0, 0.0);161 try test_f32_floatFromInt_i128(0, 0.0);
131162
132 try test__floattisf(1, 1.0);163 try test_f32_floatFromInt_i128(1, 1.0);
133 try test__floattisf(2, 2.0);164 try test_f32_floatFromInt_i128(2, 2.0);
134 try test__floattisf(-1, -1.0);165 try test_f32_floatFromInt_i128(-1, -1.0);
135 try test__floattisf(-2, -2.0);166 try test_f32_floatFromInt_i128(-2, -2.0);
136167
137 try test__floattisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);168 try test_f32_floatFromInt_i128(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
138 try test__floattisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);169 try test_f32_floatFromInt_i128(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
139170
140 try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000008000000000), -0x1.FFFFFEp+62);171 try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000008000000000), -0x1.FFFFFEp+62);
141 try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000010000000000), -0x1.FFFFFCp+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);174 try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000000), -0x1.000000p+63);
144 try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000001), -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);179 try test_f32_floatFromInt_i128(0x0007FB72EA000000, 0x1.FEDCBAp+50);
149 try test__floattisf(0x0007FB72EB000000, 0x1.FEDCBAp+50);180 try test_f32_floatFromInt_i128(0x0007FB72EB000000, 0x1.FEDCBAp+50);
150 try test__floattisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);181 try test_f32_floatFromInt_i128(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
151 try test__floattisf(0x0007FB72EC000000, 0x1.FEDCBCp+50);182 try test_f32_floatFromInt_i128(0x0007FB72EC000000, 0x1.FEDCBCp+50);
152 try test__floattisf(0x0007FB72E8000001, 0x1.FEDCBAp+50);183 try test_f32_floatFromInt_i128(0x0007FB72E8000001, 0x1.FEDCBAp+50);
153184
154 try test__floattisf(0x0007FB72E6000000, 0x1.FEDCBAp+50);185 try test_f32_floatFromInt_i128(0x0007FB72E6000000, 0x1.FEDCBAp+50);
155 try test__floattisf(0x0007FB72E7000000, 0x1.FEDCBAp+50);186 try test_f32_floatFromInt_i128(0x0007FB72E7000000, 0x1.FEDCBAp+50);
156 try test__floattisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);187 try test_f32_floatFromInt_i128(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
157 try test__floattisf(0x0007FB72E4000001, 0x1.FEDCBAp+50);188 try test_f32_floatFromInt_i128(0x0007FB72E4000001, 0x1.FEDCBAp+50);
158 try test__floattisf(0x0007FB72E4000000, 0x1.FEDCB8p+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);193 try test_f32_floatFromInt_i128(make_ti(0x0007FB72EA000000, 0), 0x1.FEDCBAp+114);
163 try test__floattisf(make_ti(0x0007FB72EB000000, 0), 0x1.FEDCBAp+114);194 try test_f32_floatFromInt_i128(make_ti(0x0007FB72EB000000, 0), 0x1.FEDCBAp+114);
164 try test__floattisf(make_ti(0x0007FB72EBFFFFFF, 0), 0x1.FEDCBAp+114);195 try test_f32_floatFromInt_i128(make_ti(0x0007FB72EBFFFFFF, 0), 0x1.FEDCBAp+114);
165 try test__floattisf(make_ti(0x0007FB72EC000000, 0), 0x1.FEDCBCp+114);196 try test_f32_floatFromInt_i128(make_ti(0x0007FB72EC000000, 0), 0x1.FEDCBCp+114);
166 try test__floattisf(make_ti(0x0007FB72E8000001, 0), 0x1.FEDCBAp+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);199 try test_f32_floatFromInt_i128(make_ti(0x0007FB72E6000000, 0), 0x1.FEDCBAp+114);
169 try test__floattisf(make_ti(0x0007FB72E7000000, 0), 0x1.FEDCBAp+114);200 try test_f32_floatFromInt_i128(make_ti(0x0007FB72E7000000, 0), 0x1.FEDCBAp+114);
170 try test__floattisf(make_ti(0x0007FB72E7FFFFFF, 0), 0x1.FEDCBAp+114);201 try test_f32_floatFromInt_i128(make_ti(0x0007FB72E7FFFFFF, 0), 0x1.FEDCBAp+114);
171 try test__floattisf(make_ti(0x0007FB72E4000001, 0), 0x1.FEDCBAp+114);202 try test_f32_floatFromInt_i128(make_ti(0x0007FB72E4000001, 0), 0x1.FEDCBAp+114);
172 try test__floattisf(make_ti(0x0007FB72E4000000, 0), 0x1.FEDCB8p+114);203 try test_f32_floatFromInt_i128(make_ti(0x0007FB72E4000000, 0), 0x1.FEDCB8p+114);
173}204}
174205
175test "floatuntisf" {206test f32_floatFromInt_u128 {
176 try test__floatuntisf(0, 0.0);207 try test_f32_floatFromInt_u128(0, 0.0);
177208
178 try test__floatuntisf(1, 1.0);209 try test_f32_floatFromInt_u128(1, 1.0);
179 try test__floatuntisf(2, 2.0);210 try test_f32_floatFromInt_u128(2, 2.0);
180 try test__floatuntisf(20, 20.0);211 try test_f32_floatFromInt_u128(20, 20.0);
181212
182 try test__floatuntisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);213 try test_f32_floatFromInt_u128(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
183 try test__floatuntisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);214 try test_f32_floatFromInt_u128(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
184215
185 try test__floatuntisf(make_uti(0x8000008000000000, 0), 0x1.000001p+127);216 try test_f32_floatFromInt_u128(make_uti(0x8000008000000000, 0), 0x1.000001p+127);
186 try test__floatuntisf(make_uti(0x8000000000000800, 0), 0x1.0p+127);217 try test_f32_floatFromInt_u128(make_uti(0x8000000000000800, 0), 0x1.0p+127);
187 try test__floatuntisf(make_uti(0x8000010000000000, 0), 0x1.000002p+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);224 try test_f32_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
194 try test__floatuntisf(0x0007FB72EB000000, 0x1.FEDCBACp+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);229 try test_f32_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCB98p+50);
199 try test__floatuntisf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);230 try test_f32_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
200 try test__floatuntisf(0x0007FB72E4000000, 0x1.FEDCB9p+50);231 try test_f32_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB9p+50);
201232
202 try test__floatuntisf(0xFFFFFFFFFFFFFFFE, 0x1p+64);233 try test_f32_floatFromInt_u128(0xFFFFFFFFFFFFFFFE, 0x1p+64);
203 try test__floatuntisf(0xFFFFFFFFFFFFFFFF, 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);238 try test_f32_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBAp+50);
208 try test__floatuntisf(0x0007FB72EB000000, 0x1.FEDCBAp+50);239 try test_f32_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBAp+50);
209 try test__floatuntisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);240 try test_f32_floatFromInt_u128(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
210 try test__floatuntisf(0x0007FB72EC000000, 0x1.FEDCBCp+50);241 try test_f32_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBCp+50);
211 try test__floatuntisf(0x0007FB72E8000001, 0x1.FEDCBAp+50);242 try test_f32_floatFromInt_u128(0x0007FB72E8000001, 0x1.FEDCBAp+50);
212243
213 try test__floatuntisf(0x0007FB72E6000000, 0x1.FEDCBAp+50);244 try test_f32_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCBAp+50);
214 try test__floatuntisf(0x0007FB72E7000000, 0x1.FEDCBAp+50);245 try test_f32_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCBAp+50);
215 try test__floatuntisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);246 try test_f32_floatFromInt_u128(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
216 try test__floatuntisf(0x0007FB72E4000001, 0x1.FEDCBAp+50);247 try test_f32_floatFromInt_u128(0x0007FB72E4000001, 0x1.FEDCBAp+50);
217 try test__floatuntisf(0x0007FB72E4000000, 0x1.FEDCB8p+50);248 try test_f32_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB8p+50);
218249
219 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCB90000000000001), 0x1.FEDCBAp+76);250 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCB90000000000001), 0x1.FEDCBAp+76);
220 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBA0000000000000), 0x1.FEDCBAp+76);251 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBA0000000000000), 0x1.FEDCBAp+76);
221 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBAFFFFFFFFFFFFF), 0x1.FEDCBAp+76);252 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBAFFFFFFFFFFFFF), 0x1.FEDCBAp+76);
222 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBB0000000000000), 0x1.FEDCBCp+76);253 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBB0000000000000), 0x1.FEDCBCp+76);
223 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBB0000000000001), 0x1.FEDCBCp+76);254 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBB0000000000001), 0x1.FEDCBCp+76);
224 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBBFFFFFFFFFFFFF), 0x1.FEDCBCp+76);255 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBBFFFFFFFFFFFFF), 0x1.FEDCBCp+76);
225 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBC0000000000000), 0x1.FEDCBCp+76);256 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBC0000000000000), 0x1.FEDCBCp+76);
226 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBC0000000000001), 0x1.FEDCBCp+76);257 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBC0000000000001), 0x1.FEDCBCp+76);
227 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBD0000000000000), 0x1.FEDCBCp+76);258 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBD0000000000000), 0x1.FEDCBCp+76);
228 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBD0000000000001), 0x1.FEDCBEp+76);259 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBD0000000000001), 0x1.FEDCBEp+76);
229 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBDFFFFFFFFFFFFF), 0x1.FEDCBEp+76);260 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBDFFFFFFFFFFFFF), 0x1.FEDCBEp+76);
230 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBE0000000000000), 0x1.FEDCBEp+76);261 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBE0000000000000), 0x1.FEDCBEp+76);
231262
232 // Test overflow to infinity263 // 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)));
234}265}
235266
236fn test_floateisf(expected: u32, comptime T: type, a: T) !void {267fn test_f32_floatFromInt(expected: u32, comptime T: type, a: T) !void {
237 const int = @typeInfo(T).int;268 const int = @typeInfo(T).int;
238 const r = switch (int.signedness) {269 const r = switch (int.signedness) {
239 .signed => __floateisf,270 .signed => f32_floatFromInt_signed,
240 .unsigned => __floatuneisf,271 .unsigned => f32_floatFromInt_unsigned,
241 }(@ptrCast(&a), int.bits);272 }(@ptrCast(&a));
242 try testing.expect(expected == @as(u32, @bitCast(r)));273 try testing.expect(expected == @as(u32, @bitCast(r)));
243}274}
244275
245test "floateisf" {276test f32_floatFromInt_signed {
246 try test_floateisf(0xFF000000, i256, -1 << 127);277 try test_f32_floatFromInt(0xFF000000, i256, -1 << 127);
247 try test_floateisf(0xFF000000, i256, -math.maxInt(u127));278 try test_f32_floatFromInt(0xFF000000, i256, -math.maxInt(u127));
248 try test_floateisf(0xDF012347, i256, -0x8123468100000000);279 try test_f32_floatFromInt(0xDF012347, i256, -0x8123468100000000);
249 try test_floateisf(0xDF012347, i256, -0x8123468000000001);280 try test_f32_floatFromInt(0xDF012347, i256, -0x8123468000000001);
250 try test_floateisf(0xDF012346, i256, -0x8123468000000000);281 try test_f32_floatFromInt(0xDF012346, i256, -0x8123468000000000);
251 try test_floateisf(0xDF012346, i256, -0x8123458100000000);282 try test_f32_floatFromInt(0xDF012346, i256, -0x8123458100000000);
252 try test_floateisf(0xDF012346, i256, -0x8123458000000001);283 try test_f32_floatFromInt(0xDF012346, i256, -0x8123458000000001);
253 try test_floateisf(0xDF012346, i256, -0x8123458000000000);284 try test_f32_floatFromInt(0xDF012346, i256, -0x8123458000000000);
254 try test_floateisf(0xDF012345, i256, -0x8123456789ABCDEF);285 try test_f32_floatFromInt(0xDF012345, i256, -0x8123456789ABCDEF);
255 try test_floateisf(0xBF800000, i256, -1);286 try test_f32_floatFromInt(0xBF800000, i256, -1);
256 try test_floateisf(0x00000000, i256, 0);287 try test_f32_floatFromInt(0x00000000, i256, 0);
257 try test_floateisf(0x5F012345, i256, 0x8123456789ABCDEF);288 try test_f32_floatFromInt(0x5F012345, i256, 0x8123456789ABCDEF);
258 try test_floateisf(0x5F012346, i256, 0x8123458000000000);289 try test_f32_floatFromInt(0x5F012346, i256, 0x8123458000000000);
259 try test_floateisf(0x5F012346, i256, 0x8123458000000001);290 try test_f32_floatFromInt(0x5F012346, i256, 0x8123458000000001);
260 try test_floateisf(0x5F012346, i256, 0x8123458100000000);291 try test_f32_floatFromInt(0x5F012346, i256, 0x8123458100000000);
261 try test_floateisf(0x5F012346, i256, 0x8123468000000000);292 try test_f32_floatFromInt(0x5F012346, i256, 0x8123468000000000);
262 try test_floateisf(0x5F012347, i256, 0x8123468000000001);293 try test_f32_floatFromInt(0x5F012347, i256, 0x8123468000000001);
263 try test_floateisf(0x5F012347, i256, 0x8123468100000000);294 try test_f32_floatFromInt(0x5F012347, i256, 0x8123468100000000);
264 try test_floateisf(0x7F000000, i256, math.maxInt(u127));295 try test_f32_floatFromInt(0x7F000000, i256, math.maxInt(u127));
265 try test_floateisf(0x7F000000, i256, 1 << 127);296 try test_f32_floatFromInt(0x7F000000, i256, 1 << 127);
266}297}
267298
268test "floatuneisf" {299test f32_floatFromInt_unsigned {
269 try test_floateisf(0x00000000, u256, 0);300 try test_f32_floatFromInt(0x00000000, u256, 0);
270 try test_floateisf(0x5F012345, u256, 0x8123456789ABCDEF);301 try test_f32_floatFromInt(0x5F012345, u256, 0x8123456789ABCDEF);
271 try test_floateisf(0x5F012346, u256, 0x8123458000000000);302 try test_f32_floatFromInt(0x5F012346, u256, 0x8123458000000000);
272 try test_floateisf(0x5F012346, u256, 0x8123458000000001);303 try test_f32_floatFromInt(0x5F012346, u256, 0x8123458000000001);
273 try test_floateisf(0x5F012346, u256, 0x8123458080000000);304 try test_f32_floatFromInt(0x5F012346, u256, 0x8123458080000000);
274 try test_floateisf(0x5F012346, u256, 0x8123468000000000);305 try test_f32_floatFromInt(0x5F012346, u256, 0x8123468000000000);
275 try test_floateisf(0x5F012347, u256, 0x8123468000000001);306 try test_f32_floatFromInt(0x5F012347, u256, 0x8123468000000001);
276 try test_floateisf(0x5F012347, u256, 0x8123468080000000);307 try test_f32_floatFromInt(0x5F012347, u256, 0x8123468080000000);
277 try test_floateisf(0x7F000000, u256, math.maxInt(u127));308 try test_f32_floatFromInt(0x7F000000, u256, math.maxInt(u127));
278 try test_floateisf(0x7F000000, u256, 1 << 127);309 try test_f32_floatFromInt(0x7F000000, u256, 1 << 127);
279 try test_floateisf(0x7F800000, u256, math.maxInt(u256));310 try test_f32_floatFromInt(0x7F800000, u256, math.maxInt(u256));
280}311}
281312
282fn test_one_floatsidf(a: i32, expected: u64) !void {313fn test_f64_floatFromInt_i32(a: i32, expected: u64) !void {
283 const r = __floatsidf(a);314 const r = f64_floatFromInt_i32(a);
284 try std.testing.expect(@as(u64, @bitCast(r)) == expected);315 try std.testing.expect(@as(u64, @bitCast(r)) == expected);
285}316}
286317
287fn test_one_floatunsidf(a: u32, expected: u64) !void {318fn test_f64_floatFromInt_u32(a: u32, expected: u64) !void {
288 const r = __floatunsidf(a);319 const r = f64_floatFromInt_u32(a);
289 try std.testing.expect(@as(u64, @bitCast(r)) == expected);320 try std.testing.expect(@as(u64, @bitCast(r)) == expected);
290}321}
291322
292test "floatsidf" {323test f64_floatFromInt_i32 {
293 try test_one_floatsidf(0, 0x0000000000000000);324 try test_f64_floatFromInt_i32(0, 0x0000000000000000);
294 try test_one_floatsidf(1, 0x3ff0000000000000);325 try test_f64_floatFromInt_i32(1, 0x3ff0000000000000);
295 try test_one_floatsidf(-1, 0xbff0000000000000);326 try test_f64_floatFromInt_i32(-1, 0xbff0000000000000);
296 try test_one_floatsidf(0x7FFFFFFF, 0x41dfffffffc00000);327 try test_f64_floatFromInt_i32(0x7FFFFFFF, 0x41dfffffffc00000);
297 try test_one_floatsidf(@bitCast(@as(u32, @intCast(0x80000000))), 0xc1e0000000000000);328 try test_f64_floatFromInt_i32(@bitCast(@as(u32, @intCast(0x80000000))), 0xc1e0000000000000);
298}329}
299330
300test "floatunsidf" {331test f64_floatFromInt_u32 {
301 try test_one_floatunsidf(0, 0x0000000000000000);332 try test_f64_floatFromInt_u32(0, 0x0000000000000000);
302 try test_one_floatunsidf(1, 0x3ff0000000000000);333 try test_f64_floatFromInt_u32(1, 0x3ff0000000000000);
303 try test_one_floatunsidf(0x7FFFFFFF, 0x41dfffffffc00000);334 try test_f64_floatFromInt_u32(0x7FFFFFFF, 0x41dfffffffc00000);
304 try test_one_floatunsidf(@intCast(0x80000000), 0x41e0000000000000);335 try test_f64_floatFromInt_u32(@intCast(0x80000000), 0x41e0000000000000);
305 try test_one_floatunsidf(@intCast(0xFFFFFFFF), 0x41efffffffe00000);336 try test_f64_floatFromInt_u32(@intCast(0xFFFFFFFF), 0x41efffffffe00000);
306}337}
307338
308fn test__floatdidf(a: i64, expected: f64) !void {339fn test_f64_floatFromInt_i64(a: i64, expected: f64) !void {
309 const r = __floatdidf(a);340 const r = f64_floatFromInt_i64(a);
310 try testing.expect(r == expected);341 try testing.expect(r == expected);
311}342}
312343
313fn test__floatundidf(a: u64, expected: f64) !void {344fn test_f64_floatFromInt_u64(a: u64, expected: f64) !void {
314 const r = __floatundidf(a);345 const r = f64_floatFromInt_u64(a);
315 try testing.expect(r == expected);346 try testing.expect(r == expected);
316}347}
317348
318test "floatdidf" {349test f64_floatFromInt_i64 {
319 try test__floatdidf(0, 0.0);350 try test_f64_floatFromInt_i64(0, 0.0);
320 try test__floatdidf(1, 1.0);351 try test_f64_floatFromInt_i64(1, 1.0);
321 try test__floatdidf(2, 2.0);352 try test_f64_floatFromInt_i64(2, 2.0);
322 try test__floatdidf(20, 20.0);353 try test_f64_floatFromInt_i64(20, 20.0);
323 try test__floatdidf(-1, -1.0);354 try test_f64_floatFromInt_i64(-1, -1.0);
324 try test__floatdidf(-2, -2.0);355 try test_f64_floatFromInt_i64(-2, -2.0);
325 try test__floatdidf(-20, -20.0);356 try test_f64_floatFromInt_i64(-20, -20.0);
326 try test__floatdidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);357 try test_f64_floatFromInt_i64(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
327 try test__floatdidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);358 try test_f64_floatFromInt_i64(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
328 try test__floatdidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);359 try test_f64_floatFromInt_i64(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
329 try test__floatdidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);360 try test_f64_floatFromInt_i64(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
330 try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000008000000000))), -0x1.FFFFFEp+62);361 try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000008000000000))), -0x1.FFFFFEp+62);
331 try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000000800))), -0x1.FFFFFFFFFFFFEp+62);362 try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000000800))), -0x1.FFFFFFFFFFFFEp+62);
332 try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000010000000000))), -0x1.FFFFFCp+62);363 try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000010000000000))), -0x1.FFFFFCp+62);
333 try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000001000))), -0x1.FFFFFFFFFFFFCp+62);364 try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000001000))), -0x1.FFFFFFFFFFFFCp+62);
334 try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000000000))), -0x1.000000p+63);365 try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000000000))), -0x1.000000p+63);
335 try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000000001))), -0x1.000000p+63); // 0x8000000000000001366 try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000000001))), -0x1.000000p+63); // 0x8000000000000001
336 try test__floatdidf(0x0007FB72E8000000, 0x1.FEDCBAp+50);367 try test_f64_floatFromInt_i64(0x0007FB72E8000000, 0x1.FEDCBAp+50);
337 try test__floatdidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);368 try test_f64_floatFromInt_i64(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
338 try test__floatdidf(0x0007FB72EB000000, 0x1.FEDCBACp+50);369 try test_f64_floatFromInt_i64(0x0007FB72EB000000, 0x1.FEDCBACp+50);
339 try test__floatdidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);370 try test_f64_floatFromInt_i64(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
340 try test__floatdidf(0x0007FB72EC000000, 0x1.FEDCBBp+50);371 try test_f64_floatFromInt_i64(0x0007FB72EC000000, 0x1.FEDCBBp+50);
341 try test__floatdidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);372 try test_f64_floatFromInt_i64(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
342 try test__floatdidf(0x0007FB72E6000000, 0x1.FEDCB98p+50);373 try test_f64_floatFromInt_i64(0x0007FB72E6000000, 0x1.FEDCB98p+50);
343 try test__floatdidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);374 try test_f64_floatFromInt_i64(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
344 try test__floatdidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);375 try test_f64_floatFromInt_i64(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
345 try test__floatdidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);376 try test_f64_floatFromInt_i64(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
346 try test__floatdidf(0x0007FB72E4000000, 0x1.FEDCB9p+50);377 try test_f64_floatFromInt_i64(0x0007FB72E4000000, 0x1.FEDCB9p+50);
347 try test__floatdidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);378 try test_f64_floatFromInt_i64(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
348 try test__floatdidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);379 try test_f64_floatFromInt_i64(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
349 try test__floatdidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);380 try test_f64_floatFromInt_i64(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
350 try test__floatdidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);381 try test_f64_floatFromInt_i64(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
351 try test__floatdidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);382 try test_f64_floatFromInt_i64(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
352 try test__floatdidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);383 try test_f64_floatFromInt_i64(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
353 try test__floatdidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);384 try test_f64_floatFromInt_i64(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
354 try test__floatdidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);385 try test_f64_floatFromInt_i64(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
355 try test__floatdidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);386 try test_f64_floatFromInt_i64(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
356 try test__floatdidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);387 try test_f64_floatFromInt_i64(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
357 try test__floatdidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);388 try test_f64_floatFromInt_i64(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
358 try test__floatdidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);389 try test_f64_floatFromInt_i64(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
359 try test__floatdidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);390 try test_f64_floatFromInt_i64(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
360 try test__floatdidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);391 try test_f64_floatFromInt_i64(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
361 try test__floatdidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);392 try test_f64_floatFromInt_i64(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
362}393}
363394
364test "floatundidf" {395test f64_floatFromInt_u64 {
365 try test__floatundidf(0, 0.0);396 try test_f64_floatFromInt_u64(0, 0.0);
366 try test__floatundidf(1, 1.0);397 try test_f64_floatFromInt_u64(1, 1.0);
367 try test__floatundidf(2, 2.0);398 try test_f64_floatFromInt_u64(2, 2.0);
368 try test__floatundidf(20, 20.0);399 try test_f64_floatFromInt_u64(20, 20.0);
369 try test__floatundidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);400 try test_f64_floatFromInt_u64(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
370 try test__floatundidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);401 try test_f64_floatFromInt_u64(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
371 try test__floatundidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);402 try test_f64_floatFromInt_u64(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
372 try test__floatundidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);403 try test_f64_floatFromInt_u64(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
373 try test__floatundidf(0x8000008000000000, 0x1.000001p+63);404 try test_f64_floatFromInt_u64(0x8000008000000000, 0x1.000001p+63);
374 try test__floatundidf(0x8000000000000800, 0x1.0000000000001p+63);405 try test_f64_floatFromInt_u64(0x8000000000000800, 0x1.0000000000001p+63);
375 try test__floatundidf(0x8000010000000000, 0x1.000002p+63);406 try test_f64_floatFromInt_u64(0x8000010000000000, 0x1.000002p+63);
376 try test__floatundidf(0x8000000000001000, 0x1.0000000000002p+63);407 try test_f64_floatFromInt_u64(0x8000000000001000, 0x1.0000000000002p+63);
377 try test__floatundidf(0x8000000000000000, 0x1p+63);408 try test_f64_floatFromInt_u64(0x8000000000000000, 0x1p+63);
378 try test__floatundidf(0x8000000000000001, 0x1p+63);409 try test_f64_floatFromInt_u64(0x8000000000000001, 0x1p+63);
379 try test__floatundidf(0x0007FB72E8000000, 0x1.FEDCBAp+50);410 try test_f64_floatFromInt_u64(0x0007FB72E8000000, 0x1.FEDCBAp+50);
380 try test__floatundidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);411 try test_f64_floatFromInt_u64(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
381 try test__floatundidf(0x0007FB72EB000000, 0x1.FEDCBACp+50);412 try test_f64_floatFromInt_u64(0x0007FB72EB000000, 0x1.FEDCBACp+50);
382 try test__floatundidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);413 try test_f64_floatFromInt_u64(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
383 try test__floatundidf(0x0007FB72EC000000, 0x1.FEDCBBp+50);414 try test_f64_floatFromInt_u64(0x0007FB72EC000000, 0x1.FEDCBBp+50);
384 try test__floatundidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);415 try test_f64_floatFromInt_u64(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
385 try test__floatundidf(0x0007FB72E6000000, 0x1.FEDCB98p+50);416 try test_f64_floatFromInt_u64(0x0007FB72E6000000, 0x1.FEDCB98p+50);
386 try test__floatundidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);417 try test_f64_floatFromInt_u64(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
387 try test__floatundidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);418 try test_f64_floatFromInt_u64(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
388 try test__floatundidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);419 try test_f64_floatFromInt_u64(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
389 try test__floatundidf(0x0007FB72E4000000, 0x1.FEDCB9p+50);420 try test_f64_floatFromInt_u64(0x0007FB72E4000000, 0x1.FEDCB9p+50);
390 try test__floatundidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);421 try test_f64_floatFromInt_u64(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
391 try test__floatundidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);422 try test_f64_floatFromInt_u64(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
392 try test__floatundidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);423 try test_f64_floatFromInt_u64(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
393 try test__floatundidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);424 try test_f64_floatFromInt_u64(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
394 try test__floatundidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);425 try test_f64_floatFromInt_u64(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
395 try test__floatundidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);426 try test_f64_floatFromInt_u64(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
396 try test__floatundidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);427 try test_f64_floatFromInt_u64(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
397 try test__floatundidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);428 try test_f64_floatFromInt_u64(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
398 try test__floatundidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);429 try test_f64_floatFromInt_u64(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
399 try test__floatundidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);430 try test_f64_floatFromInt_u64(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
400 try test__floatundidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);431 try test_f64_floatFromInt_u64(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
401 try test__floatundidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);432 try test_f64_floatFromInt_u64(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
402 try test__floatundidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);433 try test_f64_floatFromInt_u64(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
403 try test__floatundidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);434 try test_f64_floatFromInt_u64(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
404 try test__floatundidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);435 try test_f64_floatFromInt_u64(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
405}436}
406437
407fn test__floattidf(a: i128, expected: f64) !void {438fn test_f64_floatFromInt_i128(a: i128, expected: f64) !void {
408 const x = __floattidf(a);439 const x = f64_floatFromInt_i128(a);
409 try testing.expect(x == expected);440 try testing.expect(x == expected);
410}441}
411442
412fn test__floatuntidf(a: u128, expected: f64) !void {443fn test_f64_floatFromInt_u128(a: u128, expected: f64) !void {
413 const x = __floatuntidf(a);444 const x = f64_floatFromInt_u128(a);
414 try testing.expect(x == expected);445 try testing.expect(x == expected);
415}446}
416447
417test "floattidf" {448test f64_floatFromInt_i128 {
418 try test__floattidf(0, 0.0);449 try test_f64_floatFromInt_i128(0, 0.0);
419450
420 try test__floattidf(1, 1.0);451 try test_f64_floatFromInt_i128(1, 1.0);
421 try test__floattidf(2, 2.0);452 try test_f64_floatFromInt_i128(2, 2.0);
422 try test__floattidf(20, 20.0);453 try test_f64_floatFromInt_i128(20, 20.0);
423 try test__floattidf(-1, -1.0);454 try test_f64_floatFromInt_i128(-1, -1.0);
424 try test__floattidf(-2, -2.0);455 try test_f64_floatFromInt_i128(-2, -2.0);
425 try test__floattidf(-20, -20.0);456 try test_f64_floatFromInt_i128(-20, -20.0);
426457
427 try test__floattidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);458 try test_f64_floatFromInt_i128(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
428 try test__floattidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);459 try test_f64_floatFromInt_i128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
429 try test__floattidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);460 try test_f64_floatFromInt_i128(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
430 try test__floattidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);461 try test_f64_floatFromInt_i128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
431462
432 try test__floattidf(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126);463 try test_f64_floatFromInt_i128(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126);
433 try test__floattidf(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126);464 try test_f64_floatFromInt_i128(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126);
434 try test__floattidf(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126);465 try test_f64_floatFromInt_i128(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126);
435 try test__floattidf(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126);466 try test_f64_floatFromInt_i128(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126);
436467
437 try test__floattidf(make_ti(0x8000000000000000, 0), -0x1.000000p+127);468 try test_f64_floatFromInt_i128(make_ti(0x8000000000000000, 0), -0x1.000000p+127);
438 try test__floattidf(make_ti(0x8000000000000001, 0), -0x1.000000p+127);469 try test_f64_floatFromInt_i128(make_ti(0x8000000000000001, 0), -0x1.000000p+127);
439470
440 try test__floattidf(0x0007FB72E8000000, 0x1.FEDCBAp+50);471 try test_f64_floatFromInt_i128(0x0007FB72E8000000, 0x1.FEDCBAp+50);
441472
442 try test__floattidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);473 try test_f64_floatFromInt_i128(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
443 try test__floattidf(0x0007FB72EB000000, 0x1.FEDCBACp+50);474 try test_f64_floatFromInt_i128(0x0007FB72EB000000, 0x1.FEDCBACp+50);
444 try test__floattidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);475 try test_f64_floatFromInt_i128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
445 try test__floattidf(0x0007FB72EC000000, 0x1.FEDCBBp+50);476 try test_f64_floatFromInt_i128(0x0007FB72EC000000, 0x1.FEDCBBp+50);
446 try test__floattidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);477 try test_f64_floatFromInt_i128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
447478
448 try test__floattidf(0x0007FB72E6000000, 0x1.FEDCB98p+50);479 try test_f64_floatFromInt_i128(0x0007FB72E6000000, 0x1.FEDCB98p+50);
449 try test__floattidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);480 try test_f64_floatFromInt_i128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
450 try test__floattidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);481 try test_f64_floatFromInt_i128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
451 try test__floattidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);482 try test_f64_floatFromInt_i128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
452 try test__floattidf(0x0007FB72E4000000, 0x1.FEDCB9p+50);483 try test_f64_floatFromInt_i128(0x0007FB72E4000000, 0x1.FEDCB9p+50);
453484
454 try test__floattidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);485 try test_f64_floatFromInt_i128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
455 try test__floattidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);486 try test_f64_floatFromInt_i128(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
456 try test__floattidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);487 try test_f64_floatFromInt_i128(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
457 try test__floattidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);488 try test_f64_floatFromInt_i128(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
458 try test__floattidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);489 try test_f64_floatFromInt_i128(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
459 try test__floattidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);490 try test_f64_floatFromInt_i128(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
460 try test__floattidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);491 try test_f64_floatFromInt_i128(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
461 try test__floattidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);492 try test_f64_floatFromInt_i128(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
462 try test__floattidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);493 try test_f64_floatFromInt_i128(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
463 try test__floattidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);494 try test_f64_floatFromInt_i128(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
464 try test__floattidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);495 try test_f64_floatFromInt_i128(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
465 try test__floattidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);496 try test_f64_floatFromInt_i128(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
466 try test__floattidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);497 try test_f64_floatFromInt_i128(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
467 try test__floattidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);498 try test_f64_floatFromInt_i128(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
468 try test__floattidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);499 try test_f64_floatFromInt_i128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
469500
470 try test__floattidf(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);501 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);
471 try test__floattidf(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121);502 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121);
472 try test__floattidf(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121);503 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121);
473 try test__floattidf(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121);504 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121);
474 try test__floattidf(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121);505 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121);
475 try test__floattidf(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121);506 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121);
476 try test__floattidf(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121);507 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121);
477 try test__floattidf(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121);508 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121);
478 try test__floattidf(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121);509 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121);
479 try test__floattidf(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121);510 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121);
480 try test__floattidf(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121);511 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121);
481 try test__floattidf(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121);512 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121);
482 try test__floattidf(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121);513 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121);
483 try test__floattidf(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121);514 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121);
484 try test__floattidf(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);515 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);
485}516}
486517
487test "floatuntidf" {518test f64_floatFromInt_u128 {
488 try test__floatuntidf(0, 0.0);519 try test_f64_floatFromInt_u128(0, 0.0);
489520
490 try test__floatuntidf(1, 1.0);521 try test_f64_floatFromInt_u128(1, 1.0);
491 try test__floatuntidf(2, 2.0);522 try test_f64_floatFromInt_u128(2, 2.0);
492 try test__floatuntidf(20, 20.0);523 try test_f64_floatFromInt_u128(20, 20.0);
493524
494 try test__floatuntidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);525 try test_f64_floatFromInt_u128(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
495 try test__floatuntidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);526 try test_f64_floatFromInt_u128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
496 try test__floatuntidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);527 try test_f64_floatFromInt_u128(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
497 try test__floatuntidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);528 try test_f64_floatFromInt_u128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
498529
499 try test__floatuntidf(make_uti(0x8000008000000000, 0), 0x1.000001p+127);530 try test_f64_floatFromInt_u128(make_uti(0x8000008000000000, 0), 0x1.000001p+127);
500 try test__floatuntidf(make_uti(0x8000000000000800, 0), 0x1.0000000000001p+127);531 try test_f64_floatFromInt_u128(make_uti(0x8000000000000800, 0), 0x1.0000000000001p+127);
501 try test__floatuntidf(make_uti(0x8000010000000000, 0), 0x1.000002p+127);532 try test_f64_floatFromInt_u128(make_uti(0x8000010000000000, 0), 0x1.000002p+127);
502 try test__floatuntidf(make_uti(0x8000000000001000, 0), 0x1.0000000000002p+127);533 try test_f64_floatFromInt_u128(make_uti(0x8000000000001000, 0), 0x1.0000000000002p+127);
503534
504 try test__floatuntidf(make_uti(0x8000000000000000, 0), 0x1.000000p+127);535 try test_f64_floatFromInt_u128(make_uti(0x8000000000000000, 0), 0x1.000000p+127);
505 try test__floatuntidf(make_uti(0x8000000000000001, 0), 0x1.0000000000000002p+127);536 try test_f64_floatFromInt_u128(make_uti(0x8000000000000001, 0), 0x1.0000000000000002p+127);
506537
507 try test__floatuntidf(0x0007FB72E8000000, 0x1.FEDCBAp+50);538 try test_f64_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50);
508539
509 try test__floatuntidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);540 try test_f64_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
510 try test__floatuntidf(0x0007FB72EB000000, 0x1.FEDCBACp+50);541 try test_f64_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBACp+50);
511 try test__floatuntidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);542 try test_f64_floatFromInt_u128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
512 try test__floatuntidf(0x0007FB72EC000000, 0x1.FEDCBBp+50);543 try test_f64_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBBp+50);
513 try test__floatuntidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);544 try test_f64_floatFromInt_u128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
514545
515 try test__floatuntidf(0x0007FB72E6000000, 0x1.FEDCB98p+50);546 try test_f64_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCB98p+50);
516 try test__floatuntidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);547 try test_f64_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
517 try test__floatuntidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);548 try test_f64_floatFromInt_u128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
518 try test__floatuntidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);549 try test_f64_floatFromInt_u128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
519 try test__floatuntidf(0x0007FB72E4000000, 0x1.FEDCB9p+50);550 try test_f64_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB9p+50);
520551
521 try test__floatuntidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);552 try test_f64_floatFromInt_u128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
522 try test__floatuntidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);553 try test_f64_floatFromInt_u128(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
523 try test__floatuntidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);554 try test_f64_floatFromInt_u128(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
524 try test__floatuntidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);555 try test_f64_floatFromInt_u128(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
525 try test__floatuntidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);556 try test_f64_floatFromInt_u128(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
526 try test__floatuntidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);557 try test_f64_floatFromInt_u128(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
527 try test__floatuntidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);558 try test_f64_floatFromInt_u128(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
528 try test__floatuntidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);559 try test_f64_floatFromInt_u128(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
529 try test__floatuntidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);560 try test_f64_floatFromInt_u128(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
530 try test__floatuntidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);561 try test_f64_floatFromInt_u128(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
531 try test__floatuntidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);562 try test_f64_floatFromInt_u128(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
532 try test__floatuntidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);563 try test_f64_floatFromInt_u128(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
533 try test__floatuntidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);564 try test_f64_floatFromInt_u128(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
534 try test__floatuntidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);565 try test_f64_floatFromInt_u128(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
535 try test__floatuntidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);566 try test_f64_floatFromInt_u128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
536567
537 try test__floatuntidf(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);568 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);
538 try test__floatuntidf(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121);569 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121);
539 try test__floatuntidf(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121);570 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121);
540 try test__floatuntidf(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121);571 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121);
541 try test__floatuntidf(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121);572 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121);
542 try test__floatuntidf(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121);573 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121);
543 try test__floatuntidf(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121);574 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121);
544 try test__floatuntidf(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121);575 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121);
545 try test__floatuntidf(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121);576 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121);
546 try test__floatuntidf(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121);577 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121);
547 try test__floatuntidf(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121);578 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121);
548 try test__floatuntidf(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121);579 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121);
549 try test__floatuntidf(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121);580 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121);
550 try test__floatuntidf(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121);581 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121);
551 try test__floatuntidf(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);582 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);
552}583}
553584
554fn test__floatsitf(a: i32, expected: u128) !void {585fn test_f128_floatFromInt_i32(a: i32, expected: u128) !void {
555 const r = __floatsitf(a);586 const r = f128_floatFromInt_i32(a);
556 try std.testing.expect(@as(u128, @bitCast(r)) == expected);587 try std.testing.expect(@as(u128, @bitCast(r)) == expected);
557}588}
558589
559test "floatsitf" {590fn test_f128_floatFromInt_u32(a: u32, expected_hi: u64, expected_lo: u64) !void {
560 try test__floatsitf(0, 0);591 const x = f128_floatFromInt_u32(a);
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);
570592
571 const x_repr: u128 = @bitCast(x);593 const x_repr: u128 = @bitCast(x);
572 const x_hi: u64 = @intCast(x_repr >> 64);594 const x_hi: u64 = @intCast(x_repr >> 64);
...@@ -581,24 +603,32 @@ fn test__floatunsitf(a: u32, expected_hi: u64, expected_lo: u64) !void {...@@ -581,24 +603,32 @@ fn test__floatunsitf(a: u32, expected_hi: u64, expected_lo: u64) !void {
581 return;603 return;
582 }604 }
583 }605 }
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);
586}616}
587617
588test "floatunsitf" {618test f128_floatFromInt_u32 {
589 try test__floatunsitf(0x7fffffff, 0x401dfffffffc0000, 0x0);619 try test_f128_floatFromInt_u32(0x7fffffff, 0x401dfffffffc0000, 0x0);
590 try test__floatunsitf(0, 0x0, 0x0);620 try test_f128_floatFromInt_u32(0, 0x0, 0x0);
591 try test__floatunsitf(0xffffffff, 0x401efffffffe0000, 0x0);621 try test_f128_floatFromInt_u32(0xffffffff, 0x401efffffffe0000, 0x0);
592 try test__floatunsitf(0x12345678, 0x401b234567800000, 0x0);622 try test_f128_floatFromInt_u32(0x12345678, 0x401b234567800000, 0x0);
593}623}
594624
595fn test__floatditf(a: i64, expected: f128) !void {625fn test_f128_floatFromInt_i64(a: i64, expected: f128) !void {
596 const x = __floatditf(a);626 const x = f128_floatFromInt_i64(a);
597 try testing.expect(x == expected);627 try testing.expect(x == expected);
598}628}
599629
600fn test__floatunditf(a: u64, expected_hi: u64, expected_lo: u64) !void {630fn test_f128_floatFromInt_u64(a: u64, expected_hi: u64, expected_lo: u64) !void {
601 const x = __floatunditf(a);631 const x = f128_floatFromInt_u64(a);
602632
603 const x_repr: u128 = @bitCast(x);633 const x_repr: u128 = @bitCast(x);
604 const x_hi: u64 = @intCast(x_repr >> 64);634 const x_hi: u64 = @intCast(x_repr >> 64);
...@@ -613,208 +643,207 @@ fn test__floatunditf(a: u64, expected_hi: u64, expected_lo: u64) !void {...@@ -613,208 +643,207 @@ fn test__floatunditf(a: u64, expected_hi: u64, expected_lo: u64) !void {
613 return;643 return;
614 }644 }
615 }645 }
616646 return error.TestFailure;
617 @panic("__floatunditf test failure");647}
618}648
619649test f128_floatFromInt_i64 {
620test "floatditf" {650 try test_f128_floatFromInt_i64(0x7fffffffffffffff, make_tf(0x403dffffffffffff, 0xfffc000000000000));
621 try test__floatditf(0x7fffffffffffffff, make_tf(0x403dffffffffffff, 0xfffc000000000000));651 try test_f128_floatFromInt_i64(0x123456789abcdef1, make_tf(0x403b23456789abcd, 0xef10000000000000));
622 try test__floatditf(0x123456789abcdef1, make_tf(0x403b23456789abcd, 0xef10000000000000));652 try test_f128_floatFromInt_i64(0x2, make_tf(0x4000000000000000, 0x0));
623 try test__floatditf(0x2, make_tf(0x4000000000000000, 0x0));653 try test_f128_floatFromInt_i64(0x1, make_tf(0x3fff000000000000, 0x0));
624 try test__floatditf(0x1, make_tf(0x3fff000000000000, 0x0));654 try test_f128_floatFromInt_i64(0x0, make_tf(0x0, 0x0));
625 try test__floatditf(0x0, make_tf(0x0, 0x0));655 try test_f128_floatFromInt_i64(@bitCast(@as(u64, 0xffffffffffffffff)), make_tf(0xbfff000000000000, 0x0));
626 try test__floatditf(@bitCast(@as(u64, 0xffffffffffffffff)), make_tf(0xbfff000000000000, 0x0));656 try test_f128_floatFromInt_i64(@bitCast(@as(u64, 0xfffffffffffffffe)), make_tf(0xc000000000000000, 0x0));
627 try test__floatditf(@bitCast(@as(u64, 0xfffffffffffffffe)), make_tf(0xc000000000000000, 0x0));657 try test_f128_floatFromInt_i64(-0x123456789abcdef1, make_tf(0xc03b23456789abcd, 0xef10000000000000));
628 try test__floatditf(-0x123456789abcdef1, make_tf(0xc03b23456789abcd, 0xef10000000000000));658 try test_f128_floatFromInt_i64(@bitCast(@as(u64, 0x8000000000000000)), make_tf(0xc03e000000000000, 0x0));
629 try test__floatditf(@bitCast(@as(u64, 0x8000000000000000)), make_tf(0xc03e000000000000, 0x0));659}
630}660
631661test f128_floatFromInt_u64 {
632test "floatunditf" {662 try test_f128_floatFromInt_u64(0xffffffffffffffff, 0x403effffffffffff, 0xfffe000000000000);
633 try test__floatunditf(0xffffffffffffffff, 0x403effffffffffff, 0xfffe000000000000);663 try test_f128_floatFromInt_u64(0xfffffffffffffffe, 0x403effffffffffff, 0xfffc000000000000);
634 try test__floatunditf(0xfffffffffffffffe, 0x403effffffffffff, 0xfffc000000000000);664 try test_f128_floatFromInt_u64(0x8000000000000000, 0x403e000000000000, 0x0);
635 try test__floatunditf(0x8000000000000000, 0x403e000000000000, 0x0);665 try test_f128_floatFromInt_u64(0x7fffffffffffffff, 0x403dffffffffffff, 0xfffc000000000000);
636 try test__floatunditf(0x7fffffffffffffff, 0x403dffffffffffff, 0xfffc000000000000);666 try test_f128_floatFromInt_u64(0x123456789abcdef1, 0x403b23456789abcd, 0xef10000000000000);
637 try test__floatunditf(0x123456789abcdef1, 0x403b23456789abcd, 0xef10000000000000);667 try test_f128_floatFromInt_u64(0x2, 0x4000000000000000, 0x0);
638 try test__floatunditf(0x2, 0x4000000000000000, 0x0);668 try test_f128_floatFromInt_u64(0x1, 0x3fff000000000000, 0x0);
639 try test__floatunditf(0x1, 0x3fff000000000000, 0x0);669 try test_f128_floatFromInt_u64(0x0, 0x0, 0x0);
640 try test__floatunditf(0x0, 0x0, 0x0);670}
641}671
642672fn test_f128_floatFromInt_i128(a: i128, expected: f128) !void {
643fn test__floattitf(a: i128, expected: f128) !void {673 const x = f128_floatFromInt_i128(a);
644 const x = __floattitf(a);
645 try testing.expect(x == expected);674 try testing.expect(x == expected);
646}675}
647676
648fn test__floatuntitf(a: u128, expected: f128) !void {677fn test_f128_floatFromInt_u128(a: u128, expected: f128) !void {
649 const x = __floatuntitf(a);678 const x = f128_floatFromInt_u128(a);
650 try testing.expect(x == expected);679 try testing.expect(x == expected);
651}680}
652681
653test "floattitf" {682test f128_floatFromInt_i128 {
654 try test__floattitf(0, 0.0);683 try test_f128_floatFromInt_i128(0, 0.0);
655684
656 try test__floattitf(1, 1.0);685 try test_f128_floatFromInt_i128(1, 1.0);
657 try test__floattitf(2, 2.0);686 try test_f128_floatFromInt_i128(2, 2.0);
658 try test__floattitf(20, 20.0);687 try test_f128_floatFromInt_i128(20, 20.0);
659 try test__floattitf(-1, -1.0);688 try test_f128_floatFromInt_i128(-1, -1.0);
660 try test__floattitf(-2, -2.0);689 try test_f128_floatFromInt_i128(-2, -2.0);
661 try test__floattitf(-20, -20.0);690 try test_f128_floatFromInt_i128(-20, -20.0);
662691
663 try test__floattitf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);692 try test_f128_floatFromInt_i128(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
664 try test__floattitf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);693 try test_f128_floatFromInt_i128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
665 try test__floattitf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);694 try test_f128_floatFromInt_i128(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
666 try test__floattitf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);695 try test_f128_floatFromInt_i128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
667696
668 try test__floattitf(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126);697 try test_f128_floatFromInt_i128(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126);
669 try test__floattitf(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126);698 try test_f128_floatFromInt_i128(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126);
670 try test__floattitf(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126);699 try test_f128_floatFromInt_i128(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126);
671 try test__floattitf(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126);700 try test_f128_floatFromInt_i128(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126);
672701
673 try test__floattitf(make_ti(0x8000000000000000, 0), -0x1.000000p+127);702 try test_f128_floatFromInt_i128(make_ti(0x8000000000000000, 0), -0x1.000000p+127);
674 try test__floattitf(make_ti(0x8000000000000001, 0), -0x1.FFFFFFFFFFFFFFFCp+126);703 try test_f128_floatFromInt_i128(make_ti(0x8000000000000001, 0), -0x1.FFFFFFFFFFFFFFFCp+126);
675704
676 try test__floattitf(0x0007FB72E8000000, 0x1.FEDCBAp+50);705 try test_f128_floatFromInt_i128(0x0007FB72E8000000, 0x1.FEDCBAp+50);
677706
678 try test__floattitf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);707 try test_f128_floatFromInt_i128(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
679 try test__floattitf(0x0007FB72EB000000, 0x1.FEDCBACp+50);708 try test_f128_floatFromInt_i128(0x0007FB72EB000000, 0x1.FEDCBACp+50);
680 try test__floattitf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);709 try test_f128_floatFromInt_i128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
681 try test__floattitf(0x0007FB72EC000000, 0x1.FEDCBBp+50);710 try test_f128_floatFromInt_i128(0x0007FB72EC000000, 0x1.FEDCBBp+50);
682 try test__floattitf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);711 try test_f128_floatFromInt_i128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
683712
684 try test__floattitf(0x0007FB72E6000000, 0x1.FEDCB98p+50);713 try test_f128_floatFromInt_i128(0x0007FB72E6000000, 0x1.FEDCB98p+50);
685 try test__floattitf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);714 try test_f128_floatFromInt_i128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
686 try test__floattitf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);715 try test_f128_floatFromInt_i128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
687 try test__floattitf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);716 try test_f128_floatFromInt_i128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
688 try test__floattitf(0x0007FB72E4000000, 0x1.FEDCB9p+50);717 try test_f128_floatFromInt_i128(0x0007FB72E4000000, 0x1.FEDCB9p+50);
689718
690 try test__floattitf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);719 try test_f128_floatFromInt_i128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
691 try test__floattitf(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57);720 try test_f128_floatFromInt_i128(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57);
692 try test__floattitf(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57);721 try test_f128_floatFromInt_i128(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57);
693 try test__floattitf(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57);722 try test_f128_floatFromInt_i128(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57);
694 try test__floattitf(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57);723 try test_f128_floatFromInt_i128(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57);
695 try test__floattitf(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57);724 try test_f128_floatFromInt_i128(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57);
696 try test__floattitf(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57);725 try test_f128_floatFromInt_i128(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57);
697 try test__floattitf(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57);726 try test_f128_floatFromInt_i128(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57);
698 try test__floattitf(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57);727 try test_f128_floatFromInt_i128(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57);
699 try test__floattitf(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57);728 try test_f128_floatFromInt_i128(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57);
700 try test__floattitf(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57);729 try test_f128_floatFromInt_i128(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57);
701 try test__floattitf(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57);730 try test_f128_floatFromInt_i128(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57);
702 try test__floattitf(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57);731 try test_f128_floatFromInt_i128(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57);
703 try test__floattitf(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57);732 try test_f128_floatFromInt_i128(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57);
704 try test__floattitf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);733 try test_f128_floatFromInt_i128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
705734
706 try test__floattitf(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);735 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);
707 try test__floattitf(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121);736 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121);
708 try test__floattitf(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121);737 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121);
709 try test__floattitf(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121);738 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121);
710 try test__floattitf(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121);739 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121);
711 try test__floattitf(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121);740 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121);
712 try test__floattitf(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121);741 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121);
713 try test__floattitf(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121);742 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121);
714 try test__floattitf(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121);743 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121);
715 try test__floattitf(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121);744 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121);
716 try test__floattitf(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121);745 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121);
717 try test__floattitf(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121);746 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121);
718 try test__floattitf(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121);747 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121);
719 try test__floattitf(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121);748 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121);
720 try test__floattitf(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);749 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);
721750
722 try test__floattitf(make_ti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63);751 try test_f128_floatFromInt_i128(make_ti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63);
723752
724 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124);753 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124);
725 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124);754 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124);
726 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124);755 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124);
727 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124);756 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124);
728 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124);757 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124);
729 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124);758 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124);
730 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124);759 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124);
731 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124);760 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124);
732 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124);761 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124);
733}762}
734763
735test "floatuntitf" {764test f128_floatFromInt_u128 {
736 try test__floatuntitf(0, 0.0);765 try test_f128_floatFromInt_u128(0, 0.0);
737766
738 try test__floatuntitf(1, 1.0);767 try test_f128_floatFromInt_u128(1, 1.0);
739 try test__floatuntitf(2, 2.0);768 try test_f128_floatFromInt_u128(2, 2.0);
740 try test__floatuntitf(20, 20.0);769 try test_f128_floatFromInt_u128(20, 20.0);
741770
742 try test__floatuntitf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);771 try test_f128_floatFromInt_u128(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
743 try test__floatuntitf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);772 try test_f128_floatFromInt_u128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
744 try test__floatuntitf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);773 try test_f128_floatFromInt_u128(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
745 try test__floatuntitf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);774 try test_f128_floatFromInt_u128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
746 try test__floatuntitf(0x7FFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFEp+59);775 try test_f128_floatFromInt_u128(0x7FFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFEp+59);
747 try test__floatuntitf(0xFFFFFFFFFFFFFFFE, 0xF.FFFFFFFFFFFFFFEp+60);776 try test_f128_floatFromInt_u128(0xFFFFFFFFFFFFFFFE, 0xF.FFFFFFFFFFFFFFEp+60);
748 try test__floatuntitf(0xFFFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFFp+60);777 try test_f128_floatFromInt_u128(0xFFFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFFp+60);
749778
750 try test__floatuntitf(0x8000008000000000, 0x8.000008p+60);779 try test_f128_floatFromInt_u128(0x8000008000000000, 0x8.000008p+60);
751 try test__floatuntitf(0x8000000000000800, 0x8.0000000000008p+60);780 try test_f128_floatFromInt_u128(0x8000000000000800, 0x8.0000000000008p+60);
752 try test__floatuntitf(0x8000010000000000, 0x8.00001p+60);781 try test_f128_floatFromInt_u128(0x8000010000000000, 0x8.00001p+60);
753 try test__floatuntitf(0x8000000000001000, 0x8.000000000001p+60);782 try test_f128_floatFromInt_u128(0x8000000000001000, 0x8.000000000001p+60);
754783
755 try test__floatuntitf(0x8000000000000000, 0x8p+60);784 try test_f128_floatFromInt_u128(0x8000000000000000, 0x8p+60);
756 try test__floatuntitf(0x8000000000000001, 0x8.000000000000001p+60);785 try test_f128_floatFromInt_u128(0x8000000000000001, 0x8.000000000000001p+60);
757786
758 try test__floatuntitf(0x0007FB72E8000000, 0x1.FEDCBAp+50);787 try test_f128_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50);
759788
760 try test__floatuntitf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);789 try test_f128_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
761 try test__floatuntitf(0x0007FB72EB000000, 0x1.FEDCBACp+50);790 try test_f128_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBACp+50);
762 try test__floatuntitf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);791 try test_f128_floatFromInt_u128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
763 try test__floatuntitf(0x0007FB72EC000000, 0x1.FEDCBBp+50);792 try test_f128_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBBp+50);
764 try test__floatuntitf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);793 try test_f128_floatFromInt_u128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
765794
766 try test__floatuntitf(0x0007FB72E6000000, 0x1.FEDCB98p+50);795 try test_f128_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCB98p+50);
767 try test__floatuntitf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);796 try test_f128_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
768 try test__floatuntitf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);797 try test_f128_floatFromInt_u128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
769 try test__floatuntitf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);798 try test_f128_floatFromInt_u128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
770 try test__floatuntitf(0x0007FB72E4000000, 0x1.FEDCB9p+50);799 try test_f128_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB9p+50);
771800
772 try test__floatuntitf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);801 try test_f128_floatFromInt_u128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
773 try test__floatuntitf(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57);802 try test_f128_floatFromInt_u128(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57);
774 try test__floatuntitf(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57);803 try test_f128_floatFromInt_u128(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57);
775 try test__floatuntitf(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57);804 try test_f128_floatFromInt_u128(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57);
776 try test__floatuntitf(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57);805 try test_f128_floatFromInt_u128(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57);
777 try test__floatuntitf(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57);806 try test_f128_floatFromInt_u128(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57);
778 try test__floatuntitf(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57);807 try test_f128_floatFromInt_u128(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57);
779 try test__floatuntitf(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57);808 try test_f128_floatFromInt_u128(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57);
780 try test__floatuntitf(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57);809 try test_f128_floatFromInt_u128(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57);
781 try test__floatuntitf(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57);810 try test_f128_floatFromInt_u128(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57);
782 try test__floatuntitf(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57);811 try test_f128_floatFromInt_u128(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57);
783 try test__floatuntitf(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57);812 try test_f128_floatFromInt_u128(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57);
784 try test__floatuntitf(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57);813 try test_f128_floatFromInt_u128(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57);
785 try test__floatuntitf(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57);814 try test_f128_floatFromInt_u128(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57);
786 try test__floatuntitf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);815 try test_f128_floatFromInt_u128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
787816
788 try test__floatuntitf(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);817 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);
789 try test__floatuntitf(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121);818 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121);
790 try test__floatuntitf(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121);819 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121);
791 try test__floatuntitf(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121);820 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121);
792 try test__floatuntitf(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121);821 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121);
793 try test__floatuntitf(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121);822 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121);
794 try test__floatuntitf(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121);823 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121);
795 try test__floatuntitf(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121);824 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121);
796 try test__floatuntitf(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121);825 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121);
797 try test__floatuntitf(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121);826 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121);
798 try test__floatuntitf(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121);827 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121);
799 try test__floatuntitf(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121);828 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121);
800 try test__floatuntitf(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121);829 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121);
801 try test__floatuntitf(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121);830 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121);
802 try test__floatuntitf(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);831 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);
803832
804 try test__floatuntitf(make_uti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63);833 try test_f128_floatFromInt_u128(make_uti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63);
805834
806 try test__floatuntitf(make_uti(0xFFFFFFFFFFFFFFFF, 0x0000000000000000), 0x1.FFFFFFFFFFFFFFFEp+127);835 try test_f128_floatFromInt_u128(make_uti(0xFFFFFFFFFFFFFFFF, 0x0000000000000000), 0x1.FFFFFFFFFFFFFFFEp+127);
807 try test__floatuntitf(make_uti(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF), 0x1.0000000000000000p+128);836 try test_f128_floatFromInt_u128(make_uti(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF), 0x1.0000000000000000p+128);
808837
809 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124);838 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124);
810 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124);839 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124);
811 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124);840 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124);
812 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124);841 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124);
813 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124);842 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124);
814 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124);843 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124);
815 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124);844 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124);
816 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124);845 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124);
817 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124);846 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124);
818}847}
819848
820fn make_ti(high: u64, low: u64) i128 {849fn make_ti(high: u64, low: u64) i128 {
...@@ -838,45 +867,40 @@ fn make_tf(high: u64, low: u64) f128 {...@@ -838,45 +867,40 @@ fn make_tf(high: u64, low: u64) f128 {
838 return @bitCast(result);867 return @bitCast(result);
839}868}
840869
841test "conversion to f16" {870test f16_floatFromInt_u32 {
842 try testing.expect(__floatunsihf(@as(u32, 0)) == 0.0);871 try testing.expect(f16_floatFromInt_u32(0) == 0.0);
843 try testing.expect(__floatunsihf(@as(u32, 1)) == 1.0);872 try testing.expect(f16_floatFromInt_u32(1) == 1.0);
844 try testing.expect(__floatunsihf(@as(u32, 65504)) == 65504);873 try testing.expect(f16_floatFromInt_u32(65504) == 65504);
845 try testing.expect(__floatunsihf(@as(u32, 65504 + (1 << 4))) == math.inf(f16));874 try testing.expect(f16_floatFromInt_u32(65504 + (1 << 4)) == math.inf(f16));
846}875}
847876
848test "conversion to f32" {877test f80_floatFromInt_u32 {
849 try testing.expect(__floatunsisf(@as(u32, 0)) == 0.0);878 try testing.expect(f80_floatFromInt_u32(0) == 0.0);
850 try testing.expect(__floatunsisf(@as(u32, math.maxInt(u32))) != 1.0);879 try testing.expect(f80_floatFromInt_u32(1) == 1.0);
851 try testing.expect(__floatsisf(@as(i32, math.minInt(i32))) != 1.0);880 try testing.expect(f80_floatFromInt_u32(math.maxInt(u24) + 0) == math.maxInt(u24));
852 try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24))) == math.maxInt(u24));881}
853 try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 1) == math.maxInt(u24) + 1); // 0x100_0000 - Exact882
854 try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 2) == math.maxInt(u24) + 1); // 0x100_0001 - Tie: Rounds down to even883test f80_floatFromInt_u64 {
855 try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 3) == math.maxInt(u24) + 3); // 0x100_0002 - Exact884 try testing.expect(f80_floatFromInt_u64(math.maxInt(u64) + 0) == math.maxInt(u64) + 0);
856 try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 4) == math.maxInt(u24) + 5); // 0x100_0003 - Tie: Rounds up to even885}
857 try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 5) == math.maxInt(u24) + 5); // 0x100_0004 - Exact886
858}887test f80_floatFromInt_i128 {
859888 try testing.expect(f80_floatFromInt_i128(-12) == -12);
860test "conversion to f80" {889}
861 const floatFromInt = @import("./float_from_int.zig").floatFromInt;890
862891test f80_floatFromInt_u128 {
863 try testing.expect(floatFromInt(f80, @as(i80, -12)) == -12);892 try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 1) == math.maxInt(u64) + 1);
864 try testing.expect(@as(u80, @intFromFloat(floatFromInt(f80, @as(u64, math.maxInt(u64)) + 0))) == math.maxInt(u64) + 0);893
865 try testing.expect(@as(u80, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 1))) == math.maxInt(u64) + 1);894 try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 0) == math.maxInt(u64));
866895 try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 1) == math.maxInt(u64) + 1); // Exact
867 try testing.expect(floatFromInt(f80, @as(u32, 0)) == 0.0);896 try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 2) == math.maxInt(u64) + 1); // Rounds down
868 try testing.expect(floatFromInt(f80, @as(u32, 1)) == 1.0);897 try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 3) == math.maxInt(u64) + 3); // Tie - Exact
869 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u32, math.maxInt(u24)) + 0))) == math.maxInt(u24));898 try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 4) == math.maxInt(u64) + 5); // Rounds up
870 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 0))) == math.maxInt(u64));899
871 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 1))) == math.maxInt(u64) + 1); // Exact900 try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 0) == math.maxInt(u65) + 1); // Rounds up
872 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 2))) == math.maxInt(u64) + 1); // Rounds down901 try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 1) == math.maxInt(u65) + 1); // Exact
873 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 3))) == math.maxInt(u64) + 3); // Tie - Exact902 try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 2) == math.maxInt(u65) + 1); // Rounds down
874 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 4))) == math.maxInt(u64) + 5); // Rounds up903 try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 3) == math.maxInt(u65) + 1); // Tie - Rounds down
875904 try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 4) == math.maxInt(u65) + 5); // Rounds up
876 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 0))) == math.maxInt(u65) + 1); // Rounds up905 try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 5) == math.maxInt(u65) + 5); // Exact
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
882}906}
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;...@@ -15,7 +15,7 @@ const mem = std.mem;
15const expect = std.testing.expect;15const expect = std.testing.expect;
1616
17const compiler_rt = @import("../compiler_rt.zig");17const compiler_rt = @import("../compiler_rt.zig");
18const symbol = @import("../compiler_rt.zig").symbol;18const symbol = compiler_rt.symbol;
1919
20comptime {20comptime {
21 // floor21 // floor
...@@ -23,10 +23,7 @@ comptime {...@@ -23,10 +23,7 @@ comptime {
23 symbol(&floorf, "floorf");23 symbol(&floorf, "floorf");
24 symbol(&floor, "floor");24 symbol(&floor, "floor");
25 symbol(&__floorx, "__floorx");25 symbol(&__floorx, "__floorx");
26 if (compiler_rt.want_ppc_abi) {26 symbol(&floorq, "floorf128");
27 symbol(&floorq, "floorf128");
28 }
29 symbol(&floorq, "floorq");
30 symbol(&floorl, "floorl");27 symbol(&floorl, "floorl");
3128
32 // ceil29 // ceil
...@@ -34,59 +31,96 @@ comptime {...@@ -34,59 +31,96 @@ comptime {
34 symbol(&ceilf, "ceilf");31 symbol(&ceilf, "ceilf");
35 symbol(&ceil, "ceil");32 symbol(&ceil, "ceil");
36 symbol(&__ceilx, "__ceilx");33 symbol(&__ceilx, "__ceilx");
37 if (compiler_rt.want_ppc_abi) {34 symbol(&ceilq, "ceilf128");
38 symbol(&ceilq, "ceilf128");
39 }
40 symbol(&ceilq, "ceilq");
41 symbol(&ceill, "ceill");35 symbol(&ceill, "ceill");
42}36}
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 {
45 return impl(f16, .floor, x);42 return impl(f16, .floor, x);
46}43}
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 {
49 return impl(f32, .floor, x);49 return impl(f32, .floor, x);
50}50}
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 {
53 return impl(f64, .floor, x);56 return impl(f64, .floor, x);
54}57}
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 {
57 return impl(f80, .floor, x);63 return impl(f80, .floor, x);
58}64}
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 {
61 return impl(f128, .floor, x);70 return impl(f128, .floor, x);
62}71}
6372
64pub fn floorl(x: c_longdouble) callconv(.c) c_longdouble {73pub 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 }
66}80}
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 {
69 return impl(f16, .ceil, x);86 return impl(f16, .ceil, x);
70}87}
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 {
73 return impl(f32, .ceil, x);93 return impl(f32, .ceil, x);
74}94}
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 {
77 return impl(f64, .ceil, x);100 return impl(f64, .ceil, x);
78}101}
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 {
81 return impl(f80, .ceil, x);107 return impl(f80, .ceil, x);
82}108}
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 {
85 return impl(f128, .ceil, x);114 return impl(f128, .ceil, x);
86}115}
87116
88pub fn ceill(x: c_longdouble) callconv(.c) c_longdouble {117pub 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 }
90}124}
91125
92inline fn impl(comptime T: type, comptime op: enum { floor, ceil }, x: T) T {126inline 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 {...@@ -144,142 +178,122 @@ inline fn impl(comptime T: type, comptime op: enum { floor, ceil }, x: T) T {
144 }178 }
145}179}
146180
147test "floor16" {181test floor_f16 {
148 try expect(__floorh(1.3) == 1.0);182 try expect(floor_f16(1.3) == 1.0);
149 try expect(__floorh(-1.3) == -2.0);183 try expect(floor_f16(-1.3) == -2.0);
150 try expect(__floorh(0.2) == 0.0);184 try expect(floor_f16(-0.2) == -1.0);
151}185 try expect(math.isPositiveZero(floor_f16(0.2)));
152186 try expect(math.isPositiveZero(floor_f16(0.0)));
153test "floor32" {187 try expect(math.isNegativeZero(floor_f16(-0.0)));
154 try expect(floorf(1.3) == 1.0);188 try expect(math.isPositiveInf(floor_f16(math.inf(f16))));
155 try expect(floorf(-1.3) == -2.0);189 try expect(math.isNegativeInf(floor_f16(-math.inf(f16))));
156 try expect(floorf(0.2) == 0.0);190 try expect(math.isNan(floor_f16(math.nan(f16))));
157}191}
158192
159test "floor64" {193test floor_f32 {
160 try expect(floor(1.3) == 1.0);194 try expect(floor_f32(1.3) == 1.0);
161 try expect(floor(-1.3) == -2.0);195 try expect(floor_f32(-1.3) == -2.0);
162 try expect(floor(0.2) == 0.0);196 try expect(floor_f32(-0.2) == -1.0);
163}197 try expect(math.isPositiveZero(floor_f32(0.2)));
164198 try expect(math.isPositiveZero(floor_f32(0.0)));
165test "floor80" {199 try expect(math.isNegativeZero(floor_f32(-0.0)));
166 try expect(__floorx(1.3) == 1.0);200 try expect(math.isPositiveInf(floor_f32(math.inf(f32))));
167 try expect(__floorx(-1.3) == -2.0);201 try expect(math.isNegativeInf(floor_f32(-math.inf(f32))));
168 try expect(__floorx(0.2) == 0.0);202 try expect(math.isNan(floor_f32(math.nan(f32))));
169}203}
170204
171test "floor128" {205test floor_f64 {
172 try expect(floorq(1.3) == 1.0);206 try expect(floor_f64(1.3) == 1.0);
173 try expect(floorq(-1.3) == -2.0);207 try expect(floor_f64(-1.3) == -2.0);
174 try expect(floorq(0.2) == 0.0);208 try expect(floor_f64(-0.2) == -1.0);
175}209 try expect(math.isPositiveZero(floor_f64(0.2)));
176210 try expect(math.isPositiveZero(floor_f64(0.0)));
177test "floor16.special" {211 try expect(math.isNegativeZero(floor_f64(-0.0)));
178 try expect(__floorh(0.0) == 0.0);212 try expect(math.isPositiveInf(floor_f64(math.inf(f64))));
179 try expect(__floorh(-0.0) == -0.0);213 try expect(math.isNegativeInf(floor_f64(-math.inf(f64))));
180 try expect(math.isPositiveInf(__floorh(math.inf(f16))));214 try expect(math.isNan(floor_f64(math.nan(f64))));
181 try expect(math.isNegativeInf(__floorh(-math.inf(f16))));215}
182 try expect(math.isNan(__floorh(math.nan(f16))));216
183}217test floor_f80 {
184218 try expect(floor_f80(1.3) == 1.0);
185test "floor32.special" {219 try expect(floor_f80(-1.3) == -2.0);
186 try expect(floorf(0.0) == 0.0);220 try expect(floor_f80(-0.2) == -1.0);
187 try expect(floorf(-0.0) == -0.0);221 try expect(math.isPositiveZero(floor_f80(0.2)));
188 try expect(math.isPositiveInf(floorf(math.inf(f32))));222 try expect(math.isPositiveZero(floor_f80(0.0)));
189 try expect(math.isNegativeInf(floorf(-math.inf(f32))));223 try expect(math.isNegativeZero(floor_f80(-0.0)));
190 try expect(math.isNan(floorf(math.nan(f32))));224 try expect(math.isPositiveInf(floor_f80(math.inf(f80))));
191}225 try expect(math.isNegativeInf(floor_f80(-math.inf(f80))));
192226 try expect(math.isNan(floor_f80(math.nan(f80))));
193test "floor64.special" {227}
194 try expect(floor(0.0) == 0.0);228
195 try expect(floor(-0.0) == -0.0);229test floor_f128 {
196 try expect(math.isPositiveInf(floor(math.inf(f64))));230 try expect(floor_f128(1.3) == 1.0);
197 try expect(math.isNegativeInf(floor(-math.inf(f64))));231 try expect(floor_f128(-1.3) == -2.0);
198 try expect(math.isNan(floor(math.nan(f64))));232 try expect(floor_f128(-0.2) == -1.0);
199}233 try expect(math.isPositiveZero(floor_f128(0.2)));
200234 try expect(math.isPositiveZero(floor_f128(0.0)));
201test "floor80.special" {235 try expect(math.isNegativeZero(floor_f128(-0.0)));
202 try expect(__floorx(0.0) == 0.0);236 try expect(math.isPositiveInf(floor_f128(math.inf(f128))));
203 try expect(__floorx(-0.0) == -0.0);237 try expect(math.isNegativeInf(floor_f128(-math.inf(f128))));
204 try expect(math.isPositiveInf(__floorx(math.inf(f80))));238 try expect(math.isNan(floor_f128(math.nan(f128))));
205 try expect(math.isNegativeInf(__floorx(-math.inf(f80))));239}
206 try expect(math.isNan(__floorx(math.nan(f80))));240
207}241test ceil_f16 {
208242 try expect(ceil_f16(1.3) == 2.0);
209test "floor128.special" {243 try expect(ceil_f16(-1.3) == -1.0);
210 try expect(floorq(0.0) == 0.0);244 try expect(ceil_f16(0.2) == 1.0);
211 try expect(floorq(-0.0) == -0.0);245 try expect(math.isNegativeZero(ceil_f16(-0.2)));
212 try expect(math.isPositiveInf(floorq(math.inf(f128))));246 try expect(math.isPositiveZero(ceil_f16(0.0)));
213 try expect(math.isNegativeInf(floorq(-math.inf(f128))));247 try expect(math.isNegativeZero(ceil_f16(-0.0)));
214 try expect(math.isNan(floorq(math.nan(f128))));248 try expect(math.isPositiveInf(ceil_f16(math.inf(f16))));
215}249 try expect(math.isNegativeInf(ceil_f16(-math.inf(f16))));
216250 try expect(math.isNan(ceil_f16(math.nan(f16))));
217test "ceil16" {251}
218 try expect(__ceilh(1.3) == 2.0);252
219 try expect(__ceilh(-1.3) == -1.0);253test ceil_f32 {
220 try expect(__ceilh(0.2) == 1.0);254 try expect(ceil_f32(1.3) == 2.0);
221}255 try expect(ceil_f32(-1.3) == -1.0);
222256 try expect(ceil_f32(0.2) == 1.0);
223test "ceil32" {257 try expect(math.isNegativeZero(ceil_f32(-0.2)));
224 try expect(ceilf(1.3) == 2.0);258 try expect(math.isPositiveZero(ceil_f32(0.0)));
225 try expect(ceilf(-1.3) == -1.0);259 try expect(math.isNegativeZero(ceil_f32(-0.0)));
226 try expect(ceilf(0.2) == 1.0);260 try expect(math.isPositiveInf(ceil_f32(math.inf(f32))));
227}261 try expect(math.isNegativeInf(ceil_f32(-math.inf(f32))));
228262 try expect(math.isNan(ceil_f32(math.nan(f32))));
229test "ceil64" {263}
230 try expect(ceil(1.3) == 2.0);264
231 try expect(ceil(-1.3) == -1.0);265test ceil_f64 {
232 try expect(ceil(0.2) == 1.0);266 try expect(ceil_f64(1.3) == 2.0);
233}267 try expect(ceil_f64(-1.3) == -1.0);
234268 try expect(ceil_f64(0.2) == 1.0);
235test "ceil80" {269 try expect(math.isNegativeZero(ceil_f64(-0.2)));
236 try expect(__ceilx(1.3) == 2.0);270 try expect(math.isPositiveZero(ceil_f64(0.0)));
237 try expect(__ceilx(-1.3) == -1.0);271 try expect(math.isNegativeZero(ceil_f64(-0.0)));
238 try expect(__ceilx(0.2) == 1.0);272 try expect(math.isPositiveInf(ceil_f64(math.inf(f64))));
239}273 try expect(math.isNegativeInf(ceil_f64(-math.inf(f64))));
240274 try expect(math.isNan(ceil_f64(math.nan(f64))));
241test "ceil128" {275}
242 try expect(ceilq(1.3) == 2.0);276
243 try expect(ceilq(-1.3) == -1.0);277test ceil_f80 {
244 try expect(ceilq(0.2) == 1.0);278 try expect(ceil_f80(1.3) == 2.0);
245}279 try expect(ceil_f80(-1.3) == -1.0);
246280 try expect(ceil_f80(0.2) == 1.0);
247test "ceil16.special" {281 try expect(math.isNegativeZero(ceil_f80(-0.2)));
248 try expect(__ceilh(0.0) == 0.0);282 try expect(math.isPositiveZero(ceil_f80(0.0)));
249 try expect(__ceilh(-0.0) == -0.0);283 try expect(math.isNegativeZero(ceil_f80(-0.0)));
250 try expect(math.isPositiveInf(__ceilh(math.inf(f16))));284 try expect(math.isPositiveInf(ceil_f80(math.inf(f80))));
251 try expect(math.isNegativeInf(__ceilh(-math.inf(f16))));285 try expect(math.isNegativeInf(ceil_f80(-math.inf(f80))));
252 try expect(math.isNan(__ceilh(math.nan(f16))));286 try expect(math.isNan(ceil_f80(math.nan(f80))));
253}287}
254288
255test "ceil32.special" {289test ceil_f128 {
256 try expect(ceilf(0.0) == 0.0);290 try expect(ceil_f128(1.3) == 2.0);
257 try expect(ceilf(-0.0) == -0.0);291 try expect(ceil_f128(-1.3) == -1.0);
258 try expect(math.isPositiveInf(ceilf(math.inf(f32))));292 try expect(ceil_f128(0.2) == 1.0);
259 try expect(math.isNegativeInf(ceilf(-math.inf(f32))));293 try expect(math.isNegativeZero(ceil_f128(-0.2)));
260 try expect(math.isNan(ceilf(math.nan(f32))));294 try expect(math.isPositiveZero(ceil_f128(0.0)));
261}295 try expect(math.isNegativeZero(ceil_f128(-0.0)));
262296 try expect(math.isPositiveInf(ceil_f128(math.inf(f128))));
263test "ceil64.special" {297 try expect(math.isNegativeInf(ceil_f128(-math.inf(f128))));
264 try expect(ceil(0.0) == 0.0);298 try expect(math.isNan(ceil_f128(math.nan(f128))));
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))));
285}299}
lib/compiler_rt/fma.zig+48-36
...@@ -16,19 +16,22 @@ comptime {...@@ -16,19 +16,22 @@ comptime {
16 symbol(&fmaf, "fmaf");16 symbol(&fmaf, "fmaf");
17 symbol(&fma, "fma");17 symbol(&fma, "fma");
18 symbol(&__fmax, "__fmax");18 symbol(&__fmax, "__fmax");
19 if (compiler_rt.want_ppc_abi) {19 symbol(&fmaq, "fmaf128");
20 symbol(&fmaq, "fmaf128");
21 }
22 symbol(&fmaq, "fmaq");
23 symbol(&fmal, "fmal");20 symbol(&fmal, "fmal");
24}21}
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 {
27 // TODO: more efficient implementation27 // TODO: more efficient implementation
28 return @floatCast(fmaf(x, y, z));28 return @floatCast(fma_f32(x, y, z));
29}29}
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 {
32 const xy = @as(f64, x) * y;35 const xy = @as(f64, x) * y;
33 const xy_z = xy + z;36 const xy_z = xy + z;
34 const u = @as(u64, @bitCast(xy_z));37 const u = @as(u64, @bitCast(xy_z));
...@@ -42,8 +45,11 @@ pub fn fmaf(x: f32, y: f32, z: f32) callconv(.c) f32 {...@@ -42,8 +45,11 @@ pub fn fmaf(x: f32, y: f32, z: f32) callconv(.c) f32 {
42 }45 }
43}46}
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}
45/// NOTE: Upstream fma.c has been rewritten completely to raise fp exceptions more accurately.51/// 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 {
47 if (!math.isFinite(x) or !math.isFinite(y)) {53 if (!math.isFinite(x) or !math.isFinite(y)) {
48 return x * y + z;54 return x * y + z;
49 }55 }
...@@ -90,11 +96,17 @@ pub fn fma(x: f64, y: f64, z: f64) callconv(.c) f64 {...@@ -90,11 +96,17 @@ pub fn fma(x: f64, y: f64, z: f64) callconv(.c) f64 {
90 }96 }
91}97}
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 {
94 // TODO: more efficient implementation103 // TODO: more efficient implementation
95 return @floatCast(fmaq(a, b, c));104 return @floatCast(fma_f128(a, b, c));
96}105}
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}
98/// Fused multiply-add: Compute x * y + z with a single rounding error.110/// Fused multiply-add: Compute x * y + z with a single rounding error.
99///111///
100/// We use scaling to avoid overflow/underflow, along with the112/// 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 {...@@ -102,7 +114,7 @@ pub fn __fmax(a: f80, b: f80, c: f80) callconv(.c) f80 {
102///114///
103/// Dekker, T. A Floating-Point Technique for Extending the115/// Dekker, T. A Floating-Point Technique for Extending the
104/// Available Precision. Numer. Math. 18, 224-242 (1971).116/// 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 {
106 if (!math.isFinite(x) or !math.isFinite(y)) {118 if (!math.isFinite(x) or !math.isFinite(y)) {
107 return x * y + z;119 return x * y + z;
108 }120 }
...@@ -151,10 +163,10 @@ pub fn fmaq(x: f128, y: f128, z: f128) callconv(.c) f128 {...@@ -151,10 +163,10 @@ pub fn fmaq(x: f128, y: f128, z: f128) callconv(.c) f128 {
151163
152pub fn fmal(x: c_longdouble, y: c_longdouble, z: c_longdouble) callconv(.c) c_longdouble {164pub fn fmal(x: c_longdouble, y: c_longdouble, z: c_longdouble) callconv(.c) c_longdouble {
153 switch (@typeInfo(c_longdouble).float.bits) {165 switch (@typeInfo(c_longdouble).float.bits) {
154 64 => return fma(x, y, z),166 64 => return fma_f64(x, y, z),
155 80 => return __fmax(x, y, z),167 80 => return fma_f80(x, y, z),
156 128 => return fmaq(x, y, z),168 128 => return fma_f128(x, y, z),
157 else => @compileError("unreachable"),169 else => comptime unreachable,
158 }170 }
159}171}
160172
...@@ -316,35 +328,35 @@ fn dd_mul128(a: f128, b: f128) dd128 {...@@ -316,35 +328,35 @@ fn dd_mul128(a: f128, b: f128) dd128 {
316test "32" {328test "32" {
317 const epsilon = 0.000001;329 const epsilon = 0.000001;
318330
319 try expect(math.approxEqAbs(f32, fmaf(0.0, 5.0, 9.124), 9.124, epsilon));331 try expect(math.approxEqAbs(f32, fma_f32(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));332 try expect(math.approxEqAbs(f32, fma_f32(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));333 try expect(math.approxEqAbs(f32, fma_f32(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));334 try expect(math.approxEqAbs(f32, fma_f32(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));335 try expect(math.approxEqAbs(f32, fma_f32(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));336 try expect(math.approxEqAbs(f32, fma_f32(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));337 try expect(math.approxEqAbs(f32, fma_f32(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
326}338}
327339
328test "64" {340test "64" {
329 const epsilon = 0.000001;341 const epsilon = 0.000001;
330342
331 try expect(math.approxEqAbs(f64, fma(0.0, 5.0, 9.124), 9.124, epsilon));343 try expect(math.approxEqAbs(f64, fma_f64(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));344 try expect(math.approxEqAbs(f64, fma_f64(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));345 try expect(math.approxEqAbs(f64, fma_f64(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));346 try expect(math.approxEqAbs(f64, fma_f64(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));347 try expect(math.approxEqAbs(f64, fma_f64(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));348 try expect(math.approxEqAbs(f64, fma_f64(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));349 try expect(math.approxEqAbs(f64, fma_f64(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
338}350}
339351
340test "128" {352test "128" {
341 const epsilon = 0.000001;353 const epsilon = 0.000001;
342354
343 try expect(math.approxEqAbs(f128, fmaq(0.0, 5.0, 9.124), 9.124, epsilon));355 try expect(math.approxEqAbs(f128, fma_f128(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));356 try expect(math.approxEqAbs(f128, fma_f128(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));357 try expect(math.approxEqAbs(f128, fma_f128(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));358 try expect(math.approxEqAbs(f128, fma_f128(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));359 try expect(math.approxEqAbs(f128, fma_f128(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));360 try expect(math.approxEqAbs(f128, fma_f128(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));361 try expect(math.approxEqAbs(f128, fma_f128(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
350}362}
lib/compiler_rt/fmax.zig+25-13
...@@ -10,39 +10,51 @@ comptime {...@@ -10,39 +10,51 @@ comptime {
10 symbol(&fmaxf, "fmaxf");10 symbol(&fmaxf, "fmaxf");
11 symbol(&fmax, "fmax");11 symbol(&fmax, "fmax");
12 symbol(&__fmaxx, "__fmaxx");12 symbol(&__fmaxx, "__fmaxx");
13 if (compiler_rt.want_ppc_abi) {13 symbol(&fmaxq, "fmaxf128");
14 symbol(&fmaxq, "fmaxf128");
15 }
16 symbol(&fmaxq, "fmaxq");
17 symbol(&fmaxl, "fmaxl");14 symbol(&fmaxl, "fmaxl");
18}15}
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 {
21 return generic_fmax(f16, x, y);21 return generic_fmax(f16, x, y);
22}22}
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 {
25 return generic_fmax(f32, x, y);28 return generic_fmax(f32, x, y);
26}29}
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 {
29 return generic_fmax(f64, x, y);35 return generic_fmax(f64, x, y);
30}36}
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 {
33 return generic_fmax(f80, x, y);42 return generic_fmax(f80, x, y);
34}43}
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 {
37 return generic_fmax(f128, x, y);49 return generic_fmax(f128, x, y);
38}50}
3951
40pub fn fmaxl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble {52pub fn fmaxl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble {
41 switch (@typeInfo(c_longdouble).float.bits) {53 switch (@typeInfo(c_longdouble).float.bits) {
42 64 => return fmax(x, y),54 64 => return fmax_f64(x, y),
43 80 => return __fmaxx(x, y),55 80 => return fmax_f80(x, y),
44 128 => return fmaxq(x, y),56 128 => return fmax_f128(x, y),
45 else => @compileError("unreachable"),57 else => comptime unreachable,
46 }58 }
47}59}
4860
lib/compiler_rt/fmin.zig+25-13
...@@ -10,39 +10,51 @@ comptime {...@@ -10,39 +10,51 @@ comptime {
10 symbol(&fminf, "fminf");10 symbol(&fminf, "fminf");
11 symbol(&fmin, "fmin");11 symbol(&fmin, "fmin");
12 symbol(&__fminx, "__fminx");12 symbol(&__fminx, "__fminx");
13 if (compiler_rt.want_ppc_abi) {13 symbol(&fminq, "fminf128");
14 symbol(&fminq, "fminf128");
15 }
16 symbol(&fminq, "fminq");
17 symbol(&fminl, "fminl");14 symbol(&fminl, "fminl");
18}15}
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 {
21 return generic_fmin(f16, x, y);21 return generic_fmin(f16, x, y);
22}22}
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 {
25 return generic_fmin(f32, x, y);28 return generic_fmin(f32, x, y);
26}29}
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 {
29 return generic_fmin(f64, x, y);35 return generic_fmin(f64, x, y);
30}36}
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 {
33 return generic_fmin(f80, x, y);42 return generic_fmin(f80, x, y);
34}43}
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 {
37 return generic_fmin(f128, x, y);49 return generic_fmin(f128, x, y);
38}50}
3951
40pub fn fminl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble {52pub fn fminl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble {
41 switch (@typeInfo(c_longdouble).float.bits) {53 switch (@typeInfo(c_longdouble).float.bits) {
42 64 => return fmin(x, y),54 64 => return fmin_f64(x, y),
43 80 => return __fminx(x, y),55 80 => return fmin_f80(x, y),
44 128 => return fminq(x, y),56 128 => return fmin_f128(x, y),
45 else => @compileError("unreachable"),57 else => comptime unreachable,
46 }58 }
47}59}
4860
lib/compiler_rt/fmod.zig+50-38
...@@ -12,29 +12,38 @@ comptime {...@@ -12,29 +12,38 @@ comptime {
12 symbol(&fmodf, "fmodf");12 symbol(&fmodf, "fmodf");
13 symbol(&fmod, "fmod");13 symbol(&fmod, "fmod");
14 symbol(&__fmodx, "__fmodx");14 symbol(&__fmodx, "__fmodx");
15 if (compiler_rt.want_ppc_abi) {15 symbol(&fmodq, "fmodf128");
16 symbol(&fmodq, "fmodf128");
17 }
18 symbol(&fmodq, "fmodq");
19 symbol(&fmodl, "fmodl");16 symbol(&fmodl, "fmodl");
20}17}
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 {
23 // TODO: more efficient implementation23 // TODO: more efficient implementation
24 return @floatCast(fmodf(x, y));24 return @floatCast(fmod_f32(x, y));
25}25}
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 {
28 return generic_fmod(f32, x, y);31 return generic_fmod(f32, x, y);
29}32}
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 {
32 return generic_fmod(f64, x, y);38 return generic_fmod(f64, x, y);
33}39}
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}
35/// fmodx - floating modulo large, returns the remainder of division for f80 types44/// fmodx - floating modulo large, returns the remainder of division for f80 types
36/// Logic and flow heavily inspired by MUSL fmodl for 113 mantissa digits45/// 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 {
38 const T = f80;47 const T = f80;
39 const Z = @Int(.unsigned, @bitSizeOf(T));48 const Z = @Int(.unsigned, @bitSizeOf(T));
4049
...@@ -130,9 +139,12 @@ pub fn __fmodx(a: f80, b: f80) callconv(.c) f80 {...@@ -130,9 +139,12 @@ pub fn __fmodx(a: f80, b: f80) callconv(.c) f80 {
130 }139 }
131}140}
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}
133/// fmodq - floating modulo large, returns the remainder of division for f128 types145/// fmodq - floating modulo large, returns the remainder of division for f128 types
134/// Logic and flow heavily inspired by MUSL fmodl for 113 mantissa digits146/// 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 {
136 var amod = a;148 var amod = a;
137 var bmod = b;149 var bmod = b;
138 const aPtr_u64: [*]u64 = @ptrCast(&amod);150 const aPtr_u64: [*]u64 = @ptrCast(&amod);
...@@ -251,10 +263,10 @@ pub fn fmodq(a: f128, b: f128) callconv(.c) f128 {...@@ -251,10 +263,10 @@ pub fn fmodq(a: f128, b: f128) callconv(.c) f128 {
251263
252pub fn fmodl(a: c_longdouble, b: c_longdouble) callconv(.c) c_longdouble {264pub fn fmodl(a: c_longdouble, b: c_longdouble) callconv(.c) c_longdouble {
253 switch (@typeInfo(c_longdouble).float.bits) {265 switch (@typeInfo(c_longdouble).float.bits) {
254 64 => return fmod(a, b),266 64 => return fmod_f64(a, b),
255 80 => return __fmodx(a, b),267 80 => return fmod_f80(a, b),
256 128 => return fmodq(a, b),268 128 => return fmod_f128(a, b),
257 else => @compileError("unreachable"),269 else => comptime unreachable,
258 }270 }
259}271}
260272
...@@ -342,42 +354,42 @@ inline fn generic_fmod(comptime T: type, x: T, y: T) T {...@@ -342,42 +354,42 @@ inline fn generic_fmod(comptime T: type, x: T, y: T) T {
342 return @bitCast(ux);354 return @bitCast(ux);
343}355}
344356
345test "fmodf" {357test fmod_f32 {
346 const nan_val = math.nan(f32);358 const nan_val = math.nan(f32);
347 const inf_val = math.inf(f32);359 const inf_val = math.inf(f32);
348360
349 try std.testing.expect(math.isNan(fmodf(nan_val, 1.0)));361 try std.testing.expect(math.isNan(fmod_f32(nan_val, 1.0)));
350 try std.testing.expect(math.isNan(fmodf(1.0, nan_val)));362 try std.testing.expect(math.isNan(fmod_f32(1.0, nan_val)));
351 try std.testing.expect(math.isNan(fmodf(inf_val, 1.0)));363 try std.testing.expect(math.isNan(fmod_f32(inf_val, 1.0)));
352 try std.testing.expect(math.isNan(fmodf(0.0, 0.0)));364 try std.testing.expect(math.isNan(fmod_f32(0.0, 0.0)));
353 try std.testing.expect(math.isNan(fmodf(1.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));367 try std.testing.expectEqual(@as(f32, 0.0), fmod_f32(0.0, 2.0));
356 try std.testing.expectEqual(@as(f32, -0.0), fmodf(-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));370 try std.testing.expectEqual(@as(f32, -2.0), fmod_f32(-32.0, 10.0));
359 try std.testing.expectEqual(@as(f32, -2.0), fmodf(-32.0, -10.0));371 try std.testing.expectEqual(@as(f32, -2.0), fmod_f32(-32.0, -10.0));
360 try std.testing.expectEqual(@as(f32, 2.0), fmodf(32.0, 10.0));372 try std.testing.expectEqual(@as(f32, 2.0), fmod_f32(32.0, 10.0));
361 try std.testing.expectEqual(@as(f32, 2.0), fmodf(32.0, -10.0));373 try std.testing.expectEqual(@as(f32, 2.0), fmod_f32(32.0, -10.0));
362}374}
363375
364test "fmod" {376test fmod_f64 {
365 const nan_val = math.nan(f64);377 const nan_val = math.nan(f64);
366 const inf_val = math.inf(f64);378 const inf_val = math.inf(f64);
367379
368 try std.testing.expect(math.isNan(fmod(nan_val, 1.0)));380 try std.testing.expect(math.isNan(fmod_f64(nan_val, 1.0)));
369 try std.testing.expect(math.isNan(fmod(1.0, nan_val)));381 try std.testing.expect(math.isNan(fmod_f64(1.0, nan_val)));
370 try std.testing.expect(math.isNan(fmod(inf_val, 1.0)));382 try std.testing.expect(math.isNan(fmod_f64(inf_val, 1.0)));
371 try std.testing.expect(math.isNan(fmod(0.0, 0.0)));383 try std.testing.expect(math.isNan(fmod_f64(0.0, 0.0)));
372 try std.testing.expect(math.isNan(fmod(1.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));386 try std.testing.expectEqual(@as(f64, 0.0), fmod_f64(0.0, 2.0));
375 try std.testing.expectEqual(@as(f64, -0.0), fmod(-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));389 try std.testing.expectEqual(@as(f64, -2.0), fmod_f64(-32.0, 10.0));
378 try std.testing.expectEqual(@as(f64, -2.0), fmod(-32.0, -10.0));390 try std.testing.expectEqual(@as(f64, -2.0), fmod_f64(-32.0, -10.0));
379 try std.testing.expectEqual(@as(f64, 2.0), fmod(32.0, 10.0));391 try std.testing.expectEqual(@as(f64, 2.0), fmod_f64(32.0, 10.0));
380 try std.testing.expectEqual(@as(f64, 2.0), fmod(32.0, -10.0));392 try std.testing.expectEqual(@as(f64, 2.0), fmod_f64(32.0, -10.0));
381}393}
382394
383test {395test {
lib/compiler_rt/fmodq_test.zig+32-32
...@@ -1,52 +1,52 @@...@@ -1,52 +1,52 @@
1const std = @import("std");1const std = @import("std");
2const fmod = @import("fmod.zig");2const fmod_f128 = @import("fmod.zig").fmod_f128;
3const testing = std.testing;3const testing = std.testing;
44
5fn test_fmodq(a: f128, b: f128, exp: f128) !void {5fn test_fmod_f128(a: f128, b: f128, exp: f128) !void {
6 const res = fmod.fmodq(a, b);6 const res = fmod_f128(a, b);
7 try testing.expect(exp == res);7 try testing.expect(exp == res);
8}8}
99
10fn test_fmodq_nans() !void {10fn test_fmod_f128_nans() !void {
11 try testing.expect(std.math.isNan(fmod.fmodq(1.0, std.math.nan(f128))));11 try testing.expect(std.math.isNan(fmod_f128(1.0, std.math.nan(f128))));
12 try testing.expect(std.math.isNan(fmod.fmodq(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.fmodq(std.math.nan(f128), 1.0)));13 try testing.expect(std.math.isNan(fmod_f128(std.math.nan(f128), 1.0)));
14 try testing.expect(std.math.isNan(fmod.fmodq(-std.math.nan(f128), 1.0)));14 try testing.expect(std.math.isNan(fmod_f128(-std.math.nan(f128), 1.0)));
15}15}
1616
17fn test_fmodq_infs() !void {17fn test_fmod_f128_infs() !void {
18 try testing.expect(fmod.fmodq(1.0, std.math.inf(f128)) == 1.0);18 try testing.expect(fmod_f128(1.0, std.math.inf(f128)) == 1.0);
19 try testing.expect(fmod.fmodq(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.fmodq(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.fmodq(-std.math.inf(f128), 1.0)));21 try testing.expect(std.math.isNan(fmod_f128(-std.math.inf(f128), 1.0)));
22}22}
2323
24test "fmodq" {24test fmod_f128 {
25 try test_fmodq(6.8, 4.0, 2.8);25 try test_fmod_f128(6.8, 4.0, 2.8);
26 try test_fmodq(6.8, -4.0, 2.8);26 try test_fmod_f128(6.8, -4.0, 2.8);
27 try test_fmodq(-6.8, 4.0, -2.8);27 try test_fmod_f128(-6.8, 4.0, -2.8);
28 try test_fmodq(-6.8, -4.0, -2.8);28 try test_fmod_f128(-6.8, -4.0, -2.8);
29 try test_fmodq(3.0, 2.0, 1.0);29 try test_fmod_f128(3.0, 2.0, 1.0);
30 try test_fmodq(-5.0, 3.0, -2.0);30 try test_fmod_f128(-5.0, 3.0, -2.0);
31 try test_fmodq(3.0, 2.0, 1.0);31 try test_fmod_f128(3.0, 2.0, 1.0);
32 try test_fmodq(1.0, 2.0, 1.0);32 try test_fmod_f128(1.0, 2.0, 1.0);
33 try test_fmodq(0.0, 1.0, 0.0);33 try test_fmod_f128(0.0, 1.0, 0.0);
34 try test_fmodq(-0.0, 1.0, -0.0);34 try test_fmod_f128(-0.0, 1.0, -0.0);
35 try test_fmodq(7046119.0, 5558362.0, 1487757.0);35 try test_fmod_f128(7046119.0, 5558362.0, 1487757.0);
36 try test_fmodq(9010357.0, 1957236.0, 1181413.0);36 try test_fmod_f128(9010357.0, 1957236.0, 1181413.0);
37 try test_fmodq(5192296858534827628530496329220095, 10.0, 5.0);37 try test_fmod_f128(5192296858534827628530496329220095, 10.0, 5.0);
38 try test_fmodq(5192296858534827628530496329220095, 922337203681230954775807, 220474884073715748246157);38 try test_fmod_f128(5192296858534827628530496329220095, 922337203681230954775807, 220474884073715748246157);
3939
40 // Denormals40 // Denormals
41 const a1: f128 = 0xedcb34a235253948765432134674p-16494;41 const a1: f128 = 0xedcb34a235253948765432134674p-16494;
42 const b1: f128 = 0x5d2e38791cfbc0737402da5a9518p-16494;42 const b1: f128 = 0x5d2e38791cfbc0737402da5a9518p-16494;
43 const exp1: f128 = 0x336ec3affb2db8618e4e7d5e1c44p-16494;43 const exp1: f128 = 0x336ec3affb2db8618e4e7d5e1c44p-16494;
44 try test_fmodq(a1, b1, exp1);44 try test_fmod_f128(a1, b1, exp1);
45 const a2: f128 = 0x0.7654_3210_fdec_ba98_7654_3210_fdecp-16382;45 const a2: f128 = 0x0.7654_3210_fdec_ba98_7654_3210_fdecp-16382;
46 const b2: f128 = 0x0.0012_fdac_bdef_1234_fdec_3222_1111p-16382;46 const b2: f128 = 0x0.0012_fdac_bdef_1234_fdec_3222_1111p-16382;
47 const exp2: f128 = 0x0.0001_aecd_9d66_4a6e_67b7_d7d0_a901p-16382;47 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();50 try test_fmod_f128_nans();
51 try test_fmodq_infs();51 try test_fmod_f128_infs();
52}52}
lib/compiler_rt/fmodx_test.zig+31-31
...@@ -1,52 +1,52 @@...@@ -1,52 +1,52 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const fmod = @import("fmod.zig");3const fmod_f80 = @import("fmod.zig").fmod_f80;
4const testing = std.testing;4const testing = std.testing;
55
6fn test_fmodx(a: f80, b: f80, exp: f80) !void {6fn test_fmod_f80(a: f80, b: f80, exp: f80) !void {
7 const res = fmod.__fmodx(a, b);7 const res = fmod_f80(a, b);
8 try testing.expect(exp == res);8 try testing.expect(exp == res);
9}9}
1010
11fn test_fmodx_nans() !void {11fn test_fmod_f80_nans() !void {
12 try testing.expect(std.math.isNan(fmod.__fmodx(1.0, std.math.nan(f80))));12 try testing.expect(std.math.isNan(fmod_f80(1.0, std.math.nan(f80))));
13 try testing.expect(std.math.isNan(fmod.__fmodx(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.__fmodx(std.math.nan(f80), 1.0)));14 try testing.expect(std.math.isNan(fmod_f80(std.math.nan(f80), 1.0)));
15 try testing.expect(std.math.isNan(fmod.__fmodx(-std.math.nan(f80), 1.0)));15 try testing.expect(std.math.isNan(fmod_f80(-std.math.nan(f80), 1.0)));
16}16}
1717
18fn test_fmodx_infs() !void {18fn test_fmod_f80_infs() !void {
19 try testing.expect(fmod.__fmodx(1.0, std.math.inf(f80)) == 1.0);19 try testing.expect(fmod_f80(1.0, std.math.inf(f80)) == 1.0);
20 try testing.expect(fmod.__fmodx(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.__fmodx(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.__fmodx(-std.math.inf(f80), 1.0)));22 try testing.expect(std.math.isNan(fmod_f80(-std.math.inf(f80), 1.0)));
23}23}
2424
25test "fmodx" {25test fmod_f80 {
26 try test_fmodx(6.4, 4.0, 2.4);26 try test_fmod_f80(6.4, 4.0, 2.4);
27 try test_fmodx(6.4, -4.0, 2.4);27 try test_fmod_f80(6.4, -4.0, 2.4);
28 try test_fmodx(-6.4, 4.0, -2.4);28 try test_fmod_f80(-6.4, 4.0, -2.4);
29 try test_fmodx(-6.4, -4.0, -2.4);29 try test_fmod_f80(-6.4, -4.0, -2.4);
30 try test_fmodx(3.0, 2.0, 1.0);30 try test_fmod_f80(3.0, 2.0, 1.0);
31 try test_fmodx(-5.0, 3.0, -2.0);31 try test_fmod_f80(-5.0, 3.0, -2.0);
32 try test_fmodx(3.0, 2.0, 1.0);32 try test_fmod_f80(3.0, 2.0, 1.0);
33 try test_fmodx(1.0, 2.0, 1.0);33 try test_fmod_f80(1.0, 2.0, 1.0);
34 try test_fmodx(0.0, 1.0, 0.0);34 try test_fmod_f80(0.0, 1.0, 0.0);
35 try test_fmodx(-0.0, 1.0, -0.0);35 try test_fmod_f80(-0.0, 1.0, -0.0);
36 try test_fmodx(7046119.0, 5558362.0, 1487757.0);36 try test_fmod_f80(7046119.0, 5558362.0, 1487757.0);
37 try test_fmodx(9010357.0, 1957236.0, 1181413.0);37 try test_fmod_f80(9010357.0, 1957236.0, 1181413.0);
38 try test_fmodx(9223372036854775807, 10.0, 7.0);38 try test_fmod_f80(9223372036854775807, 10.0, 7.0);
3939
40 // Denormals40 // Denormals
41 const a1: f80 = 0x0.76e5_9a51_1a92_9ca4p-16381;41 const a1: f80 = 0x0.76e5_9a51_1a92_9ca4p-16381;
42 const b1: f80 = 0x0.2e97_1c3c_8e7d_e03ap-16381;42 const b1: f80 = 0x0.2e97_1c3c_8e7d_e03ap-16381;
43 const exp1: f80 = 0x0.19b7_61d7_fd96_dc30p-16381;43 const exp1: f80 = 0x0.19b7_61d7_fd96_dc30p-16381;
44 try test_fmodx(a1, b1, exp1);44 try test_fmod_f80(a1, b1, exp1);
45 const a2: f80 = 0x0.76e5_9a51_1a92_9ca4p-16381;45 const a2: f80 = 0x0.76e5_9a51_1a92_9ca4p-16381;
46 const b2: f80 = 0x0.0e97_1c3c_8e7d_e03ap-16381;46 const b2: f80 = 0x0.0e97_1c3c_8e7d_e03ap-16381;
47 const exp2: f80 = 0x0.022c_b86c_a6a3_9ad4p-16381;47 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();50 try test_fmod_f80_nans();
51 try test_fmodx_infs();51 try test_fmod_f80_infs();
52}52}
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 {...@@ -36,7 +36,7 @@ comptime {
3636
37pub fn __divmodti4(a: i128, b: i128, rem: *i128) callconv(.c) i128 {37pub fn __divmodti4(a: i128, b: i128, rem: *i128) callconv(.c) i128 {
38 const d = __divti3(a, b);38 const d = __divti3(a, b);
39 rem.* = a -% (d * b);39 rem.* = a - d *% b;
40 return d;40 return d;
41}41}
4242
...@@ -69,7 +69,7 @@ fn test_one_divmodti4(a: i128, b: i128, expected_q: i128, expected_r: i128) !voi...@@ -69,7 +69,7 @@ fn test_one_divmodti4(a: i128, b: i128, expected_q: i128, expected_r: i128) !voi
6969
70pub fn __divmoddi4(a: i64, b: i64, rem: *i64) callconv(.c) i64 {70pub fn __divmoddi4(a: i64, b: i64, rem: *i64) callconv(.c) i64 {
71 const d = __divdi3(a, b);71 const d = __divdi3(a, b);
72 rem.* = a -% (d * b);72 rem.* = a - d *% b;
73 return d;73 return d;
74}74}
7575
...@@ -79,21 +79,20 @@ fn test_one_divmoddi4(a: i64, b: i64, expected_q: i64, expected_r: i64) !void {...@@ -79,21 +79,20 @@ fn test_one_divmoddi4(a: i64, b: i64, expected_q: i64, expected_r: i64) !void {
79 try testing.expect(q == expected_q and r == expected_r);79 try testing.expect(q == expected_q and r == expected_r);
80}80}
8181
82const cases__divmoddi4 =82const cases__divmoddi4 = [_][4]i64{
83 [_][4]i64{83 [_]i64{ 0, 1, 0, 0 },
84 [_]i64{ 0, 1, 0, 0 },84 [_]i64{ 0, -1, 0, 0 },
85 [_]i64{ 0, -1, 0, 0 },85 [_]i64{ 2, 1, 2, 0 },
86 [_]i64{ 2, 1, 2, 0 },86 [_]i64{ 2, -1, -2, 0 },
87 [_]i64{ 2, -1, -2, 0 },87 [_]i64{ -2, 1, -2, 0 },
88 [_]i64{ -2, 1, -2, 0 },88 [_]i64{ -2, -1, 2, 0 },
89 [_]i64{ -2, -1, 2, 0 },89 [_]i64{ 7, 5, 1, 2 },
90 [_]i64{ 7, 5, 1, 2 },90 [_]i64{ -7, 5, -1, -2 },
91 [_]i64{ -7, 5, -1, -2 },91 [_]i64{ 19, 5, 3, 4 },
92 [_]i64{ 19, 5, 3, 4 },92 [_]i64{ 19, -5, -3, 4 },
93 [_]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, 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 [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000007))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000001))), -1 },95};
96 };
9796
98test "test_divmoddi4" {97test "test_divmoddi4" {
99 for (cases__divmoddi4) |case| {98 for (cases__divmoddi4) |case| {
...@@ -105,10 +104,6 @@ pub fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?*u64) callconv(.c) u64 {...@@ -105,10 +104,6 @@ pub fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?*u64) callconv(.c) u64 {
105 return udivmod(u64, a, b, maybe_rem);104 return udivmod(u64, a, b, maybe_rem);
106}105}
107106
108test "test_udivmoddi4" {
109 _ = @import("udivmoddi4_test.zig");
110}
111
112pub fn __divdi3(a: i64, b: i64) callconv(.c) i64 {107pub fn __divdi3(a: i64, b: i64) callconv(.c) i64 {
113 // Set aside the sign of the quotient.108 // Set aside the sign of the quotient.
114 const sign: u64 = @bitCast((a ^ b) >> 63);109 const sign: u64 = @bitCast((a ^ b) >> 63);
...@@ -209,25 +204,24 @@ fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) !void {...@@ -209,25 +204,24 @@ fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) !void {
209204
210pub fn __divmodsi4(a: i32, b: i32, rem: *i32) callconv(.c) i32 {205pub fn __divmodsi4(a: i32, b: i32, rem: *i32) callconv(.c) i32 {
211 const d = __divsi3(a, b);206 const d = __divsi3(a, b);
212 rem.* = a -% (d * b);207 rem.* = a - d *% b;
213 return d;208 return d;
214}209}
215210
216const cases__divmodsi4 =211const cases__divmodsi4 = [_][4]i32{
217 [_][4]i32{212 [_]i32{ 0, 1, 0, 0 },
218 [_]i32{ 0, 1, 0, 0 },213 [_]i32{ 0, -1, 0, 0 },
219 [_]i32{ 0, -1, 0, 0 },214 [_]i32{ 2, 1, 2, 0 },
220 [_]i32{ 2, 1, 2, 0 },215 [_]i32{ 2, -1, -2, 0 },
221 [_]i32{ 2, -1, -2, 0 },216 [_]i32{ -2, 1, -2, 0 },
222 [_]i32{ -2, 1, -2, 0 },217 [_]i32{ -2, -1, 2, 0 },
223 [_]i32{ -2, -1, 2, 0 },218 [_]i32{ 7, 5, 1, 2 },
224 [_]i32{ 7, 5, 1, 2 },219 [_]i32{ -7, 5, -1, -2 },
225 [_]i32{ -7, 5, -1, -2 },220 [_]i32{ 19, 5, 3, 4 },
226 [_]i32{ 19, 5, 3, 4 },221 [_]i32{ 19, -5, -3, 4 },
227 [_]i32{ 19, -5, -3, 4 },222 [_]i32{ @bitCast(@as(u32, 0x80000000)), 8, @bitCast(@as(u32, 0xf0000000)), 0 },
228 [_]i32{ @bitCast(@as(u32, 0x80000000)), 8, @bitCast(@as(u32, 0xf0000000)), 0 },223 [_]i32{ @bitCast(@as(u32, 0x80000007)), 8, @bitCast(@as(u32, 0xf0000001)), -1 },
229 [_]i32{ @bitCast(@as(u32, 0x80000007)), 8, @bitCast(@as(u32, 0xf0000001)), -1 },224};
230 };
231225
232fn test_one_divmodsi4(a: i32, b: i32, expected_q: i32, expected_r: i32) !void {226fn test_one_divmodsi4(a: i32, b: i32, expected_q: i32, expected_r: i32) !void {
233 var r: i32 = undefined;227 var r: i32 = undefined;
...@@ -243,7 +237,7 @@ test "test_divmodsi4" {...@@ -243,7 +237,7 @@ test "test_divmodsi4" {
243237
244pub fn __udivmodsi4(a: u32, b: u32, rem: *u32) callconv(.c) u32 {238pub fn __udivmodsi4(a: u32, b: u32, rem: *u32) callconv(.c) u32 {
245 const d = __udivsi3(a, b);239 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;
247 return d;241 return d;
248}242}
249243
...@@ -486,7 +480,7 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) !void {...@@ -486,7 +480,7 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) !void {
486}480}
487481
488pub fn __modsi3(n: i32, d: i32) callconv(.c) i32 {482pub fn __modsi3(n: i32, d: i32) callconv(.c) i32 {
489 return n -% __divsi3(n, d) * d;483 return n - __divsi3(n, d) *% d;
490}484}
491485
492test "test_modsi3" {486test "test_modsi3" {
...@@ -515,7 +509,7 @@ fn test_one_modsi3(a: i32, b: i32, expected_r: i32) !void {...@@ -515,7 +509,7 @@ fn test_one_modsi3(a: i32, b: i32, expected_r: i32) !void {
515}509}
516510
517pub fn __umodsi3(n: u32, d: u32) callconv(.c) u32 {511pub fn __umodsi3(n: u32, d: u32) callconv(.c) u32 {
518 return n -% __udivsi3(n, d) * d;512 return n - __udivsi3(n, d) * d;
519}513}
520514
521test "test_umodsi3" {515test "test_umodsi3" {
...@@ -663,3 +657,8 @@ fn test_one_umodsi3(a: u32, b: u32, expected_r: u32) !void {...@@ -663,3 +657,8 @@ fn test_one_umodsi3(a: u32, b: u32, expected_r: u32) !void {
663 const r: u32 = __umodsi3(a, b);657 const r: u32 = __umodsi3(a, b);
664 try testing.expect(r == expected_r);658 try testing.expect(r == expected_r);
665}659}
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 @@...@@ -1,3 +1,4 @@
1const builtin = @import("builtin");
1const std = @import("std");2const std = @import("std");
2const math = std.math;3const math = std.math;
3const Log2Int = std.math.Log2Int;4const Log2Int = std.math.Log2Int;
...@@ -6,29 +7,532 @@ const compiler_rt = @import("../compiler_rt.zig");...@@ -6,29 +7,532 @@ const compiler_rt = @import("../compiler_rt.zig");
6const symbol = compiler_rt.symbol;7const symbol = compiler_rt.symbol;
78
8comptime {9comptime {
9 symbol(&__fixxfti, "__fixxfti");
10 symbol(&__fixhfsi, "__fixhfsi");10 symbol(&__fixhfsi, "__fixhfsi");
11 symbol(&__fixhfdi, "__fixhfdi");11 symbol(&__fixhfdi, "__fixhfdi");
12 symbol(&__fixhfti, "__fixhfti");12 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);
13}169}
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 {
16 return intFromFloat(i128, a);197 return intFromFloat(i128, a);
17}198}
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 {
20 return intFromFloat(i64, a);219 return intFromFloat(i64, a);
21}220}
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 {
24 return intFromFloat(i32, a);244 return intFromFloat(i32, a);
25}245}
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 {
28 return intFromFloat(i128, a);261 return intFromFloat(i128, a);
29}262}
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 {
32 const F = @TypeOf(a);536 const F = @TypeOf(a);
33 const float_bits = @typeInfo(F).float.bits;537 const float_bits = @typeInfo(F).float.bits;
34 const int_bits = @typeInfo(I).int.bits;538 const int_bits = @typeInfo(I).int.bits;
...@@ -76,13 +580,14 @@ pub inline fn intFromFloat(comptime I: type, a: anytype) I {...@@ -76,13 +580,14 @@ pub inline fn intFromFloat(comptime I: type, a: anytype) I {
76 return result;580 return result;
77}581}
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();
80 switch (result.len) {585 switch (result.len) {
81 0 => return,586 0 => return,
82 inline 1...4 => |limbs_len| {587 inline 1...4 => |limbs_len| {
83 const I = @Int(signedness, 32 * limbs_len);588 const I = @Int(signedness, 32 * limbs_len);
84 const low_to_high: [limbs_len]u32 = @bitCast(@as(I, @intFromFloat(a)));589 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) {
86 .little => low_to_high,591 .little => low_to_high,
87 .big => switch (limbs_len) {592 .big => switch (limbs_len) {
88 1 => .{low_to_high[0]},593 1 => .{low_to_high[0]},
...@@ -111,7 +616,6 @@ pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, resul...@@ -111,7 +616,6 @@ pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, resul
111 });616 });
112 switch (signedness) {617 switch (signedness) {
113 .signed => {618 .signed => {
114 const endian = @import("builtin").cpu.arch.endian();
115 const exponent_limb = switch (endian) {619 const exponent_limb = switch (endian) {
116 .little => exponent / 32,620 .little => exponent / 32,
117 .big => result.len - 1 - exponent / 32,621 .big => result.len - 1 - exponent / 32,
lib/compiler_rt/int_from_float_test.zig+913-897
...@@ -2,1023 +2,1039 @@ const std = @import("std");...@@ -2,1023 +2,1039 @@ const std = @import("std");
2const testing = std.testing;2const testing = std.testing;
3const math = std.math;3const math = std.math;
44
5const __fixunshfti = @import("fixunshfti.zig").__fixunshfti;5const impl = @import("int_from_float.zig");
6const __fixunsxfti = @import("fixunsxfti.zig").__fixunsxfti;6
77const i32_intFromFloat_f16 = impl.i32_intFromFloat_f16;
8// Conversion from f328const u32_intFromFloat_f16 = impl.u32_intFromFloat_f16;
9const __fixsfsi = @import("fixsfsi.zig").__fixsfsi;9const i64_intFromFloat_f16 = impl.i64_intFromFloat_f16;
10const __fixunssfsi = @import("fixunssfsi.zig").__fixunssfsi;10const u64_intFromFloat_f16 = impl.u64_intFromFloat_f16;
11const __fixsfdi = @import("fixsfdi.zig").__fixsfdi;11const i128_intFromFloat_f16 = impl.i128_intFromFloat_f16;
12const __fixunssfdi = @import("fixunssfdi.zig").__fixunssfdi;12const u128_intFromFloat_f16 = impl.u128_intFromFloat_f16;
13const __fixsfti = @import("fixsfti.zig").__fixsfti;13const signed_intFromFloat_f16 = impl.signed_intFromFloat_f16;
14const __fixunssfti = @import("fixunssfti.zig").__fixunssfti;14const unsigned_intFromFloat_f16 = impl.unsigned_intFromFloat_f16;
15const __fixsfei = @import("fixsfei.zig").__fixsfei;15
16const __fixunssfei = @import("fixunssfei.zig").__fixunssfei;16const i32_intFromFloat_f32 = impl.i32_intFromFloat_f32;
1717const u32_intFromFloat_f32 = impl.u32_intFromFloat_f32;
18// Conversion from f6418const i64_intFromFloat_f32 = impl.i64_intFromFloat_f32;
19const __fixdfsi = @import("fixdfsi.zig").__fixdfsi;19const u64_intFromFloat_f32 = impl.u64_intFromFloat_f32;
20const __fixunsdfsi = @import("fixunsdfsi.zig").__fixunsdfsi;20const i128_intFromFloat_f32 = impl.i128_intFromFloat_f32;
21const __fixdfdi = @import("fixdfdi.zig").__fixdfdi;21const u128_intFromFloat_f32 = impl.u128_intFromFloat_f32;
22const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi;22const signed_intFromFloat_f32 = impl.signed_intFromFloat_f32;
23const __fixdfti = @import("fixdfti.zig").__fixdfti;23const unsigned_intFromFloat_f32 = impl.unsigned_intFromFloat_f32;
24const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti;24
25const __fixdfei = @import("fixdfei.zig").__fixdfei;25const i32_intFromFloat_f64 = impl.i32_intFromFloat_f64;
26const __fixunsdfei = @import("fixunsdfei.zig").__fixunsdfei;26const u32_intFromFloat_f64 = impl.u32_intFromFloat_f64;
2727const i64_intFromFloat_f64 = impl.i64_intFromFloat_f64;
28// Conversion from f12828const u64_intFromFloat_f64 = impl.u64_intFromFloat_f64;
29const __fixtfsi = @import("fixtfsi.zig").__fixtfsi;29const i128_intFromFloat_f64 = impl.i128_intFromFloat_f64;
30const __fixunstfsi = @import("fixunstfsi.zig").__fixunstfsi;30const u128_intFromFloat_f64 = impl.u128_intFromFloat_f64;
31const __fixtfdi = @import("fixtfdi.zig").__fixtfdi;31const signed_intFromFloat_f64 = impl.signed_intFromFloat_f64;
32const __fixunstfdi = @import("fixunstfdi.zig").__fixunstfdi;32const unsigned_intFromFloat_f64 = impl.unsigned_intFromFloat_f64;
33const __fixtfti = @import("fixtfti.zig").__fixtfti;33
34const __fixunstfti = @import("fixunstfti.zig").__fixunstfti;34const i32_intFromFloat_f80 = impl.i32_intFromFloat_f80;
3535const u32_intFromFloat_f80 = impl.u32_intFromFloat_f80;
36fn test__fixsfsi(a: f32, expected: i32) !void {36const i64_intFromFloat_f80 = impl.i64_intFromFloat_f80;
37 const x = __fixsfsi(a);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);
38 try testing.expect(x == expected);54 try testing.expect(x == expected);
39}55}
4056
41fn test__fixunssfsi(a: f32, expected: u32) !void {57fn test_u32_intFromFloat_f32(a: f32, expected: u32) !void {
42 const x = __fixunssfsi(a);58 const x = u32_intFromFloat_f32(a);
43 try testing.expect(x == expected);59 try testing.expect(x == expected);
44}60}
4561
46test "fixsfsi" {62test i32_intFromFloat_f32 {
47 try test__fixsfsi(-math.floatMax(f32), math.minInt(i32));63 try test_i32_intFromFloat_f32(-math.floatMax(f32), math.minInt(i32));
4864
49 try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));65 try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
50 try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);66 try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
5167
52 try test__fixsfsi(-0x1.0000000000000p+127, -0x80000000);68 try test_i32_intFromFloat_f32(-0x1.0000000000000p+127, -0x80000000);
53 try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);69 try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
54 try test__fixsfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);70 try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
5571
56 try test__fixsfsi(-0x1.0000000000001p+63, -0x80000000);72 try test_i32_intFromFloat_f32(-0x1.0000000000001p+63, -0x80000000);
57 try test__fixsfsi(-0x1.0000000000000p+63, -0x80000000);73 try test_i32_intFromFloat_f32(-0x1.0000000000000p+63, -0x80000000);
58 try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);74 try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
59 try test__fixsfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);75 try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
6076
61 try test__fixsfsi(-0x1.FFFFFEp+62, -0x80000000);77 try test_i32_intFromFloat_f32(-0x1.FFFFFEp+62, -0x80000000);
62 try test__fixsfsi(-0x1.FFFFFCp+62, -0x80000000);78 try test_i32_intFromFloat_f32(-0x1.FFFFFCp+62, -0x80000000);
6379
64 try test__fixsfsi(-0x1.000000p+31, -0x80000000);80 try test_i32_intFromFloat_f32(-0x1.000000p+31, -0x80000000);
65 try test__fixsfsi(-0x1.FFFFFFp+30, -0x80000000);81 try test_i32_intFromFloat_f32(-0x1.FFFFFFp+30, -0x80000000);
66 try test__fixsfsi(-0x1.FFFFFEp+30, -0x7FFFFF80);82 try test_i32_intFromFloat_f32(-0x1.FFFFFEp+30, -0x7FFFFF80);
67 try test__fixsfsi(-0x1.FFFFFCp+30, -0x7FFFFF00);83 try test_i32_intFromFloat_f32(-0x1.FFFFFCp+30, -0x7FFFFF00);
6884
69 try test__fixsfsi(-2.01, -2);85 try test_i32_intFromFloat_f32(-2.01, -2);
70 try test__fixsfsi(-2.0, -2);86 try test_i32_intFromFloat_f32(-2.0, -2);
71 try test__fixsfsi(-1.99, -1);87 try test_i32_intFromFloat_f32(-1.99, -1);
72 try test__fixsfsi(-1.0, -1);88 try test_i32_intFromFloat_f32(-1.0, -1);
73 try test__fixsfsi(-0.99, 0);89 try test_i32_intFromFloat_f32(-0.99, 0);
74 try test__fixsfsi(-0.5, 0);90 try test_i32_intFromFloat_f32(-0.5, 0);
7591
76 try test__fixsfsi(-math.floatMin(f32), 0);92 try test_i32_intFromFloat_f32(-math.floatMin(f32), 0);
77 try test__fixsfsi(0.0, 0);93 try test_i32_intFromFloat_f32(0.0, 0);
78 try test__fixsfsi(math.floatMin(f32), 0);94 try test_i32_intFromFloat_f32(math.floatMin(f32), 0);
79 try test__fixsfsi(0.5, 0);95 try test_i32_intFromFloat_f32(0.5, 0);
80 try test__fixsfsi(0.99, 0);96 try test_i32_intFromFloat_f32(0.99, 0);
81 try test__fixsfsi(1.0, 1);97 try test_i32_intFromFloat_f32(1.0, 1);
82 try test__fixsfsi(1.5, 1);98 try test_i32_intFromFloat_f32(1.5, 1);
83 try test__fixsfsi(1.99, 1);99 try test_i32_intFromFloat_f32(1.99, 1);
84 try test__fixsfsi(2.0, 2);100 try test_i32_intFromFloat_f32(2.0, 2);
85 try test__fixsfsi(2.01, 2);101 try test_i32_intFromFloat_f32(2.01, 2);
86102
87 try test__fixsfsi(0x1.FFFFFCp+30, 0x7FFFFF00);103 try test_i32_intFromFloat_f32(0x1.FFFFFCp+30, 0x7FFFFF00);
88 try test__fixsfsi(0x1.FFFFFEp+30, 0x7FFFFF80);104 try test_i32_intFromFloat_f32(0x1.FFFFFEp+30, 0x7FFFFF80);
89 try test__fixsfsi(0x1.FFFFFFp+30, 0x7FFFFFFF);105 try test_i32_intFromFloat_f32(0x1.FFFFFFp+30, 0x7FFFFFFF);
90 try test__fixsfsi(0x1.000000p+31, 0x7FFFFFFF);106 try test_i32_intFromFloat_f32(0x1.000000p+31, 0x7FFFFFFF);
91107
92 try test__fixsfsi(0x1.FFFFFCp+62, 0x7FFFFFFF);108 try test_i32_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFFFF);
93 try test__fixsfsi(0x1.FFFFFEp+62, 0x7FFFFFFF);109 try test_i32_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFFFF);
94110
95 try test__fixsfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);111 try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
96 try test__fixsfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);112 try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
97 try test__fixsfsi(0x1.0000000000000p+63, 0x7FFFFFFF);113 try test_i32_intFromFloat_f32(0x1.0000000000000p+63, 0x7FFFFFFF);
98 try test__fixsfsi(0x1.0000000000001p+63, 0x7FFFFFFF);114 try test_i32_intFromFloat_f32(0x1.0000000000001p+63, 0x7FFFFFFF);
99115
100 try test__fixsfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);116 try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
101 try test__fixsfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);117 try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
102 try test__fixsfsi(0x1.0000000000000p+127, 0x7FFFFFFF);118 try test_i32_intFromFloat_f32(0x1.0000000000000p+127, 0x7FFFFFFF);
103119
104 try test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);120 try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
105 try test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));121 try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
106122
107 try test__fixsfsi(math.floatMax(f32), math.maxInt(i32));123 try test_i32_intFromFloat_f32(math.floatMax(f32), math.maxInt(i32));
108}124}
109125
110test "fixunssfsi" {126test u32_intFromFloat_f32 {
111 try test__fixunssfsi(0.0, 0);127 try test_u32_intFromFloat_f32(0.0, 0);
112128
113 try test__fixunssfsi(0.5, 0);129 try test_u32_intFromFloat_f32(0.5, 0);
114 try test__fixunssfsi(0.99, 0);130 try test_u32_intFromFloat_f32(0.99, 0);
115 try test__fixunssfsi(1.0, 1);131 try test_u32_intFromFloat_f32(1.0, 1);
116 try test__fixunssfsi(1.5, 1);132 try test_u32_intFromFloat_f32(1.5, 1);
117 try test__fixunssfsi(1.99, 1);133 try test_u32_intFromFloat_f32(1.99, 1);
118 try test__fixunssfsi(2.0, 2);134 try test_u32_intFromFloat_f32(2.0, 2);
119 try test__fixunssfsi(2.01, 2);135 try test_u32_intFromFloat_f32(2.01, 2);
120 try test__fixunssfsi(-0.5, 0);136 try test_u32_intFromFloat_f32(-0.5, 0);
121 try test__fixunssfsi(-0.99, 0);137 try test_u32_intFromFloat_f32(-0.99, 0);
122138
123 try test__fixunssfsi(-1.0, 0);139 try test_u32_intFromFloat_f32(-1.0, 0);
124 try test__fixunssfsi(-1.5, 0);140 try test_u32_intFromFloat_f32(-1.5, 0);
125 try test__fixunssfsi(-1.99, 0);141 try test_u32_intFromFloat_f32(-1.99, 0);
126 try test__fixunssfsi(-2.0, 0);142 try test_u32_intFromFloat_f32(-2.0, 0);
127 try test__fixunssfsi(-2.01, 0);143 try test_u32_intFromFloat_f32(-2.01, 0);
128144
129 try test__fixunssfsi(0x1.000000p+31, 0x80000000);145 try test_u32_intFromFloat_f32(0x1.000000p+31, 0x80000000);
130 try test__fixunssfsi(0x1.000000p+32, 0xFFFFFFFF);146 try test_u32_intFromFloat_f32(0x1.000000p+32, 0xFFFFFFFF);
131 try test__fixunssfsi(0x1.FFFFFEp+31, 0xFFFFFF00);147 try test_u32_intFromFloat_f32(0x1.FFFFFEp+31, 0xFFFFFF00);
132 try test__fixunssfsi(0x1.FFFFFEp+30, 0x7FFFFF80);148 try test_u32_intFromFloat_f32(0x1.FFFFFEp+30, 0x7FFFFF80);
133 try test__fixunssfsi(0x1.FFFFFCp+30, 0x7FFFFF00);149 try test_u32_intFromFloat_f32(0x1.FFFFFCp+30, 0x7FFFFF00);
134150
135 try test__fixunssfsi(-0x1.FFFFFEp+30, 0);151 try test_u32_intFromFloat_f32(-0x1.FFFFFEp+30, 0);
136 try test__fixunssfsi(-0x1.FFFFFCp+30, 0);152 try test_u32_intFromFloat_f32(-0x1.FFFFFCp+30, 0);
137}153}
138154
139fn test__fixsfdi(a: f32, expected: i64) !void {155fn test_i64_intFromFloat_f32(a: f32, expected: i64) !void {
140 const x = __fixsfdi(a);156 const x = i64_intFromFloat_f32(a);
141 try testing.expect(x == expected);157 try testing.expect(x == expected);
142}158}
143159
144fn test__fixunssfdi(a: f32, expected: u64) !void {160fn test_u64_intFromFloat_f32(a: f32, expected: u64) !void {
145 const x = __fixunssfdi(a);161 const x = u64_intFromFloat_f32(a);
146 try testing.expect(x == expected);162 try testing.expect(x == expected);
147}163}
148164
149test "fixsfdi" {165test i64_intFromFloat_f32 {
150 try test__fixsfdi(-math.floatMax(f32), math.minInt(i64));166 try test_i64_intFromFloat_f32(-math.floatMax(f32), math.minInt(i64));
151167
152 try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));168 try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
153 try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);169 try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
154170
155 try test__fixsfdi(-0x1.0000000000000p+127, -0x8000000000000000);171 try test_i64_intFromFloat_f32(-0x1.0000000000000p+127, -0x8000000000000000);
156 try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);172 try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
157 try test__fixsfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);173 try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
158174
159 try test__fixsfdi(-0x1.0000000000001p+63, -0x8000000000000000);175 try test_i64_intFromFloat_f32(-0x1.0000000000001p+63, -0x8000000000000000);
160 try test__fixsfdi(-0x1.0000000000000p+63, -0x8000000000000000);176 try test_i64_intFromFloat_f32(-0x1.0000000000000p+63, -0x8000000000000000);
161 try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000);177 try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000);
162 try test__fixsfdi(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000);178 try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000);
163179
164 try test__fixsfdi(-0x1.FFFFFFp+62, -0x8000000000000000);180 try test_i64_intFromFloat_f32(-0x1.FFFFFFp+62, -0x8000000000000000);
165 try test__fixsfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000);181 try test_i64_intFromFloat_f32(-0x1.FFFFFEp+62, -0x7fffff8000000000);
166 try test__fixsfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000);182 try test_i64_intFromFloat_f32(-0x1.FFFFFCp+62, -0x7fffff0000000000);
167183
168 try test__fixsfdi(-2.01, -2);184 try test_i64_intFromFloat_f32(-2.01, -2);
169 try test__fixsfdi(-2.0, -2);185 try test_i64_intFromFloat_f32(-2.0, -2);
170 try test__fixsfdi(-1.99, -1);186 try test_i64_intFromFloat_f32(-1.99, -1);
171 try test__fixsfdi(-1.0, -1);187 try test_i64_intFromFloat_f32(-1.0, -1);
172 try test__fixsfdi(-0.99, 0);188 try test_i64_intFromFloat_f32(-0.99, 0);
173 try test__fixsfdi(-0.5, 0);189 try test_i64_intFromFloat_f32(-0.5, 0);
174 try test__fixsfdi(-math.floatMin(f32), 0);190 try test_i64_intFromFloat_f32(-math.floatMin(f32), 0);
175 try test__fixsfdi(0.0, 0);191 try test_i64_intFromFloat_f32(0.0, 0);
176 try test__fixsfdi(math.floatMin(f32), 0);192 try test_i64_intFromFloat_f32(math.floatMin(f32), 0);
177 try test__fixsfdi(0.5, 0);193 try test_i64_intFromFloat_f32(0.5, 0);
178 try test__fixsfdi(0.99, 0);194 try test_i64_intFromFloat_f32(0.99, 0);
179 try test__fixsfdi(1.0, 1);195 try test_i64_intFromFloat_f32(1.0, 1);
180 try test__fixsfdi(1.5, 1);196 try test_i64_intFromFloat_f32(1.5, 1);
181 try test__fixsfdi(1.99, 1);197 try test_i64_intFromFloat_f32(1.99, 1);
182 try test__fixsfdi(2.0, 2);198 try test_i64_intFromFloat_f32(2.0, 2);
183 try test__fixsfdi(2.01, 2);199 try test_i64_intFromFloat_f32(2.01, 2);
184200
185 try test__fixsfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);201 try test_i64_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
186 try test__fixsfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);202 try test_i64_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
187 try test__fixsfdi(0x1.FFFFFFp+62, 0x7FFFFFFFFFFFFFFF);203 try test_i64_intFromFloat_f32(0x1.FFFFFFp+62, 0x7FFFFFFFFFFFFFFF);
188204
189 try test__fixsfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFFFFF);205 try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFFFFF);
190 try test__fixsfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFFFF);206 try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFFFF);
191 try test__fixsfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);207 try test_i64_intFromFloat_f32(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
192 try test__fixsfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);208 try test_i64_intFromFloat_f32(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
193209
194 try test__fixsfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);210 try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
195 try test__fixsfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);211 try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
196 try test__fixsfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);212 try test_i64_intFromFloat_f32(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
197213
198 try test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);214 try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
199 try test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));215 try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
200216
201 try test__fixsfdi(math.floatMax(f32), math.maxInt(i64));217 try test_i64_intFromFloat_f32(math.floatMax(f32), math.maxInt(i64));
202}218}
203219
204test "fixunssfdi" {220test u64_intFromFloat_f32 {
205 try test__fixunssfdi(0.0, 0);221 try test_u64_intFromFloat_f32(0.0, 0);
206222
207 try test__fixunssfdi(0.5, 0);223 try test_u64_intFromFloat_f32(0.5, 0);
208 try test__fixunssfdi(0.99, 0);224 try test_u64_intFromFloat_f32(0.99, 0);
209 try test__fixunssfdi(1.0, 1);225 try test_u64_intFromFloat_f32(1.0, 1);
210 try test__fixunssfdi(1.5, 1);226 try test_u64_intFromFloat_f32(1.5, 1);
211 try test__fixunssfdi(1.99, 1);227 try test_u64_intFromFloat_f32(1.99, 1);
212 try test__fixunssfdi(2.0, 2);228 try test_u64_intFromFloat_f32(2.0, 2);
213 try test__fixunssfdi(2.01, 2);229 try test_u64_intFromFloat_f32(2.01, 2);
214 try test__fixunssfdi(-0.5, 0);230 try test_u64_intFromFloat_f32(-0.5, 0);
215 try test__fixunssfdi(-0.99, 0);231 try test_u64_intFromFloat_f32(-0.99, 0);
216232
217 try test__fixunssfdi(-1.0, 0);233 try test_u64_intFromFloat_f32(-1.0, 0);
218 try test__fixunssfdi(-1.5, 0);234 try test_u64_intFromFloat_f32(-1.5, 0);
219 try test__fixunssfdi(-1.99, 0);235 try test_u64_intFromFloat_f32(-1.99, 0);
220 try test__fixunssfdi(-2.0, 0);236 try test_u64_intFromFloat_f32(-2.0, 0);
221 try test__fixunssfdi(-2.01, 0);237 try test_u64_intFromFloat_f32(-2.01, 0);
222238
223 try test__fixunssfdi(0x1.FFFFFEp+63, 0xFFFFFF0000000000);239 try test_u64_intFromFloat_f32(0x1.FFFFFEp+63, 0xFFFFFF0000000000);
224 try test__fixunssfdi(0x1.000000p+63, 0x8000000000000000);240 try test_u64_intFromFloat_f32(0x1.000000p+63, 0x8000000000000000);
225 try test__fixunssfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);241 try test_u64_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
226 try test__fixunssfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);242 try test_u64_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
227243
228 try test__fixunssfdi(-0x1.FFFFFEp+62, 0x0000000000000000);244 try test_u64_intFromFloat_f32(-0x1.FFFFFEp+62, 0x0000000000000000);
229 try test__fixunssfdi(-0x1.FFFFFCp+62, 0x0000000000000000);245 try test_u64_intFromFloat_f32(-0x1.FFFFFCp+62, 0x0000000000000000);
230}246}
231247
232fn test__fixsfti(a: f32, expected: i128) !void {248fn test_i128_intFromFloat_f32(a: f32, expected: i128) !void {
233 const x = __fixsfti(a);249 const x = i128_intFromFloat_f32(a);
234 try testing.expect(x == expected);250 try testing.expect(x == expected);
235}251}
236252
237fn test__fixunssfti(a: f32, expected: u128) !void {253fn test_u128_intFromFloat_f32(a: f32, expected: u128) !void {
238 const x = __fixunssfti(a);254 const x = u128_intFromFloat_f32(a);
239 try testing.expect(x == expected);255 try testing.expect(x == expected);
240}256}
241257
242test "fixsfti" {258test i128_intFromFloat_f32 {
243 try test__fixsfti(-math.floatMax(f32), math.minInt(i128));259 try test_i128_intFromFloat_f32(-math.floatMax(f32), math.minInt(i128));
244260
245 try test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));261 try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
246 try test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);262 try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
247263
248 try test__fixsfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);264 try test_i128_intFromFloat_f32(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
249 try test__fixsfti(-0x1.FFFFFFFFFFFFFp+126, -0x80000000000000000000000000000000);265 try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+126, -0x80000000000000000000000000000000);
250 try test__fixsfti(-0x1.FFFFFFFFFFFFEp+126, -0x80000000000000000000000000000000);266 try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+126, -0x80000000000000000000000000000000);
251 try test__fixsfti(-0x1.FFFFFF0000000p+126, -0x80000000000000000000000000000000);267 try test_i128_intFromFloat_f32(-0x1.FFFFFF0000000p+126, -0x80000000000000000000000000000000);
252 try test__fixsfti(-0x1.FFFFFE0000000p+126, -0x7FFFFF80000000000000000000000000);268 try test_i128_intFromFloat_f32(-0x1.FFFFFE0000000p+126, -0x7FFFFF80000000000000000000000000);
253 try test__fixsfti(-0x1.FFFFFC0000000p+126, -0x7FFFFF00000000000000000000000000);269 try test_i128_intFromFloat_f32(-0x1.FFFFFC0000000p+126, -0x7FFFFF00000000000000000000000000);
254270
255 try test__fixsfti(-0x1.0000000000001p+63, -0x8000000000000000);271 try test_i128_intFromFloat_f32(-0x1.0000000000001p+63, -0x8000000000000000);
256 try test__fixsfti(-0x1.0000000000000p+63, -0x8000000000000000);272 try test_i128_intFromFloat_f32(-0x1.0000000000000p+63, -0x8000000000000000);
257 try test__fixsfti(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000);273 try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000);
258 try test__fixsfti(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000);274 try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000);
259275
260 try test__fixsfti(-0x1.FFFFFFp+62, -0x8000000000000000);276 try test_i128_intFromFloat_f32(-0x1.FFFFFFp+62, -0x8000000000000000);
261 try test__fixsfti(-0x1.FFFFFEp+62, -0x7fffff8000000000);277 try test_i128_intFromFloat_f32(-0x1.FFFFFEp+62, -0x7fffff8000000000);
262 try test__fixsfti(-0x1.FFFFFCp+62, -0x7fffff0000000000);278 try test_i128_intFromFloat_f32(-0x1.FFFFFCp+62, -0x7fffff0000000000);
263279
264 try test__fixsfti(-0x1.000000p+31, -0x80000000);280 try test_i128_intFromFloat_f32(-0x1.000000p+31, -0x80000000);
265 try test__fixsfti(-0x1.FFFFFFp+30, -0x80000000);281 try test_i128_intFromFloat_f32(-0x1.FFFFFFp+30, -0x80000000);
266 try test__fixsfti(-0x1.FFFFFEp+30, -0x7FFFFF80);282 try test_i128_intFromFloat_f32(-0x1.FFFFFEp+30, -0x7FFFFF80);
267 try test__fixsfti(-0x1.FFFFFCp+30, -0x7FFFFF00);283 try test_i128_intFromFloat_f32(-0x1.FFFFFCp+30, -0x7FFFFF00);
268284
269 try test__fixsfti(-2.01, -2);285 try test_i128_intFromFloat_f32(-2.01, -2);
270 try test__fixsfti(-2.0, -2);286 try test_i128_intFromFloat_f32(-2.0, -2);
271 try test__fixsfti(-1.99, -1);287 try test_i128_intFromFloat_f32(-1.99, -1);
272 try test__fixsfti(-1.0, -1);288 try test_i128_intFromFloat_f32(-1.0, -1);
273 try test__fixsfti(-0.99, 0);289 try test_i128_intFromFloat_f32(-0.99, 0);
274 try test__fixsfti(-0.5, 0);290 try test_i128_intFromFloat_f32(-0.5, 0);
275 try test__fixsfti(-math.floatMin(f32), 0);291 try test_i128_intFromFloat_f32(-math.floatMin(f32), 0);
276 try test__fixsfti(0.0, 0);292 try test_i128_intFromFloat_f32(0.0, 0);
277 try test__fixsfti(math.floatMin(f32), 0);293 try test_i128_intFromFloat_f32(math.floatMin(f32), 0);
278 try test__fixsfti(0.5, 0);294 try test_i128_intFromFloat_f32(0.5, 0);
279 try test__fixsfti(0.99, 0);295 try test_i128_intFromFloat_f32(0.99, 0);
280 try test__fixsfti(1.0, 1);296 try test_i128_intFromFloat_f32(1.0, 1);
281 try test__fixsfti(1.5, 1);297 try test_i128_intFromFloat_f32(1.5, 1);
282 try test__fixsfti(1.99, 1);298 try test_i128_intFromFloat_f32(1.99, 1);
283 try test__fixsfti(2.0, 2);299 try test_i128_intFromFloat_f32(2.0, 2);
284 try test__fixsfti(2.01, 2);300 try test_i128_intFromFloat_f32(2.01, 2);
285301
286 try test__fixsfti(0x1.FFFFFCp+30, 0x7FFFFF00);302 try test_i128_intFromFloat_f32(0x1.FFFFFCp+30, 0x7FFFFF00);
287 try test__fixsfti(0x1.FFFFFEp+30, 0x7FFFFF80);303 try test_i128_intFromFloat_f32(0x1.FFFFFEp+30, 0x7FFFFF80);
288 try test__fixsfti(0x1.FFFFFFp+30, 0x80000000);304 try test_i128_intFromFloat_f32(0x1.FFFFFFp+30, 0x80000000);
289 try test__fixsfti(0x1.000000p+31, 0x80000000);305 try test_i128_intFromFloat_f32(0x1.000000p+31, 0x80000000);
290306
291 try test__fixsfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);307 try test_i128_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
292 try test__fixsfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);308 try test_i128_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
293 try test__fixsfti(0x1.FFFFFFp+62, 0x8000000000000000);309 try test_i128_intFromFloat_f32(0x1.FFFFFFp+62, 0x8000000000000000);
294310
295 try test__fixsfti(0x1.FFFFFFFFFFFFEp+62, 0x8000000000000000);311 try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+62, 0x8000000000000000);
296 try test__fixsfti(0x1.FFFFFFFFFFFFFp+62, 0x8000000000000000);312 try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+62, 0x8000000000000000);
297 try test__fixsfti(0x1.0000000000000p+63, 0x8000000000000000);313 try test_i128_intFromFloat_f32(0x1.0000000000000p+63, 0x8000000000000000);
298 try test__fixsfti(0x1.0000000000001p+63, 0x8000000000000000);314 try test_i128_intFromFloat_f32(0x1.0000000000001p+63, 0x8000000000000000);
299315
300 try test__fixsfti(0x1.FFFFFC0000000p+126, 0x7FFFFF00000000000000000000000000);316 try test_i128_intFromFloat_f32(0x1.FFFFFC0000000p+126, 0x7FFFFF00000000000000000000000000);
301 try test__fixsfti(0x1.FFFFFE0000000p+126, 0x7FFFFF80000000000000000000000000);317 try test_i128_intFromFloat_f32(0x1.FFFFFE0000000p+126, 0x7FFFFF80000000000000000000000000);
302 try test__fixsfti(0x1.FFFFFF0000000p+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);318 try test_i128_intFromFloat_f32(0x1.FFFFFF0000000p+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
303 try test__fixsfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);319 try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
304 try test__fixsfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);320 try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
305 try test__fixsfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);321 try test_i128_intFromFloat_f32(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
306322
307 try test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);323 try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
308 try test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));324 try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
309325
310 try test__fixsfti(math.floatMax(f32), math.maxInt(i128));326 try test_i128_intFromFloat_f32(math.floatMax(f32), math.maxInt(i128));
311}327}
312328
313test "fixunssfti" {329test u128_intFromFloat_f32 {
314 try test__fixunssfti(0.0, 0);330 try test_u128_intFromFloat_f32(0.0, 0);
315331
316 try test__fixunssfti(0.5, 0);332 try test_u128_intFromFloat_f32(0.5, 0);
317 try test__fixunssfti(0.99, 0);333 try test_u128_intFromFloat_f32(0.99, 0);
318 try test__fixunssfti(1.0, 1);334 try test_u128_intFromFloat_f32(1.0, 1);
319 try test__fixunssfti(1.5, 1);335 try test_u128_intFromFloat_f32(1.5, 1);
320 try test__fixunssfti(1.99, 1);336 try test_u128_intFromFloat_f32(1.99, 1);
321 try test__fixunssfti(2.0, 2);337 try test_u128_intFromFloat_f32(2.0, 2);
322 try test__fixunssfti(2.01, 2);338 try test_u128_intFromFloat_f32(2.01, 2);
323 try test__fixunssfti(-0.5, 0);339 try test_u128_intFromFloat_f32(-0.5, 0);
324 try test__fixunssfti(-0.99, 0);340 try test_u128_intFromFloat_f32(-0.99, 0);
325341
326 try test__fixunssfti(-1.0, 0);342 try test_u128_intFromFloat_f32(-1.0, 0);
327 try test__fixunssfti(-1.5, 0);343 try test_u128_intFromFloat_f32(-1.5, 0);
328 try test__fixunssfti(-1.99, 0);344 try test_u128_intFromFloat_f32(-1.99, 0);
329 try test__fixunssfti(-2.0, 0);345 try test_u128_intFromFloat_f32(-2.0, 0);
330 try test__fixunssfti(-2.01, 0);346 try test_u128_intFromFloat_f32(-2.01, 0);
331347
332 try test__fixunssfti(0x1.FFFFFEp+63, 0xFFFFFF0000000000);348 try test_u128_intFromFloat_f32(0x1.FFFFFEp+63, 0xFFFFFF0000000000);
333 try test__fixunssfti(0x1.000000p+63, 0x8000000000000000);349 try test_u128_intFromFloat_f32(0x1.000000p+63, 0x8000000000000000);
334 try test__fixunssfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);350 try test_u128_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
335 try test__fixunssfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);351 try test_u128_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
336 try test__fixunssfti(0x1.FFFFFEp+127, 0xFFFFFF00000000000000000000000000);352 try test_u128_intFromFloat_f32(0x1.FFFFFEp+127, 0xFFFFFF00000000000000000000000000);
337 try test__fixunssfti(0x1.000000p+127, 0x80000000000000000000000000000000);353 try test_u128_intFromFloat_f32(0x1.000000p+127, 0x80000000000000000000000000000000);
338 try test__fixunssfti(0x1.FFFFFEp+126, 0x7FFFFF80000000000000000000000000);354 try test_u128_intFromFloat_f32(0x1.FFFFFEp+126, 0x7FFFFF80000000000000000000000000);
339 try test__fixunssfti(0x1.FFFFFCp+126, 0x7FFFFF00000000000000000000000000);355 try test_u128_intFromFloat_f32(0x1.FFFFFCp+126, 0x7FFFFF00000000000000000000000000);
340356
341 try test__fixunssfti(-0x1.FFFFFEp+62, 0x0000000000000000);357 try test_u128_intFromFloat_f32(-0x1.FFFFFEp+62, 0x0000000000000000);
342 try test__fixunssfti(-0x1.FFFFFCp+62, 0x0000000000000000);358 try test_u128_intFromFloat_f32(-0x1.FFFFFCp+62, 0x0000000000000000);
343 try test__fixunssfti(-0x1.FFFFFEp+126, 0x0000000000000000);359 try test_u128_intFromFloat_f32(-0x1.FFFFFEp+126, 0x0000000000000000);
344 try test__fixunssfti(-0x1.FFFFFCp+126, 0x0000000000000000);360 try test_u128_intFromFloat_f32(-0x1.FFFFFCp+126, 0x0000000000000000);
345 try test__fixunssfti(math.floatMax(f32), 0xffffff00000000000000000000000000);361 try test_u128_intFromFloat_f32(math.floatMax(f32), 0xffffff00000000000000000000000000);
346 try test__fixunssfti(math.inf(f32), math.maxInt(u128));362 try test_u128_intFromFloat_f32(math.inf(f32), math.maxInt(u128));
347}363}
348364
349fn test_fixsfei(comptime T: type, expected: T, a: f32) !void {365fn test_intFromFloat_f32(comptime T: type, expected: T, a: f32) !void {
350 const int = @typeInfo(T).int;366 const int = @typeInfo(T).int;
351 var actual: T = undefined;367 var actual: T = undefined;
352 _ = switch (int.signedness) {368 _ = switch (int.signedness) {
353 .signed => __fixsfei,369 .signed => signed_intFromFloat_f32,
354 .unsigned => __fixunssfei,370 .unsigned => unsigned_intFromFloat_f32,
355 }(@ptrCast(&actual), int.bits, a);371 }(@ptrCast(&actual), a);
356 try testing.expect(expected == actual);372 try testing.expect(expected == actual);
357}373}
358374
359test "fixsfei" {375test signed_intFromFloat_f32 {
360 try test_fixsfei(i256, -1 << 127, -0x1p127);376 try test_intFromFloat_f32(i256, -1 << 127, -0x1p127);
361 try test_fixsfei(i256, -1 << 100, -0x1p100);377 try test_intFromFloat_f32(i256, -1 << 100, -0x1p100);
362 try test_fixsfei(i256, -1 << 50, -0x1p50);378 try test_intFromFloat_f32(i256, -1 << 50, -0x1p50);
363 try test_fixsfei(i256, -1 << 1, -0x1p1);379 try test_intFromFloat_f32(i256, -1 << 1, -0x1p1);
364 try test_fixsfei(i256, -1 << 0, -0x1p0);380 try test_intFromFloat_f32(i256, -1 << 0, -0x1p0);
365 try test_fixsfei(i256, 0, 0);381 try test_intFromFloat_f32(i256, 0, 0);
366 try test_fixsfei(i256, 1 << 0, 0x1p0);382 try test_intFromFloat_f32(i256, 1 << 0, 0x1p0);
367 try test_fixsfei(i256, 1 << 1, 0x1p1);383 try test_intFromFloat_f32(i256, 1 << 1, 0x1p1);
368 try test_fixsfei(i256, 1 << 50, 0x1p50);384 try test_intFromFloat_f32(i256, 1 << 50, 0x1p50);
369 try test_fixsfei(i256, 1 << 100, 0x1p100);385 try test_intFromFloat_f32(i256, 1 << 100, 0x1p100);
370 try test_fixsfei(i256, 1 << 127, 0x1p127);386 try test_intFromFloat_f32(i256, 1 << 127, 0x1p127);
371}387}
372388
373test "fixunsfei" {389test unsigned_intFromFloat_f32 {
374 try test_fixsfei(u256, 0, 0);390 try test_intFromFloat_f32(u256, 0, 0);
375 try test_fixsfei(u256, 1 << 0, 0x1p0);391 try test_intFromFloat_f32(u256, 1 << 0, 0x1p0);
376 try test_fixsfei(u256, 1 << 1, 0x1p1);392 try test_intFromFloat_f32(u256, 1 << 1, 0x1p1);
377 try test_fixsfei(u256, 1 << 50, 0x1p50);393 try test_intFromFloat_f32(u256, 1 << 50, 0x1p50);
378 try test_fixsfei(u256, 1 << 100, 0x1p100);394 try test_intFromFloat_f32(u256, 1 << 100, 0x1p100);
379 try test_fixsfei(u256, 1 << 127, 0x1p127);395 try test_intFromFloat_f32(u256, 1 << 127, 0x1p127);
380}396}
381397
382fn test__fixdfsi(a: f64, expected: i32) !void {398fn test_i32_intFromFloat_f64(a: f64, expected: i32) !void {
383 const x = __fixdfsi(a);399 const x = i32_intFromFloat_f64(a);
384 try testing.expect(x == expected);400 try testing.expect(x == expected);
385}401}
386402
387fn test__fixunsdfsi(a: f64, expected: u32) !void {403fn test_u32_intFromFloat_f64(a: f64, expected: u32) !void {
388 const x = __fixunsdfsi(a);404 const x = u32_intFromFloat_f64(a);
389 try testing.expect(x == expected);405 try testing.expect(x == expected);
390}406}
391407
392test "fixdfsi" {408test i32_intFromFloat_f64 {
393 try test__fixdfsi(-math.floatMax(f64), math.minInt(i32));409 try test_i32_intFromFloat_f64(-math.floatMax(f64), math.minInt(i32));
394410
395 try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));411 try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
396 try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);412 try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
397413
398 try test__fixdfsi(-0x1.0000000000000p+127, -0x80000000);414 try test_i32_intFromFloat_f64(-0x1.0000000000000p+127, -0x80000000);
399 try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);415 try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
400 try test__fixdfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);416 try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
401417
402 try test__fixdfsi(-0x1.0000000000001p+63, -0x80000000);418 try test_i32_intFromFloat_f64(-0x1.0000000000001p+63, -0x80000000);
403 try test__fixdfsi(-0x1.0000000000000p+63, -0x80000000);419 try test_i32_intFromFloat_f64(-0x1.0000000000000p+63, -0x80000000);
404 try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);420 try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
405 try test__fixdfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);421 try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
406422
407 try test__fixdfsi(-0x1.FFFFFEp+62, -0x80000000);423 try test_i32_intFromFloat_f64(-0x1.FFFFFEp+62, -0x80000000);
408 try test__fixdfsi(-0x1.FFFFFCp+62, -0x80000000);424 try test_i32_intFromFloat_f64(-0x1.FFFFFCp+62, -0x80000000);
409425
410 try test__fixdfsi(-0x1.000000p+31, -0x80000000);426 try test_i32_intFromFloat_f64(-0x1.000000p+31, -0x80000000);
411 try test__fixdfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0);427 try test_i32_intFromFloat_f64(-0x1.FFFFFFp+30, -0x7FFFFFC0);
412 try test__fixdfsi(-0x1.FFFFFEp+30, -0x7FFFFF80);428 try test_i32_intFromFloat_f64(-0x1.FFFFFEp+30, -0x7FFFFF80);
413429
414 try test__fixdfsi(-2.01, -2);430 try test_i32_intFromFloat_f64(-2.01, -2);
415 try test__fixdfsi(-2.0, -2);431 try test_i32_intFromFloat_f64(-2.0, -2);
416 try test__fixdfsi(-1.99, -1);432 try test_i32_intFromFloat_f64(-1.99, -1);
417 try test__fixdfsi(-1.0, -1);433 try test_i32_intFromFloat_f64(-1.0, -1);
418 try test__fixdfsi(-0.99, 0);434 try test_i32_intFromFloat_f64(-0.99, 0);
419 try test__fixdfsi(-0.5, 0);435 try test_i32_intFromFloat_f64(-0.5, 0);
420 try test__fixdfsi(-math.floatMin(f64), 0);436 try test_i32_intFromFloat_f64(-math.floatMin(f64), 0);
421 try test__fixdfsi(0.0, 0);437 try test_i32_intFromFloat_f64(0.0, 0);
422 try test__fixdfsi(math.floatMin(f64), 0);438 try test_i32_intFromFloat_f64(math.floatMin(f64), 0);
423 try test__fixdfsi(0.5, 0);439 try test_i32_intFromFloat_f64(0.5, 0);
424 try test__fixdfsi(0.99, 0);440 try test_i32_intFromFloat_f64(0.99, 0);
425 try test__fixdfsi(1.0, 1);441 try test_i32_intFromFloat_f64(1.0, 1);
426 try test__fixdfsi(1.5, 1);442 try test_i32_intFromFloat_f64(1.5, 1);
427 try test__fixdfsi(1.99, 1);443 try test_i32_intFromFloat_f64(1.99, 1);
428 try test__fixdfsi(2.0, 2);444 try test_i32_intFromFloat_f64(2.0, 2);
429 try test__fixdfsi(2.01, 2);445 try test_i32_intFromFloat_f64(2.01, 2);
430446
431 try test__fixdfsi(0x1.FFFFFEp+30, 0x7FFFFF80);447 try test_i32_intFromFloat_f64(0x1.FFFFFEp+30, 0x7FFFFF80);
432 try test__fixdfsi(0x1.FFFFFFp+30, 0x7FFFFFC0);448 try test_i32_intFromFloat_f64(0x1.FFFFFFp+30, 0x7FFFFFC0);
433 try test__fixdfsi(0x1.000000p+31, 0x7FFFFFFF);449 try test_i32_intFromFloat_f64(0x1.000000p+31, 0x7FFFFFFF);
434450
435 try test__fixdfsi(0x1.FFFFFCp+62, 0x7FFFFFFF);451 try test_i32_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFFFF);
436 try test__fixdfsi(0x1.FFFFFEp+62, 0x7FFFFFFF);452 try test_i32_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFFFF);
437453
438 try test__fixdfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);454 try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
439 try test__fixdfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);455 try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
440 try test__fixdfsi(0x1.0000000000000p+63, 0x7FFFFFFF);456 try test_i32_intFromFloat_f64(0x1.0000000000000p+63, 0x7FFFFFFF);
441 try test__fixdfsi(0x1.0000000000001p+63, 0x7FFFFFFF);457 try test_i32_intFromFloat_f64(0x1.0000000000001p+63, 0x7FFFFFFF);
442458
443 try test__fixdfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);459 try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
444 try test__fixdfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);460 try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
445 try test__fixdfsi(0x1.0000000000000p+127, 0x7FFFFFFF);461 try test_i32_intFromFloat_f64(0x1.0000000000000p+127, 0x7FFFFFFF);
446462
447 try test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);463 try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
448 try test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));464 try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
449465
450 try test__fixdfsi(math.floatMax(f64), math.maxInt(i32));466 try test_i32_intFromFloat_f64(math.floatMax(f64), math.maxInt(i32));
451}467}
452468
453test "fixunsdfsi" {469test u32_intFromFloat_f64 {
454 try test__fixunsdfsi(0.0, 0);470 try test_u32_intFromFloat_f64(0.0, 0);
455471
456 try test__fixunsdfsi(0.5, 0);472 try test_u32_intFromFloat_f64(0.5, 0);
457 try test__fixunsdfsi(0.99, 0);473 try test_u32_intFromFloat_f64(0.99, 0);
458 try test__fixunsdfsi(1.0, 1);474 try test_u32_intFromFloat_f64(1.0, 1);
459 try test__fixunsdfsi(1.5, 1);475 try test_u32_intFromFloat_f64(1.5, 1);
460 try test__fixunsdfsi(1.99, 1);476 try test_u32_intFromFloat_f64(1.99, 1);
461 try test__fixunsdfsi(2.0, 2);477 try test_u32_intFromFloat_f64(2.0, 2);
462 try test__fixunsdfsi(2.01, 2);478 try test_u32_intFromFloat_f64(2.01, 2);
463 try test__fixunsdfsi(-0.5, 0);479 try test_u32_intFromFloat_f64(-0.5, 0);
464 try test__fixunsdfsi(-0.99, 0);480 try test_u32_intFromFloat_f64(-0.99, 0);
465 try test__fixunsdfsi(-1.0, 0);481 try test_u32_intFromFloat_f64(-1.0, 0);
466 try test__fixunsdfsi(-1.5, 0);482 try test_u32_intFromFloat_f64(-1.5, 0);
467 try test__fixunsdfsi(-1.99, 0);483 try test_u32_intFromFloat_f64(-1.99, 0);
468 try test__fixunsdfsi(-2.0, 0);484 try test_u32_intFromFloat_f64(-2.0, 0);
469 try test__fixunsdfsi(-2.01, 0);485 try test_u32_intFromFloat_f64(-2.01, 0);
470486
471 try test__fixunsdfsi(0x1.000000p+31, 0x80000000);487 try test_u32_intFromFloat_f64(0x1.000000p+31, 0x80000000);
472 try test__fixunsdfsi(0x1.000000p+32, 0xFFFFFFFF);488 try test_u32_intFromFloat_f64(0x1.000000p+32, 0xFFFFFFFF);
473 try test__fixunsdfsi(0x1.FFFFFEp+31, 0xFFFFFF00);489 try test_u32_intFromFloat_f64(0x1.FFFFFEp+31, 0xFFFFFF00);
474 try test__fixunsdfsi(0x1.FFFFFEp+30, 0x7FFFFF80);490 try test_u32_intFromFloat_f64(0x1.FFFFFEp+30, 0x7FFFFF80);
475 try test__fixunsdfsi(0x1.FFFFFCp+30, 0x7FFFFF00);491 try test_u32_intFromFloat_f64(0x1.FFFFFCp+30, 0x7FFFFF00);
476492
477 try test__fixunsdfsi(-0x1.FFFFFEp+30, 0);493 try test_u32_intFromFloat_f64(-0x1.FFFFFEp+30, 0);
478 try test__fixunsdfsi(-0x1.FFFFFCp+30, 0);494 try test_u32_intFromFloat_f64(-0x1.FFFFFCp+30, 0);
479495
480 try test__fixunsdfsi(0x1.FFFFFFFEp+31, 0xFFFFFFFF);496 try test_u32_intFromFloat_f64(0x1.FFFFFFFEp+31, 0xFFFFFFFF);
481 try test__fixunsdfsi(0x1.FFFFFFFC00000p+30, 0x7FFFFFFF);497 try test_u32_intFromFloat_f64(0x1.FFFFFFFC00000p+30, 0x7FFFFFFF);
482 try test__fixunsdfsi(0x1.FFFFFFF800000p+30, 0x7FFFFFFE);498 try test_u32_intFromFloat_f64(0x1.FFFFFFF800000p+30, 0x7FFFFFFE);
483}499}
484500
485fn test__fixdfdi(a: f64, expected: i64) !void {501fn test_i64_intFromFloat_f64(a: f64, expected: i64) !void {
486 const x = __fixdfdi(a);502 const x = i64_intFromFloat_f64(a);
487 try testing.expect(x == expected);503 try testing.expect(x == expected);
488}504}
489505
490fn test__fixunsdfdi(a: f64, expected: u64) !void {506fn test_u64_intFromFloat_f64(a: f64, expected: u64) !void {
491 const x = __fixunsdfdi(a);507 const x = u64_intFromFloat_f64(a);
492 try testing.expect(x == expected);508 try testing.expect(x == expected);
493}509}
494510
495test "fixdfdi" {511test i64_intFromFloat_f64 {
496 try test__fixdfdi(-math.floatMax(f64), math.minInt(i64));512 try test_i64_intFromFloat_f64(-math.floatMax(f64), math.minInt(i64));
497513
498 try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));514 try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
499 try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);515 try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
500516
501 try test__fixdfdi(-0x1.0000000000000p+127, -0x8000000000000000);517 try test_i64_intFromFloat_f64(-0x1.0000000000000p+127, -0x8000000000000000);
502 try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);518 try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
503 try test__fixdfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);519 try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
504520
505 try test__fixdfdi(-0x1.0000000000001p+63, -0x8000000000000000);521 try test_i64_intFromFloat_f64(-0x1.0000000000001p+63, -0x8000000000000000);
506 try test__fixdfdi(-0x1.0000000000000p+63, -0x8000000000000000);522 try test_i64_intFromFloat_f64(-0x1.0000000000000p+63, -0x8000000000000000);
507 try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);523 try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
508 try test__fixdfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);524 try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
509525
510 try test__fixdfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000);526 try test_i64_intFromFloat_f64(-0x1.FFFFFEp+62, -0x7fffff8000000000);
511 try test__fixdfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000);527 try test_i64_intFromFloat_f64(-0x1.FFFFFCp+62, -0x7fffff0000000000);
512528
513 try test__fixdfdi(-2.01, -2);529 try test_i64_intFromFloat_f64(-2.01, -2);
514 try test__fixdfdi(-2.0, -2);530 try test_i64_intFromFloat_f64(-2.0, -2);
515 try test__fixdfdi(-1.99, -1);531 try test_i64_intFromFloat_f64(-1.99, -1);
516 try test__fixdfdi(-1.0, -1);532 try test_i64_intFromFloat_f64(-1.0, -1);
517 try test__fixdfdi(-0.99, 0);533 try test_i64_intFromFloat_f64(-0.99, 0);
518 try test__fixdfdi(-0.5, 0);534 try test_i64_intFromFloat_f64(-0.5, 0);
519 try test__fixdfdi(-math.floatMin(f64), 0);535 try test_i64_intFromFloat_f64(-math.floatMin(f64), 0);
520 try test__fixdfdi(0.0, 0);536 try test_i64_intFromFloat_f64(0.0, 0);
521 try test__fixdfdi(math.floatMin(f64), 0);537 try test_i64_intFromFloat_f64(math.floatMin(f64), 0);
522 try test__fixdfdi(0.5, 0);538 try test_i64_intFromFloat_f64(0.5, 0);
523 try test__fixdfdi(0.99, 0);539 try test_i64_intFromFloat_f64(0.99, 0);
524 try test__fixdfdi(1.0, 1);540 try test_i64_intFromFloat_f64(1.0, 1);
525 try test__fixdfdi(1.5, 1);541 try test_i64_intFromFloat_f64(1.5, 1);
526 try test__fixdfdi(1.99, 1);542 try test_i64_intFromFloat_f64(1.99, 1);
527 try test__fixdfdi(2.0, 2);543 try test_i64_intFromFloat_f64(2.0, 2);
528 try test__fixdfdi(2.01, 2);544 try test_i64_intFromFloat_f64(2.01, 2);
529545
530 try test__fixdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);546 try test_i64_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
531 try test__fixdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);547 try test_i64_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
532548
533 try test__fixdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);549 try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
534 try test__fixdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);550 try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
535 try test__fixdfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);551 try test_i64_intFromFloat_f64(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
536 try test__fixdfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);552 try test_i64_intFromFloat_f64(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
537553
538 try test__fixdfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);554 try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
539 try test__fixdfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);555 try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
540 try test__fixdfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);556 try test_i64_intFromFloat_f64(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
541557
542 try test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);558 try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
543 try test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));559 try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
544560
545 try test__fixdfdi(math.floatMax(f64), math.maxInt(i64));561 try test_i64_intFromFloat_f64(math.floatMax(f64), math.maxInt(i64));
546}562}
547563
548test "fixunsdfdi" {564test u64_intFromFloat_f64 {
549 try test__fixunsdfdi(0.0, 0);565 try test_u64_intFromFloat_f64(0.0, 0);
550 try test__fixunsdfdi(0.5, 0);566 try test_u64_intFromFloat_f64(0.5, 0);
551 try test__fixunsdfdi(0.99, 0);567 try test_u64_intFromFloat_f64(0.99, 0);
552 try test__fixunsdfdi(1.0, 1);568 try test_u64_intFromFloat_f64(1.0, 1);
553 try test__fixunsdfdi(1.5, 1);569 try test_u64_intFromFloat_f64(1.5, 1);
554 try test__fixunsdfdi(1.99, 1);570 try test_u64_intFromFloat_f64(1.99, 1);
555 try test__fixunsdfdi(2.0, 2);571 try test_u64_intFromFloat_f64(2.0, 2);
556 try test__fixunsdfdi(2.01, 2);572 try test_u64_intFromFloat_f64(2.01, 2);
557 try test__fixunsdfdi(-0.5, 0);573 try test_u64_intFromFloat_f64(-0.5, 0);
558 try test__fixunsdfdi(-0.99, 0);574 try test_u64_intFromFloat_f64(-0.99, 0);
559 try test__fixunsdfdi(-1.0, 0);575 try test_u64_intFromFloat_f64(-1.0, 0);
560 try test__fixunsdfdi(-1.5, 0);576 try test_u64_intFromFloat_f64(-1.5, 0);
561 try test__fixunsdfdi(-1.99, 0);577 try test_u64_intFromFloat_f64(-1.99, 0);
562 try test__fixunsdfdi(-2.0, 0);578 try test_u64_intFromFloat_f64(-2.0, 0);
563 try test__fixunsdfdi(-2.01, 0);579 try test_u64_intFromFloat_f64(-2.01, 0);
564580
565 try test__fixunsdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);581 try test_u64_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
566 try test__fixunsdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);582 try test_u64_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
567583
568 try test__fixunsdfdi(-0x1.FFFFFEp+62, 0);584 try test_u64_intFromFloat_f64(-0x1.FFFFFEp+62, 0);
569 try test__fixunsdfdi(-0x1.FFFFFCp+62, 0);585 try test_u64_intFromFloat_f64(-0x1.FFFFFCp+62, 0);
570586
571 try test__fixunsdfdi(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800);587 try test_u64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800);
572 try test__fixunsdfdi(0x1.0000000000000p+63, 0x8000000000000000);588 try test_u64_intFromFloat_f64(0x1.0000000000000p+63, 0x8000000000000000);
573 try test__fixunsdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);589 try test_u64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
574 try test__fixunsdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);590 try test_u64_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
575591
576 try test__fixunsdfdi(-0x1.FFFFFFFFFFFFFp+62, 0);592 try test_u64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, 0);
577 try test__fixunsdfdi(-0x1.FFFFFFFFFFFFEp+62, 0);593 try test_u64_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, 0);
578}594}
579595
580fn test__fixdfti(a: f64, expected: i128) !void {596fn test_i128_intFromFloat_f64(a: f64, expected: i128) !void {
581 const x = __fixdfti(a);597 const x = i128_intFromFloat_f64(a);
582 try testing.expect(x == expected);598 try testing.expect(x == expected);
583}599}
584600
585fn test__fixunsdfti(a: f64, expected: u128) !void {601fn test_u128_intFromFloat_f64(a: f64, expected: u128) !void {
586 const x = __fixunsdfti(a);602 const x = u128_intFromFloat_f64(a);
587 try testing.expect(x == expected);603 try testing.expect(x == expected);
588}604}
589605
590test "fixdfti" {606test i128_intFromFloat_f64 {
591 try test__fixdfti(-math.floatMax(f64), math.minInt(i128));607 try test_i128_intFromFloat_f64(-math.floatMax(f64), math.minInt(i128));
592608
593 try test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));609 try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
594 try test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);610 try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
595611
596 try test__fixdfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);612 try test_i128_intFromFloat_f64(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
597 try test__fixdfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000);613 try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000);
598 try test__fixdfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000);614 try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000);
599615
600 try test__fixdfti(-0x1.0000000000001p+63, -0x8000000000000800);616 try test_i128_intFromFloat_f64(-0x1.0000000000001p+63, -0x8000000000000800);
601 try test__fixdfti(-0x1.0000000000000p+63, -0x8000000000000000);617 try test_i128_intFromFloat_f64(-0x1.0000000000000p+63, -0x8000000000000000);
602 try test__fixdfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);618 try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
603 try test__fixdfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);619 try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
604620
605 try test__fixdfti(-0x1.FFFFFEp+62, -0x7fffff8000000000);621 try test_i128_intFromFloat_f64(-0x1.FFFFFEp+62, -0x7fffff8000000000);
606 try test__fixdfti(-0x1.FFFFFCp+62, -0x7fffff0000000000);622 try test_i128_intFromFloat_f64(-0x1.FFFFFCp+62, -0x7fffff0000000000);
607623
608 try test__fixdfti(-2.01, -2);624 try test_i128_intFromFloat_f64(-2.01, -2);
609 try test__fixdfti(-2.0, -2);625 try test_i128_intFromFloat_f64(-2.0, -2);
610 try test__fixdfti(-1.99, -1);626 try test_i128_intFromFloat_f64(-1.99, -1);
611 try test__fixdfti(-1.0, -1);627 try test_i128_intFromFloat_f64(-1.0, -1);
612 try test__fixdfti(-0.99, 0);628 try test_i128_intFromFloat_f64(-0.99, 0);
613 try test__fixdfti(-0.5, 0);629 try test_i128_intFromFloat_f64(-0.5, 0);
614 try test__fixdfti(-math.floatMin(f64), 0);630 try test_i128_intFromFloat_f64(-math.floatMin(f64), 0);
615 try test__fixdfti(0.0, 0);631 try test_i128_intFromFloat_f64(0.0, 0);
616 try test__fixdfti(math.floatMin(f64), 0);632 try test_i128_intFromFloat_f64(math.floatMin(f64), 0);
617 try test__fixdfti(0.5, 0);633 try test_i128_intFromFloat_f64(0.5, 0);
618 try test__fixdfti(0.99, 0);634 try test_i128_intFromFloat_f64(0.99, 0);
619 try test__fixdfti(1.0, 1);635 try test_i128_intFromFloat_f64(1.0, 1);
620 try test__fixdfti(1.5, 1);636 try test_i128_intFromFloat_f64(1.5, 1);
621 try test__fixdfti(1.99, 1);637 try test_i128_intFromFloat_f64(1.99, 1);
622 try test__fixdfti(2.0, 2);638 try test_i128_intFromFloat_f64(2.0, 2);
623 try test__fixdfti(2.01, 2);639 try test_i128_intFromFloat_f64(2.01, 2);
624640
625 try test__fixdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);641 try test_i128_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
626 try test__fixdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);642 try test_i128_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
627643
628 try test__fixdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);644 try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
629 try test__fixdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);645 try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
630 try test__fixdfti(0x1.0000000000000p+63, 0x8000000000000000);646 try test_i128_intFromFloat_f64(0x1.0000000000000p+63, 0x8000000000000000);
631 try test__fixdfti(0x1.0000000000001p+63, 0x8000000000000800);647 try test_i128_intFromFloat_f64(0x1.0000000000001p+63, 0x8000000000000800);
632648
633 try test__fixdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);649 try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
634 try test__fixdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);650 try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
635 try test__fixdfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);651 try test_i128_intFromFloat_f64(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
636652
637 try test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);653 try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
638 try test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));654 try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
639655
640 try test__fixdfti(math.floatMax(f64), math.maxInt(i128));656 try test_i128_intFromFloat_f64(math.floatMax(f64), math.maxInt(i128));
641}657}
642658
643test "fixunsdfti" {659test u128_intFromFloat_f64 {
644 try test__fixunsdfti(0.0, 0);660 try test_u128_intFromFloat_f64(0.0, 0);
645661
646 try test__fixunsdfti(0.5, 0);662 try test_u128_intFromFloat_f64(0.5, 0);
647 try test__fixunsdfti(0.99, 0);663 try test_u128_intFromFloat_f64(0.99, 0);
648 try test__fixunsdfti(1.0, 1);664 try test_u128_intFromFloat_f64(1.0, 1);
649 try test__fixunsdfti(1.5, 1);665 try test_u128_intFromFloat_f64(1.5, 1);
650 try test__fixunsdfti(1.99, 1);666 try test_u128_intFromFloat_f64(1.99, 1);
651 try test__fixunsdfti(2.0, 2);667 try test_u128_intFromFloat_f64(2.0, 2);
652 try test__fixunsdfti(2.01, 2);668 try test_u128_intFromFloat_f64(2.01, 2);
653 try test__fixunsdfti(-0.5, 0);669 try test_u128_intFromFloat_f64(-0.5, 0);
654 try test__fixunsdfti(-0.99, 0);670 try test_u128_intFromFloat_f64(-0.99, 0);
655 try test__fixunsdfti(-1.0, 0);671 try test_u128_intFromFloat_f64(-1.0, 0);
656 try test__fixunsdfti(-1.5, 0);672 try test_u128_intFromFloat_f64(-1.5, 0);
657 try test__fixunsdfti(-1.99, 0);673 try test_u128_intFromFloat_f64(-1.99, 0);
658 try test__fixunsdfti(-2.0, 0);674 try test_u128_intFromFloat_f64(-2.0, 0);
659 try test__fixunsdfti(-2.01, 0);675 try test_u128_intFromFloat_f64(-2.01, 0);
660676
661 try test__fixunsdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);677 try test_u128_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
662 try test__fixunsdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);678 try test_u128_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
663679
664 try test__fixunsdfti(-0x1.FFFFFEp+62, 0);680 try test_u128_intFromFloat_f64(-0x1.FFFFFEp+62, 0);
665 try test__fixunsdfti(-0x1.FFFFFCp+62, 0);681 try test_u128_intFromFloat_f64(-0x1.FFFFFCp+62, 0);
666682
667 try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800);683 try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800);
668 try test__fixunsdfti(0x1.0000000000000p+63, 0x8000000000000000);684 try test_u128_intFromFloat_f64(0x1.0000000000000p+63, 0x8000000000000000);
669 try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);685 try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
670 try test__fixunsdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);686 try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
671687
672 try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+127, 0xFFFFFFFFFFFFF8000000000000000000);688 try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+127, 0xFFFFFFFFFFFFF8000000000000000000);
673 try test__fixunsdfti(0x1.0000000000000p+127, 0x80000000000000000000000000000000);689 try test_u128_intFromFloat_f64(0x1.0000000000000p+127, 0x80000000000000000000000000000000);
674 try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);690 try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
675 try test__fixunsdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);691 try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
676 try test__fixunsdfti(0x1.0000000000000p+128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);692 try test_u128_intFromFloat_f64(0x1.0000000000000p+128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
677693
678 try test__fixunsdfti(-0x1.FFFFFFFFFFFFFp+62, 0);694 try test_u128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, 0);
679 try test__fixunsdfti(-0x1.FFFFFFFFFFFFEp+62, 0);695 try test_u128_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, 0);
680}696}
681697
682fn test_fixdfei(comptime T: type, expected: T, a: f64) !void {698fn test_intFromFloat_f64(comptime T: type, expected: T, a: f64) !void {
683 const int = @typeInfo(T).int;699 const int = @typeInfo(T).int;
684 var actual: T = undefined;700 var actual: T = undefined;
685 _ = switch (int.signedness) {701 _ = switch (int.signedness) {
686 .signed => __fixdfei,702 .signed => signed_intFromFloat_f64,
687 .unsigned => __fixunsdfei,703 .unsigned => unsigned_intFromFloat_f64,
688 }(@ptrCast(&actual), int.bits, a);704 }(@ptrCast(&actual), a);
689 try testing.expect(expected == actual);705 try testing.expect(expected == actual);
690}706}
691707
692test "fixdfei" {708test signed_intFromFloat_f64 {
693 try test_fixdfei(i256, -1 << 255, -0x1p255);709 try test_intFromFloat_f64(i256, -1 << 255, -0x1p255);
694 try test_fixdfei(i256, -1 << 127, -0x1p127);710 try test_intFromFloat_f64(i256, -1 << 127, -0x1p127);
695 try test_fixdfei(i256, -1 << 100, -0x1p100);711 try test_intFromFloat_f64(i256, -1 << 100, -0x1p100);
696 try test_fixdfei(i256, -1 << 50, -0x1p50);712 try test_intFromFloat_f64(i256, -1 << 50, -0x1p50);
697 try test_fixdfei(i256, -1 << 1, -0x1p1);713 try test_intFromFloat_f64(i256, -1 << 1, -0x1p1);
698 try test_fixdfei(i256, -1 << 0, -0x1p0);714 try test_intFromFloat_f64(i256, -1 << 0, -0x1p0);
699 try test_fixdfei(i256, 0, 0);715 try test_intFromFloat_f64(i256, 0, 0);
700 try test_fixdfei(i256, 1 << 0, 0x1p0);716 try test_intFromFloat_f64(i256, 1 << 0, 0x1p0);
701 try test_fixdfei(i256, 1 << 1, 0x1p1);717 try test_intFromFloat_f64(i256, 1 << 1, 0x1p1);
702 try test_fixdfei(i256, 1 << 50, 0x1p50);718 try test_intFromFloat_f64(i256, 1 << 50, 0x1p50);
703 try test_fixdfei(i256, 1 << 100, 0x1p100);719 try test_intFromFloat_f64(i256, 1 << 100, 0x1p100);
704 try test_fixdfei(i256, 1 << 127, 0x1p127);720 try test_intFromFloat_f64(i256, 1 << 127, 0x1p127);
705 try test_fixdfei(i256, 1 << 254, 0x1p254);721 try test_intFromFloat_f64(i256, 1 << 254, 0x1p254);
706}722}
707723
708test "fixundfei" {724test unsigned_intFromFloat_f64 {
709 try test_fixdfei(u256, 0, 0);725 try test_intFromFloat_f64(u256, 0, 0);
710 try test_fixdfei(u256, 1 << 0, 0x1p0);726 try test_intFromFloat_f64(u256, 1 << 0, 0x1p0);
711 try test_fixdfei(u256, 1 << 1, 0x1p1);727 try test_intFromFloat_f64(u256, 1 << 1, 0x1p1);
712 try test_fixdfei(u256, 1 << 50, 0x1p50);728 try test_intFromFloat_f64(u256, 1 << 50, 0x1p50);
713 try test_fixdfei(u256, 1 << 100, 0x1p100);729 try test_intFromFloat_f64(u256, 1 << 100, 0x1p100);
714 try test_fixdfei(u256, 1 << 127, 0x1p127);730 try test_intFromFloat_f64(u256, 1 << 127, 0x1p127);
715 try test_fixdfei(u256, 1 << 255, 0x1p255);731 try test_intFromFloat_f64(u256, 1 << 255, 0x1p255);
716}732}
717733
718fn test__fixtfsi(a: f128, expected: i32) !void {734fn test_i32_intFromFloat_f128(a: f128, expected: i32) !void {
719 const x = __fixtfsi(a);735 const x = i32_intFromFloat_f128(a);
720 try testing.expect(x == expected);736 try testing.expect(x == expected);
721}737}
722738
723fn test__fixunstfsi(a: f128, expected: u32) !void {739fn test_u32_intFromFloat_f128(a: f128, expected: u32) !void {
724 const x = __fixunstfsi(a);740 const x = u32_intFromFloat_f128(a);
725 try testing.expect(x == expected);741 try testing.expect(x == expected);
726}742}
727743
728test "fixtfsi" {744test i32_intFromFloat_f128 {
729 try test__fixtfsi(-math.floatMax(f128), math.minInt(i32));745 try test_i32_intFromFloat_f128(-math.floatMax(f128), math.minInt(i32));
730746
731 try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));747 try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
732 try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);748 try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
733749
734 try test__fixtfsi(-0x1.0000000000000p+127, -0x80000000);750 try test_i32_intFromFloat_f128(-0x1.0000000000000p+127, -0x80000000);
735 try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);751 try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
736 try test__fixtfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);752 try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
737753
738 try test__fixtfsi(-0x1.0000000000001p+63, -0x80000000);754 try test_i32_intFromFloat_f128(-0x1.0000000000001p+63, -0x80000000);
739 try test__fixtfsi(-0x1.0000000000000p+63, -0x80000000);755 try test_i32_intFromFloat_f128(-0x1.0000000000000p+63, -0x80000000);
740 try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);756 try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
741 try test__fixtfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);757 try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
742758
743 try test__fixtfsi(-0x1.FFFFFEp+62, -0x80000000);759 try test_i32_intFromFloat_f128(-0x1.FFFFFEp+62, -0x80000000);
744 try test__fixtfsi(-0x1.FFFFFCp+62, -0x80000000);760 try test_i32_intFromFloat_f128(-0x1.FFFFFCp+62, -0x80000000);
745761
746 try test__fixtfsi(-0x1.000000p+31, -0x80000000);762 try test_i32_intFromFloat_f128(-0x1.000000p+31, -0x80000000);
747 try test__fixtfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0);763 try test_i32_intFromFloat_f128(-0x1.FFFFFFp+30, -0x7FFFFFC0);
748 try test__fixtfsi(-0x1.FFFFFEp+30, -0x7FFFFF80);764 try test_i32_intFromFloat_f128(-0x1.FFFFFEp+30, -0x7FFFFF80);
749 try test__fixtfsi(-0x1.FFFFFCp+30, -0x7FFFFF00);765 try test_i32_intFromFloat_f128(-0x1.FFFFFCp+30, -0x7FFFFF00);
750766
751 try test__fixtfsi(-2.01, -2);767 try test_i32_intFromFloat_f128(-2.01, -2);
752 try test__fixtfsi(-2.0, -2);768 try test_i32_intFromFloat_f128(-2.0, -2);
753 try test__fixtfsi(-1.99, -1);769 try test_i32_intFromFloat_f128(-1.99, -1);
754 try test__fixtfsi(-1.0, -1);770 try test_i32_intFromFloat_f128(-1.0, -1);
755 try test__fixtfsi(-0.99, 0);771 try test_i32_intFromFloat_f128(-0.99, 0);
756 try test__fixtfsi(-0.5, 0);772 try test_i32_intFromFloat_f128(-0.5, 0);
757 try test__fixtfsi(-math.floatMin(f32), 0);773 try test_i32_intFromFloat_f128(-math.floatMin(f32), 0);
758 try test__fixtfsi(0.0, 0);774 try test_i32_intFromFloat_f128(0.0, 0);
759 try test__fixtfsi(math.floatMin(f32), 0);775 try test_i32_intFromFloat_f128(math.floatMin(f32), 0);
760 try test__fixtfsi(0.5, 0);776 try test_i32_intFromFloat_f128(0.5, 0);
761 try test__fixtfsi(0.99, 0);777 try test_i32_intFromFloat_f128(0.99, 0);
762 try test__fixtfsi(1.0, 1);778 try test_i32_intFromFloat_f128(1.0, 1);
763 try test__fixtfsi(1.5, 1);779 try test_i32_intFromFloat_f128(1.5, 1);
764 try test__fixtfsi(1.99, 1);780 try test_i32_intFromFloat_f128(1.99, 1);
765 try test__fixtfsi(2.0, 2);781 try test_i32_intFromFloat_f128(2.0, 2);
766 try test__fixtfsi(2.01, 2);782 try test_i32_intFromFloat_f128(2.01, 2);
767783
768 try test__fixtfsi(0x1.FFFFFCp+30, 0x7FFFFF00);784 try test_i32_intFromFloat_f128(0x1.FFFFFCp+30, 0x7FFFFF00);
769 try test__fixtfsi(0x1.FFFFFEp+30, 0x7FFFFF80);785 try test_i32_intFromFloat_f128(0x1.FFFFFEp+30, 0x7FFFFF80);
770 try test__fixtfsi(0x1.FFFFFFp+30, 0x7FFFFFC0);786 try test_i32_intFromFloat_f128(0x1.FFFFFFp+30, 0x7FFFFFC0);
771 try test__fixtfsi(0x1.000000p+31, 0x7FFFFFFF);787 try test_i32_intFromFloat_f128(0x1.000000p+31, 0x7FFFFFFF);
772788
773 try test__fixtfsi(0x1.FFFFFCp+62, 0x7FFFFFFF);789 try test_i32_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFFFF);
774 try test__fixtfsi(0x1.FFFFFEp+62, 0x7FFFFFFF);790 try test_i32_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFFFF);
775791
776 try test__fixtfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);792 try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
777 try test__fixtfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);793 try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
778 try test__fixtfsi(0x1.0000000000000p+63, 0x7FFFFFFF);794 try test_i32_intFromFloat_f128(0x1.0000000000000p+63, 0x7FFFFFFF);
779 try test__fixtfsi(0x1.0000000000001p+63, 0x7FFFFFFF);795 try test_i32_intFromFloat_f128(0x1.0000000000001p+63, 0x7FFFFFFF);
780796
781 try test__fixtfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);797 try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
782 try test__fixtfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);798 try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
783 try test__fixtfsi(0x1.0000000000000p+127, 0x7FFFFFFF);799 try test_i32_intFromFloat_f128(0x1.0000000000000p+127, 0x7FFFFFFF);
784800
785 try test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);801 try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
786 try test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));802 try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
787803
788 try test__fixtfsi(math.floatMax(f128), math.maxInt(i32));804 try test_i32_intFromFloat_f128(math.floatMax(f128), math.maxInt(i32));
789}805}
790806
791test "fixunstfsi" {807test u32_intFromFloat_f128 {
792 try test__fixunstfsi(math.inf(f128), 0xffffffff);808 try test_u32_intFromFloat_f128(math.inf(f128), 0xffffffff);
793 try test__fixunstfsi(0, 0x0);809 try test_u32_intFromFloat_f128(0, 0x0);
794 try test__fixunstfsi(0x1.23456789abcdefp+5, 0x24);810 try test_u32_intFromFloat_f128(0x1.23456789abcdefp+5, 0x24);
795 try test__fixunstfsi(0x1.23456789abcdefp-3, 0x0);811 try test_u32_intFromFloat_f128(0x1.23456789abcdefp-3, 0x0);
796 try test__fixunstfsi(0x1.23456789abcdefp+20, 0x123456);812 try test_u32_intFromFloat_f128(0x1.23456789abcdefp+20, 0x123456);
797 try test__fixunstfsi(0x1.23456789abcdefp+40, 0xffffffff);813 try test_u32_intFromFloat_f128(0x1.23456789abcdefp+40, 0xffffffff);
798 try test__fixunstfsi(0x1.23456789abcdefp+256, 0xffffffff);814 try test_u32_intFromFloat_f128(0x1.23456789abcdefp+256, 0xffffffff);
799 try test__fixunstfsi(-0x1.23456789abcdefp+3, 0x0);815 try test_u32_intFromFloat_f128(-0x1.23456789abcdefp+3, 0x0);
800816
801 try test__fixunstfsi(0x1p+32, 0xFFFFFFFF);817 try test_u32_intFromFloat_f128(0x1p+32, 0xFFFFFFFF);
802}818}
803819
804fn test__fixtfdi(a: f128, expected: i64) !void {820fn test_i64_intFromFloat_f128(a: f128, expected: i64) !void {
805 const x = __fixtfdi(a);821 const x = i64_intFromFloat_f128(a);
806 try testing.expect(x == expected);822 try testing.expect(x == expected);
807}823}
808824
809fn test__fixunstfdi(a: f128, expected: u64) !void {825fn test_u64_intFromFloat_f128(a: f128, expected: u64) !void {
810 const x = __fixunstfdi(a);826 const x = u64_intFromFloat_f128(a);
811 try testing.expect(x == expected);827 try testing.expect(x == expected);
812}828}
813829
814test "fixtfdi" {830test i64_intFromFloat_f128 {
815 try test__fixtfdi(-math.floatMax(f128), math.minInt(i64));831 try test_i64_intFromFloat_f128(-math.floatMax(f128), math.minInt(i64));
816832
817 try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));833 try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
818 try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);834 try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
819835
820 try test__fixtfdi(-0x1.0000000000000p+127, -0x8000000000000000);836 try test_i64_intFromFloat_f128(-0x1.0000000000000p+127, -0x8000000000000000);
821 try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);837 try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
822 try test__fixtfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);838 try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
823839
824 try test__fixtfdi(-0x1.0000000000001p+63, -0x8000000000000000);840 try test_i64_intFromFloat_f128(-0x1.0000000000001p+63, -0x8000000000000000);
825 try test__fixtfdi(-0x1.0000000000000p+63, -0x8000000000000000);841 try test_i64_intFromFloat_f128(-0x1.0000000000000p+63, -0x8000000000000000);
826 try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);842 try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
827 try test__fixtfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);843 try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
828844
829 try test__fixtfdi(-0x1.FFFFFEp+62, -0x7FFFFF8000000000);845 try test_i64_intFromFloat_f128(-0x1.FFFFFEp+62, -0x7FFFFF8000000000);
830 try test__fixtfdi(-0x1.FFFFFCp+62, -0x7FFFFF0000000000);846 try test_i64_intFromFloat_f128(-0x1.FFFFFCp+62, -0x7FFFFF0000000000);
831847
832 try test__fixtfdi(-0x1.000000p+31, -0x80000000);848 try test_i64_intFromFloat_f128(-0x1.000000p+31, -0x80000000);
833 try test__fixtfdi(-0x1.FFFFFFp+30, -0x7FFFFFC0);849 try test_i64_intFromFloat_f128(-0x1.FFFFFFp+30, -0x7FFFFFC0);
834 try test__fixtfdi(-0x1.FFFFFEp+30, -0x7FFFFF80);850 try test_i64_intFromFloat_f128(-0x1.FFFFFEp+30, -0x7FFFFF80);
835 try test__fixtfdi(-0x1.FFFFFCp+30, -0x7FFFFF00);851 try test_i64_intFromFloat_f128(-0x1.FFFFFCp+30, -0x7FFFFF00);
836852
837 try test__fixtfdi(-2.01, -2);853 try test_i64_intFromFloat_f128(-2.01, -2);
838 try test__fixtfdi(-2.0, -2);854 try test_i64_intFromFloat_f128(-2.0, -2);
839 try test__fixtfdi(-1.99, -1);855 try test_i64_intFromFloat_f128(-1.99, -1);
840 try test__fixtfdi(-1.0, -1);856 try test_i64_intFromFloat_f128(-1.0, -1);
841 try test__fixtfdi(-0.99, 0);857 try test_i64_intFromFloat_f128(-0.99, 0);
842 try test__fixtfdi(-0.5, 0);858 try test_i64_intFromFloat_f128(-0.5, 0);
843 try test__fixtfdi(-math.floatMin(f64), 0);859 try test_i64_intFromFloat_f128(-math.floatMin(f64), 0);
844 try test__fixtfdi(0.0, 0);860 try test_i64_intFromFloat_f128(0.0, 0);
845 try test__fixtfdi(math.floatMin(f64), 0);861 try test_i64_intFromFloat_f128(math.floatMin(f64), 0);
846 try test__fixtfdi(0.5, 0);862 try test_i64_intFromFloat_f128(0.5, 0);
847 try test__fixtfdi(0.99, 0);863 try test_i64_intFromFloat_f128(0.99, 0);
848 try test__fixtfdi(1.0, 1);864 try test_i64_intFromFloat_f128(1.0, 1);
849 try test__fixtfdi(1.5, 1);865 try test_i64_intFromFloat_f128(1.5, 1);
850 try test__fixtfdi(1.99, 1);866 try test_i64_intFromFloat_f128(1.99, 1);
851 try test__fixtfdi(2.0, 2);867 try test_i64_intFromFloat_f128(2.0, 2);
852 try test__fixtfdi(2.01, 2);868 try test_i64_intFromFloat_f128(2.01, 2);
853869
854 try test__fixtfdi(0x1.FFFFFCp+30, 0x7FFFFF00);870 try test_i64_intFromFloat_f128(0x1.FFFFFCp+30, 0x7FFFFF00);
855 try test__fixtfdi(0x1.FFFFFEp+30, 0x7FFFFF80);871 try test_i64_intFromFloat_f128(0x1.FFFFFEp+30, 0x7FFFFF80);
856 try test__fixtfdi(0x1.FFFFFFp+30, 0x7FFFFFC0);872 try test_i64_intFromFloat_f128(0x1.FFFFFFp+30, 0x7FFFFFC0);
857 try test__fixtfdi(0x1.000000p+31, 0x80000000);873 try test_i64_intFromFloat_f128(0x1.000000p+31, 0x80000000);
858874
859 try test__fixtfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);875 try test_i64_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
860 try test__fixtfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);876 try test_i64_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
861877
862 try test__fixtfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);878 try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
863 try test__fixtfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);879 try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
864 try test__fixtfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);880 try test_i64_intFromFloat_f128(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
865 try test__fixtfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);881 try test_i64_intFromFloat_f128(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
866882
867 try test__fixtfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);883 try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
868 try test__fixtfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);884 try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
869 try test__fixtfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);885 try test_i64_intFromFloat_f128(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
870886
871 try test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);887 try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
872 try test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));888 try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
873889
874 try test__fixtfdi(math.floatMax(f128), math.maxInt(i64));890 try test_i64_intFromFloat_f128(math.floatMax(f128), math.maxInt(i64));
875}891}
876892
877test "fixunstfdi" {893test u64_intFromFloat_f128 {
878 try test__fixunstfdi(0.0, 0);894 try test_u64_intFromFloat_f128(0.0, 0);
879895
880 try test__fixunstfdi(0.5, 0);896 try test_u64_intFromFloat_f128(0.5, 0);
881 try test__fixunstfdi(0.99, 0);897 try test_u64_intFromFloat_f128(0.99, 0);
882 try test__fixunstfdi(1.0, 1);898 try test_u64_intFromFloat_f128(1.0, 1);
883 try test__fixunstfdi(1.5, 1);899 try test_u64_intFromFloat_f128(1.5, 1);
884 try test__fixunstfdi(1.99, 1);900 try test_u64_intFromFloat_f128(1.99, 1);
885 try test__fixunstfdi(2.0, 2);901 try test_u64_intFromFloat_f128(2.0, 2);
886 try test__fixunstfdi(2.01, 2);902 try test_u64_intFromFloat_f128(2.01, 2);
887 try test__fixunstfdi(-0.5, 0);903 try test_u64_intFromFloat_f128(-0.5, 0);
888 try test__fixunstfdi(-0.99, 0);904 try test_u64_intFromFloat_f128(-0.99, 0);
889 try test__fixunstfdi(-1.0, 0);905 try test_u64_intFromFloat_f128(-1.0, 0);
890 try test__fixunstfdi(-1.5, 0);906 try test_u64_intFromFloat_f128(-1.5, 0);
891 try test__fixunstfdi(-1.99, 0);907 try test_u64_intFromFloat_f128(-1.99, 0);
892 try test__fixunstfdi(-2.0, 0);908 try test_u64_intFromFloat_f128(-2.0, 0);
893 try test__fixunstfdi(-2.01, 0);909 try test_u64_intFromFloat_f128(-2.01, 0);
894910
895 try test__fixunstfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);911 try test_u64_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
896 try test__fixunstfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);912 try test_u64_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
897913
898 try test__fixunstfdi(-0x1.FFFFFEp+62, 0);914 try test_u64_intFromFloat_f128(-0x1.FFFFFEp+62, 0);
899 try test__fixunstfdi(-0x1.FFFFFCp+62, 0);915 try test_u64_intFromFloat_f128(-0x1.FFFFFCp+62, 0);
900916
901 try test__fixunstfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);917 try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
902 try test__fixunstfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);918 try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
903919
904 try test__fixunstfdi(-0x1.FFFFFFFFFFFFFp+62, 0);920 try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, 0);
905 try test__fixunstfdi(-0x1.FFFFFFFFFFFFEp+62, 0);921 try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, 0);
906922
907 try test__fixunstfdi(0x1.FFFFFFFFFFFFFFFEp+63, 0xFFFFFFFFFFFFFFFF);923 try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFFFEp+63, 0xFFFFFFFFFFFFFFFF);
908 try test__fixunstfdi(0x1.0000000000000002p+63, 0x8000000000000001);924 try test_u64_intFromFloat_f128(0x1.0000000000000002p+63, 0x8000000000000001);
909 try test__fixunstfdi(0x1.0000000000000000p+63, 0x8000000000000000);925 try test_u64_intFromFloat_f128(0x1.0000000000000000p+63, 0x8000000000000000);
910 try test__fixunstfdi(0x1.FFFFFFFFFFFFFFFCp+62, 0x7FFFFFFFFFFFFFFF);926 try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFFFCp+62, 0x7FFFFFFFFFFFFFFF);
911 try test__fixunstfdi(0x1.FFFFFFFFFFFFFFF8p+62, 0x7FFFFFFFFFFFFFFE);927 try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFFF8p+62, 0x7FFFFFFFFFFFFFFE);
912 try test__fixunstfdi(0x1p+64, 0xFFFFFFFFFFFFFFFF);928 try test_u64_intFromFloat_f128(0x1p+64, 0xFFFFFFFFFFFFFFFF);
913929
914 try test__fixunstfdi(-0x1.0000000000000000p+63, 0);930 try test_u64_intFromFloat_f128(-0x1.0000000000000000p+63, 0);
915 try test__fixunstfdi(-0x1.FFFFFFFFFFFFFFFCp+62, 0);931 try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFFFCp+62, 0);
916 try test__fixunstfdi(-0x1.FFFFFFFFFFFFFFF8p+62, 0);932 try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFFF8p+62, 0);
917}933}
918934
919fn test__fixtfti(a: f128, expected: i128) !void {935fn test_i128_intFromFloat_f128(a: f128, expected: i128) !void {
920 const x = __fixtfti(a);936 const x = i128_intFromFloat_f128(a);
921 try testing.expect(x == expected);937 try testing.expect(x == expected);
922}938}
923939
924fn test__fixunstfti(a: f128, expected: u128) !void {940fn test_u128_intFromFloat_f128(a: f128, expected: u128) !void {
925 const x = __fixunstfti(a);941 const x = u128_intFromFloat_f128(a);
926 try testing.expect(x == expected);942 try testing.expect(x == expected);
927}943}
928944
929test "fixtfti" {945test i128_intFromFloat_f128 {
930 try test__fixtfti(-math.floatMax(f128), math.minInt(i128));946 try test_i128_intFromFloat_f128(-math.floatMax(f128), math.minInt(i128));
931947
932 try test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));948 try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
933 try test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);949 try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
934950
935 try test__fixtfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);951 try test_i128_intFromFloat_f128(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
936 try test__fixtfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000);952 try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000);
937 try test__fixtfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000);953 try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000);
938954
939 try test__fixtfti(-0x1.0000000000001p+63, -0x8000000000000800);955 try test_i128_intFromFloat_f128(-0x1.0000000000001p+63, -0x8000000000000800);
940 try test__fixtfti(-0x1.0000000000000p+63, -0x8000000000000000);956 try test_i128_intFromFloat_f128(-0x1.0000000000000p+63, -0x8000000000000000);
941 try test__fixtfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);957 try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
942 try test__fixtfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);958 try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
943959
944 try test__fixtfti(-0x1.FFFFFEp+62, -0x7fffff8000000000);960 try test_i128_intFromFloat_f128(-0x1.FFFFFEp+62, -0x7fffff8000000000);
945 try test__fixtfti(-0x1.FFFFFCp+62, -0x7fffff0000000000);961 try test_i128_intFromFloat_f128(-0x1.FFFFFCp+62, -0x7fffff0000000000);
946962
947 try test__fixtfti(-2.01, -2);963 try test_i128_intFromFloat_f128(-2.01, -2);
948 try test__fixtfti(-2.0, -2);964 try test_i128_intFromFloat_f128(-2.0, -2);
949 try test__fixtfti(-1.99, -1);965 try test_i128_intFromFloat_f128(-1.99, -1);
950 try test__fixtfti(-1.0, -1);966 try test_i128_intFromFloat_f128(-1.0, -1);
951 try test__fixtfti(-0.99, 0);967 try test_i128_intFromFloat_f128(-0.99, 0);
952 try test__fixtfti(-0.5, 0);968 try test_i128_intFromFloat_f128(-0.5, 0);
953 try test__fixtfti(-math.floatMin(f128), 0);969 try test_i128_intFromFloat_f128(-math.floatMin(f128), 0);
954 try test__fixtfti(0.0, 0);970 try test_i128_intFromFloat_f128(0.0, 0);
955 try test__fixtfti(math.floatMin(f128), 0);971 try test_i128_intFromFloat_f128(math.floatMin(f128), 0);
956 try test__fixtfti(0.5, 0);972 try test_i128_intFromFloat_f128(0.5, 0);
957 try test__fixtfti(0.99, 0);973 try test_i128_intFromFloat_f128(0.99, 0);
958 try test__fixtfti(1.0, 1);974 try test_i128_intFromFloat_f128(1.0, 1);
959 try test__fixtfti(1.5, 1);975 try test_i128_intFromFloat_f128(1.5, 1);
960 try test__fixtfti(1.99, 1);976 try test_i128_intFromFloat_f128(1.99, 1);
961 try test__fixtfti(2.0, 2);977 try test_i128_intFromFloat_f128(2.0, 2);
962 try test__fixtfti(2.01, 2);978 try test_i128_intFromFloat_f128(2.01, 2);
963979
964 try test__fixtfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);980 try test_i128_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
965 try test__fixtfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);981 try test_i128_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
966982
967 try test__fixtfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);983 try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
968 try test__fixtfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);984 try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
969 try test__fixtfti(0x1.0000000000000p+63, 0x8000000000000000);985 try test_i128_intFromFloat_f128(0x1.0000000000000p+63, 0x8000000000000000);
970 try test__fixtfti(0x1.0000000000001p+63, 0x8000000000000800);986 try test_i128_intFromFloat_f128(0x1.0000000000001p+63, 0x8000000000000800);
971987
972 try test__fixtfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);988 try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
973 try test__fixtfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);989 try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
974 try test__fixtfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);990 try test_i128_intFromFloat_f128(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
975991
976 try test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);992 try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
977 try test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));993 try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
978994
979 try test__fixtfti(math.floatMax(f128), math.maxInt(i128));995 try test_i128_intFromFloat_f128(math.floatMax(f128), math.maxInt(i128));
980}996}
981997
982test "fixunstfti" {998test u128_intFromFloat_f128 {
983 try test__fixunstfti(math.inf(f128), 0xffffffffffffffffffffffffffffffff);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);1003 try test_u128_intFromFloat_f128(0.5, 0);
988 try test__fixunstfti(0.99, 0);1004 try test_u128_intFromFloat_f128(0.99, 0);
989 try test__fixunstfti(1.0, 1);1005 try test_u128_intFromFloat_f128(1.0, 1);
990 try test__fixunstfti(1.5, 1);1006 try test_u128_intFromFloat_f128(1.5, 1);
991 try test__fixunstfti(1.99, 1);1007 try test_u128_intFromFloat_f128(1.99, 1);
992 try test__fixunstfti(2.0, 2);1008 try test_u128_intFromFloat_f128(2.0, 2);
993 try test__fixunstfti(2.01, 2);1009 try test_u128_intFromFloat_f128(2.01, 2);
994 try test__fixunstfti(-0.01, 0);1010 try test_u128_intFromFloat_f128(-0.01, 0);
995 try test__fixunstfti(-0.99, 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);1015 try test_u128_intFromFloat_f128(0x1.FFFFFEp+126, 0x7fffff80000000000000000000000000);
1000 try test__fixunstfti(0x1.FFFFFEp+127, 0xffffff00000000000000000000000000);1016 try test_u128_intFromFloat_f128(0x1.FFFFFEp+127, 0xffffff00000000000000000000000000);
1001 try test__fixunstfti(0x1.FFFFFEp+128, 0xffffffffffffffffffffffffffffffff);1017 try test_u128_intFromFloat_f128(0x1.FFFFFEp+128, 0xffffffffffffffffffffffffffffffff);
1002 try test__fixunstfti(0x1.FFFFFEp+129, 0xffffffffffffffffffffffffffffffff);1018 try test_u128_intFromFloat_f128(0x1.FFFFFEp+129, 0xffffffffffffffffffffffffffffffff);
1003}1019}
10041020
1005fn test__fixunshfti(a: f16, expected: u128) !void {1021fn test_u128_intFromFloat_f16(a: f16, expected: u128) !void {
1006 const x = __fixunshfti(a);1022 const x = impl.u128_intFromFloat_f16(a);
1007 try testing.expect(x == expected);1023 try testing.expect(x == expected);
1008}1024}
10091025
1010test "fixunshfti for f16" {1026test u128_intFromFloat_f16 {
1011 try test__fixunshfti(math.inf(f16), math.maxInt(u128));1027 try test_u128_intFromFloat_f16(math.inf(f16), math.maxInt(u128));
1012 try test__fixunshfti(math.floatMax(f16), 65504);1028 try test_u128_intFromFloat_f16(math.floatMax(f16), 65504);
1013}1029}
10141030
1015fn test__fixunsxfti(a: f80, expected: u128) !void {1031fn test_u128_intFromFloat_f80(a: f80, expected: u128) !void {
1016 const x = __fixunsxfti(a);1032 const x = impl.u128_intFromFloat_f80(a);
1017 try testing.expect(x == expected);1033 try testing.expect(x == expected);
1018}1034}
10191035
1020test "fixunsxfti for f80" {1036test u128_intFromFloat_f80 {
1021 try test__fixunsxfti(math.inf(f80), math.maxInt(u128));1037 try test_u128_intFromFloat_f80(math.inf(f80), math.maxInt(u128));
1022 try test__fixunsxfti(math.floatMax(f80), math.maxInt(u128));1038 try test_u128_intFromFloat_f80(math.floatMax(f80), math.maxInt(u128));
1023 try test__fixunsxfti(math.maxInt(u64), math.maxInt(u64));1039 try test_u128_intFromFloat_f80(math.maxInt(u64), math.maxInt(u64));
1024}1040}
lib/compiler_rt/limb64.zig+1-1
...@@ -6,7 +6,7 @@ const minInt = std.math.minInt;...@@ -6,7 +6,7 @@ const minInt = std.math.minInt;
66
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const compiler_rt = @import("../compiler_rt.zig");8const compiler_rt = @import("../compiler_rt.zig");
9const symbol = @import("../compiler_rt.zig").symbol;9const symbol = compiler_rt.symbol;
1010
11const endian = builtin.cpu.arch.endian();11const endian = builtin.cpu.arch.endian();
1212
lib/compiler_rt/log.zig+113-101
...@@ -11,26 +11,29 @@ const expectEqual = std.testing.expectEqual;...@@ -11,26 +11,29 @@ const expectEqual = std.testing.expectEqual;
11const expectApproxEqRel = std.testing.expectApproxEqRel;11const expectApproxEqRel = std.testing.expectApproxEqRel;
1212
13const compiler_rt = @import("../compiler_rt.zig");13const compiler_rt = @import("../compiler_rt.zig");
14const symbol = @import("../compiler_rt.zig").symbol;14const symbol = compiler_rt.symbol;
1515
16comptime {16comptime {
17 symbol(&__logh, "__logh");17 symbol(&__logh, "__logh");
18 symbol(&logf, "logf");18 symbol(&logf, "logf");
19 symbol(&log, "log");19 symbol(&log, "log");
20 symbol(&__logx, "__logx");20 symbol(&__logx, "__logx");
21 if (compiler_rt.want_ppc_abi) {21 symbol(&logq, "logf128");
22 symbol(&logq, "logf128");
23 }
24 symbol(&logq, "logq");
25 symbol(&logl, "logl");22 symbol(&logl, "logl");
26}23}
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 {
29 // TODO: more efficient implementation29 // TODO: more efficient implementation
30 return @floatCast(logf(a));30 return @floatCast(log_f32(a));
31}31}
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 {
34 const ln2_hi: f32 = 6.9313812256e-01;37 const ln2_hi: f32 = 6.9313812256e-01;
35 const ln2_lo: f32 = 9.0580006145e-06;38 const ln2_lo: f32 = 9.0580006145e-06;
36 const Lg1: f32 = 0xaaaaaa.0p-24;39 const Lg1: f32 = 0xaaaaaa.0p-24;
...@@ -82,7 +85,10 @@ pub fn logf(x_: f32) callconv(.c) f32 {...@@ -82,7 +85,10 @@ pub fn logf(x_: f32) callconv(.c) f32 {
82 return s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi;85 return s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi;
83}86}
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 {
86 const poly1 = [_]f64{92 const poly1 = [_]f64{
87 -0x1p-1,93 -0x1p-1,
88 0x1.5555555555577p-2,94 0x1.5555555555577p-2,
...@@ -432,11 +438,17 @@ pub fn log(x: f64) callconv(.c) f64 {...@@ -432,11 +438,17 @@ pub fn log(x: f64) callconv(.c) f64 {
432 return @bitCast(y);438 return @bitCast(y);
433}439}
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 {
436 // TODO: more efficient implementation445 // TODO: more efficient implementation
437 return @floatCast(logq(a));446 return @floatCast(log_f128(a));
438}447}
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}
440/// Implementation of "Table-driven implementation of the logarithm function in IEEE floating-point arithmetic"452/// Implementation of "Table-driven implementation of the logarithm function in IEEE floating-point arithmetic"
441/// by PTP Tang in ACM Transactions on Mathematical Software (TOMS), 1990453/// by PTP Tang in ACM Transactions on Mathematical Software (TOMS), 1990
442///454///
...@@ -449,7 +461,7 @@ pub fn __logx(a: f80) callconv(.c) f80 {...@@ -449,7 +461,7 @@ pub fn __logx(a: f80) callconv(.c) f80 {
449///461///
450/// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case):462/// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case):
451/// <= 0.5 ulp: 99.96%, worst case <= 0.528 ulp463/// <= 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 {
453 const impl = @import("log_f128.zig");465 const impl = @import("log_f128.zig");
454466
455 if (impl.specialCases(x)) |y|467 if (impl.specialCases(x)) |y|
...@@ -626,123 +638,123 @@ pub fn logq(x: f128) callconv(.c) f128 {...@@ -626,123 +638,123 @@ pub fn logq(x: f128) callconv(.c) f128 {
626638
627pub fn logl(x: c_longdouble) callconv(.c) c_longdouble {639pub fn logl(x: c_longdouble) callconv(.c) c_longdouble {
628 switch (@typeInfo(c_longdouble).float.bits) {640 switch (@typeInfo(c_longdouble).float.bits) {
629 64 => return log(x),641 64 => return log_f64(x),
630 80 => return __logx(x),642 80 => return log_f80(x),
631 128 => return logq(x),643 128 => return log_f128(x),
632 else => @compileError("unreachable"),644 else => comptime unreachable,
633 }645 }
634}646}
635647
636test "logf() special" {648test "logf() special" {
637 try expectEqual(logf(0.0), -math.inf(f32));649 try expectEqual(log_f32(0.0), -math.inf(f32));
638 try expectEqual(logf(-0.0), -math.inf(f32));650 try expectEqual(log_f32(-0.0), -math.inf(f32));
639 try expect(math.isPositiveZero(logf(1.0)));651 try expect(math.isPositiveZero(log_f32(1.0)));
640 try expectEqual(logf(math.e), 1.0);652 try expectEqual(log_f32(math.e), 1.0);
641 try expectEqual(logf(math.inf(f32)), math.inf(f32));653 try expectEqual(log_f32(math.inf(f32)), math.inf(f32));
642 try expect(math.isNan(logf(-1.0)));654 try expect(math.isNan(log_f32(-1.0)));
643 try expect(math.isNan(logf(-math.inf(f32))));655 try expect(math.isNan(log_f32(-math.inf(f32))));
644 try expect(math.isNan(logf(math.nan(f32))));656 try expect(math.isNan(log_f32(math.nan(f32))));
645 try expect(math.isNan(logf(math.snan(f32))));657 try expect(math.isNan(log_f32(math.snan(f32))));
646}658}
647659
648test "logf() sanity" {660test "logf() sanity" {
649 try expect(math.isNan(logf(-0x1.0223a0p+3)));661 try expect(math.isNan(log_f32(-0x1.0223a0p+3)));
650 try expectEqual(logf(0x1.161868p+2), 0x1.7815b0p+0);662 try expectEqual(log_f32(0x1.161868p+2), 0x1.7815b0p+0);
651 try expect(math.isNan(logf(-0x1.0c34b4p+3)));663 try expect(math.isNan(log_f32(-0x1.0c34b4p+3)));
652 try expect(math.isNan(logf(-0x1.a206f0p+2)));664 try expect(math.isNan(log_f32(-0x1.a206f0p+2)));
653 try expectEqual(logf(0x1.288bbcp+3), 0x1.1cfcd6p+1);665 try expectEqual(log_f32(0x1.288bbcp+3), 0x1.1cfcd6p+1);
654 try expectEqual(logf(0x1.52efd0p-1), -0x1.a6694cp-2);666 try expectEqual(log_f32(0x1.52efd0p-1), -0x1.a6694cp-2);
655 try expect(math.isNan(logf(-0x1.a05cc8p-2)));667 try expect(math.isNan(log_f32(-0x1.a05cc8p-2)));
656 try expectEqual(logf(0x1.1f9efap-1), -0x1.2742bap-1);668 try expectEqual(log_f32(0x1.1f9efap-1), -0x1.2742bap-1);
657 try expectEqual(logf(0x1.8c5db0p-1), -0x1.062160p-2);669 try expectEqual(log_f32(0x1.8c5db0p-1), -0x1.062160p-2);
658 try expect(math.isNan(logf(-0x1.5b86eap-1)));670 try expect(math.isNan(log_f32(-0x1.5b86eap-1)));
659}671}
660672
661test "logf() boundary" {673test "logf() boundary" {
662 try expectEqual(logf(0x1.fffffep+127), 0x1.62e430p+6); // Max input value674 try expectEqual(log_f32(0x1.fffffep+127), 0x1.62e430p+6); // Max input value
663 try expectEqual(logf(0x1p-149), -0x1.9d1da0p+6); // Min positive input value675 try expectEqual(log_f32(0x1p-149), -0x1.9d1da0p+6); // Min positive input value
664 try expect(math.isNan(logf(-0x1p-149))); // Min negative input value676 try expect(math.isNan(log_f32(-0x1p-149))); // Min negative input value
665 try expectEqual(logf(0x1.000002p+0), 0x1.fffffep-24); // Last value before result reaches +0677 try expectEqual(log_f32(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 -0678 try expectEqual(log_f32(0x1.fffffep-1), -0x1p-24); // Last value before result reaches -0
667 try expectEqual(logf(0x1p-126), -0x1.5d58a0p+6); // First subnormal679 try expectEqual(log_f32(0x1p-126), -0x1.5d58a0p+6); // First subnormal
668 try expect(math.isNan(logf(-0x1p-126))); // First negative subnormal680 try expect(math.isNan(log_f32(-0x1p-126))); // First negative subnormal
669}681}
670682
671test "log() special" {683test "log() special" {
672 try expectEqual(log(0.0), -math.inf(f64));684 try expectEqual(log_f64(0.0), -math.inf(f64));
673 try expectEqual(log(-0.0), -math.inf(f64));685 try expectEqual(log_f64(-0.0), -math.inf(f64));
674 try expect(math.isPositiveZero(log(1.0)));686 try expect(math.isPositiveZero(log_f64(1.0)));
675 try expectEqual(log(math.e), 1.0);687 try expectEqual(log_f64(math.e), 1.0);
676 try expectEqual(log(math.inf(f64)), math.inf(f64));688 try expectEqual(log_f64(math.inf(f64)), math.inf(f64));
677 try expect(math.isNan(log(-1.0)));689 try expect(math.isNan(log_f64(-1.0)));
678 try expect(math.isNan(log(-math.inf(f64))));690 try expect(math.isNan(log_f64(-math.inf(f64))));
679 try expect(math.isNan(log(math.nan(f64))));691 try expect(math.isNan(log_f64(math.nan(f64))));
680 try expect(math.isNan(log(math.snan(f64))));692 try expect(math.isNan(log_f64(math.snan(f64))));
681}693}
682694
683test "log() sanity" {695test "log() sanity" {
684 try expect(math.isNan(log(-0x1.02239f3c6a8f1p+3)));696 try expect(math.isNan(log_f64(-0x1.02239f3c6a8f1p+3)));
685 try expectEqual(log(0x1.161868e18bc67p+2), 0x1.7815b08f99c65p+0);697 try expectEqual(log_f64(0x1.161868e18bc67p+2), 0x1.7815b08f99c65p+0);
686 try expect(math.isNan(log(-0x1.0c34b3e01e6e7p+3)));698 try expect(math.isNan(log_f64(-0x1.0c34b3e01e6e7p+3)));
687 try expect(math.isNan(log(-0x1.a206f0a19dcc4p+2)));699 try expect(math.isNan(log_f64(-0x1.a206f0a19dcc4p+2)));
688 try expectEqual(log(0x1.288bbb0d6a1e6p+3), 0x1.1cfcd53d72604p+1);700 try expectEqual(log_f64(0x1.288bbb0d6a1e6p+3), 0x1.1cfcd53d72604p+1);
689 try expectEqual(log(0x1.52efd0cd80497p-1), -0x1.a6694a4a85621p-2);701 try expectEqual(log_f64(0x1.52efd0cd80497p-1), -0x1.a6694a4a85621p-2);
690 try expect(math.isNan(log(-0x1.a05cc754481d1p-2)));702 try expect(math.isNan(log_f64(-0x1.a05cc754481d1p-2)));
691 try expectEqual(log(0x1.1f9ef934745cbp-1), -0x1.2742bc03d02ddp-1);703 try expectEqual(log_f64(0x1.1f9ef934745cbp-1), -0x1.2742bc03d02ddp-1);
692 try expectEqual(log(0x1.8c5db097f7442p-1), -0x1.06215de4a3f92p-2);704 try expectEqual(log_f64(0x1.8c5db097f7442p-1), -0x1.06215de4a3f92p-2);
693 try expect(math.isNan(log(-0x1.5b86ea8118a0ep-1)));705 try expect(math.isNan(log_f64(-0x1.5b86ea8118a0ep-1)));
694}706}
695707
696test "log() boundary" {708test "log() boundary" {
697 try expectEqual(log(0x1.fffffffffffffp+1023), 0x1.62e42fefa39efp+9); // Max input value709 try expectEqual(log_f64(0x1.fffffffffffffp+1023), 0x1.62e42fefa39efp+9); // Max input value
698 try expectEqual(log(0x1p-1074), -0x1.74385446d71c3p+9); // Min positive input value710 try expectEqual(log_f64(0x1p-1074), -0x1.74385446d71c3p+9); // Min positive input value
699 try expect(math.isNan(log(-0x1p-1074))); // Min negative input value711 try expect(math.isNan(log_f64(-0x1p-1074))); // Min negative input value
700 try expectEqual(log(0x1.0000000000001p+0), 0x1.fffffffffffffp-53); // Last value before result reaches +0712 try expectEqual(log_f64(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 -0713 try expectEqual(log_f64(0x1.fffffffffffffp-1), -0x1p-53); // Last value before result reaches -0
702 try expectEqual(log(0x1p-1022), -0x1.6232bdd7abcd2p+9); // First subnormal714 try expectEqual(log_f64(0x1p-1022), -0x1.6232bdd7abcd2p+9); // First subnormal
703 try expect(math.isNan(log(-0x1p-1022))); // First negative subnormal715 try expect(math.isNan(log_f64(-0x1p-1022))); // First negative subnormal
704}716}
705717
706test "logq() special" {718test "logq() special" {
707 try expectEqual(logq(0.0), -math.inf(f128));719 try expectEqual(log_f128(0.0), -math.inf(f128));
708 try expectEqual(logq(-0.0), -math.inf(f128));720 try expectEqual(log_f128(-0.0), -math.inf(f128));
709 try expect(math.isPositiveZero(logq(1.0)));721 try expect(math.isPositiveZero(log_f128(1.0)));
710 // Sadly, the rounding gods decided that 0.9999999999999999999999999999999999722 // Sadly, the rounding gods decided that 0.9999999999999999999999999999999999
711 // is the correctly rounded value of logq(math.e)723 // is the correctly rounded value of log_f128(math.e)
712 try expectApproxEqRel(logq(math.e), 1.0, math.floatEpsAt(f128, 1.0));724 try expectApproxEqRel(log_f128(math.e), 1.0, math.floatEpsAt(f128, 1.0));
713 try expectEqual(logq(math.inf(f128)), math.inf(f128));725 try expectEqual(log_f128(math.inf(f128)), math.inf(f128));
714 try expect(math.isNan(logq(-1.0)));726 try expect(math.isNan(log_f128(-1.0)));
715 try expect(math.isNan(logq(-math.inf(f128))));727 try expect(math.isNan(log_f128(-math.inf(f128))));
716 try expect(math.isNan(logq(math.nan(f128))));728 try expect(math.isNan(log_f128(math.nan(f128))));
717 try expect(math.isNan(logq(math.snan(f128))));729 try expect(math.isNan(log_f128(math.snan(f128))));
718}730}
719731
720test "logq() boundary" {732test "logq() boundary" {
721 try expectEqual(logq(0x1.ffffffffffffffffffffffffffffp16383), 0x1.62e42fefa39ef35793c7673007e6p13); // Max input value733 try expectEqual(log_f128(0x1.ffffffffffffffffffffffffffffp16383), 0x1.62e42fefa39ef35793c7673007e6p13); // Max input value
722 try expectEqual(logq(0x1p-16494), -0x1.6546282207802c89d24d65e96274p13); // Min positive input value734 try expectEqual(log_f128(0x1p-16494), -0x1.6546282207802c89d24d65e96274p13); // Min positive input value
723 try expect(math.isNan(logq(-0x1p-16494))); // Min negative input value735 try expect(math.isNan(log_f128(-0x1p-16494))); // Min negative input value
724 try expectEqual(logq(0x1.0000000000000000000000000001p0), 0x1.ffffffffffffffffffffffffffffp-113); // Last value before result reaches +0736 try expectEqual(log_f128(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 -0737 try expectEqual(log_f128(0x1.ffffffffffffffffffffffffffffp-1), -0x1p-113); // Last value before result reaches -0
726 try expectEqual(logq(0x1p-16382), -0x1.62d918ce2421d65ff90ac8f4ce66p13); // First subnormal738 try expectEqual(log_f128(0x1p-16382), -0x1.62d918ce2421d65ff90ac8f4ce66p13); // First subnormal
727 try expect(math.isNan(logq(-0x1p-16382))); // First negative subnormal739 try expect(math.isNan(log_f128(-0x1p-16382))); // First negative subnormal
728}740}
729741
730test "logq() sanity" {742test "logq() sanity" {
731 try expectEqual(logq(4.151135979023751199079583784623537e-4), -7.7869583453055243113993340258295346e0);743 try expectEqual(log_f128(4.151135979023751199079583784623537e-4), -7.7869583453055243113993340258295346e0);
732 try expectEqual(logq(9.614234245933828353176667689130293e-14), -2.9972946567656004014786271559909435e1);744 try expectEqual(log_f128(9.614234245933828353176667689130293e-14), -2.9972946567656004014786271559909435e1);
733 try expectEqual(logq(1.012889803704721484375e13), 2.9946413646144315985379677542014356e1);745 try expectEqual(log_f128(1.012889803704721484375e13), 2.9946413646144315985379677542014356e1);
734 try expectEqual(logq(2.397741857206453154086912e24), 5.613656963346284538829358703465392e1);746 try expectEqual(log_f128(2.397741857206453154086912e24), 5.613656963346284538829358703465392e1);
735 try expectEqual(logq(3.442377567808290806386655232e27), 6.3405959896920645453203836625419693e1);747 try expectEqual(log_f128(3.442377567808290806386655232e27), 6.3405959896920645453203836625419693e1);
736 try expectEqual(logq(1.0689155158234028407981544637594257e-8), -1.835403614606774451014272772421113e1);748 try expectEqual(log_f128(1.0689155158234028407981544637594257e-8), -1.835403614606774451014272772421113e1);
737 try expectEqual(logq(1.4813913545768791536741499811327596e-10), -2.263286917934202003739900705050399e1);749 try expectEqual(log_f128(1.4813913545768791536741499811327596e-10), -2.263286917934202003739900705050399e1);
738 try expectEqual(logq(4.518948965781299591064453125e10), 2.453413036705097282892685629562292e1);750 try expectEqual(log_f128(4.518948965781299591064453125e10), 2.453413036705097282892685629562292e1);
739 try expectEqual(logq(1.200355637363589375e14), 3.2418809179272977400408325788186897e1);751 try expectEqual(log_f128(1.200355637363589375e14), 3.2418809179272977400408325788186897e1);
740 try expectEqual(logq(6.6145398293682003021240234375e9), 2.261253606737223221601998075023261e1);752 try expectEqual(log_f128(6.6145398293682003021240234375e9), 2.261253606737223221601998075023261e1);
741 try expectEqual(logq(5.16179116383965741056e20), 4.7692985503915646405875629300054525e1);753 try expectEqual(log_f128(5.16179116383965741056e20), 4.7692985503915646405875629300054525e1);
742 // testing near 1754 // testing near 1
743 try expectEqual(logq(1.026586845186097528392910049888087e0), 2.6239557099466251374193777672800004e-2);755 try expectEqual(log_f128(1.026586845186097528392910049888087e0), 2.6239557099466251374193777672800004e-2);
744 try expectEqual(logq(9.878220373715243107115568932385941e-1), -1.2252721576456821219120474521538944e-2);756 try expectEqual(log_f128(9.878220373715243107115568932385941e-1), -1.2252721576456821219120474521538944e-2);
745 try expectEqual(logq(9.417921077517196685541245315675951e-1), -5.997072116986790367958922503195352e-2);757 try expectEqual(log_f128(9.417921077517196685541245315675951e-1), -5.997072116986790367958922503195352e-2);
746 try expectEqual(logq(1.043095786320424537962914257605007e0), 4.219300911769055080390811808602425e-2);758 try expectEqual(log_f128(1.043095786320424537962914257605007e0), 4.219300911769055080390811808602425e-2);
747 try expectEqual(logq(1.019043049323190694932517175175235e0), 1.8863999985309781522599012445793722e-2);759 try expectEqual(log_f128(1.019043049323190694932517175175235e0), 1.8863999985309781522599012445793722e-2);
748}760}
lib/compiler_rt/log10.zig+114-102
...@@ -18,19 +18,22 @@ comptime {...@@ -18,19 +18,22 @@ comptime {
18 symbol(&log10f, "log10f");18 symbol(&log10f, "log10f");
19 symbol(&log10, "log10");19 symbol(&log10, "log10");
20 symbol(&__log10x, "__log10x");20 symbol(&__log10x, "__log10x");
21 if (compiler_rt.want_ppc_abi) {21 symbol(&log10q, "log10f128");
22 symbol(&log10q, "log10f128");
23 }
24 symbol(&log10q, "log10q");
25 symbol(&log10l, "log10l");22 symbol(&log10l, "log10l");
26}23}
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 {
29 // TODO: more efficient implementation29 // TODO: more efficient implementation
30 return @floatCast(log10f(a));30 return @floatCast(log10_f32(a));
31}31}
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 {
34 const ivln10hi: f32 = 4.3432617188e-01;37 const ivln10hi: f32 = 4.3432617188e-01;
35 const ivln10lo: f32 = -3.1689971365e-05;38 const ivln10lo: f32 = -3.1689971365e-05;
36 const log10_2hi: f32 = 3.0102920532e-01;39 const log10_2hi: f32 = 3.0102920532e-01;
...@@ -90,7 +93,10 @@ pub fn log10f(x_: f32) callconv(.c) f32 {...@@ -90,7 +93,10 @@ pub fn log10f(x_: f32) callconv(.c) f32 {
90 return dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi + hi * ivln10hi + dk * log10_2hi;93 return dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi + hi * ivln10hi + dk * log10_2hi;
91}94}
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 {
94 const ivln10hi: f64 = 4.34294481878168880939e-01;100 const ivln10hi: f64 = 4.34294481878168880939e-01;
95 const ivln10lo: f64 = 2.50829467116452752298e-11;101 const ivln10lo: f64 = 2.50829467116452752298e-11;
96 const log10_2hi: f64 = 3.01029995663611771306e-01;102 const log10_2hi: f64 = 3.01029995663611771306e-01;
...@@ -165,11 +171,17 @@ pub fn log10(x_: f64) callconv(.c) f64 {...@@ -165,11 +171,17 @@ pub fn log10(x_: f64) callconv(.c) f64 {
165 return val_lo + val_hi;171 return val_lo + val_hi;
166}172}
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 {
169 // TODO: more efficient implementation178 // TODO: more efficient implementation
170 return @floatCast(log10q(a));179 return @floatCast(log10_f128(a));
171}180}
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}
173/// Implementation of "Table-driven implementation of the logarithm function in IEEE floating-point arithmetic"185/// Implementation of "Table-driven implementation of the logarithm function in IEEE floating-point arithmetic"
174/// by PTP Tang in ACM Transactions on Mathematical Software (TOMS), 1990186/// by PTP Tang in ACM Transactions on Mathematical Software (TOMS), 1990
175///187///
...@@ -182,7 +194,7 @@ pub fn __log10x(a: f80) callconv(.c) f80 {...@@ -182,7 +194,7 @@ pub fn __log10x(a: f80) callconv(.c) f80 {
182///194///
183/// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case):195/// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case):
184/// <= 0.5 ulp: 99.96%, worst case <= 0.565 ulp196/// <= 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 {
186 const impl = @import("log_f128.zig");198 const impl = @import("log_f128.zig");
187199
188 if (impl.specialCases(x)) |y|200 if (impl.specialCases(x)) |y|
...@@ -359,124 +371,124 @@ pub fn log10q(x: f128) callconv(.c) f128 {...@@ -359,124 +371,124 @@ pub fn log10q(x: f128) callconv(.c) f128 {
359371
360pub fn log10l(x: c_longdouble) callconv(.c) c_longdouble {372pub fn log10l(x: c_longdouble) callconv(.c) c_longdouble {
361 switch (@typeInfo(c_longdouble).float.bits) {373 switch (@typeInfo(c_longdouble).float.bits) {
362 64 => return log10(x),374 64 => return log10_f64(x),
363 80 => return __log10x(x),375 80 => return log10_f80(x),
364 128 => return log10q(x),376 128 => return log10_f128(x),
365 else => @compileError("unreachable"),377 else => comptime unreachable,
366 }378 }
367}379}
368380
369test "log10f() special" {381test "log10f() special" {
370 try expectEqual(log10f(0.0), -math.inf(f32));382 try expectEqual(log10_f32(0.0), -math.inf(f32));
371 try expectEqual(log10f(-0.0), -math.inf(f32));383 try expectEqual(log10_f32(-0.0), -math.inf(f32));
372 try expect(math.isPositiveZero(log10f(1.0)));384 try expect(math.isPositiveZero(log10_f32(1.0)));
373 try expectEqual(log10f(10.0), 1.0);385 try expectEqual(log10_f32(10.0), 1.0);
374 try expectEqual(log10f(0.1), -1.0);386 try expectEqual(log10_f32(0.1), -1.0);
375 try expectEqual(log10f(math.inf(f32)), math.inf(f32));387 try expectEqual(log10_f32(math.inf(f32)), math.inf(f32));
376 try expect(math.isNan(log10f(-1.0)));388 try expect(math.isNan(log10_f32(-1.0)));
377 try expect(math.isNan(log10f(-math.inf(f32))));389 try expect(math.isNan(log10_f32(-math.inf(f32))));
378 try expect(math.isNan(log10f(math.nan(f32))));390 try expect(math.isNan(log10_f32(math.nan(f32))));
379 try expect(math.isNan(log10f(math.snan(f32))));391 try expect(math.isNan(log10_f32(math.snan(f32))));
380}392}
381393
382test "log10f() sanity" {394test "log10f() sanity" {
383 try expect(math.isNan(log10f(-0x1.0223a0p+3)));395 try expect(math.isNan(log10_f32(-0x1.0223a0p+3)));
384 try expectEqual(log10f(0x1.161868p+2), 0x1.46a9bcp-1);396 try expectEqual(log10_f32(0x1.161868p+2), 0x1.46a9bcp-1);
385 try expect(math.isNan(log10f(-0x1.0c34b4p+3)));397 try expect(math.isNan(log10_f32(-0x1.0c34b4p+3)));
386 try expect(math.isNan(log10f(-0x1.a206f0p+2)));398 try expect(math.isNan(log10_f32(-0x1.a206f0p+2)));
387 try expectEqual(log10f(0x1.288bbcp+3), 0x1.ef1300p-1);399 try expectEqual(log10_f32(0x1.288bbcp+3), 0x1.ef1300p-1);
388 try expectEqual(log10f(0x1.52efd0p-1), -0x1.6ee6dcp-3); // Disagrees with GCC in last bit400 try expectEqual(log10_f32(0x1.52efd0p-1), -0x1.6ee6dcp-3); // Disagrees with GCC in last bit
389 try expect(math.isNan(log10f(-0x1.a05cc8p-2)));401 try expect(math.isNan(log10_f32(-0x1.a05cc8p-2)));
390 try expectEqual(log10f(0x1.1f9efap-1), -0x1.0075ccp-2);402 try expectEqual(log10_f32(0x1.1f9efap-1), -0x1.0075ccp-2);
391 try expectEqual(log10f(0x1.8c5db0p-1), -0x1.c75df8p-4);403 try expectEqual(log10_f32(0x1.8c5db0p-1), -0x1.c75df8p-4);
392 try expect(math.isNan(log10f(-0x1.5b86eap-1)));404 try expect(math.isNan(log10_f32(-0x1.5b86eap-1)));
393}405}
394406
395test "log10f() boundary" {407test "log10f() boundary" {
396 try expectEqual(log10f(0x1.fffffep+127), 0x1.344136p+5); // Max input value408 try expectEqual(log10_f32(0x1.fffffep+127), 0x1.344136p+5); // Max input value
397 try expectEqual(log10f(0x1p-149), -0x1.66d3e8p+5); // Min positive input value409 try expectEqual(log10_f32(0x1p-149), -0x1.66d3e8p+5); // Min positive input value
398 try expect(math.isNan(log10f(-0x1p-149))); // Min negative input value410 try expect(math.isNan(log10_f32(-0x1p-149))); // Min negative input value
399 try expectEqual(log10f(0x1.000002p+0), 0x1.bcb7b0p-25); // Last value before result reaches +0411 try expectEqual(log10_f32(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 -0412 try expectEqual(log10_f32(0x1.fffffep-1), -0x1.bcb7b2p-26); // Last value before result reaches -0
401 try expectEqual(log10f(0x1p-126), -0x1.2f7030p+5); // First subnormal413 try expectEqual(log10_f32(0x1p-126), -0x1.2f7030p+5); // First subnormal
402 try expect(math.isNan(log10f(-0x1p-126))); // First negative subnormal414 try expect(math.isNan(log10_f32(-0x1p-126))); // First negative subnormal
403}415}
404416
405test "log10() special" {417test "log10() special" {
406 try expectEqual(log10(0.0), -math.inf(f64));418 try expectEqual(log10_f64(0.0), -math.inf(f64));
407 try expectEqual(log10(-0.0), -math.inf(f64));419 try expectEqual(log10_f64(-0.0), -math.inf(f64));
408 try expect(math.isPositiveZero(log10(1.0)));420 try expect(math.isPositiveZero(log10_f64(1.0)));
409 try expectEqual(log10(10.0), 1.0);421 try expectEqual(log10_f64(10.0), 1.0);
410 try expectEqual(log10(0.1), -1.0);422 try expectEqual(log10_f64(0.1), -1.0);
411 try expectEqual(log10(math.inf(f64)), math.inf(f64));423 try expectEqual(log10_f64(math.inf(f64)), math.inf(f64));
412 try expect(math.isNan(log10(-1.0)));424 try expect(math.isNan(log10_f64(-1.0)));
413 try expect(math.isNan(log10(-math.inf(f64))));425 try expect(math.isNan(log10_f64(-math.inf(f64))));
414 try expect(math.isNan(log10(math.nan(f64))));426 try expect(math.isNan(log10_f64(math.nan(f64))));
415 try expect(math.isNan(log10(math.snan(f64))));427 try expect(math.isNan(log10_f64(math.snan(f64))));
416}428}
417429
418test "log10() sanity" {430test "log10() sanity" {
419 try expect(math.isNan(log10(-0x1.02239f3c6a8f1p+3)));431 try expect(math.isNan(log10_f64(-0x1.02239f3c6a8f1p+3)));
420 try expectEqual(log10(0x1.161868e18bc67p+2), 0x1.46a9bd1d2eb87p-1);432 try expectEqual(log10_f64(0x1.161868e18bc67p+2), 0x1.46a9bd1d2eb87p-1);
421 try expect(math.isNan(log10(-0x1.0c34b3e01e6e7p+3)));433 try expect(math.isNan(log10_f64(-0x1.0c34b3e01e6e7p+3)));
422 try expect(math.isNan(log10(-0x1.a206f0a19dcc4p+2)));434 try expect(math.isNan(log10_f64(-0x1.a206f0a19dcc4p+2)));
423 try expectEqual(log10(0x1.288bbb0d6a1e6p+3), 0x1.ef12fff994862p-1);435 try expectEqual(log10_f64(0x1.288bbb0d6a1e6p+3), 0x1.ef12fff994862p-1);
424 try expectEqual(log10(0x1.52efd0cd80497p-1), -0x1.6ee6db5a155cbp-3);436 try expectEqual(log10_f64(0x1.52efd0cd80497p-1), -0x1.6ee6db5a155cbp-3);
425 try expect(math.isNan(log10(-0x1.a05cc754481d1p-2)));437 try expect(math.isNan(log10_f64(-0x1.a05cc754481d1p-2)));
426 try expectEqual(log10(0x1.1f9ef934745cbp-1), -0x1.0075cda79d321p-2);438 try expectEqual(log10_f64(0x1.1f9ef934745cbp-1), -0x1.0075cda79d321p-2);
427 try expectEqual(log10(0x1.8c5db097f7442p-1), -0x1.c75df6442465ap-4);439 try expectEqual(log10_f64(0x1.8c5db097f7442p-1), -0x1.c75df6442465ap-4);
428 try expect(math.isNan(log10(-0x1.5b86ea8118a0ep-1)));440 try expect(math.isNan(log10_f64(-0x1.5b86ea8118a0ep-1)));
429}441}
430442
431test "log10() boundary" {443test "log10() boundary" {
432 try expectEqual(log10(0x1.fffffffffffffp+1023), 0x1.34413509f79ffp+8); // Max input value444 try expectEqual(log10_f64(0x1.fffffffffffffp+1023), 0x1.34413509f79ffp+8); // Max input value
433 try expectEqual(log10(0x1p-1074), -0x1.434e6420f4374p+8); // Min positive input value445 try expectEqual(log10_f64(0x1p-1074), -0x1.434e6420f4374p+8); // Min positive input value
434 try expect(math.isNan(log10(-0x1p-1074))); // Min negative input value446 try expect(math.isNan(log10_f64(-0x1p-1074))); // Min negative input value
435 try expectEqual(log10(0x1.0000000000001p+0), 0x1.bcb7b1526e50dp-54); // Last value before result reaches +0447 try expectEqual(log10_f64(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 -0448 try expectEqual(log10_f64(0x1.fffffffffffffp-1), -0x1.bcb7b1526e50fp-55); // Last value before result reaches -0
437 try expectEqual(log10(0x1p-1022), -0x1.33a7146f72a42p+8); // First subnormal449 try expectEqual(log10_f64(0x1p-1022), -0x1.33a7146f72a42p+8); // First subnormal
438 try expect(math.isNan(log10(-0x1p-1022))); // First negative subnormal450 try expect(math.isNan(log10_f64(-0x1p-1022))); // First negative subnormal
439}451}
440452
441test "log10q() special" {453test "log10q() special" {
442 try expectEqual(log10q(0.0), -math.inf(f128));454 try expectEqual(log10_f128(0.0), -math.inf(f128));
443 try expectEqual(log10q(-0.0), -math.inf(f128));455 try expectEqual(log10_f128(-0.0), -math.inf(f128));
444 try expect(math.isPositiveZero(log10q(1.0)));456 try expect(math.isPositiveZero(log10_f128(1.0)));
445 try expectEqual(log10q(10.0), 1.0);457 try expectEqual(log10_f128(10.0), 1.0);
446 try expectEqual(log10q(0.1), -1.0);458 try expectEqual(log10_f128(0.1), -1.0);
447 try expectEqual(log10q(math.inf(f128)), math.inf(f128));459 try expectEqual(log10_f128(math.inf(f128)), math.inf(f128));
448 try expect(math.isNan(log10q(-1.0)));460 try expect(math.isNan(log10_f128(-1.0)));
449 try expect(math.isNan(log10q(-math.inf(f128))));461 try expect(math.isNan(log10_f128(-math.inf(f128))));
450 try expect(math.isNan(log10q(math.nan(f128))));462 try expect(math.isNan(log10_f128(math.nan(f128))));
451 try expect(math.isNan(log10q(math.snan(f128))));463 try expect(math.isNan(log10_f128(math.snan(f128))));
452}464}
453465
454test "log10q() sanity" {466test "log10q() sanity" {
455 try expectEqual(log10q(2.1744503117482705706605762784484114e1949), 1.949337349488073972035715318447419e3);467 try expectEqual(log10_f128(2.1744503117482705706605762784484114e1949), 1.949337349488073972035715318447419e3);
456 try expectEqual(log10q(2.3695331993665660983204066767386505e2150), 2.1503746627979481420243846411400265e3);468 try expectEqual(log10_f128(2.3695331993665660983204066767386505e2150), 2.1503746627979481420243846411400265e3);
457 try expectEqual(log10q(1.8071775728314983136779370752110857e612), 6.122570008283284411311428111991705e2);469 try expectEqual(log10_f128(1.8071775728314983136779370752110857e612), 6.122570008283284411311428111991705e2);
458 try expectEqual(log10q(2.612170297226630737309271722008693e-2629), -2.628582998513179919647069989114319e3);470 try expectEqual(log10_f128(2.612170297226630737309271722008693e-2629), -2.628582998513179919647069989114319e3);
459 try expectEqual(log10q(8.485091636263895897993044621224502e-3748), -3.7470713434630800881474518447042895e3);471 try expectEqual(log10_f128(8.485091636263895897993044621224502e-3748), -3.7470713434630800881474518447042895e3);
460 try expectEqual(log10q(4.3668077579803801413736022136116655e-4051), -4.0503598359268068567757367259544416e3);472 try expectEqual(log10_f128(4.3668077579803801413736022136116655e-4051), -4.0503598359268068567757367259544416e3);
461 try expectEqual(log10q(2.9321353260885285826237030859036923e4830), 4.830467184010313310864606285356782e3);473 try expectEqual(log10_f128(2.9321353260885285826237030859036923e4830), 4.830467184010313310864606285356782e3);
462 try expectEqual(log10q(6.6119754254652455408442826553161645e-1417), -1.416179668769227128601620567685071e3);474 try expectEqual(log10_f128(6.6119754254652455408442826553161645e-1417), -1.416179668769227128601620567685071e3);
463 try expectEqual(log10q(5.2459104673488555418645321788108695e4178), 4.178719820874155944446586083585479e3);475 try expectEqual(log10_f128(5.2459104673488555418645321788108695e4178), 4.178719820874155944446586083585479e3);
464 try expectEqual(log10q(7.809812890804996586377267218360886e-418), -4.1710735937091966815220294599598215e2);476 try expectEqual(log10_f128(7.809812890804996586377267218360886e-418), -4.1710735937091966815220294599598215e2);
465 // testing near 1477 // testing near 1
466 try expectEqual(log10q(1.0291437165967803055610652052109798e0), 1.2476026819466393459130418401605807e-2);478 try expectEqual(log10_f128(1.0291437165967803055610652052109798e0), 1.2476026819466393459130418401605807e-2);
467 try expectEqual(log10q(1.043095786320424537962914257605007e0), 1.8324191034706598279642145362763252e-2);479 try expectEqual(log10_f128(1.043095786320424537962914257605007e0), 1.8324191034706598279642145362763252e-2);
468 try expectEqual(log10q(9.900264873754467234601150948947179e-1), -4.3531860417287584780652055666513634e-3);480 try expectEqual(log10_f128(9.900264873754467234601150948947179e-1), -4.3531860417287584780652055666513634e-3);
469 try expectEqual(log10q(1.038295346547007736348611217636062e0), 1.6320907588397540309035279023485962e-2);481 try expectEqual(log10_f128(1.038295346547007736348611217636062e0), 1.6320907588397540309035279023485962e-2);
470 try expectEqual(log10q(9.821701941230028324703038578036285e-1), -7.813249520562034832371814409278784e-3);482 try expectEqual(log10_f128(9.821701941230028324703038578036285e-1), -7.813249520562034832371814409278784e-3);
471 try expectEqual(log10q(9.593555263530179895381522214847791e-1), -1.8020418356217558657107271163588764e-2);483 try expectEqual(log10_f128(9.593555263530179895381522214847791e-1), -1.8020418356217558657107271163588764e-2);
472}484}
473485
474test "log10q() boundary" {486test "log10q() boundary" {
475 try expectEqual(log10q(0x1.ffffffffffffffffffffffffffffp16383), 0x1.34413509f79fef311f12b35816f9p12); // Max input value487 try expectEqual(log10_f128(0x1.ffffffffffffffffffffffffffffp16383), 0x1.34413509f79fef311f12b35816f9p12); // Max input value
476 try expectEqual(log10q(0x1p-16494), -0x1.3653051d20c18a143b801b7c5661p12); // Min positive input value488 try expectEqual(log10_f128(0x1p-16494), -0x1.3653051d20c18a143b801b7c5661p12); // Min positive input value
477 try expect(math.isNan(log10q(-0x1p-16494))); // Min negative input value489 try expect(math.isNan(log10_f128(-0x1p-16494))); // Min negative input value
478 try expectEqual(log10q(0x1.0000000000000000000000000001p0), 0x1.bcb7b1526e50e32a6ab7555f5a67p-114); // Last value before result reaches +0490 try expectEqual(log10_f128(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 -0491 try expectEqual(log10_f128(0x1.ffffffffffffffffffffffffffffp-1), -0x1.bcb7b1526e50e32a6ab7555f5a68p-115); // Last value before result reaches -0
480 try expectEqual(log10q(0x1p-16382), -0x1.343793004f503231a589bac27c38p12); // First subnormal492 try expectEqual(log10_f128(0x1p-16382), -0x1.343793004f503231a589bac27c38p12); // First subnormal
481 try expect(math.isNan(log10q(-0x1p-16382))); // First negative subnormal493 try expect(math.isNan(log10_f128(-0x1p-16382))); // First negative subnormal
482}494}
lib/compiler_rt/log2.zig+106-94
...@@ -19,19 +19,22 @@ comptime {...@@ -19,19 +19,22 @@ comptime {
19 symbol(&log2f, "log2f");19 symbol(&log2f, "log2f");
20 symbol(&log2, "log2");20 symbol(&log2, "log2");
21 symbol(&__log2x, "__log2x");21 symbol(&__log2x, "__log2x");
22 if (compiler_rt.want_ppc_abi) {22 symbol(&log2q, "log2f128");
23 symbol(&log2q, "log2f128");
24 }
25 symbol(&log2q, "log2q");
26 symbol(&log2l, "log2l");23 symbol(&log2l, "log2l");
27}24}
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 {
30 // TODO: more efficient implementation30 // TODO: more efficient implementation
31 return @floatCast(log2f(a));31 return @floatCast(log2_f32(a));
32}32}
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 {
35 const ivln2hi: f32 = 1.4428710938e+00;38 const ivln2hi: f32 = 1.4428710938e+00;
36 const ivln2lo: f32 = -1.7605285393e-04;39 const ivln2lo: f32 = -1.7605285393e-04;
37 const Lg1: f32 = 0xaaaaaa.0p-24;40 const Lg1: f32 = 0xaaaaaa.0p-24;
...@@ -87,7 +90,10 @@ pub fn log2f(x_: f32) callconv(.c) f32 {...@@ -87,7 +90,10 @@ pub fn log2f(x_: f32) callconv(.c) f32 {
87 return (lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + @as(f32, @floatFromInt(k));90 return (lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + @as(f32, @floatFromInt(k));
88}91}
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 {
91 const ivln2hi: f64 = 1.44269504072144627571e+00;97 const ivln2hi: f64 = 1.44269504072144627571e+00;
92 const ivln2lo: f64 = 1.67517131648865118353e-10;98 const ivln2lo: f64 = 1.67517131648865118353e-10;
93 const Lg1: f64 = 6.666666666666735130e-01;99 const Lg1: f64 = 6.666666666666735130e-01;
...@@ -158,11 +164,17 @@ pub fn log2(x_: f64) callconv(.c) f64 {...@@ -158,11 +164,17 @@ pub fn log2(x_: f64) callconv(.c) f64 {
158 return val_lo + val_hi;164 return val_lo + val_hi;
159}165}
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 {
162 // TODO: more efficient implementation171 // TODO: more efficient implementation
163 return @floatCast(log2q(a));172 return @floatCast(log2_f128(a));
164}173}
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}
166/// Implementation of "Table-driven implementation of the logarithm function in IEEE floating-point arithmetic"178/// Implementation of "Table-driven implementation of the logarithm function in IEEE floating-point arithmetic"
167/// by PTP Tang in ACM Transactions on Mathematical Software (TOMS), 1990179/// by PTP Tang in ACM Transactions on Mathematical Software (TOMS), 1990
168///180///
...@@ -175,7 +187,7 @@ pub fn __log2x(a: f80) callconv(.c) f80 {...@@ -175,7 +187,7 @@ pub fn __log2x(a: f80) callconv(.c) f80 {
175///187///
176/// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case):188/// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case):
177/// <= 0.5 ulp: 99.86%, worst case <= 0.546 ulp189/// <= 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 {
179 const impl = @import("log_f128.zig");191 const impl = @import("log_f128.zig");
180192
181 if (impl.specialCases(x)) |y|193 if (impl.specialCases(x)) |y|
...@@ -351,117 +363,117 @@ pub fn log2q(x: f128) callconv(.c) f128 {...@@ -351,117 +363,117 @@ pub fn log2q(x: f128) callconv(.c) f128 {
351363
352pub fn log2l(x: c_longdouble) callconv(.c) c_longdouble {364pub fn log2l(x: c_longdouble) callconv(.c) c_longdouble {
353 switch (@typeInfo(c_longdouble).float.bits) {365 switch (@typeInfo(c_longdouble).float.bits) {
354 64 => return log2(x),366 64 => return log2_f64(x),
355 80 => return __log2x(x),367 80 => return log2_f80(x),
356 128 => return log2q(x),368 128 => return log2_f128(x),
357 else => @compileError("unreachable"),369 else => comptime unreachable,
358 }370 }
359}371}
360372
361test "log2f() special" {373test "log2f() special" {
362 try expectEqual(log2f(0.0), -math.inf(f32));374 try expectEqual(log2_f32(0.0), -math.inf(f32));
363 try expectEqual(log2f(-0.0), -math.inf(f32));375 try expectEqual(log2_f32(-0.0), -math.inf(f32));
364 try expect(math.isPositiveZero(log2f(1.0)));376 try expect(math.isPositiveZero(log2_f32(1.0)));
365 try expectEqual(log2f(2.0), 1.0);377 try expectEqual(log2_f32(2.0), 1.0);
366 try expectEqual(log2f(math.inf(f32)), math.inf(f32));378 try expectEqual(log2_f32(math.inf(f32)), math.inf(f32));
367 try expect(math.isNan(log2f(-1.0)));379 try expect(math.isNan(log2_f32(-1.0)));
368 try expect(math.isNan(log2f(-math.inf(f32))));380 try expect(math.isNan(log2_f32(-math.inf(f32))));
369 try expect(math.isNan(log2f(math.nan(f32))));381 try expect(math.isNan(log2_f32(math.nan(f32))));
370 try expect(math.isNan(log2f(math.snan(f32))));382 try expect(math.isNan(log2_f32(math.snan(f32))));
371}383}
372384
373test "log2f() sanity" {385test "log2f() sanity" {
374 try expect(math.isNan(log2f(-0x1.0223a0p+3)));386 try expect(math.isNan(log2_f32(-0x1.0223a0p+3)));
375 try expectEqual(log2f(0x1.161868p+2), 0x1.0f49acp+1);387 try expectEqual(log2_f32(0x1.161868p+2), 0x1.0f49acp+1);
376 try expect(math.isNan(log2f(-0x1.0c34b4p+3)));388 try expect(math.isNan(log2_f32(-0x1.0c34b4p+3)));
377 try expect(math.isNan(log2f(-0x1.a206f0p+2)));389 try expect(math.isNan(log2_f32(-0x1.a206f0p+2)));
378 try expectEqual(log2f(0x1.288bbcp+3), 0x1.9b2676p+1);390 try expectEqual(log2_f32(0x1.288bbcp+3), 0x1.9b2676p+1);
379 try expectEqual(log2f(0x1.52efd0p-1), -0x1.30b494p-1); // Disagrees with GCC in last bit391 try expectEqual(log2_f32(0x1.52efd0p-1), -0x1.30b494p-1); // Disagrees with GCC in last bit
380 try expect(math.isNan(log2f(-0x1.a05cc8p-2)));392 try expect(math.isNan(log2_f32(-0x1.a05cc8p-2)));
381 try expectEqual(log2f(0x1.1f9efap-1), -0x1.a9f89ap-1);393 try expectEqual(log2_f32(0x1.1f9efap-1), -0x1.a9f89ap-1);
382 try expectEqual(log2f(0x1.8c5db0p-1), -0x1.7a2c96p-2);394 try expectEqual(log2_f32(0x1.8c5db0p-1), -0x1.7a2c96p-2);
383 try expect(math.isNan(log2f(-0x1.5b86eap-1)));395 try expect(math.isNan(log2_f32(-0x1.5b86eap-1)));
384}396}
385397
386test "log2f() boundary" {398test "log2f() boundary" {
387 try expectEqual(log2f(0x1.fffffep+127), 0x1p+7); // Max input value399 try expectEqual(log2_f32(0x1.fffffep+127), 0x1p+7); // Max input value
388 try expectEqual(log2f(0x1p-149), -0x1.2ap+7); // Min positive input value400 try expectEqual(log2_f32(0x1p-149), -0x1.2ap+7); // Min positive input value
389 try expect(math.isNan(log2f(-0x1p-149))); // Min negative input value401 try expect(math.isNan(log2_f32(-0x1p-149))); // Min negative input value
390 try expectEqual(log2f(0x1.000002p+0), 0x1.715474p-23); // Last value before result reaches +0402 try expectEqual(log2_f32(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 -0403 try expectEqual(log2_f32(0x1.fffffep-1), -0x1.715478p-24); // Last value before result reaches -0
392 try expectEqual(log2f(0x1p-126), -0x1.f8p+6); // First subnormal404 try expectEqual(log2_f32(0x1p-126), -0x1.f8p+6); // First subnormal
393 try expect(math.isNan(log2f(-0x1p-126))); // First negative subnormal405 try expect(math.isNan(log2_f32(-0x1p-126))); // First negative subnormal
394406
395}407}
396408
397test "log2() special" {409test "log2() special" {
398 try expectEqual(log2(0.0), -math.inf(f64));410 try expectEqual(log2_f64(0.0), -math.inf(f64));
399 try expectEqual(log2(-0.0), -math.inf(f64));411 try expectEqual(log2_f64(-0.0), -math.inf(f64));
400 try expect(math.isPositiveZero(log2(1.0)));412 try expect(math.isPositiveZero(log2_f64(1.0)));
401 try expectEqual(log2(2.0), 1.0);413 try expectEqual(log2_f64(2.0), 1.0);
402 try expectEqual(log2(math.inf(f64)), math.inf(f64));414 try expectEqual(log2_f64(math.inf(f64)), math.inf(f64));
403 try expect(math.isNan(log2(-1.0)));415 try expect(math.isNan(log2_f64(-1.0)));
404 try expect(math.isNan(log2(-math.inf(f64))));416 try expect(math.isNan(log2_f64(-math.inf(f64))));
405 try expect(math.isNan(log2(math.nan(f64))));417 try expect(math.isNan(log2_f64(math.nan(f64))));
406 try expect(math.isNan(log2(math.snan(f64))));418 try expect(math.isNan(log2_f64(math.snan(f64))));
407}419}
408420
409test "log2() sanity" {421test "log2() sanity" {
410 try expect(math.isNan(log2(-0x1.02239f3c6a8f1p+3)));422 try expect(math.isNan(log2_f64(-0x1.02239f3c6a8f1p+3)));
411 try expectEqual(log2(0x1.161868e18bc67p+2), 0x1.0f49ac3838580p+1);423 try expectEqual(log2_f64(0x1.161868e18bc67p+2), 0x1.0f49ac3838580p+1);
412 try expect(math.isNan(log2(-0x1.0c34b3e01e6e7p+3)));424 try expect(math.isNan(log2_f64(-0x1.0c34b3e01e6e7p+3)));
413 try expect(math.isNan(log2(-0x1.a206f0a19dcc4p+2)));425 try expect(math.isNan(log2_f64(-0x1.a206f0a19dcc4p+2)));
414 try expectEqual(log2(0x1.288bbb0d6a1e6p+3), 0x1.9b26760c2a57ep+1);426 try expectEqual(log2_f64(0x1.288bbb0d6a1e6p+3), 0x1.9b26760c2a57ep+1);
415 try expectEqual(log2(0x1.52efd0cd80497p-1), -0x1.30b490ef684c7p-1);427 try expectEqual(log2_f64(0x1.52efd0cd80497p-1), -0x1.30b490ef684c7p-1);
416 try expect(math.isNan(log2(-0x1.a05cc754481d1p-2)));428 try expect(math.isNan(log2_f64(-0x1.a05cc754481d1p-2)));
417 try expectEqual(log2(0x1.1f9ef934745cbp-1), -0x1.a9f89b5f5acb8p-1);429 try expectEqual(log2_f64(0x1.1f9ef934745cbp-1), -0x1.a9f89b5f5acb8p-1);
418 try expectEqual(log2(0x1.8c5db097f7442p-1), -0x1.7a2c947173f06p-2);430 try expectEqual(log2_f64(0x1.8c5db097f7442p-1), -0x1.7a2c947173f06p-2);
419 try expect(math.isNan(log2(-0x1.5b86ea8118a0ep-1)));431 try expect(math.isNan(log2_f64(-0x1.5b86ea8118a0ep-1)));
420}432}
421433
422test "log2() boundary" {434test "log2() boundary" {
423 try expectEqual(log2(0x1.fffffffffffffp+1023), 0x1p+10); // Max input value435 try expectEqual(log2_f64(0x1.fffffffffffffp+1023), 0x1p+10); // Max input value
424 try expectEqual(log2(0x1p-1074), -0x1.0c8p+10); // Min positive input value436 try expectEqual(log2_f64(0x1p-1074), -0x1.0c8p+10); // Min positive input value
425 try expect(math.isNan(log2(-0x1p-1074))); // Min negative input value437 try expect(math.isNan(log2_f64(-0x1p-1074))); // Min negative input value
426 try expectEqual(log2(0x1.0000000000001p+0), 0x1.71547652b82fdp-52); // Last value before result reaches +0438 try expectEqual(log2_f64(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 -0439 try expectEqual(log2_f64(0x1.fffffffffffffp-1), -0x1.71547652b82fep-53); // Last value before result reaches -0
428 try expectEqual(log2(0x1p-1022), -0x1.ffp+9); // First subnormal440 try expectEqual(log2_f64(0x1p-1022), -0x1.ffp+9); // First subnormal
429 try expect(math.isNan(log2(-0x1p-1022))); // First negative subnormal441 try expect(math.isNan(log2_f64(-0x1p-1022))); // First negative subnormal
430}442}
431443
432test "log2q() special" {444test "log2q() special" {
433 try expectEqual(log2q(0.0), -math.inf(f128));445 try expectEqual(log2_f128(0.0), -math.inf(f128));
434 try expectEqual(log2q(-0.0), -math.inf(f128));446 try expectEqual(log2_f128(-0.0), -math.inf(f128));
435 try expect(math.isPositiveZero(log2q(1.0)));447 try expect(math.isPositiveZero(log2_f128(1.0)));
436 try expectEqual(log2q(2.0), 1.0);448 try expectEqual(log2_f128(2.0), 1.0);
437 try expectEqual(log2q(math.inf(f128)), math.inf(f128));449 try expectEqual(log2_f128(math.inf(f128)), math.inf(f128));
438 try expect(math.isNan(log2q(-1.0)));450 try expect(math.isNan(log2_f128(-1.0)));
439 try expect(math.isNan(log2q(-math.inf(f128))));451 try expect(math.isNan(log2_f128(-math.inf(f128))));
440 try expect(math.isNan(log2q(math.nan(f128))));452 try expect(math.isNan(log2_f128(math.nan(f128))));
441 try expect(math.isNan(log2q(math.snan(f128))));453 try expect(math.isNan(log2_f128(math.snan(f128))));
442}454}
443455
444test "log2q() boundary" {456test "log2q() boundary" {
445 try expectEqual(log2q(0x1.ffffffffffffffffffffffffffffp16383), 0x1p14); // Max input value457 try expectEqual(log2_f128(0x1.ffffffffffffffffffffffffffffp16383), 0x1p14); // Max input value
446 try expectEqual(log2q(0x1p-16494), -0x1.01b8p14); // Min positive input value458 try expectEqual(log2_f128(0x1p-16494), -0x1.01b8p14); // Min positive input value
447 try expect(math.isNan(log2q(-0x1p-16494))); // Min negative input value459 try expect(math.isNan(log2_f128(-0x1p-16494))); // Min negative input value
448 try expectEqual(log2q(0x1.0000000000000000000000000001p0), 0x1.71547652b82fe1777d0ffda0d23ap-112); // Last value before result reaches +0460 try expectEqual(log2_f128(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 -0461 try expectEqual(log2_f128(0x1.ffffffffffffffffffffffffffffp-1), -0x1.71547652b82fe1777d0ffda0d23bp-113); // Last value before result reaches -0
450 try expectEqual(log2q(0x1p-16382), -0x1.fffp13); // First subnormal462 try expectEqual(log2_f128(0x1p-16382), -0x1.fffp13); // First subnormal
451 try expect(math.isNan(log2q(-0x1p-16382))); // First negative subnormal463 try expect(math.isNan(log2_f128(-0x1p-16382))); // First negative subnormal
452}464}
453465
454test "log2q() sanity" {466test "log2q() sanity" {
455 try expectEqual(log2q(8.0965013884643408203125e11), 3.955850767769801288865582596068254e1);467 try expectEqual(log2_f128(8.0965013884643408203125e11), 3.955850767769801288865582596068254e1);
456 try expectEqual(log2q(8.346531942223744e15), 5.28900982928636641107356163006646e1);468 try expectEqual(log2_f128(8.346531942223744e15), 5.28900982928636641107356163006646e1);
457 try expectEqual(log2q(9.707809913413123613777865431464565e-20), -6.315941603809020445822192336703809e1);469 try expectEqual(log2_f128(9.707809913413123613777865431464565e-20), -6.315941603809020445822192336703809e1);
458 try expectEqual(log2q(1.9179565888043380306021427656243352e-24), -7.878670421065570557450089031998522e1);470 try expectEqual(log2_f128(1.9179565888043380306021427656243352e-24), -7.878670421065570557450089031998522e1);
459 try expectEqual(log2q(2.5260048200126556877075044745936796e-25), -8.17113449801679676275805009400338e1);471 try expectEqual(log2_f128(2.5260048200126556877075044745936796e-25), -8.17113449801679676275805009400338e1);
460 try expectEqual(log2q(3.1170134002568967640399932861328125e7), 2.489366102143423848582774267206741e1);472 try expectEqual(log2_f128(3.1170134002568967640399932861328125e7), 2.489366102143423848582774267206741e1);
461 // test near 1473 // test near 1
462 try expectEqual(log2q(1.026586845186097528392910049888087e0), 3.7855678902522753591699367969189364e-2);474 try expectEqual(log2_f128(1.026586845186097528392910049888087e0), 3.7855678902522753591699367969189364e-2);
463 try expectEqual(log2q(1.0005582850578053877743656130405725e0), 8.052103367568488432896147152682078e-4);475 try expectEqual(log2_f128(1.0005582850578053877743656130405725e0), 8.052103367568488432896147152682078e-4);
464 try expectEqual(log2q(1.0370174103591254835765589348284266e0), 5.244011558596899945639244281954306e-2);476 try expectEqual(log2_f128(1.0370174103591254835765589348284266e0), 5.244011558596899945639244281954306e-2);
465 try expectEqual(log2q(1.0429996503525671713075162472250667e0), 6.073867421942172944687194557176633e-2);477 try expectEqual(log2_f128(1.0429996503525671713075162472250667e0), 6.073867421942172944687194557176633e-2);
466 try expectEqual(log2q(1.0383384027961064621892184334228659e0), 5.4276706191956281784022630732940314e-2);478 try expectEqual(log2_f128(1.0383384027961064621892184334228659e0), 5.4276706191956281784022630732940314e-2);
467}479}
lib/compiler_rt/memcpy.zig+1-1
...@@ -11,7 +11,7 @@ comptime {...@@ -11,7 +11,7 @@ comptime {
11 .visibility = compiler_rt.visibility,11 .visibility = compiler_rt.visibility,
12 };12 };
1313
14 if (builtin.mode == .ReleaseSmall or builtin.zig_backend == .stage2_aarch64)14 if (builtin.mode == .small or builtin.zig_backend == .stage2_aarch64)
15 @export(&memcpySmall, export_options)15 @export(&memcpySmall, export_options)
16 else16 else
17 @export(&memcpyFast, export_options);17 @export(&memcpyFast, export_options);
lib/compiler_rt/memmove.zig+1-1
...@@ -14,7 +14,7 @@ comptime {...@@ -14,7 +14,7 @@ comptime {
14 .visibility = compiler_rt.visibility,14 .visibility = compiler_rt.visibility,
15 };15 };
1616
17 if (builtin.mode == .ReleaseSmall or builtin.zig_backend == .stage2_aarch64)17 if (builtin.mode == .small or builtin.zig_backend == .stage2_aarch64)
18 @export(&memmoveSmall, export_options)18 @export(&memmoveSmall, export_options)
19 else19 else
20 @export(&memmoveFast, export_options);20 @export(&memmoveFast, export_options);
lib/compiler_rt/mulc3.zig+75-10
...@@ -3,19 +3,80 @@ const isNan = std.math.isNan;...@@ -3,19 +3,80 @@ const isNan = std.math.isNan;
3const isInf = std.math.isInf;3const isInf = std.math.isInf;
4const copysign = std.math.copysign;4const copysign = std.math.copysign;
55
6pub fn Complex(comptime T: type) type {6const compiler_rt = @import("../compiler_rt.zig");
7 return extern struct {7const symbol = compiler_rt.symbol;
8 real: T,8const Complex = compiler_rt.Complex;
9 imag: T,9
10 };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);
11}72}
1273
13/// Implementation based on Annex G of C17 Standard (N2176)74/// 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) {75inline fn mulc3(comptime T: type, lhs: Complex(T), rhs: Complex(T)) Complex(T) {
15 var a = a_in;76 var a = lhs.real;
16 var b = b_in;77 var b = lhs.imag;
17 var c = c_in;78 var c = rhs.real;
18 var d = d_in;79 var d = rhs.imag;
1980
20 const ac = a * c;81 const ac = a * c;
21 const bd = b * d;82 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...@@ -77,3 +138,7 @@ pub inline fn mulc3(comptime T: type, a_in: T, b_in: T, c_in: T, d_in: T) Comple
77 }138 }
78 return z;139 return z;
79}140}
141
142test {
143 _ = @import("mulc3_test.zig");
144}
lib/compiler_rt/mulc3_test.zig+23-42
...@@ -2,64 +2,45 @@ const std = @import("std");...@@ -2,64 +2,45 @@ const std = @import("std");
2const math = std.math;2const math = std.math;
3const expect = std.testing.expect;3const expect = std.testing.expect;
44
5const Complex = @import("./mulc3.zig").Complex;5const Complex = @import("../compiler_rt.zig").Complex;
6const __mulhc3 = @import("./mulhc3.zig").__mulhc3;6const impl = @import("mulc3.zig");
7const __mulsc3 = @import("./mulsc3.zig").__mulsc3;7const mul_cf16 = impl.mul_cf16;
8const __muldc3 = @import("./muldc3.zig").__muldc3;8const mul_cf32 = impl.mul_cf32;
9const __mulxc3 = @import("./mulxc3.zig").__mulxc3;9const mul_cf64 = impl.mul_cf64;
10const __multc3 = @import("./multc3.zig").__multc3;10const mul_cf80 = impl.mul_cf80;
11const mul_cf128 = impl.mul_cf128;
1112
12test "mulc3" {13test "mulc3" {
13 try testMul(f16, __mulhc3);14 try testMul(f16, mul_cf16);
14 try testMul(f32, __mulsc3);15 try testMul(f32, mul_cf32);
15 try testMul(f64, __muldc3);16 try testMul(f64, mul_cf64);
16 try testMul(f80, __mulxc3);17 try testMul(f80, mul_cf80);
17 try testMul(f128, __multc3);18 try testMul(f128, mul_cf128);
18}19}
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 {
21 {22 {
22 const a: T = 1.0;23 const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -1.0, .imag = 0.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);
28 try expect(result.real == -1.0);24 try expect(result.real == -1.0);
29 try expect(result.imag == 0.0);25 try expect(math.isPositiveZero(result.imag));
30 }26 }
31 {27 {
32 const a: T = 1.0;28 const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -4.0, .imag = 0.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);
38 try expect(result.real == -4.0);29 try expect(result.real == -4.0);
39 try expect(result.imag == 0.0);30 try expect(math.isPositiveZero(result.imag));
40 }31 }
41 {32 {
42 // if one operand is an infinity and the other operand is a nonzero finite number or an infinity,33 // if one operand is an infinity and the other operand is a nonzero finite number or an infinity,
43 // then the result of the * operator is an infinity;34 // then the result of the * operator is an infinity;
44 const a: T = math.inf(T);35 const result = f(.{ .real = math.inf(T), .imag = -math.inf(T) }, .{ .real = 1.0, .imag = 0.0 });
45 const b: T = -math.inf(T);36 try expect(math.isPositiveInf(result.real));
46 const c: T = 1.0;37 try expect(math.isNegativeInf(result.imag));
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));
52 }38 }
53 {39 {
54 // if one operand is an infinity and the other operand is a nonzero finite number or an infinity,40 // if one operand is an infinity and the other operand is a nonzero finite number or an infinity,
55 // then the result of the * operator is an infinity;41 // then the result of the * operator is an infinity;
56 const a: T = math.inf(T);42 const result = f(.{ .real = math.inf(T), .imag = -1.0 }, .{ .real = 1.0, .imag = math.inf(T) });
57 const b: T = -1.0;43 try expect(math.isPositiveInf(result.real));
58 const c: T = 1.0;44 try expect(math.isPositiveInf(result.imag));
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));
64 }45 }
65}46}
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");...@@ -2,10 +2,76 @@ const std = @import("std");
2const math = std.math;2const math = std.math;
3const builtin = @import("builtin");3const builtin = @import("builtin");
4const compiler_rt = @import("../compiler_rt.zig");4const 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
6/// Ported from:72/// Ported from:
7/// https://github.com/llvm/llvm-project/blob/2ffb1b0413efa9a24eb3c49e710e36f92e2cb50b/compiler-rt/lib/builtins/fp_mul_impl.inc73/// 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 {
9 @setRuntimeSafety(compiler_rt.test_safety);75 @setRuntimeSafety(compiler_rt.test_safety);
10 const typeWidth = @typeInfo(T).float.bits;76 const typeWidth = @typeInfo(T).float.bits;
11 const significandBits = math.floatMantissaBits(T);77 const significandBits = math.floatMantissaBits(T);
lib/compiler_rt/mulf3_test.zig+48-46
...@@ -7,10 +7,12 @@ const math = std.math;...@@ -7,10 +7,12 @@ const math = std.math;
7const qnan128: f128 = @bitCast(@as(u128, 0x7fff800000000000) << 64);7const qnan128: f128 = @bitCast(@as(u128, 0x7fff800000000000) << 64);
8const inf128: f128 = @bitCast(@as(u128, 0x7fff000000000000) << 64);8const inf128: f128 = @bitCast(@as(u128, 0x7fff000000000000) << 64);
99
10const __multf3 = @import("multf3.zig").__multf3;10const impl = @import("mulf3.zig");
11const __mulxf3 = @import("mulxf3.zig").__mulxf3;11const mul_f16 = impl.mul_f16;
12const __muldf3 = @import("muldf3.zig").__muldf3;12const mul_f32 = impl.mul_f32;
13const __mulsf3 = @import("mulsf3.zig").__mulsf3;13const mul_f64 = impl.mul_f64;
14const mul_f80 = impl.mul_f80;
15const mul_f128 = impl.mul_f128;
1416
15// return true if equal17// return true if equal
16// use two 64-bit integers instead of one 128-bit integer18// use two 64-bit integers instead of one 128-bit integer
...@@ -34,8 +36,8 @@ fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool {...@@ -34,8 +36,8 @@ fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool {
34 return false;36 return false;
35}37}
3638
37fn test__multf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void {39fn test_mul_f128(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void {
38 const x = __multf3(a, b);40 const x = mul_f128(a, b);
3941
40 if (compareResultLD(x, expected_hi, expected_lo))42 if (compareResultLD(x, expected_hi, expected_lo))
41 return;43 return;
...@@ -49,68 +51,68 @@ fn makeNaN128(rand: u64) f128 {...@@ -49,68 +51,68 @@ fn makeNaN128(rand: u64) f128 {
49}51}
50test "multf3" {52test "multf3" {
51 // qNaN * any = qNaN53 // 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
54 // NaN * any = NaN56 // NaN * any = NaN
55 const a = makeNaN128(0x800030000000);57 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);
57 // inf * any = inf59 // 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
60 // any * any62 // any * any
61 try test__multf3(63 try test_mul_f128(
62 @as(f128, @bitCast(@as(u128, 0x40042eab345678439abcdefea5678234))),64 @as(f128, @bitCast(@as(u128, 0x40042eab345678439abcdefea5678234))),
63 @as(f128, @bitCast(@as(u128, 0x3ffeedcb34a235253948765432134675))),65 @as(f128, @bitCast(@as(u128, 0x3ffeedcb34a235253948765432134675))),
64 0x400423e7f9e3c9fc,66 0x400423e7f9e3c9fc,
65 0xd906c2c2a85777c4,67 0xd906c2c2a85777c4,
66 );68 );
6769
68 try test__multf3(70 try test_mul_f128(
69 @as(f128, @bitCast(@as(u128, 0x3fcd353e45674d89abacc3a2ebf3ff50))),71 @as(f128, @bitCast(@as(u128, 0x3fcd353e45674d89abacc3a2ebf3ff50))),
70 @as(f128, @bitCast(@as(u128, 0x3ff6ed8764648369535adf4be3214568))),72 @as(f128, @bitCast(@as(u128, 0x3ff6ed8764648369535adf4be3214568))),
71 0x3fc52a163c6223fc,73 0x3fc52a163c6223fc,
72 0xc94c4bf0430768b4,74 0xc94c4bf0430768b4,
73 );75 );
7476
75 try test__multf3(77 try test_mul_f128(
76 0x1.234425696abcad34a35eeffefdcbap+456,78 0x1.234425696abcad34a35eeffefdcbap+456,
77 0x451.ed98d76e5d46e5f24323dff21ffp+600,79 0x451.ed98d76e5d46e5f24323dff21ffp+600,
78 0x44293a91de5e0e94,80 0x44293a91de5e0e94,
79 0xe8ed17cc2cdf64ac,81 0xe8ed17cc2cdf64ac,
80 );82 );
8183
82 try test__multf3(84 try test_mul_f128(
83 @as(f128, @bitCast(@as(u128, 0x3f154356473c82a9fabf2d22ace345df))),85 @as(f128, @bitCast(@as(u128, 0x3f154356473c82a9fabf2d22ace345df))),
84 @as(f128, @bitCast(@as(u128, 0x3e38eda98765476743ab21da23d45679))),86 @as(f128, @bitCast(@as(u128, 0x3e38eda98765476743ab21da23d45679))),
85 0x3d4f37c1a3137cae,87 0x3d4f37c1a3137cae,
86 0xfc6807048bc2836a,88 0xfc6807048bc2836a,
87 );89 );
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
91 // Denormal operands.93 // Denormal operands.
92 try test__multf3(94 try test_mul_f128(
93 0x0.0000000000000000000000000001p-16382,95 0x0.0000000000000000000000000001p-16382,
94 0x1p16383,96 0x1p16383,
95 0x3f90000000000000,97 0x3f90000000000000,
96 0x0,98 0x0,
97 );99 );
98 try test__multf3(100 try test_mul_f128(
99 0x1p16383,101 0x1p16383,
100 0x0.0000000000000000000000000001p-16382,102 0x0.0000000000000000000000000001p-16382,
101 0x3f90000000000000,103 0x3f90000000000000,
102 0x0,104 0x0,
103 );105 );
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);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);
106 try test__multf3(0x1.0000_0000_0000_0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0003);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);
107 try test__multf3(2.0, math.floatTrueMin(f128), 0x0000_0000_0000_0000, 0x0000_0000_0000_0002);109 try test_mul_f128(2.0, math.floatTrueMin(f128), 0x0000_0000_0000_0000, 0x0000_0000_0000_0002);
108}110}
109111
110const qnan80: f80 = @bitCast(@as(u80, @bitCast(math.nan(f80))) | (1 << (math.floatFractionalBits(f80) - 1)));112const 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 {114fn test_mul_f80(a: f80, b: f80, expected: u80) !void {
113 const x = __mulxf3(a, b);115 const x = mul_f80(a, b);
114 const rep: u80 = @bitCast(x);116 const rep: u80 = @bitCast(x);
115117
116 if (rep == expected)118 if (rep == expected)
...@@ -124,47 +126,47 @@ fn test__mulxf3(a: f80, b: f80, expected: u80) !void {...@@ -124,47 +126,47 @@ fn test__mulxf3(a: f80, b: f80, expected: u80) !void {
124126
125test "mulxf3" {127test "mulxf3" {
126 // NaN * any = NaN128 // NaN * any = NaN
127 try test__mulxf3(qnan80, 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80)));129 try test_mul_f80(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)));130 try test_mul_f80(@as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80)));
129131
130 // any * NaN = NaN132 // any * NaN = NaN
131 try test__mulxf3(0x1.23456789abcdefp+5, qnan80, @as(u80, @bitCast(qnan80)));133 try test_mul_f80(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)));134 try test_mul_f80(0x1.23456789abcdefp+5, @as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), @as(u80, @bitCast(qnan80)));
133135
134 // NaN * inf = NaN136 // 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
137 // inf * NaN = NaN139 // 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
140 // inf * inf = inf142 // 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
143 // inf * -inf = -inf145 // 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
146 // -inf + inf = -inf148 // -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
149 // inf * any = inf151 // 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
152 // any * inf = inf154 // 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
155 // any * any157 // any * any
156 try test__mulxf3(0x1.0p+0, 0x1.dcba987654321p+5, 0x4004_ee5d_4c3b_2a19_0800);158 try test_mul_f80(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); // exact159 try test_mul_f80(0x1.0000_0000_0000_0004p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0003); // exact
158160
159 try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.0p+5, 0x4004_8000_0000_0000_0001); // exact161 try test_mul_f80(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 down162 try test_mul_f80(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 even163 try test_mul_f80(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 up164 try test_mul_f80(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); // exact165 try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.0p+6, 0x4005_8000_0000_0000_0001); // exact
164166
165 try test__mulxf3(0x1.0000_0001p+0, 0x1.0000_0001p+0, 0x3FFF_8000_0001_0000_0000); // round down to even167 try test_mul_f80(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 up168 try test_mul_f80(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 -> normal169 try test_mul_f80(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 -> normal170 try test_mul_f80(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 -> denormal171 try test_mul_f80(0x0.7fff_ffff_ffff_fffep-16382, 0x1.0000_0000_0000_0000p0, 0x0000_3FFF_FFFF_FFFF_FFFF); // denormal -> denormal
170}172}
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 @@...@@ -1,7 +1,8 @@
1const testing = @import("std").testing;1const testing = @import("std").testing;
22
3const mulv = @import("mulo.zig");3const mulv = @import("mulo.zig");
4const symbol = @import("../compiler_rt.zig").symbol;4const compiler_rt = @import("../compiler_rt.zig");
5const symbol = compiler_rt.symbol;
56
6comptime {7comptime {
7 symbol(&__mulvsi3, "__mulvsi3");8 symbol(&__mulvsi3, "__mulvsi3");
...@@ -10,7 +11,7 @@ comptime {...@@ -10,7 +11,7 @@ comptime {
10pub fn __mulvsi3(a: i32, b: i32) callconv(.c) i32 {11pub fn __mulvsi3(a: i32, b: i32) callconv(.c) i32 {
11 var overflow: c_int = 0;12 var overflow: c_int = 0;
12 const sum = mulv.__mulosi4(a, b, &overflow);13 const sum = mulv.__mulosi4(a, b, &overflow);
13 if (overflow != 0) @panic("compiler-rt: integer overflow");14 if (overflow != 0) @panic("integer overflow");
14 return sum;15 return sum;
15}16}
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 {...@@ -33,8 +33,7 @@ inline fn negvXi(comptime ST: type, a: ST) ST {
33 };33 };
34 const N: UT = @bitSizeOf(ST);34 const N: UT = @bitSizeOf(ST);
35 const min: ST = @as(ST, @bitCast((@as(UT, 1) << (N - 1))));35 const min: ST = @as(ST, @bitCast((@as(UT, 1) << (N - 1))));
36 if (a == min)36 if (a == min) @panic("integer overflow");
37 @panic("compiler_rt negv: overflow");
38 return -a;37 return -a;
39}38}
4039
lib/compiler_rt/os_version_check.zig-1
...@@ -3,7 +3,6 @@ const testing = std.testing;...@@ -3,7 +3,6 @@ const testing = std.testing;
3const builtin = @import("builtin");3const builtin = @import("builtin");
4const compiler_rt = @import("../compiler_rt.zig");4const compiler_rt = @import("../compiler_rt.zig");
5const symbol = compiler_rt.symbol;5const symbol = compiler_rt.symbol;
6const panic = @import("../compiler_rt.zig").panic;
76
8const have_availability_version_check = builtin.os.tag.isDarwin() and7const have_availability_version_check = builtin.os.tag.isDarwin() and
9 builtin.os.version_range.semver.min.order(.{ .major = 10, .minor = 15, .patch = 0 }).compare(.gte);8 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 @@...@@ -1,6 +1,7 @@
1//! parity - if number of bits set is even => 0, else => 11//! parity - if number of bits set is even => 0, else => 1
2//! - pariytXi2_generic for big and little endian2//! - 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
5comptime {6comptime {
6 symbol(&__paritysi2, "__paritysi2");7 symbol(&__paritysi2, "__paritysi2");
lib/compiler_rt/popcount.zig+2-1
...@@ -6,7 +6,8 @@...@@ -6,7 +6,8 @@
6//! TAOCP: Combinational Algorithms, Bitwise Tricks And Techniques,6//! TAOCP: Combinational Algorithms, Bitwise Tricks And Techniques,
7//! subsubsection "Working with the rightmost bits" and "Sideways addition".7//! 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
11comptime {12comptime {
12 symbol(&__popcountsi2, "__popcountsi2");13 symbol(&__popcountsi2, "__popcountsi2");
lib/compiler_rt/powiXf2.zig+28-11
...@@ -4,16 +4,18 @@...@@ -4,16 +4,18 @@
4//! error propagation and this method is optimized for performance, not accuracy.4//! error propagation and this method is optimized for performance, not accuracy.
55
6const compiler_rt = @import("../compiler_rt.zig");6const compiler_rt = @import("../compiler_rt.zig");
7const symbol = @import("../compiler_rt.zig").symbol;7const symbol = compiler_rt.symbol;
88
9comptime {9comptime {
10 symbol(&__powihf2, "__powihf2");10 symbol(&__powihf2, "__powihf2");
11 symbol(&__powisf2, "__powisf2");11 symbol(&__powisf2, "__powisf2");
12 symbol(&__powidf2, "__powidf2");12 symbol(&__powidf2, "__powidf2");
13 if (compiler_rt.want_ppc_abi)
14 symbol(&__powitf2, "__powikf2");
15 symbol(&__powitf2, "__powitf2");
16 symbol(&__powixf2, "__powixf2");13 symbol(&__powixf2, "__powixf2");
14 if (compiler_rt.want_ppc_abi) {
15 symbol(&__powitf2, "__powikf2");
16 } else {
17 symbol(&__powitf2, "__powitf2");
18 }
17}19}
1820
19inline fn powiXf2(comptime FT: type, a: FT, b: i32) FT {21inline 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 {...@@ -32,26 +34,41 @@ inline fn powiXf2(comptime FT: type, a: FT, b: i32) FT {
32 return if (is_recip) 1 / r else r;34 return if (is_recip) 1 / r else r;
33}35}
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 {
36 return powiXf2(f16, a, b);41 return powiXf2(f16, a, b);
37}42}
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 {
40 return powiXf2(f32, a, b);48 return powiXf2(f32, a, b);
41}49}
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 {
44 return powiXf2(f64, a, b);55 return powiXf2(f64, a, b);
45}56}
4657
47pub fn __powitf2(a: f128, b: i32) callconv(.c) f128 {58fn __powixf2(a: compiler_rt.f80.Abi, b: i32) callconv(.c) compiler_rt.f80.Abi {
48 return powiXf2(f128, a, b);59 return compiler_rt.f80.toAbi(powi_f80(compiler_rt.f80.fromAbi(a), b));
49}60}
5061pub fn powi_f80(a: f80, b: i32) f80 {
51pub fn __powixf2(a: f80, b: i32) callconv(.c) f80 {
52 return powiXf2(f80, a, b);62 return powiXf2(f80, a, b);
53}63}
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
55test {72test {
56 _ = @import("powiXf2_test.zig");73 _ = @import("powiXf2_test.zig");
57}74}
lib/compiler_rt/powiXf2_test.zig+531-525
...@@ -2,562 +2,568 @@...@@ -2,562 +2,568 @@
2// powisf2_test.c, powidf2_test.c, powitf2_test.c, powixf2_test.c2// powisf2_test.c, powidf2_test.c, powitf2_test.c, powixf2_test.c
3// powihf2 adapted from powisf2 tests3// powihf2 adapted from powisf2 tests
44
5const powiXf2 = @import("powiXf2.zig");
6const std = @import("std");5const std = @import("std");
7const builtin = @import("builtin");
8const testing = std.testing;6const testing = std.testing;
9const math = std.math;7const math = std.math;
108
11fn test__powihf2(a: f16, b: i32, expected: f16) !void {9const impl = @import("powiXf2.zig");
12 const result = powiXf2.__powihf2(a, b);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);
13 try testing.expectEqual(expected, result);19 try testing.expectEqual(expected, result);
14}20}
1521
16fn test__powisf2(a: f32, b: i32, expected: f32) !void {22fn test_powi_f32(a: f32, b: i32, expected: f32) !void {
17 const result = powiXf2.__powisf2(a, b);23 const result = powi_f32(a, b);
18 try testing.expectEqual(expected, result);24 try testing.expectEqual(expected, result);
19}25}
2026
21fn test__powidf2(a: f64, b: i32, expected: f64) !void {27fn test_powi_f64(a: f64, b: i32, expected: f64) !void {
22 const result = powiXf2.__powidf2(a, b);28 const result = powi_f64(a, b);
23 try testing.expectEqual(expected, result);29 try testing.expectEqual(expected, result);
24}30}
2531
26fn test__powitf2(a: f128, b: i32, expected: f128) !void {32fn test_powi_f80(a: f80, b: i32, expected: f80) !void {
27 const result = powiXf2.__powitf2(a, b);33 const result = powi_f80(a, b);
28 try testing.expectEqual(expected, result);34 try testing.expectEqual(expected, result);
29}35}
3036
31fn test__powixf2(a: f80, b: i32, expected: f80) !void {37fn test_powi_f128(a: f128, b: i32, expected: f128) !void {
32 const result = powiXf2.__powixf2(a, b);38 const result = powi_f128(a, b);
33 try testing.expectEqual(expected, result);39 try testing.expectEqual(expected, result);
34}40}
3541
36test "powihf2" {42test powi_f16 {
37 const inf_f16 = math.inf(f16);43 const inf_f16 = math.inf(f16);
38 try test__powisf2(0, 0, 1);44 try test_powi_f16(0, 0, 1);
39 try test__powihf2(1, 0, 1);45 try test_powi_f16(1, 0, 1);
40 try test__powihf2(1.5, 0, 1);46 try test_powi_f16(1.5, 0, 1);
41 try test__powihf2(2, 0, 1);47 try test_powi_f16(2, 0, 1);
42 try test__powihf2(inf_f16, 0, 1);48 try test_powi_f16(inf_f16, 0, 1);
4349
44 try test__powihf2(-0.0, 0, 1);50 try test_powi_f16(-0.0, 0, 1);
45 try test__powihf2(-1, 0, 1);51 try test_powi_f16(-1, 0, 1);
46 try test__powihf2(-1.5, 0, 1);52 try test_powi_f16(-1.5, 0, 1);
47 try test__powihf2(-2, 0, 1);53 try test_powi_f16(-2, 0, 1);
48 try test__powihf2(-inf_f16, 0, 1);54 try test_powi_f16(-inf_f16, 0, 1);
4955
50 try test__powihf2(0, 1, 0);56 try test_powi_f16(0, 1, 0);
51 try test__powihf2(0, 2, 0);57 try test_powi_f16(0, 2, 0);
52 try test__powihf2(0, 3, 0);58 try test_powi_f16(0, 3, 0);
53 try test__powihf2(0, 4, 0);59 try test_powi_f16(0, 4, 0);
54 try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);60 try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
55 try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);61 try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
5662
57 try test__powihf2(-0.0, 1, -0.0);63 try test_powi_f16(-0.0, 1, -0.0);
58 try test__powihf2(-0.0, 2, 0);64 try test_powi_f16(-0.0, 2, 0);
59 try test__powihf2(-0.0, 3, -0.0);65 try test_powi_f16(-0.0, 3, -0.0);
60 try test__powihf2(-0.0, 4, 0);66 try test_powi_f16(-0.0, 4, 0);
61 try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);67 try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
62 try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);68 try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
6369
64 try test__powihf2(1, 1, 1);70 try test_powi_f16(1, 1, 1);
65 try test__powihf2(1, 2, 1);71 try test_powi_f16(1, 2, 1);
66 try test__powihf2(1, 3, 1);72 try test_powi_f16(1, 3, 1);
67 try test__powihf2(1, 4, 1);73 try test_powi_f16(1, 4, 1);
68 try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);74 try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
69 try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);75 try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
7076
71 try test__powihf2(inf_f16, 1, inf_f16);77 try test_powi_f16(inf_f16, 1, inf_f16);
72 try test__powihf2(inf_f16, 2, inf_f16);78 try test_powi_f16(inf_f16, 2, inf_f16);
73 try test__powihf2(inf_f16, 3, inf_f16);79 try test_powi_f16(inf_f16, 3, inf_f16);
74 try test__powihf2(inf_f16, 4, inf_f16);80 try test_powi_f16(inf_f16, 4, inf_f16);
75 try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16);81 try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16);
76 try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f16);82 try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f16);
7783
78 try test__powihf2(-inf_f16, 1, -inf_f16);84 try test_powi_f16(-inf_f16, 1, -inf_f16);
79 try test__powihf2(-inf_f16, 2, inf_f16);85 try test_powi_f16(-inf_f16, 2, inf_f16);
80 try test__powihf2(-inf_f16, 3, -inf_f16);86 try test_powi_f16(-inf_f16, 3, -inf_f16);
81 try test__powihf2(-inf_f16, 4, inf_f16);87 try test_powi_f16(-inf_f16, 4, inf_f16);
82 try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16);88 try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16);
83 try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f16);89 try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f16);
84 //90 //
85 try test__powihf2(0, -1, inf_f16);91 try test_powi_f16(0, -1, inf_f16);
86 try test__powihf2(0, -2, inf_f16);92 try test_powi_f16(0, -2, inf_f16);
87 try test__powihf2(0, -3, inf_f16);93 try test_powi_f16(0, -3, inf_f16);
88 try test__powihf2(0, -4, inf_f16);94 try test_powi_f16(0, -4, inf_f16);
89 try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // 0 ^ anything = +inf95 try test_powi_f16(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);96 try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f16);
91 try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16);97 try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16);
9298
93 try test__powihf2(-0.0, -1, -inf_f16);99 try test_powi_f16(-0.0, -1, -inf_f16);
94 try test__powihf2(-0.0, -2, inf_f16);100 try test_powi_f16(-0.0, -2, inf_f16);
95 try test__powihf2(-0.0, -3, -inf_f16);101 try test_powi_f16(-0.0, -3, -inf_f16);
96 try test__powihf2(-0.0, -4, inf_f16);102 try test_powi_f16(-0.0, -4, inf_f16);
97 try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // -0 ^ anything even = +inf103 try test_powi_f16(-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 = -inf104 try test_powi_f16(-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);105 try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16);
100106
101 try test__powihf2(1, -1, 1);107 try test_powi_f16(1, -1, 1);
102 try test__powihf2(1, -2, 1);108 try test_powi_f16(1, -2, 1);
103 try test__powihf2(1, -3, 1);109 try test_powi_f16(1, -3, 1);
104 try test__powihf2(1, -4, 1);110 try test_powi_f16(1, -4, 1);
105 try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); // 1.0 ^ anything = 1111 try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); // 1.0 ^ anything = 1
106 try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);112 try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
107 try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);113 try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
108114
109 try test__powihf2(inf_f16, -1, 0);115 try test_powi_f16(inf_f16, -1, 0);
110 try test__powihf2(inf_f16, -2, 0);116 try test_powi_f16(inf_f16, -2, 0);
111 try test__powihf2(inf_f16, -3, 0);117 try test_powi_f16(inf_f16, -3, 0);
112 try test__powihf2(inf_f16, -4, 0);118 try test_powi_f16(inf_f16, -4, 0);
113 try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);119 try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
114 try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);120 try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
115 try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);121 try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
116 //122 //
117 try test__powihf2(-inf_f16, -1, -0.0);123 try test_powi_f16(-inf_f16, -1, -0.0);
118 try test__powihf2(-inf_f16, -2, 0);124 try test_powi_f16(-inf_f16, -2, 0);
119 try test__powihf2(-inf_f16, -3, -0.0);125 try test_powi_f16(-inf_f16, -3, -0.0);
120 try test__powihf2(-inf_f16, -4, 0);126 try test_powi_f16(-inf_f16, -4, 0);
121 try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);127 try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
122 try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);128 try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
123 try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);129 try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
124130
125 try test__powihf2(2, 10, 1024.0);131 try test_powi_f16(2, 10, 1024.0);
126 try test__powihf2(-2, 10, 1024.0);132 try test_powi_f16(-2, 10, 1024.0);
127 try test__powihf2(2, -10, 1.0 / 1024.0);133 try test_powi_f16(2, -10, 1.0 / 1024.0);
128 try test__powihf2(-2, -10, 1.0 / 1024.0);134 try test_powi_f16(-2, -10, 1.0 / 1024.0);
129135
130 try test__powihf2(2, 14, 16384.0);136 try test_powi_f16(2, 14, 16384.0);
131 try test__powihf2(-2, 14, 16384.0);137 try test_powi_f16(-2, 14, 16384.0);
132 try test__powihf2(2, 15, 32768.0);138 try test_powi_f16(2, 15, 32768.0);
133 try test__powihf2(-2, 15, -32768.0);139 try test_powi_f16(-2, 15, -32768.0);
134 try test__powihf2(2, 16, inf_f16);140 try test_powi_f16(2, 16, inf_f16);
135 try test__powihf2(-2, 16, inf_f16);141 try test_powi_f16(-2, 16, inf_f16);
136142
137 try test__powihf2(2, -13, 1.0 / 8192.0);143 try test_powi_f16(2, -13, 1.0 / 8192.0);
138 try test__powihf2(-2, -13, -1.0 / 8192.0);144 try test_powi_f16(-2, -13, -1.0 / 8192.0);
139 try test__powihf2(2, -15, 1.0 / 32768.0);145 try test_powi_f16(2, -15, 1.0 / 32768.0);
140 try test__powihf2(-2, -15, -1.0 / 32768.0);146 try test_powi_f16(-2, -15, -1.0 / 32768.0);
141 try test__powihf2(2, -16, 0.0); // expected = 0.0 = 1/(-2**16)147 try test_powi_f16(2, -16, 0.0); // expected = 0.0 = 1/(-2**16)
142 try test__powihf2(-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)
143}149}
144150
145test "powisf2" {151test powi_f32 {
146 const inf_f32 = math.inf(f32);152 const inf_f32 = math.inf(f32);
147 try test__powisf2(0, 0, 1);153 try test_powi_f32(0, 0, 1);
148 try test__powisf2(1, 0, 1);154 try test_powi_f32(1, 0, 1);
149 try test__powisf2(1.5, 0, 1);155 try test_powi_f32(1.5, 0, 1);
150 try test__powisf2(2, 0, 1);156 try test_powi_f32(2, 0, 1);
151 try test__powisf2(inf_f32, 0, 1);157 try test_powi_f32(inf_f32, 0, 1);
152158
153 try test__powisf2(-0.0, 0, 1);159 try test_powi_f32(-0.0, 0, 1);
154 try test__powisf2(-1, 0, 1);160 try test_powi_f32(-1, 0, 1);
155 try test__powisf2(-1.5, 0, 1);161 try test_powi_f32(-1.5, 0, 1);
156 try test__powisf2(-2, 0, 1);162 try test_powi_f32(-2, 0, 1);
157 try test__powisf2(-inf_f32, 0, 1);163 try test_powi_f32(-inf_f32, 0, 1);
158164
159 try test__powisf2(0, 1, 0);165 try test_powi_f32(0, 1, 0);
160 try test__powisf2(0, 2, 0);166 try test_powi_f32(0, 2, 0);
161 try test__powisf2(0, 3, 0);167 try test_powi_f32(0, 3, 0);
162 try test__powisf2(0, 4, 0);168 try test_powi_f32(0, 4, 0);
163 try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);169 try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
164 try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);170 try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
165171
166 try test__powisf2(-0.0, 1, -0.0);172 try test_powi_f32(-0.0, 1, -0.0);
167 try test__powisf2(-0.0, 2, 0);173 try test_powi_f32(-0.0, 2, 0);
168 try test__powisf2(-0.0, 3, -0.0);174 try test_powi_f32(-0.0, 3, -0.0);
169 try test__powisf2(-0.0, 4, 0);175 try test_powi_f32(-0.0, 4, 0);
170 try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);176 try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
171 try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);177 try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
172178
173 try test__powisf2(1, 1, 1);179 try test_powi_f32(1, 1, 1);
174 try test__powisf2(1, 2, 1);180 try test_powi_f32(1, 2, 1);
175 try test__powisf2(1, 3, 1);181 try test_powi_f32(1, 3, 1);
176 try test__powisf2(1, 4, 1);182 try test_powi_f32(1, 4, 1);
177 try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);183 try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
178 try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);184 try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
179185
180 try test__powisf2(inf_f32, 1, inf_f32);186 try test_powi_f32(inf_f32, 1, inf_f32);
181 try test__powisf2(inf_f32, 2, inf_f32);187 try test_powi_f32(inf_f32, 2, inf_f32);
182 try test__powisf2(inf_f32, 3, inf_f32);188 try test_powi_f32(inf_f32, 3, inf_f32);
183 try test__powisf2(inf_f32, 4, inf_f32);189 try test_powi_f32(inf_f32, 4, inf_f32);
184 try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32);190 try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32);
185 try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f32);191 try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f32);
186192
187 try test__powisf2(-inf_f32, 1, -inf_f32);193 try test_powi_f32(-inf_f32, 1, -inf_f32);
188 try test__powisf2(-inf_f32, 2, inf_f32);194 try test_powi_f32(-inf_f32, 2, inf_f32);
189 try test__powisf2(-inf_f32, 3, -inf_f32);195 try test_powi_f32(-inf_f32, 3, -inf_f32);
190 try test__powisf2(-inf_f32, 4, inf_f32);196 try test_powi_f32(-inf_f32, 4, inf_f32);
191 try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32);197 try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32);
192 try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f32);198 try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f32);
193199
194 try test__powisf2(0, -1, inf_f32);200 try test_powi_f32(0, -1, inf_f32);
195 try test__powisf2(0, -2, inf_f32);201 try test_powi_f32(0, -2, inf_f32);
196 try test__powisf2(0, -3, inf_f32);202 try test_powi_f32(0, -3, inf_f32);
197 try test__powisf2(0, -4, inf_f32);203 try test_powi_f32(0, -4, inf_f32);
198 try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32);204 try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32);
199 try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f32);205 try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f32);
200 try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32);206 try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32);
201207
202 try test__powisf2(-0.0, -1, -inf_f32);208 try test_powi_f32(-0.0, -1, -inf_f32);
203 try test__powisf2(-0.0, -2, inf_f32);209 try test_powi_f32(-0.0, -2, inf_f32);
204 try test__powisf2(-0.0, -3, -inf_f32);210 try test_powi_f32(-0.0, -3, -inf_f32);
205 try test__powisf2(-0.0, -4, inf_f32);211 try test_powi_f32(-0.0, -4, inf_f32);
206 try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32);212 try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32);
207 try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f32);213 try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f32);
208 try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32);214 try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32);
209215
210 try test__powisf2(1, -1, 1);216 try test_powi_f32(1, -1, 1);
211 try test__powisf2(1, -2, 1);217 try test_powi_f32(1, -2, 1);
212 try test__powisf2(1, -3, 1);218 try test_powi_f32(1, -3, 1);
213 try test__powisf2(1, -4, 1);219 try test_powi_f32(1, -4, 1);
214 try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);220 try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
215 try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);221 try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
216 try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);222 try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
217223
218 try test__powisf2(inf_f32, -1, 0);224 try test_powi_f32(inf_f32, -1, 0);
219 try test__powisf2(inf_f32, -2, 0);225 try test_powi_f32(inf_f32, -2, 0);
220 try test__powisf2(inf_f32, -3, 0);226 try test_powi_f32(inf_f32, -3, 0);
221 try test__powisf2(inf_f32, -4, 0);227 try test_powi_f32(inf_f32, -4, 0);
222 try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);228 try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
223 try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);229 try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
224 try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);230 try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
225231
226 try test__powisf2(-inf_f32, -1, -0.0);232 try test_powi_f32(-inf_f32, -1, -0.0);
227 try test__powisf2(-inf_f32, -2, 0);233 try test_powi_f32(-inf_f32, -2, 0);
228 try test__powisf2(-inf_f32, -3, -0.0);234 try test_powi_f32(-inf_f32, -3, -0.0);
229 try test__powisf2(-inf_f32, -4, 0);235 try test_powi_f32(-inf_f32, -4, 0);
230 try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);236 try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
231 try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);237 try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
232 try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);238 try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
233239
234 try test__powisf2(2.0, 10, 1024.0);240 try test_powi_f32(2.0, 10, 1024.0);
235 try test__powisf2(-2, 10, 1024.0);241 try test_powi_f32(-2, 10, 1024.0);
236 try test__powisf2(2, -10, 1.0 / 1024.0);242 try test_powi_f32(2, -10, 1.0 / 1024.0);
237 try test__powisf2(-2, -10, 1.0 / 1024.0);243 try test_powi_f32(-2, -10, 1.0 / 1024.0);
238 //244 //
239 try test__powisf2(2, 19, 524288.0);245 try test_powi_f32(2, 19, 524288.0);
240 try test__powisf2(-2, 19, -524288.0);246 try test_powi_f32(-2, 19, -524288.0);
241 try test__powisf2(2, -19, 1.0 / 524288.0);247 try test_powi_f32(2, -19, 1.0 / 524288.0);
242 try test__powisf2(-2, -19, -1.0 / 524288.0);248 try test_powi_f32(-2, -19, -1.0 / 524288.0);
243249
244 try test__powisf2(2, 31, 2147483648.0);250 try test_powi_f32(2, 31, 2147483648.0);
245 try test__powisf2(-2, 31, -2147483648.0);251 try test_powi_f32(-2, 31, -2147483648.0);
246 try test__powisf2(2, -31, 1.0 / 2147483648.0);252 try test_powi_f32(2, -31, 1.0 / 2147483648.0);
247 try test__powisf2(-2, -31, -1.0 / 2147483648.0);253 try test_powi_f32(-2, -31, -1.0 / 2147483648.0);
248}254}
249255
250test "powidf2" {256test powi_f64 {
251 const inf_f64 = math.inf(f64);257 const inf_f64 = math.inf(f64);
252 try test__powidf2(0, 0, 1);258 try test_powi_f64(0, 0, 1);
253 try test__powidf2(1, 0, 1);259 try test_powi_f64(1, 0, 1);
254 try test__powidf2(1.5, 0, 1);260 try test_powi_f64(1.5, 0, 1);
255 try test__powidf2(2, 0, 1);261 try test_powi_f64(2, 0, 1);
256 try test__powidf2(inf_f64, 0, 1);262 try test_powi_f64(inf_f64, 0, 1);
257263
258 try test__powidf2(-0.0, 0, 1);264 try test_powi_f64(-0.0, 0, 1);
259 try test__powidf2(-1, 0, 1);265 try test_powi_f64(-1, 0, 1);
260 try test__powidf2(-1.5, 0, 1);266 try test_powi_f64(-1.5, 0, 1);
261 try test__powidf2(-2, 0, 1);267 try test_powi_f64(-2, 0, 1);
262 try test__powidf2(-inf_f64, 0, 1);268 try test_powi_f64(-inf_f64, 0, 1);
263269
264 try test__powidf2(0, 1, 0);270 try test_powi_f64(0, 1, 0);
265 try test__powidf2(0, 2, 0);271 try test_powi_f64(0, 2, 0);
266 try test__powidf2(0, 3, 0);272 try test_powi_f64(0, 3, 0);
267 try test__powidf2(0, 4, 0);273 try test_powi_f64(0, 4, 0);
268 try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);274 try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
269 try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);275 try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
270276
271 try test__powidf2(-0.0, 1, -0.0);277 try test_powi_f64(-0.0, 1, -0.0);
272 try test__powidf2(-0.0, 2, 0);278 try test_powi_f64(-0.0, 2, 0);
273 try test__powidf2(-0.0, 3, -0.0);279 try test_powi_f64(-0.0, 3, -0.0);
274 try test__powidf2(-0.0, 4, 0);280 try test_powi_f64(-0.0, 4, 0);
275 try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);281 try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
276 try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);282 try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
277283
278 try test__powidf2(1, 1, 1);284 try test_powi_f64(1, 1, 1);
279 try test__powidf2(1, 2, 1);285 try test_powi_f64(1, 2, 1);
280 try test__powidf2(1, 3, 1);286 try test_powi_f64(1, 3, 1);
281 try test__powidf2(1, 4, 1);287 try test_powi_f64(1, 4, 1);
282 try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);288 try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
283 try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);289 try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
284290
285 try test__powidf2(inf_f64, 1, inf_f64);291 try test_powi_f64(inf_f64, 1, inf_f64);
286 try test__powidf2(inf_f64, 2, inf_f64);292 try test_powi_f64(inf_f64, 2, inf_f64);
287 try test__powidf2(inf_f64, 3, inf_f64);293 try test_powi_f64(inf_f64, 3, inf_f64);
288 try test__powidf2(inf_f64, 4, inf_f64);294 try test_powi_f64(inf_f64, 4, inf_f64);
289 try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64);295 try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64);
290 try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f64);296 try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f64);
291297
292 try test__powidf2(-inf_f64, 1, -inf_f64);298 try test_powi_f64(-inf_f64, 1, -inf_f64);
293 try test__powidf2(-inf_f64, 2, inf_f64);299 try test_powi_f64(-inf_f64, 2, inf_f64);
294 try test__powidf2(-inf_f64, 3, -inf_f64);300 try test_powi_f64(-inf_f64, 3, -inf_f64);
295 try test__powidf2(-inf_f64, 4, inf_f64);301 try test_powi_f64(-inf_f64, 4, inf_f64);
296 try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64);302 try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64);
297 try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f64);303 try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f64);
298304
299 try test__powidf2(0, -1, inf_f64);305 try test_powi_f64(0, -1, inf_f64);
300 try test__powidf2(0, -2, inf_f64);306 try test_powi_f64(0, -2, inf_f64);
301 try test__powidf2(0, -3, inf_f64);307 try test_powi_f64(0, -3, inf_f64);
302 try test__powidf2(0, -4, inf_f64);308 try test_powi_f64(0, -4, inf_f64);
303 try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64);309 try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64);
304 try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f64);310 try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f64);
305 try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64);311 try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64);
306312
307 try test__powidf2(-0.0, -1, -inf_f64);313 try test_powi_f64(-0.0, -1, -inf_f64);
308 try test__powidf2(-0.0, -2, inf_f64);314 try test_powi_f64(-0.0, -2, inf_f64);
309 try test__powidf2(-0.0, -3, -inf_f64);315 try test_powi_f64(-0.0, -3, -inf_f64);
310 try test__powidf2(-0.0, -4, inf_f64);316 try test_powi_f64(-0.0, -4, inf_f64);
311 try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64);317 try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64);
312 try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f64);318 try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f64);
313 try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64);319 try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64);
314320
315 try test__powidf2(1, -1, 1);321 try test_powi_f64(1, -1, 1);
316 try test__powidf2(1, -2, 1);322 try test_powi_f64(1, -2, 1);
317 try test__powidf2(1, -3, 1);323 try test_powi_f64(1, -3, 1);
318 try test__powidf2(1, -4, 1);324 try test_powi_f64(1, -4, 1);
319 try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);325 try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
320 try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);326 try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
321 try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);327 try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
322328
323 try test__powidf2(inf_f64, -1, 0);329 try test_powi_f64(inf_f64, -1, 0);
324 try test__powidf2(inf_f64, -2, 0);330 try test_powi_f64(inf_f64, -2, 0);
325 try test__powidf2(inf_f64, -3, 0);331 try test_powi_f64(inf_f64, -3, 0);
326 try test__powidf2(inf_f64, -4, 0);332 try test_powi_f64(inf_f64, -4, 0);
327 try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);333 try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
328 try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);334 try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
329 try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);335 try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
330336
331 try test__powidf2(-inf_f64, -1, -0.0);337 try test_powi_f64(-inf_f64, -1, -0.0);
332 try test__powidf2(-inf_f64, -2, 0);338 try test_powi_f64(-inf_f64, -2, 0);
333 try test__powidf2(-inf_f64, -3, -0.0);339 try test_powi_f64(-inf_f64, -3, -0.0);
334 try test__powidf2(-inf_f64, -4, 0);340 try test_powi_f64(-inf_f64, -4, 0);
335 try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);341 try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
336 try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);342 try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
337 try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);343 try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
338344
339 try test__powidf2(2, 10, 1024.0);345 try test_powi_f64(2, 10, 1024.0);
340 try test__powidf2(-2, 10, 1024.0);346 try test_powi_f64(-2, 10, 1024.0);
341 try test__powidf2(2, -10, 1.0 / 1024.0);347 try test_powi_f64(2, -10, 1.0 / 1024.0);
342 try test__powidf2(-2, -10, 1.0 / 1024.0);348 try test_powi_f64(-2, -10, 1.0 / 1024.0);
343349
344 try test__powidf2(2, 19, 524288.0);350 try test_powi_f64(2, 19, 524288.0);
345 try test__powidf2(-2, 19, -524288.0);351 try test_powi_f64(-2, 19, -524288.0);
346 try test__powidf2(2, -19, 1.0 / 524288.0);352 try test_powi_f64(2, -19, 1.0 / 524288.0);
347 try test__powidf2(-2, -19, -1.0 / 524288.0);353 try test_powi_f64(-2, -19, -1.0 / 524288.0);
348354
349 try test__powidf2(2, 31, 2147483648.0);355 try test_powi_f64(2, 31, 2147483648.0);
350 try test__powidf2(-2, 31, -2147483648.0);356 try test_powi_f64(-2, 31, -2147483648.0);
351 try test__powidf2(2, -31, 1.0 / 2147483648.0);357 try test_powi_f64(2, -31, 1.0 / 2147483648.0);
352 try test__powidf2(-2, -31, -1.0 / 2147483648.0);358 try test_powi_f64(-2, -31, -1.0 / 2147483648.0);
353}359}
354360
355test "powitf2" {361test powi_f80 {
356 const inf_f128 = math.inf(f128);362 const inf_f80 = math.inf(f80);
357 try test__powitf2(0, 0, 1);363 try test_powi_f80(0, 0, 1);
358 try test__powitf2(1, 0, 1);364 try test_powi_f80(1, 0, 1);
359 try test__powitf2(1.5, 0, 1);365 try test_powi_f80(1.5, 0, 1);
360 try test__powitf2(2, 0, 1);366 try test_powi_f80(2, 0, 1);
361 try test__powitf2(inf_f128, 0, 1);367 try test_powi_f80(inf_f80, 0, 1);
362368
363 try test__powitf2(-0.0, 0, 1);369 try test_powi_f80(-0.0, 0, 1);
364 try test__powitf2(-1, 0, 1);370 try test_powi_f80(-1, 0, 1);
365 try test__powitf2(-1.5, 0, 1);371 try test_powi_f80(-1.5, 0, 1);
366 try test__powitf2(-2, 0, 1);372 try test_powi_f80(-2, 0, 1);
367 try test__powitf2(-inf_f128, 0, 1);373 try test_powi_f80(-inf_f80, 0, 1);
368374
369 try test__powitf2(0, 1, 0);375 try test_powi_f80(0, 1, 0);
370 try test__powitf2(0, 2, 0);376 try test_powi_f80(0, 2, 0);
371 try test__powitf2(0, 3, 0);377 try test_powi_f80(0, 3, 0);
372 try test__powitf2(0, 4, 0);378 try test_powi_f80(0, 4, 0);
373 try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);379 try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
374 try test__powitf2(0, 0x7FFFFFFF, 0);380 try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
375381
376 try test__powitf2(-0.0, 1, -0.0);382 try test_powi_f80(-0.0, 1, -0.0);
377 try test__powitf2(-0.0, 2, 0);383 try test_powi_f80(-0.0, 2, 0);
378 try test__powitf2(-0.0, 3, -0.0);384 try test_powi_f80(-0.0, 3, -0.0);
379 try test__powitf2(-0.0, 4, 0);385 try test_powi_f80(-0.0, 4, 0);
380 try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);386 try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
381 try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);387 try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
382388
383 try test__powitf2(1, 1, 1);389 try test_powi_f80(1, 1, 1);
384 try test__powitf2(1, 2, 1);390 try test_powi_f80(1, 2, 1);
385 try test__powitf2(1, 3, 1);391 try test_powi_f80(1, 3, 1);
386 try test__powitf2(1, 4, 1);392 try test_powi_f80(1, 4, 1);
387 try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);393 try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
388 try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);394 try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
389395
390 try test__powitf2(inf_f128, 1, inf_f128);396 try test_powi_f80(inf_f80, 1, inf_f80);
391 try test__powitf2(inf_f128, 2, inf_f128);397 try test_powi_f80(inf_f80, 2, inf_f80);
392 try test__powitf2(inf_f128, 3, inf_f128);398 try test_powi_f80(inf_f80, 3, inf_f80);
393 try test__powitf2(inf_f128, 4, inf_f128);399 try test_powi_f80(inf_f80, 4, inf_f80);
394 try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128);400 try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80);
395 try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f128);401 try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f80);
396402
397 try test__powitf2(-inf_f128, 1, -inf_f128);403 try test_powi_f80(-inf_f80, 1, -inf_f80);
398 try test__powitf2(-inf_f128, 2, inf_f128);404 try test_powi_f80(-inf_f80, 2, inf_f80);
399 try test__powitf2(-inf_f128, 3, -inf_f128);405 try test_powi_f80(-inf_f80, 3, -inf_f80);
400 try test__powitf2(-inf_f128, 4, inf_f128);406 try test_powi_f80(-inf_f80, 4, inf_f80);
401 try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128);407 try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80);
402 try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f128);408 try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f80);
403409
404 try test__powitf2(0, -1, inf_f128);410 try test_powi_f80(0, -1, inf_f80);
405 try test__powitf2(0, -2, inf_f128);411 try test_powi_f80(0, -2, inf_f80);
406 try test__powitf2(0, -3, inf_f128);412 try test_powi_f80(0, -3, inf_f80);
407 try test__powitf2(0, -4, inf_f128);413 try test_powi_f80(0, -4, inf_f80);
408 try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128);414 try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80);
409 try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f128);415 try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f80);
410 try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128);416 try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80);
411417
412 try test__powitf2(-0.0, -1, -inf_f128);418 try test_powi_f80(-0.0, -1, -inf_f80);
413 try test__powitf2(-0.0, -2, inf_f128);419 try test_powi_f80(-0.0, -2, inf_f80);
414 try test__powitf2(-0.0, -3, -inf_f128);420 try test_powi_f80(-0.0, -3, -inf_f80);
415 try test__powitf2(-0.0, -4, inf_f128);421 try test_powi_f80(-0.0, -4, inf_f80);
416 try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128);422 try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80);
417 try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f128);423 try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f80);
418 try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128);424 try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80);
419425
420 try test__powitf2(1, -1, 1);426 try test_powi_f80(1, -1, 1);
421 try test__powitf2(1, -2, 1);427 try test_powi_f80(1, -2, 1);
422 try test__powitf2(1, -3, 1);428 try test_powi_f80(1, -3, 1);
423 try test__powitf2(1, -4, 1);429 try test_powi_f80(1, -4, 1);
424 try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);430 try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
425 try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);431 try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
426 try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);432 try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
427433
428 try test__powitf2(inf_f128, -1, 0);434 try test_powi_f80(inf_f80, -1, 0);
429 try test__powitf2(inf_f128, -2, 0);435 try test_powi_f80(inf_f80, -2, 0);
430 try test__powitf2(inf_f128, -3, 0);436 try test_powi_f80(inf_f80, -3, 0);
431 try test__powitf2(inf_f128, -4, 0);437 try test_powi_f80(inf_f80, -4, 0);
432 try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);438 try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
433 try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);439 try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
434 try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);440 try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
435441
436 try test__powitf2(-inf_f128, -1, -0.0);442 try test_powi_f80(-inf_f80, -1, -0.0);
437 try test__powitf2(-inf_f128, -2, 0);443 try test_powi_f80(-inf_f80, -2, 0);
438 try test__powitf2(-inf_f128, -3, -0.0);444 try test_powi_f80(-inf_f80, -3, -0.0);
439 try test__powitf2(-inf_f128, -4, 0);445 try test_powi_f80(-inf_f80, -4, 0);
440 try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);446 try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
441 try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);447 try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
442 try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);448 try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
443449
444 try test__powitf2(2, 10, 1024.0);450 try test_powi_f80(2, 10, 1024.0);
445 try test__powitf2(-2, 10, 1024.0);451 try test_powi_f80(-2, 10, 1024.0);
446 try test__powitf2(2, -10, 1.0 / 1024.0);452 try test_powi_f80(2, -10, 1.0 / 1024.0);
447 try test__powitf2(-2, -10, 1.0 / 1024.0);453 try test_powi_f80(-2, -10, 1.0 / 1024.0);
448454
449 try test__powitf2(2, 19, 524288.0);455 try test_powi_f80(2, 19, 524288.0);
450 try test__powitf2(-2, 19, -524288.0);456 try test_powi_f80(-2, 19, -524288.0);
451 try test__powitf2(2, -19, 1.0 / 524288.0);457 try test_powi_f80(2, -19, 1.0 / 524288.0);
452 try test__powitf2(-2, -19, -1.0 / 524288.0);458 try test_powi_f80(-2, -19, -1.0 / 524288.0);
453459
454 try test__powitf2(2, 31, 2147483648.0);460 try test_powi_f80(2, 31, 2147483648.0);
455 try test__powitf2(-2, 31, -2147483648.0);461 try test_powi_f80(-2, 31, -2147483648.0);
456 try test__powitf2(2, -31, 1.0 / 2147483648.0);462 try test_powi_f80(2, -31, 1.0 / 2147483648.0);
457 try test__powitf2(-2, -31, -1.0 / 2147483648.0);463 try test_powi_f80(-2, -31, -1.0 / 2147483648.0);
458}464}
459465
460test "powixf2" {466test powi_f128 {
461 const inf_f80 = math.inf(f80);467 const inf_f128 = math.inf(f128);
462 try test__powixf2(0, 0, 1);468 try test_powi_f128(0, 0, 1);
463 try test__powixf2(1, 0, 1);469 try test_powi_f128(1, 0, 1);
464 try test__powixf2(1.5, 0, 1);470 try test_powi_f128(1.5, 0, 1);
465 try test__powixf2(2, 0, 1);471 try test_powi_f128(2, 0, 1);
466 try test__powixf2(inf_f80, 0, 1);472 try test_powi_f128(inf_f128, 0, 1);
467473
468 try test__powixf2(-0.0, 0, 1);474 try test_powi_f128(-0.0, 0, 1);
469 try test__powixf2(-1, 0, 1);475 try test_powi_f128(-1, 0, 1);
470 try test__powixf2(-1.5, 0, 1);476 try test_powi_f128(-1.5, 0, 1);
471 try test__powixf2(-2, 0, 1);477 try test_powi_f128(-2, 0, 1);
472 try test__powixf2(-inf_f80, 0, 1);478 try test_powi_f128(-inf_f128, 0, 1);
473479
474 try test__powixf2(0, 1, 0);480 try test_powi_f128(0, 1, 0);
475 try test__powixf2(0, 2, 0);481 try test_powi_f128(0, 2, 0);
476 try test__powixf2(0, 3, 0);482 try test_powi_f128(0, 3, 0);
477 try test__powixf2(0, 4, 0);483 try test_powi_f128(0, 4, 0);
478 try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);484 try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
479 try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);485 try test_powi_f128(0, 0x7FFFFFFF, 0);
480486
481 try test__powixf2(-0.0, 1, -0.0);487 try test_powi_f128(-0.0, 1, -0.0);
482 try test__powixf2(-0.0, 2, 0);488 try test_powi_f128(-0.0, 2, 0);
483 try test__powixf2(-0.0, 3, -0.0);489 try test_powi_f128(-0.0, 3, -0.0);
484 try test__powixf2(-0.0, 4, 0);490 try test_powi_f128(-0.0, 4, 0);
485 try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);491 try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
486 try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);492 try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
487493
488 try test__powixf2(1, 1, 1);494 try test_powi_f128(1, 1, 1);
489 try test__powixf2(1, 2, 1);495 try test_powi_f128(1, 2, 1);
490 try test__powixf2(1, 3, 1);496 try test_powi_f128(1, 3, 1);
491 try test__powixf2(1, 4, 1);497 try test_powi_f128(1, 4, 1);
492 try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);498 try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
493 try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);499 try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
494500
495 try test__powixf2(inf_f80, 1, inf_f80);501 try test_powi_f128(inf_f128, 1, inf_f128);
496 try test__powixf2(inf_f80, 2, inf_f80);502 try test_powi_f128(inf_f128, 2, inf_f128);
497 try test__powixf2(inf_f80, 3, inf_f80);503 try test_powi_f128(inf_f128, 3, inf_f128);
498 try test__powixf2(inf_f80, 4, inf_f80);504 try test_powi_f128(inf_f128, 4, inf_f128);
499 try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80);505 try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128);
500 try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f80);506 try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f128);
501507
502 try test__powixf2(-inf_f80, 1, -inf_f80);508 try test_powi_f128(-inf_f128, 1, -inf_f128);
503 try test__powixf2(-inf_f80, 2, inf_f80);509 try test_powi_f128(-inf_f128, 2, inf_f128);
504 try test__powixf2(-inf_f80, 3, -inf_f80);510 try test_powi_f128(-inf_f128, 3, -inf_f128);
505 try test__powixf2(-inf_f80, 4, inf_f80);511 try test_powi_f128(-inf_f128, 4, inf_f128);
506 try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80);512 try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128);
507 try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f80);513 try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f128);
508514
509 try test__powixf2(0, -1, inf_f80);515 try test_powi_f128(0, -1, inf_f128);
510 try test__powixf2(0, -2, inf_f80);516 try test_powi_f128(0, -2, inf_f128);
511 try test__powixf2(0, -3, inf_f80);517 try test_powi_f128(0, -3, inf_f128);
512 try test__powixf2(0, -4, inf_f80);518 try test_powi_f128(0, -4, inf_f128);
513 try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80);519 try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128);
514 try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f80);520 try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f128);
515 try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80);521 try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128);
516522
517 try test__powixf2(-0.0, -1, -inf_f80);523 try test_powi_f128(-0.0, -1, -inf_f128);
518 try test__powixf2(-0.0, -2, inf_f80);524 try test_powi_f128(-0.0, -2, inf_f128);
519 try test__powixf2(-0.0, -3, -inf_f80);525 try test_powi_f128(-0.0, -3, -inf_f128);
520 try test__powixf2(-0.0, -4, inf_f80);526 try test_powi_f128(-0.0, -4, inf_f128);
521 try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80);527 try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128);
522 try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f80);528 try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f128);
523 try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80);529 try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128);
524530
525 try test__powixf2(1, -1, 1);531 try test_powi_f128(1, -1, 1);
526 try test__powixf2(1, -2, 1);532 try test_powi_f128(1, -2, 1);
527 try test__powixf2(1, -3, 1);533 try test_powi_f128(1, -3, 1);
528 try test__powixf2(1, -4, 1);534 try test_powi_f128(1, -4, 1);
529 try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);535 try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
530 try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);536 try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
531 try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);537 try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
532538
533 try test__powixf2(inf_f80, -1, 0);539 try test_powi_f128(inf_f128, -1, 0);
534 try test__powixf2(inf_f80, -2, 0);540 try test_powi_f128(inf_f128, -2, 0);
535 try test__powixf2(inf_f80, -3, 0);541 try test_powi_f128(inf_f128, -3, 0);
536 try test__powixf2(inf_f80, -4, 0);542 try test_powi_f128(inf_f128, -4, 0);
537 try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);543 try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
538 try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);544 try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
539 try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);545 try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
540546
541 try test__powixf2(-inf_f80, -1, -0.0);547 try test_powi_f128(-inf_f128, -1, -0.0);
542 try test__powixf2(-inf_f80, -2, 0);548 try test_powi_f128(-inf_f128, -2, 0);
543 try test__powixf2(-inf_f80, -3, -0.0);549 try test_powi_f128(-inf_f128, -3, -0.0);
544 try test__powixf2(-inf_f80, -4, 0);550 try test_powi_f128(-inf_f128, -4, 0);
545 try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);551 try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
546 try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);552 try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
547 try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);553 try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
548554
549 try test__powixf2(2, 10, 1024.0);555 try test_powi_f128(2, 10, 1024.0);
550 try test__powixf2(-2, 10, 1024.0);556 try test_powi_f128(-2, 10, 1024.0);
551 try test__powixf2(2, -10, 1.0 / 1024.0);557 try test_powi_f128(2, -10, 1.0 / 1024.0);
552 try test__powixf2(-2, -10, 1.0 / 1024.0);558 try test_powi_f128(-2, -10, 1.0 / 1024.0);
553559
554 try test__powixf2(2, 19, 524288.0);560 try test_powi_f128(2, 19, 524288.0);
555 try test__powixf2(-2, 19, -524288.0);561 try test_powi_f128(-2, 19, -524288.0);
556 try test__powixf2(2, -19, 1.0 / 524288.0);562 try test_powi_f128(2, -19, 1.0 / 524288.0);
557 try test__powixf2(-2, -19, -1.0 / 524288.0);563 try test_powi_f128(-2, -19, -1.0 / 524288.0);
558564
559 try test__powixf2(2, 31, 2147483648.0);565 try test_powi_f128(2, 31, 2147483648.0);
560 try test__powixf2(-2, 31, -2147483648.0);566 try test_powi_f128(-2, 31, -2147483648.0);
561 try test__powixf2(2, -31, 1.0 / 2147483648.0);567 try test_powi_f128(2, -31, 1.0 / 2147483648.0);
562 try test__powixf2(-2, -31, -1.0 / 2147483648.0);568 try test_powi_f128(-2, -31, -1.0 / 2147483648.0);
563}569}
lib/compiler_rt/round.zig+87-50
...@@ -18,19 +18,22 @@ comptime {...@@ -18,19 +18,22 @@ comptime {
18 symbol(&roundf, "roundf");18 symbol(&roundf, "roundf");
19 symbol(&round, "round");19 symbol(&round, "round");
20 symbol(&__roundx, "__roundx");20 symbol(&__roundx, "__roundx");
21 if (compiler_rt.want_ppc_abi) {21 symbol(&roundq, "roundf128");
22 symbol(&roundq, "roundf128");
23 }
24 symbol(&roundq, "roundq");
25 symbol(&roundl, "roundl");22 symbol(&roundl, "roundl");
26}23}
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 {
29 // TODO: more efficient implementation29 // TODO: more efficient implementation
30 return @floatCast(roundf(x));30 return @floatCast(round_f32(x));
31}31}
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 {
34 const f32_toint = 1.0 / math.floatEps(f32);37 const f32_toint = 1.0 / math.floatEps(f32);
3538
36 var x = x_;39 var x = x_;
...@@ -65,7 +68,10 @@ pub fn roundf(x_: f32) callconv(.c) f32 {...@@ -65,7 +68,10 @@ pub fn roundf(x_: f32) callconv(.c) f32 {
65 }68 }
66}69}
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 {
69 const f64_toint = 1.0 / math.floatEps(f64);75 const f64_toint = 1.0 / math.floatEps(f64);
7076
71 var x = x_;77 var x = x_;
...@@ -100,12 +106,18 @@ pub fn round(x_: f64) callconv(.c) f64 {...@@ -100,12 +106,18 @@ pub fn round(x_: f64) callconv(.c) f64 {
100 }106 }
101}107}
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 {
104 // TODO: more efficient implementation113 // TODO: more efficient implementation
105 return @floatCast(roundq(x));114 return @floatCast(round_f128(x));
106}115}
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 {
109 const f128_toint = 1.0 / math.floatEps(f128);121 const f128_toint = 1.0 / math.floatEps(f128);
110122
111 var x = x_;123 var x = x_;
...@@ -142,54 +154,79 @@ pub fn roundq(x_: f128) callconv(.c) f128 {...@@ -142,54 +154,79 @@ pub fn roundq(x_: f128) callconv(.c) f128 {
142154
143pub fn roundl(x: c_longdouble) callconv(.c) c_longdouble {155pub fn roundl(x: c_longdouble) callconv(.c) c_longdouble {
144 switch (@typeInfo(c_longdouble).float.bits) {156 switch (@typeInfo(c_longdouble).float.bits) {
145 64 => return round(x),157 64 => return round_f64(x),
146 80 => return __roundx(x),158 80 => return round_f80(x),
147 128 => return roundq(x),159 128 => return round_f128(x),
148 else => @compileError("unreachable"),160 else => comptime unreachable,
149 }161 }
150}162}
151163
152test "round32" {164test round_f16 {
153 try expect(roundf(1.3) == 1.0);165 try expect(round_f16(1.3) == 1.0);
154 try expect(roundf(-1.3) == -1.0);166 try expect(round_f16(-1.3) == -1.0);
155 try expect(roundf(0.2) == 0.0);167 try expect(round_f16(1.8) == 2.0);
156 try expect(roundf(1.8) == 2.0);168 try expect(round_f16(-1.8) == -2.0);
157}169 try expect(math.isPositiveZero(round_f16(0.2)));
158170 try expect(math.isNegativeZero(round_f16(-0.2)));
159test "round64" {171 try expect(math.isPositiveZero(round_f16(0.0)));
160 try expect(round(1.3) == 1.0);172 try expect(math.isNegativeZero(round_f16(-0.0)));
161 try expect(round(-1.3) == -1.0);173 try expect(math.isPositiveInf(round_f16(math.inf(f32))));
162 try expect(round(0.2) == 0.0);174 try expect(math.isNegativeInf(round_f16(-math.inf(f32))));
163 try expect(round(1.8) == 2.0);175 try expect(math.isNan(round_f16(math.nan(f32))));
164}176}
165177
166test "round128" {178test round_f32 {
167 try expect(roundq(1.3) == 1.0);179 try expect(round_f32(1.3) == 1.0);
168 try expect(roundq(-1.3) == -1.0);180 try expect(round_f32(-1.3) == -1.0);
169 try expect(roundq(0.2) == 0.0);181 try expect(round_f32(1.8) == 2.0);
170 try expect(roundq(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))));
171}190}
172191
173test "round32.special" {192test round_f64 {
174 try expect(roundf(0.0) == 0.0);193 try expect(round_f64(1.3) == 1.0);
175 try expect(roundf(-0.0) == -0.0);194 try expect(round_f64(-1.3) == -1.0);
176 try expect(math.isPositiveInf(roundf(math.inf(f32))));195 try expect(round_f64(1.8) == 2.0);
177 try expect(math.isNegativeInf(roundf(-math.inf(f32))));196 try expect(round_f64(-1.8) == -2.0);
178 try expect(math.isNan(roundf(math.nan(f32))));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))));
179}204}
180205
181test "round64.special" {206test round_f80 {
182 try expect(round(0.0) == 0.0);207 try expect(round_f80(1.3) == 1.0);
183 try expect(round(-0.0) == -0.0);208 try expect(round_f80(-1.3) == -1.0);
184 try expect(math.isPositiveInf(round(math.inf(f64))));209 try expect(round_f80(1.8) == 2.0);
185 try expect(math.isNegativeInf(round(-math.inf(f64))));210 try expect(round_f80(-1.8) == -2.0);
186 try expect(math.isNan(round(math.nan(f64))));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))));
187}218}
188219
189test "round128.special" {220test round_f128 {
190 try expect(roundq(0.0) == 0.0);221 try expect(round_f128(1.3) == 1.0);
191 try expect(roundq(-0.0) == -0.0);222 try expect(round_f128(-1.3) == -1.0);
192 try expect(math.isPositiveInf(roundq(math.inf(f128))));223 try expect(round_f128(1.8) == 2.0);
193 try expect(math.isNegativeInf(roundq(-math.inf(f128))));224 try expect(round_f128(-1.8) == -2.0);
194 try expect(math.isNan(roundq(math.nan(f128))));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))));
195}232}
lib/compiler_rt/sin.zig+66-53
...@@ -13,31 +13,34 @@ const expect = std.testing.expect;...@@ -13,31 +13,34 @@ const expect = std.testing.expect;
13const expectApproxEqAbs = std.testing.expectApproxEqAbs;13const expectApproxEqAbs = std.testing.expectApproxEqAbs;
1414
15const compiler_rt = @import("../compiler_rt.zig");15const compiler_rt = @import("../compiler_rt.zig");
16const symbol = @import("../compiler_rt.zig").symbol;16const symbol = compiler_rt.symbol;
17const trig = @import("trig.zig");17const trig = @import("trig.zig");
18const rem_pio2 = @import("rem_pio2.zig").rem_pio2;18const rem_pio2 = @import("rem_pio2.zig").rem_pio2;
19const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f;19const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f;
20const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l;20const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l;
2121
22comptime {22comptime {
23 symbol(&sinh, "__sinh");23 symbol(&__sinh, "__sinh");
24 symbol(&sinl, "__sinl");
25 symbol(&sinf, "sinf");24 symbol(&sinf, "sinf");
26 symbol(&sin, "sin");25 symbol(&sin, "sin");
27 symbol(&sinx, "__sinx");26 symbol(&__sinx, "__sinx");
28 if (compiler_rt.want_ppc_abi) {27 symbol(&sinq, "sinf128");
29 symbol(&sinq, "sinf128");
30 }
31 symbol(&sinq, "sinq");
32 symbol(&sinl, "sinl");28 symbol(&sinl, "sinl");
29 symbol(&sinl, "__sinl"); // required by musl
33}30}
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 {
36 // TODO: more efficient implementation36 // TODO: more efficient implementation
37 return @floatCast(sinf(x));37 return @floatCast(sin_f32(x));
38}38}
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 {
41 // Small multiples of pi/2 rounded to double precision.44 // Small multiples of pi/2 rounded to double precision.
42 const s1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D1845 const s1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18
43 const s2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D1846 const s2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18
...@@ -98,7 +101,10 @@ pub fn sinf(x: f32) callconv(.c) f32 {...@@ -98,7 +101,10 @@ pub fn sinf(x: f32) callconv(.c) f32 {
98 };101 };
99}102}
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 {
102 var ix = @as(u64, @bitCast(x)) >> 32;108 var ix = @as(u64, @bitCast(x)) >> 32;
103 ix &= 0x7fffffff;109 ix &= 0x7fffffff;
104110
...@@ -133,7 +139,10 @@ pub fn sin(x: f64) callconv(.c) f64 {...@@ -133,7 +139,10 @@ pub fn sin(x: f64) callconv(.c) f64 {
133 };139 };
134}140}
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 {
137 const se = ld.signExponent(x) & 0x7fff;146 const se = ld.signExponent(x) & 0x7fff;
138 if (se == 0x7fff) {147 if (se == 0x7fff) {
139 return x - x;148 return x - x;
...@@ -160,7 +169,10 @@ fn sinx(x: f80) callconv(.c) f80 {...@@ -160,7 +169,10 @@ fn sinx(x: f80) callconv(.c) f80 {
160 };169 };
161}170}
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 {
164 const se = ld.signExponent(x) & 0x7fff;176 const se = ld.signExponent(x) & 0x7fff;
165 if (se == 0x7fff) {177 if (se == 0x7fff) {
166 return x - x;178 return x - x;
...@@ -189,20 +201,21 @@ pub fn sinq(x: f128) callconv(.c) f128 {...@@ -189,20 +201,21 @@ pub fn sinq(x: f128) callconv(.c) f128 {
189201
190pub fn sinl(x: c_longdouble) callconv(.c) c_longdouble {202pub fn sinl(x: c_longdouble) callconv(.c) c_longdouble {
191 switch (@typeInfo(c_longdouble).float.bits) {203 switch (@typeInfo(c_longdouble).float.bits) {
192 64 => return sin(x),204 64 => return sin_f64(x),
193 80 => return sinx(x),205 80 => return sin_f80(x),
194 128 => return sinq(x),206 128 => return sin_f128(x),
195 else => @compileError("unreachable"),207 else => comptime unreachable,
196 }208 }
197}209}
198210
199fn testSinSpecial(comptime T: type) !void {211fn testSinSpecial(comptime T: type) !void {
200 const f = switch (T) {212 const f = switch (T) {
201 f32 => sinf,213 f16 => sin_f16,
202 f64 => sin,214 f32 => sin_f32,
203 f80 => sinx,215 f64 => sin_f64,
204 f128 => sinq,216 f80 => sin_f80,
205 else => @compileError("unimplemented"),217 f128 => sin_f128,
218 else => comptime unreachable,
206 };219 };
207220
208 try expect(math.isPositiveZero(f(0.0)));221 try expect(math.isPositiveZero(f(0.0)));
...@@ -214,13 +227,13 @@ fn testSinSpecial(comptime T: type) !void {...@@ -214,13 +227,13 @@ fn testSinSpecial(comptime T: type) !void {
214227
215test "sin32.normal" {228test "sin32.normal" {
216 const epsilon = math.floatEps(f32);229 const epsilon = math.floatEps(f32);
217 try expectApproxEqAbs(@as(f32, 0.0), sinf(0.0), epsilon);230 try expectApproxEqAbs(@as(f32, 0.0), sin_f32(0.0), epsilon);
218 try expectApproxEqAbs(@as(f32, 0.19866933), sinf(0.2), epsilon);231 try expectApproxEqAbs(@as(f32, 0.19866933), sin_f32(0.2), epsilon);
219 try expectApproxEqAbs(@as(f32, 0.77851737), sinf(0.8923), epsilon);232 try expectApproxEqAbs(@as(f32, 0.77851737), sin_f32(0.8923), epsilon);
220 try expectApproxEqAbs(@as(f32, 0.997495), sinf(1.5), epsilon);233 try expectApproxEqAbs(@as(f32, 0.997495), sin_f32(1.5), epsilon);
221 try expectApproxEqAbs(@as(f32, -0.997495), sinf(-1.5), epsilon);234 try expectApproxEqAbs(@as(f32, -0.997495), sin_f32(-1.5), epsilon);
222 try expectApproxEqAbs(@as(f32, -0.24654257), sinf(37.45), epsilon);235 try expectApproxEqAbs(@as(f32, -0.24654257), sin_f32(37.45), epsilon);
223 try expectApproxEqAbs(@as(f32, 0.9161657), sinf(89.123), epsilon);236 try expectApproxEqAbs(@as(f32, 0.9161657), sin_f32(89.123), epsilon);
224}237}
225238
226test "sin32.special" {239test "sin32.special" {
...@@ -229,13 +242,13 @@ test "sin32.special" {...@@ -229,13 +242,13 @@ test "sin32.special" {
229242
230test "sin64.normal" {243test "sin64.normal" {
231 const epsilon = math.floatEps(f64);244 const epsilon = math.floatEps(f64);
232 try expectApproxEqAbs(@as(f64, 0.0), sin(0.0), epsilon);245 try expectApproxEqAbs(@as(f64, 0.0), sin_f64(0.0), epsilon);
233 try expectApproxEqAbs(@as(f64, 0.19866933079506122), sin(0.2), epsilon);246 try expectApproxEqAbs(@as(f64, 0.19866933079506122), sin_f64(0.2), epsilon);
234 try expectApproxEqAbs(@as(f64, 0.7785173385577349), sin(0.8923), epsilon);247 try expectApproxEqAbs(@as(f64, 0.7785173385577349), sin_f64(0.8923), epsilon);
235 try expectApproxEqAbs(@as(f64, 0.9974949866040544), sin(1.5), epsilon);248 try expectApproxEqAbs(@as(f64, 0.9974949866040544), sin_f64(1.5), epsilon);
236 try expectApproxEqAbs(@as(f64, -0.9974949866040544), sin(-1.5), epsilon);249 try expectApproxEqAbs(@as(f64, -0.9974949866040544), sin_f64(-1.5), epsilon);
237 try expectApproxEqAbs(@as(f64, -0.24654331551411082), sin(37.45), epsilon);250 try expectApproxEqAbs(@as(f64, -0.24654331551411082), sin_f64(37.45), epsilon);
238 try expectApproxEqAbs(@as(f64, 0.9161652766622714), sin(89.123), epsilon);251 try expectApproxEqAbs(@as(f64, 0.9161652766622714), sin_f64(89.123), epsilon);
239}252}
240253
241test "sin64.special" {254test "sin64.special" {
...@@ -244,13 +257,13 @@ test "sin64.special" {...@@ -244,13 +257,13 @@ test "sin64.special" {
244257
245test "sin80.normal" {258test "sin80.normal" {
246 const epsilon = math.floatEps(f80);259 const epsilon = math.floatEps(f80);
247 try expectApproxEqAbs(@as(f80, 0.0), sinx(0.0), epsilon);260 try expectApproxEqAbs(@as(f80, 0.0), sin_f80(0.0), epsilon);
248 try expectApproxEqAbs(@as(f80, 0.19866933079506121545941262711838975), sinx(0.2), epsilon);261 try expectApproxEqAbs(@as(f80, 0.19866933079506121545941262711838975), sin_f80(0.2), epsilon);
249 try expectApproxEqAbs(@as(f80, 0.77851733855773487830689285621486050), sinx(0.8923), epsilon);262 try expectApproxEqAbs(@as(f80, 0.77851733855773487830689285621486050), sin_f80(0.8923), epsilon);
250 try expectApproxEqAbs(@as(f80, 0.99749498660405443094172337114148732), sinx(1.5), epsilon);263 try expectApproxEqAbs(@as(f80, 0.99749498660405443094172337114148732), sin_f80(1.5), epsilon);
251 try expectApproxEqAbs(@as(f80, -0.99749498660405443094172337114148732), sinx(-1.5), epsilon);264 try expectApproxEqAbs(@as(f80, -0.99749498660405443094172337114148732), sin_f80(-1.5), epsilon);
252 try expectApproxEqAbs(@as(f80, -0.24654331551411356504), sinx(37.45), epsilon);265 try expectApproxEqAbs(@as(f80, -0.24654331551411356504), sin_f80(37.45), epsilon);
253 try expectApproxEqAbs(@as(f80, 0.91616527666226951006), sinx(89.123), epsilon);266 try expectApproxEqAbs(@as(f80, 0.91616527666226951006), sin_f80(89.123), epsilon);
254}267}
255268
256test "sin80.special" {269test "sin80.special" {
...@@ -259,13 +272,13 @@ test "sin80.special" {...@@ -259,13 +272,13 @@ test "sin80.special" {
259272
260test "sin128.normal" {273test "sin128.normal" {
261 const epsilon = math.floatEps(f128);274 const epsilon = math.floatEps(f128);
262 try expectApproxEqAbs(@as(f128, 0.0), sinq(0.0), epsilon);275 try expectApproxEqAbs(@as(f128, 0.0), sin_f128(0.0), epsilon);
263 try expectApproxEqAbs(@as(f128, 0.19866933079506121545941262711838975), sinq(0.2), epsilon);276 try expectApproxEqAbs(@as(f128, 0.19866933079506121545941262711838975), sin_f128(0.2), epsilon);
264 try expectApproxEqAbs(@as(f128, 0.77851733855773487830689285621486050), sinq(0.8923), epsilon);277 try expectApproxEqAbs(@as(f128, 0.77851733855773487830689285621486050), sin_f128(0.8923), epsilon);
265 try expectApproxEqAbs(@as(f128, 0.99749498660405443094172337114148732), sinq(1.5), epsilon);278 try expectApproxEqAbs(@as(f128, 0.99749498660405443094172337114148732), sin_f128(1.5), epsilon);
266 try expectApproxEqAbs(@as(f128, -0.99749498660405443094172337114148732), sinq(-1.5), epsilon);279 try expectApproxEqAbs(@as(f128, -0.99749498660405443094172337114148732), sin_f128(-1.5), epsilon);
267 try expectApproxEqAbs(@as(f128, -0.24654331551411356571238581321661085), sinq(37.45), epsilon);280 try expectApproxEqAbs(@as(f128, -0.24654331551411356571238581321661085), sin_f128(37.45), epsilon);
268 try expectApproxEqAbs(@as(f128, 0.91616527666226951075019849560482170), sinq(89.123), epsilon);281 try expectApproxEqAbs(@as(f128, 0.91616527666226951075019849560482170), sin_f128(89.123), epsilon);
269}282}
270283
271test "sin128.special" {284test "sin128.special" {
...@@ -274,10 +287,10 @@ test "sin128.special" {...@@ -274,10 +287,10 @@ test "sin128.special" {
274287
275test "sin32 #9901" {288test "sin32 #9901" {
276 const float: f32 = @bitCast(@as(u32, 0b11100011111111110000000000000000));289 const float: f32 = @bitCast(@as(u32, 0b11100011111111110000000000000000));
277 _ = sinf(float);290 _ = sin_f32(float);
278}291}
279292
280test "sin64 #9901" {293test "sin64 #9901" {
281 const float: f64 = @bitCast(@as(u64, 0b1111111101000001000000001111110111111111100000000000000000000001));294 const float: f64 = @bitCast(@as(u64, 0b1111111101000001000000001111110111111111100000000000000000000001));
282 _ = sin(float);295 _ = sin_f64(float);
283}296}
lib/compiler_rt/sincos.zig+125-181
...@@ -18,23 +18,27 @@ comptime {...@@ -18,23 +18,27 @@ comptime {
18 symbol(&sincosf, "sincosf");18 symbol(&sincosf, "sincosf");
19 symbol(&sincos, "sincos");19 symbol(&sincos, "sincos");
20 symbol(&sincosx, "__sincosx");20 symbol(&sincosx, "__sincosx");
21 if (compiler_rt.want_ppc_abi) {21 symbol(&sincosq, "sincosf128");
22 symbol(&sincosq, "sincosf128");
23 }
24 symbol(&sincosq, "sincosq");
25 symbol(&sincosl, "sincosl");22 symbol(&sincosl, "sincosl");
26}23}
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 } {
29 // TODO: more efficient implementation31 // TODO: more efficient implementation
30 var big_sin: f32 = undefined;32 const s, const c = sincos_f32(x);
31 var big_cos: f32 = undefined;33 return .{ @floatCast(s), @floatCast(c) };
32 sincosf(x, &big_sin, &big_cos);
33 r_sin.* = @as(f16, @floatCast(big_sin));
34 r_cos.* = @as(f16, @floatCast(big_cos));
35}34}
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 } {
38 const sc1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D1842 const sc1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18
39 const sc2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D1843 const sc2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18
40 const sc3pio2: f64 = 3.0 * math.pi / 2.0; // 0x4012D97C, 0x7F3321D244 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 {...@@ -56,13 +60,9 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void {
56 mem.doNotOptimizeAway(x + 0x1p120);60 mem.doNotOptimizeAway(x + 0x1p120);
57 }61 }
58 }62 }
59 r_sin.* = x;63 return .{ x, 1.0 };
60 r_cos.* = 1.0;
61 return;
62 }64 }
63 r_sin.* = trig.sindf(x);65 return .{ trig.sindf(x), trig.cosdf(x) };
64 r_cos.* = trig.cosdf(x);
65 return;
66 }66 }
6767
68 // |x| ~<= 5*pi/468 // |x| ~<= 5*pi/4
...@@ -70,18 +70,16 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void {...@@ -70,18 +70,16 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void {
70 // |x| ~<= 3pi/470 // |x| ~<= 3pi/4
71 if (ix <= 0x4016cbe3) {71 if (ix <= 0x4016cbe3) {
72 if (sign) {72 if (sign) {
73 r_sin.* = -trig.cosdf(x + sc1pio2);73 return .{ -trig.cosdf(x + sc1pio2), trig.sindf(x + sc1pio2) };
74 r_cos.* = trig.sindf(x + sc1pio2);
75 } else {74 } else {
76 r_sin.* = trig.cosdf(sc1pio2 - x);75 return .{ trig.cosdf(sc1pio2 - x), trig.sindf(sc1pio2 - x) };
77 r_cos.* = trig.sindf(sc1pio2 - x);
78 }76 }
79 return;
80 }77 }
81 // -sin(x+c) is not correct if x+c could be 0: -0 vs +078 // -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);79 return .{
83 r_cos.* = -trig.cosdf(if (sign) x + sc2pio2 else x - sc2pio2);80 -trig.sindf(if (sign) x + sc2pio2 else x - sc2pio2),
84 return;81 -trig.cosdf(if (sign) x + sc2pio2 else x - sc2pio2),
82 };
85 }83 }
8684
87 // |x| ~<= 9*pi/485 // |x| ~<= 9*pi/4
...@@ -89,25 +87,21 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void {...@@ -89,25 +87,21 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void {
89 // |x| ~<= 7*pi/487 // |x| ~<= 7*pi/4
90 if (ix <= 0x40afeddf) {88 if (ix <= 0x40afeddf) {
91 if (sign) {89 if (sign) {
92 r_sin.* = trig.cosdf(x + sc3pio2);90 return .{ trig.cosdf(x + sc3pio2), -trig.sindf(x + sc3pio2) };
93 r_cos.* = -trig.sindf(x + sc3pio2);
94 } else {91 } else {
95 r_sin.* = -trig.cosdf(x - sc3pio2);92 return .{ -trig.cosdf(x - sc3pio2), trig.sindf(x - sc3pio2) };
96 r_cos.* = trig.sindf(x - sc3pio2);
97 }93 }
98 return;
99 }94 }
100 r_sin.* = trig.sindf(if (sign) x + sc4pio2 else x - sc4pio2);95 return .{
101 r_cos.* = trig.cosdf(if (sign) x + sc4pio2 else x - sc4pio2);96 trig.sindf(if (sign) x + sc4pio2 else x - sc4pio2),
102 return;97 trig.cosdf(if (sign) x + sc4pio2 else x - sc4pio2),
98 };
103 }99 }
104100
105 // sin(Inf or NaN) is NaN101 // sin(Inf or NaN) is NaN
106 if (ix >= 0x7f800000) {102 if (ix >= 0x7f800000) {
107 const result = x - x;103 const result = x - x;
108 r_sin.* = result;104 return .{ result, result };
109 r_cos.* = result;
110 return;
111 }105 }
112106
113 // general argument reduction needed107 // general argument reduction needed
...@@ -115,27 +109,20 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void {...@@ -115,27 +109,20 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void {
115 const n = rem_pio2f(x, &y);109 const n = rem_pio2f(x, &y);
116 const s = trig.sindf(y);110 const s = trig.sindf(y);
117 const c = trig.cosdf(y);111 const c = trig.cosdf(y);
118 switch (n & 3) {112 return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) {
119 0 => {113 0 => .{ s, c },
120 r_sin.* = s;114 1 => .{ c, -s },
121 r_cos.* = c;115 2 => .{ -s, -c },
122 },116 3 => .{ -c, s },
123 1 => {117 };
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 }
136}118}
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 } {
139 const ix = @as(u32, @truncate(@as(u64, @bitCast(x)) >> 32)) & 0x7fffffff;126 const ix = @as(u32, @truncate(@as(u64, @bitCast(x)) >> 32)) & 0x7fffffff;
140127
141 // |x| ~< pi/4128 // |x| ~< pi/4
...@@ -150,21 +137,15 @@ pub fn sincos(x: f64, r_sin: *f64, r_cos: *f64) callconv(.c) void {...@@ -150,21 +137,15 @@ pub fn sincos(x: f64, r_sin: *f64, r_cos: *f64) callconv(.c) void {
150 mem.doNotOptimizeAway(x + 0x1p120);137 mem.doNotOptimizeAway(x + 0x1p120);
151 }138 }
152 }139 }
153 r_sin.* = x;140 return .{ x, 1.0 };
154 r_cos.* = 1.0;
155 return;
156 }141 }
157 r_sin.* = trig.sin(x, 0.0, 0);142 return .{ trig.sin(x, 0.0, 0), trig.cos(x, 0.0) };
158 r_cos.* = trig.cos(x, 0.0);
159 return;
160 }143 }
161144
162 // sincos(Inf or NaN) is NaN145 // sincos(Inf or NaN) is NaN
163 if (ix >= 0x7ff00000) {146 if (ix >= 0x7ff00000) {
164 const result = x - x;147 const result = x - x;
165 r_sin.* = result;148 return .{ result, result };
166 r_cos.* = result;
167 return;
168 }149 }
169150
170 // argument reduction needed151 // argument reduction needed
...@@ -172,33 +153,24 @@ pub fn sincos(x: f64, r_sin: *f64, r_cos: *f64) callconv(.c) void {...@@ -172,33 +153,24 @@ pub fn sincos(x: f64, r_sin: *f64, r_cos: *f64) callconv(.c) void {
172 const n = rem_pio2(x, &y);153 const n = rem_pio2(x, &y);
173 const s = trig.sin(y[0], y[1], 1);154 const s = trig.sin(y[0], y[1], 1);
174 const c = trig.cos(y[0], y[1]);155 const c = trig.cos(y[0], y[1]);
175 switch (n & 3) {156 return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) {
176 0 => {157 0 => .{ s, c },
177 r_sin.* = s;158 1 => .{ c, -s },
178 r_cos.* = c;159 2 => .{ -s, -c },
179 },160 3 => .{ -c, s },
180 1 => {161 };
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 }
193}162}
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 } {
196 const se = ld.signExponent(x) & 0x7fff;170 const se = ld.signExponent(x) & 0x7fff;
197 if (se == 0x7fff) {171 if (se == 0x7fff) {
198 const result = x - x;172 const result = x - x;
199 r_sin.* = result;173 return .{ result, result };
200 r_cos.* = result;
201 return;
202 }174 }
203175
204 if (@abs(x) < trig.pi_4) {176 if (@abs(x) < trig.pi_4) {
...@@ -207,47 +179,34 @@ pub fn sincosx(x: f80, r_sin: *f80, r_cos: *f80) callconv(.c) void {...@@ -207,47 +179,34 @@ pub fn sincosx(x: f80, r_sin: *f80, r_cos: *f80) callconv(.c) void {
207 if (compiler_rt.want_float_exceptions and se == 0) {179 if (compiler_rt.want_float_exceptions and se == 0) {
208 mem.doNotOptimizeAway(x * 0x1p-120);180 mem.doNotOptimizeAway(x * 0x1p-120);
209 }181 }
210 r_sin.* = x;
211 // raise inexact if x!=0182 // raise inexact if x!=0
212 r_cos.* = 1.0 + x;183 return .{ x, 1.0 + x };
213 return;
214 }184 }
215 r_sin.* = trig.sinx(x, 0.0, 0);185 return .{ trig.sinx(x, 0.0, 0), trig.cosx(x, 0.0) };
216 r_cos.* = trig.cosx(x, 0.0);
217 return;
218 }186 }
219187
220 var y: [2]f80 = undefined;188 var y: [2]f80 = undefined;
221 const n = rem_pio2l(f80, x, &y);189 const n = rem_pio2l(f80, x, &y);
222 const s = trig.sinx(y[0], y[1], 1);190 const s = trig.sinx(y[0], y[1], 1);
223 const c = trig.cosx(y[0], y[1]);191 const c = trig.cosx(y[0], y[1]);
224 switch (n & 3) {192 return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) {
225 0 => {193 0 => .{ s, c },
226 r_sin.* = s;194 1 => .{ c, -s },
227 r_cos.* = c;195 2 => .{ -s, -c },
228 },196 3 => .{ -c, s },
229 1 => {197 };
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 }
242}198}
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 } {
245 const se = ld.signExponent(x) & 0x7fff;206 const se = ld.signExponent(x) & 0x7fff;
246 if (se == 0x7fff) {207 if (se == 0x7fff) {
247 const result = x - x;208 const result = x - x;
248 r_sin.* = result;209 return .{ result, result };
249 r_cos.* = result;
250 return;
251 }210 }
252211
253 if (@abs(x) < trig.pi_4) {212 if (@abs(x) < trig.pi_4) {
...@@ -256,78 +215,63 @@ pub fn sincosq(x: f128, r_sin: *f128, r_cos: *f128) callconv(.c) void {...@@ -256,78 +215,63 @@ pub fn sincosq(x: f128, r_sin: *f128, r_cos: *f128) callconv(.c) void {
256 if (compiler_rt.want_float_exceptions and se == 0) {215 if (compiler_rt.want_float_exceptions and se == 0) {
257 mem.doNotOptimizeAway(x * 0x1p-120);216 mem.doNotOptimizeAway(x * 0x1p-120);
258 }217 }
259 r_sin.* = x;
260 // raise inexact if x!=0218 // raise inexact if x!=0
261 r_cos.* = 1.0 + x;219 return .{ x, 1.0 + x };
262 return;
263 }220 }
264 r_sin.* = trig.sinq(x, 0.0, 0);221 return .{ trig.sinq(x, 0.0, 0), trig.cosq(x, 0.0) };
265 r_cos.* = trig.cosq(x, 0.0);
266 return;
267 }222 }
268223
269 var y: [2]f128 = undefined;224 var y: [2]f128 = undefined;
270 const n = rem_pio2l(f128, x, &y);225 const n = rem_pio2l(f128, x, &y);
271 const s = trig.sinq(y[0], y[1], 1);226 const s = trig.sinq(y[0], y[1], 1);
272 const c = trig.cosq(y[0], y[1]);227 const c = trig.cosq(y[0], y[1]);
273 switch (n & 3) {228 return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) {
274 0 => {229 0 => .{ s, c },
275 r_sin.* = s;230 1 => .{ c, -s },
276 r_cos.* = c;231 2 => .{ -s, -c },
277 },232 3 => .{ -c, s },
278 1 => {233 };
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 }
291}234}
292235
293pub fn sincosl(x: c_longdouble, r_sin: *c_longdouble, r_cos: *c_longdouble) callconv(.c) void {236pub fn sincosl(x: c_longdouble, r_sin: *c_longdouble, r_cos: *c_longdouble) callconv(.c) void {
294 switch (@typeInfo(c_longdouble).float.bits) {237 r_sin.*, r_cos.* = switch (@typeInfo(c_longdouble).float.bits) {
295 64 => return sincos(x, r_sin, r_cos),238 64 => sincos_f64(x),
296 80 => return sincosx(x, r_sin, r_cos),239 80 => sincos_f80(x),
297 128 => return sincosq(x, r_sin, r_cos),240 128 => sincos_f128(x),
298 else => @compileError("unreachable"),241 else => comptime unreachable,
299 }242 };
300}243}
301244
302fn testSincosSpecial(comptime T: type) !void {245fn testSincosSpecial(comptime T: type) !void {
303 const f = switch (T) {246 const f = switch (T) {
304 f32 => sincosf,247 f16 => sincos_f16,
305 f64 => sincos,248 f32 => sincos_f32,
306 f80 => sincosx,249 f64 => sincos_f64,
307 f128 => sincosq,250 f80 => sincos_f80,
251 f128 => sincos_f128,
308 else => @compileError("unimplemented"),252 else => @compileError("unimplemented"),
309 };253 };
310254
311 var s: T = undefined;255 var s: T = undefined;
312 var c: T = undefined;256 var c: T = undefined;
313257
314 f(0.0, &s, &c);258 s, c = f(0.0);
315 try expect(math.isPositiveZero(s));259 try expect(math.isPositiveZero(s));
316 try expect(c == 1.0);260 try expect(c == 1.0);
317261
318 f(-0.0, &s, &c);262 s, c = f(-0.0);
319 try expect(math.isNegativeZero(s));263 try expect(math.isNegativeZero(s));
320 try expect(c == 1.0);264 try expect(c == 1.0);
321265
322 f(math.inf(T), &s, &c);266 s, c = f(math.inf(T));
323 try expect(math.isNan(s));267 try expect(math.isNan(s));
324 try expect(math.isNan(c));268 try expect(math.isNan(c));
325269
326 f(-math.inf(T), &s, &c);270 s, c = f(-math.inf(T));
327 try expect(math.isNan(s));271 try expect(math.isNan(s));
328 try expect(math.isNan(c));272 try expect(math.isNan(c));
329273
330 f(math.nan(T), &s, &c);274 s, c = f(math.nan(T));
331 try expect(math.isNan(s));275 try expect(math.isNan(s));
332 try expect(math.isNan(c));276 try expect(math.isNan(c));
333}277}
...@@ -337,31 +281,31 @@ test "sincos32.normal" {...@@ -337,31 +281,31 @@ test "sincos32.normal" {
337 var s: f32 = undefined;281 var s: f32 = undefined;
338 var c: f32 = undefined;282 var c: f32 = undefined;
339283
340 sincosf(0.0, &s, &c);284 s, c = sincos_f32(0.0);
341 try expectApproxEqAbs(@as(f32, 0.0), s, epsilon);285 try expectApproxEqAbs(@as(f32, 0.0), s, epsilon);
342 try expectApproxEqAbs(@as(f32, 1.0), c, epsilon);286 try expectApproxEqAbs(@as(f32, 1.0), c, epsilon);
343287
344 sincosf(0.2, &s, &c);288 s, c = sincos_f32(0.2);
345 try expectApproxEqAbs(@as(f32, 0.19866933), s, epsilon);289 try expectApproxEqAbs(@as(f32, 0.19866933), s, epsilon);
346 try expectApproxEqAbs(@as(f32, 0.9800666), c, epsilon);290 try expectApproxEqAbs(@as(f32, 0.9800666), c, epsilon);
347291
348 sincosf(0.8923, &s, &c);292 s, c = sincos_f32(0.8923);
349 try expectApproxEqAbs(@as(f32, 0.77851737), s, epsilon);293 try expectApproxEqAbs(@as(f32, 0.77851737), s, epsilon);
350 try expectApproxEqAbs(@as(f32, 0.6276231), c, epsilon);294 try expectApproxEqAbs(@as(f32, 0.6276231), c, epsilon);
351295
352 sincosf(1.5, &s, &c);296 s, c = sincos_f32(1.5);
353 try expectApproxEqAbs(@as(f32, 0.997495), s, epsilon);297 try expectApproxEqAbs(@as(f32, 0.997495), s, epsilon);
354 try expectApproxEqAbs(@as(f32, 0.0707372), c, epsilon);298 try expectApproxEqAbs(@as(f32, 0.0707372), c, epsilon);
355299
356 sincosf(-1.5, &s, &c);300 s, c = sincos_f32(-1.5);
357 try expectApproxEqAbs(@as(f32, -0.997495), s, epsilon);301 try expectApproxEqAbs(@as(f32, -0.997495), s, epsilon);
358 try expectApproxEqAbs(@as(f32, 0.0707372), c, epsilon);302 try expectApproxEqAbs(@as(f32, 0.0707372), c, epsilon);
359303
360 sincosf(37.45, &s, &c);304 s, c = sincos_f32(37.45);
361 try expectApproxEqAbs(@as(f32, -0.24654257), s, epsilon);305 try expectApproxEqAbs(@as(f32, -0.24654257), s, epsilon);
362 try expectApproxEqAbs(@as(f32, 0.96913195), c, epsilon);306 try expectApproxEqAbs(@as(f32, 0.96913195), c, epsilon);
363307
364 sincosf(89.123, &s, &c);308 s, c = sincos_f32(89.123);
365 try expectApproxEqAbs(@as(f32, 0.9161657), s, epsilon);309 try expectApproxEqAbs(@as(f32, 0.9161657), s, epsilon);
366 try expectApproxEqAbs(@as(f32, 0.40079966), c, epsilon);310 try expectApproxEqAbs(@as(f32, 0.40079966), c, epsilon);
367}311}
...@@ -375,31 +319,31 @@ test "sincos64.normal" {...@@ -375,31 +319,31 @@ test "sincos64.normal" {
375 var s: f64 = undefined;319 var s: f64 = undefined;
376 var c: f64 = undefined;320 var c: f64 = undefined;
377321
378 sincos(0.0, &s, &c);322 s, c = sincos_f64(0.0);
379 try expectApproxEqAbs(@as(f64, 0.0), s, epsilon);323 try expectApproxEqAbs(@as(f64, 0.0), s, epsilon);
380 try expectApproxEqAbs(@as(f64, 1.0), c, epsilon);324 try expectApproxEqAbs(@as(f64, 1.0), c, epsilon);
381325
382 sincos(0.2, &s, &c);326 s, c = sincos_f64(0.2);
383 try expectApproxEqAbs(@as(f64, 0.19866933079506122), s, epsilon);327 try expectApproxEqAbs(@as(f64, 0.19866933079506122), s, epsilon);
384 try expectApproxEqAbs(@as(f64, 0.9800665778412416), c, epsilon);328 try expectApproxEqAbs(@as(f64, 0.9800665778412416), c, epsilon);
385329
386 sincos(0.8923, &s, &c);330 s, c = sincos_f64(0.8923);
387 try expectApproxEqAbs(@as(f64, 0.7785173385577349), s, epsilon);331 try expectApproxEqAbs(@as(f64, 0.7785173385577349), s, epsilon);
388 try expectApproxEqAbs(@as(f64, 0.6276230983360804), c, epsilon);332 try expectApproxEqAbs(@as(f64, 0.6276230983360804), c, epsilon);
389333
390 sincos(1.5, &s, &c);334 s, c = sincos_f64(1.5);
391 try expectApproxEqAbs(@as(f64, 0.9974949866040544), s, epsilon);335 try expectApproxEqAbs(@as(f64, 0.9974949866040544), s, epsilon);
392 try expectApproxEqAbs(@as(f64, 0.0707372016677029), c, epsilon);336 try expectApproxEqAbs(@as(f64, 0.0707372016677029), c, epsilon);
393337
394 sincos(-1.5, &s, &c);338 s, c = sincos_f64(-1.5);
395 try expectApproxEqAbs(@as(f64, -0.9974949866040544), s, epsilon);339 try expectApproxEqAbs(@as(f64, -0.9974949866040544), s, epsilon);
396 try expectApproxEqAbs(@as(f64, 0.0707372016677029), c, epsilon);340 try expectApproxEqAbs(@as(f64, 0.0707372016677029), c, epsilon);
397341
398 sincos(37.45, &s, &c);342 s, c = sincos_f64(37.45);
399 try expectApproxEqAbs(@as(f64, -0.24654331551411082), s, epsilon);343 try expectApproxEqAbs(@as(f64, -0.24654331551411082), s, epsilon);
400 try expectApproxEqAbs(@as(f64, 0.9691317730707778), c, epsilon);344 try expectApproxEqAbs(@as(f64, 0.9691317730707778), c, epsilon);
401345
402 sincos(89.123, &s, &c);346 s, c = sincos_f64(89.123);
403 try expectApproxEqAbs(@as(f64, 0.9161652766622714), s, epsilon);347 try expectApproxEqAbs(@as(f64, 0.9161652766622714), s, epsilon);
404 try expectApproxEqAbs(@as(f64, 0.4008006809354791), c, epsilon);348 try expectApproxEqAbs(@as(f64, 0.4008006809354791), c, epsilon);
405}349}
...@@ -413,31 +357,31 @@ test "sincos80.normal" {...@@ -413,31 +357,31 @@ test "sincos80.normal" {
413 var s: f80 = undefined;357 var s: f80 = undefined;
414 var c: f80 = undefined;358 var c: f80 = undefined;
415359
416 sincosx(0.0, &s, &c);360 s, c = sincos_f80(0.0);
417 try expectApproxEqAbs(@as(f80, 0.0), s, epsilon);361 try expectApproxEqAbs(@as(f80, 0.0), s, epsilon);
418 try expectApproxEqAbs(@as(f80, 1.0), c, epsilon);362 try expectApproxEqAbs(@as(f80, 1.0), c, epsilon);
419363
420 sincosx(0.2, &s, &c);364 s, c = sincos_f80(0.2);
421 try expectApproxEqAbs(@as(f80, 0.19866933079506121545941262711838975), s, epsilon);365 try expectApproxEqAbs(@as(f80, 0.19866933079506121545941262711838975), s, epsilon);
422 try expectApproxEqAbs(@as(f80, 0.98006657784124163112419651674816888), c, epsilon);366 try expectApproxEqAbs(@as(f80, 0.98006657784124163112419651674816888), c, epsilon);
423367
424 sincosx(0.8923, &s, &c);368 s, c = sincos_f80(0.8923);
425 try expectApproxEqAbs(@as(f80, 0.77851733855773487830689285621486050), s, epsilon);369 try expectApproxEqAbs(@as(f80, 0.77851733855773487830689285621486050), s, epsilon);
426 try expectApproxEqAbs(@as(f80, 0.62762309833608037003563995939286067), c, epsilon);370 try expectApproxEqAbs(@as(f80, 0.62762309833608037003563995939286067), c, epsilon);
427371
428 sincosx(1.5, &s, &c);372 s, c = sincos_f80(1.5);
429 try expectApproxEqAbs(@as(f80, 0.99749498660405443094172337114148732), s, epsilon);373 try expectApproxEqAbs(@as(f80, 0.99749498660405443094172337114148732), s, epsilon);
430 try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), c, epsilon);374 try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), c, epsilon);
431375
432 sincosx(-1.5, &s, &c);376 s, c = sincos_f80(-1.5);
433 try expectApproxEqAbs(@as(f80, -0.99749498660405443094172337114148732), s, epsilon);377 try expectApproxEqAbs(@as(f80, -0.99749498660405443094172337114148732), s, epsilon);
434 try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), c, epsilon);378 try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), c, epsilon);
435379
436 sincosx(37.45, &s, &c);380 s, c = sincos_f80(37.45);
437 try expectApproxEqAbs(@as(f80, -0.24654331551411356504), s, epsilon);381 try expectApproxEqAbs(@as(f80, -0.24654331551411356504), s, epsilon);
438 try expectApproxEqAbs(@as(f80, 0.9691317730707771246), c, epsilon);382 try expectApproxEqAbs(@as(f80, 0.9691317730707771246), c, epsilon);
439383
440 sincosx(89.123, &s, &c);384 s, c = sincos_f80(89.123);
441 try expectApproxEqAbs(@as(f80, 0.91616527666226951006), s, epsilon);385 try expectApproxEqAbs(@as(f80, 0.91616527666226951006), s, epsilon);
442 try expectApproxEqAbs(@as(f80, 0.4008006809354834001), c, epsilon);386 try expectApproxEqAbs(@as(f80, 0.4008006809354834001), c, epsilon);
443}387}
...@@ -451,31 +395,31 @@ test "sincos128.normal" {...@@ -451,31 +395,31 @@ test "sincos128.normal" {
451 var s: f128 = undefined;395 var s: f128 = undefined;
452 var c: f128 = undefined;396 var c: f128 = undefined;
453397
454 sincosq(0.0, &s, &c);398 s, c = sincos_f128(0.0);
455 try expectApproxEqAbs(@as(f128, 0.0), s, epsilon);399 try expectApproxEqAbs(@as(f128, 0.0), s, epsilon);
456 try expectApproxEqAbs(@as(f128, 1.0), c, epsilon);400 try expectApproxEqAbs(@as(f128, 1.0), c, epsilon);
457401
458 sincosq(0.2, &s, &c);402 s, c = sincos_f128(0.2);
459 try expectApproxEqAbs(@as(f128, 0.19866933079506121545941262711838975), s, epsilon);403 try expectApproxEqAbs(@as(f128, 0.19866933079506121545941262711838975), s, epsilon);
460 try expectApproxEqAbs(@as(f128, 0.98006657784124163112419651674816888), c, epsilon);404 try expectApproxEqAbs(@as(f128, 0.98006657784124163112419651674816888), c, epsilon);
461405
462 sincosq(0.8923, &s, &c);406 s, c = sincos_f128(0.8923);
463 try expectApproxEqAbs(@as(f128, 0.77851733855773487830689285621486050), s, epsilon);407 try expectApproxEqAbs(@as(f128, 0.77851733855773487830689285621486050), s, epsilon);
464 try expectApproxEqAbs(@as(f128, 0.62762309833608037003563995939286067), c, epsilon);408 try expectApproxEqAbs(@as(f128, 0.62762309833608037003563995939286067), c, epsilon);
465409
466 sincosq(1.5, &s, &c);410 s, c = sincos_f128(1.5);
467 try expectApproxEqAbs(@as(f128, 0.99749498660405443094172337114148732), s, epsilon);411 try expectApproxEqAbs(@as(f128, 0.99749498660405443094172337114148732), s, epsilon);
468 try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), c, epsilon);412 try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), c, epsilon);
469413
470 sincosq(-1.5, &s, &c);414 s, c = sincos_f128(-1.5);
471 try expectApproxEqAbs(@as(f128, -0.99749498660405443094172337114148732), s, epsilon);415 try expectApproxEqAbs(@as(f128, -0.99749498660405443094172337114148732), s, epsilon);
472 try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), c, epsilon);416 try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), c, epsilon);
473417
474 sincosq(37.45, &s, &c);418 s, c = sincos_f128(37.45);
475 try expectApproxEqAbs(@as(f128, -0.24654331551411356571238581321661085), s, epsilon);419 try expectApproxEqAbs(@as(f128, -0.24654331551411356571238581321661085), s, epsilon);
476 try expectApproxEqAbs(@as(f128, 0.96913177307077712443149563847233230), c, epsilon);420 try expectApproxEqAbs(@as(f128, 0.96913177307077712443149563847233230), c, epsilon);
477421
478 sincosq(89.123, &s, &c);422 s, c = sincos_f128(89.123);
479 try expectApproxEqAbs(@as(f128, 0.91616527666226951075019849560482170), s, epsilon);423 try expectApproxEqAbs(@as(f128, 0.91616527666226951075019849560482170), s, epsilon);
480 try expectApproxEqAbs(@as(f128, 0.40080068093548339848199454493704702), c, epsilon);424 try expectApproxEqAbs(@as(f128, 0.40080068093548339848199454493704702), c, epsilon);
481}425}
lib/compiler_rt/sqrt.zig+150-137
...@@ -17,18 +17,19 @@ comptime {...@@ -17,18 +17,19 @@ comptime {
17 symbol(&sqrtf, "sqrtf");17 symbol(&sqrtf, "sqrtf");
18 symbol(&sqrt, "sqrt");18 symbol(&sqrt, "sqrt");
19 symbol(&__sqrtx, "__sqrtx");19 symbol(&__sqrtx, "__sqrtx");
20 if (compiler_rt.want_ppc_abi) {20 symbol(&sqrtq, "sqrtf128");
21 symbol(&sqrtq, "sqrtf128");21 if (compiler_rt.want_sparc64_abi) {
22 } else if (compiler_rt.want_sparc64_abi) {
23 symbol(&_Qp_sqrt, "_Qp_sqrt");22 symbol(&_Qp_sqrt, "_Qp_sqrt");
24 } else if (compiler_rt.want_sparc32_abi) {23 } else if (compiler_rt.want_sparc32_abi) {
25 symbol(&sqrtq, "_Q_sqrt");24 symbol(&sqrtq, "_Q_sqrt");
26 }25 }
27 symbol(&sqrtq, "sqrtq");
28 symbol(&sqrtl, "sqrtl");26 symbol(&sqrtl, "sqrtl");
29}27}
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 {
32 var ix: u16 = @bitCast(x);33 var ix: u16 = @bitCast(x);
33 var top = ix >> 10;34 var top = ix >> 10;
3435
...@@ -93,7 +94,10 @@ pub fn __sqrth(x: f16) callconv(.c) f16 {...@@ -93,7 +94,10 @@ pub fn __sqrth(x: f16) callconv(.c) f16 {
93 return y;94 return y;
94}95}
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 {
97 var ix: u32 = @bitCast(x);101 var ix: u32 = @bitCast(x);
98102
99 if (ix < @as(u32, @bitCast(@as(f32, 0x1p-126))) or @as(u32, @bitCast(std.math.inf(f32))) <= ix) {103 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 {...@@ -147,7 +151,10 @@ pub fn sqrtf(x: f32) callconv(.c) f32 {
147 return y + t;151 return y + t;
148}152}
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 {
151 var ix: u64 = @bitCast(x);158 var ix: u64 = @bitCast(x);
152 var top = ix >> 52;159 var top = ix >> 52;
153160
...@@ -284,7 +291,10 @@ pub fn sqrt(x: f64) callconv(.c) f64 {...@@ -284,7 +291,10 @@ pub fn sqrt(x: f64) callconv(.c) f64 {
284 return y;291 return y;
285}292}
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 {
288 var ix: u80 = @bitCast(x);298 var ix: u80 = @bitCast(x);
289 var top = ix >> 64;299 var top = ix >> 64;
290300
...@@ -381,7 +391,10 @@ pub fn __sqrtx(x: f80) callconv(.c) f80 {...@@ -381,7 +391,10 @@ pub fn __sqrtx(x: f80) callconv(.c) f80 {
381 return y;391 return y;
382}392}
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 {
385 var ix: u128 = @bitCast(x);398 var ix: u128 = @bitCast(x);
386 var top = ix >> 112;399 var top = ix >> 112;
387400
...@@ -483,10 +496,10 @@ fn _Qp_sqrt(c: *f128, a: *f128) callconv(.c) void {...@@ -483,10 +496,10 @@ fn _Qp_sqrt(c: *f128, a: *f128) callconv(.c) void {
483496
484pub fn sqrtl(x: c_longdouble) callconv(.c) c_longdouble {497pub fn sqrtl(x: c_longdouble) callconv(.c) c_longdouble {
485 switch (@typeInfo(c_longdouble).float.bits) {498 switch (@typeInfo(c_longdouble).float.bits) {
486 64 => return sqrt(x),499 64 => return sqrt_f64(x),
487 80 => return __sqrtx(x),500 80 => return sqrt_f80(x),
488 128 => return sqrtq(x),501 128 => return sqrt_f128(x),
489 else => @compileError("unreachable"),502 else => comptime unreachable,
490 }503 }
491}504}
492505
...@@ -545,187 +558,187 @@ inline fn mul80_tail(a: u80, b: u80) u80 {...@@ -545,187 +558,187 @@ inline fn mul80_tail(a: u80, b: u80) u80 {
545 return alo * blo +% ((ahi * blo) << 40) +% ((alo * bhi) << 40);558 return alo * blo +% ((ahi * blo) << 40) +% ((alo * bhi) << 40);
546}559}
547560
548test "__sqrth" {561test "sqrt_f16" {
549 // sqrt(±0) is ±0562 // sqrt(±0) is ±0
550 try std.testing.expectEqual(__sqrth(0x0.0p0), 0x0.0p0);563 try std.testing.expectEqual(sqrt_f16(0x0.0p0), 0x0.0p0);
551 try std.testing.expectEqual(__sqrth(-0x0.0p0), -0x0.0p0);564 try std.testing.expectEqual(sqrt_f16(-0x0.0p0), -0x0.0p0);
552 // sqrt(+max) is finite565 // 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);
554 // sqrt(4)=2567 // sqrt(4)=2
555 try std.testing.expectEqual(__sqrth(0x1p2), 0x1p1);568 try std.testing.expectEqual(sqrt_f16(0x1p2), 0x1p1);
556 // sqrt(x) for x=1, 1±ulp569 // sqrt(x) for x=1, 1±ulp
557 try std.testing.expectEqual(__sqrth(0x1p0), 0x1p0);570 try std.testing.expectEqual(sqrt_f16(0x1p0), 0x1p0);
558 try std.testing.expectEqual(__sqrth(0x1.004p0), 0x1p0);571 try std.testing.expectEqual(sqrt_f16(0x1.004p0), 0x1p0);
559 try std.testing.expectEqual(__sqrth(0x1.FF8p-1), 0x1.FFCp-1);572 try std.testing.expectEqual(sqrt_f16(0x1.FF8p-1), 0x1.FFCp-1);
560 // sqrt(+min) is non-zero573 // 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);
562 // sqrt(min subnormal) is non-zero575 // 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);
564 // sqrt(inf) is inf577 // 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))));
566 // sqrt(nan) is nan579 // 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))));
568 // sqrt(-ve) is nan581 // sqrt(-ve) is nan
569 try std.testing.expect(math.isNan(__sqrth(-0x1p-14)));582 try std.testing.expect(math.isNan(sqrt_f16(-0x1p-14)));
570 try std.testing.expect(math.isNan(__sqrth(-0x1p+0)));583 try std.testing.expect(math.isNan(sqrt_f16(-0x1p+0)));
571 try std.testing.expect(math.isNan(__sqrth(-math.inf(f16))));584 try std.testing.expect(math.isNan(sqrt_f16(-math.inf(f16))));
572 // random arguments585 // random arguments
573 try std.testing.expectEqual(__sqrth(0x1.1p14), 0x1.08p7);586 try std.testing.expectEqual(sqrt_f16(0x1.1p14), 0x1.08p7);
574 try std.testing.expectEqual(__sqrth(0x1.C9p-12), 0x1.56p-6);587 try std.testing.expectEqual(sqrt_f16(0x1.C9p-12), 0x1.56p-6);
575 try std.testing.expectEqual(__sqrth(0x1.CE8p-7), 0x1.E68p-4);588 try std.testing.expectEqual(sqrt_f16(0x1.CE8p-7), 0x1.E68p-4);
576 try std.testing.expectEqual(__sqrth(0x1.134p-7), 0x1.778p-4);589 try std.testing.expectEqual(sqrt_f16(0x1.134p-7), 0x1.778p-4);
577 try std.testing.expectEqual(__sqrth(0x1.E9Cp-10), 0x1.62p-5);590 try std.testing.expectEqual(sqrt_f16(0x1.E9Cp-10), 0x1.62p-5);
578 try std.testing.expectEqual(__sqrth(0x1.3Dp9), 0x1.92Cp4);591 try std.testing.expectEqual(sqrt_f16(0x1.3Dp9), 0x1.92Cp4);
579 try std.testing.expectEqual(__sqrth(0x1.AA4p8), 0x1.4A4p4);592 try std.testing.expectEqual(sqrt_f16(0x1.AA4p8), 0x1.4A4p4);
580 try std.testing.expectEqual(__sqrth(0x1.8A8p4), 0x1.3DCp2);593 try std.testing.expectEqual(sqrt_f16(0x1.8A8p4), 0x1.3DCp2);
581 try std.testing.expectEqual(__sqrth(0x1.8Fp-7), 0x1.C4p-4);594 try std.testing.expectEqual(sqrt_f16(0x1.8Fp-7), 0x1.C4p-4);
582 try std.testing.expectEqual(__sqrth(0x1.584p-11), 0x1.A3Cp-6);595 try std.testing.expectEqual(sqrt_f16(0x1.584p-11), 0x1.A3Cp-6);
583}596}
584597
585test "sqrtf" {598test "sqrt_f32" {
586 // sqrt(±0) is ±0599 // sqrt(±0) is ±0
587 try std.testing.expectEqual(sqrtf(0x0.0p0), 0x0.0p0);600 try std.testing.expectEqual(sqrt_f32(0x0.0p0), 0x0.0p0);
588 try std.testing.expectEqual(sqrtf(-0x0.0p0), -0x0.0p0);601 try std.testing.expectEqual(sqrt_f32(-0x0.0p0), -0x0.0p0);
589 // sqrt(+max) is finite602 // 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);
591 // sqrt(4)=2604 // sqrt(4)=2
592 try std.testing.expectEqual(sqrtf(0x1p2), 0x1p1);605 try std.testing.expectEqual(sqrt_f32(0x1p2), 0x1p1);
593 // sqrt(x) for x=1, 1±ulp606 // sqrt(x) for x=1, 1±ulp
594 try std.testing.expectEqual(sqrtf(0x1p0), 0x1p0);607 try std.testing.expectEqual(sqrt_f32(0x1p0), 0x1p0);
595 try std.testing.expectEqual(sqrtf(0x1.000002p0), 0x1p0);608 try std.testing.expectEqual(sqrt_f32(0x1.000002p0), 0x1p0);
596 try std.testing.expectEqual(sqrtf(0x1.FFFFFEp-1), 0x1.FFFFFEp-1);609 try std.testing.expectEqual(sqrt_f32(0x1.FFFFFEp-1), 0x1.FFFFFEp-1);
597 // sqrt(+min) is non-zero610 // 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);
599 // sqrt(min subnormal) is non-zero612 // 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);
601 // sqrt(inf) is inf614 // 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))));
603 // sqrt(nan) is nan616 // 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))));
605 // sqrt(-ve) is nan618 // sqrt(-ve) is nan
606 try std.testing.expect(math.isNan(sqrtf(-0x1p-149)));619 try std.testing.expect(math.isNan(sqrt_f32(-0x1p-149)));
607 try std.testing.expect(math.isNan(sqrtf(-0x1p0)));620 try std.testing.expect(math.isNan(sqrt_f32(-0x1p0)));
608 try std.testing.expect(math.isNan(sqrtf(-math.inf(f32))));621 try std.testing.expect(math.isNan(sqrt_f32(-math.inf(f32))));
609 // random arguments622 // random arguments
610 try std.testing.expectEqual(sqrtf(0x1.4DD57Ep77), 0x1.9D6DA8p38);623 try std.testing.expectEqual(sqrt_f32(0x1.4DD57Ep77), 0x1.9D6DA8p38);
611 try std.testing.expectEqual(sqrtf(0x1.871848p102), 0x1.3C6AFAp51);624 try std.testing.expectEqual(sqrt_f32(0x1.871848p102), 0x1.3C6AFAp51);
612 try std.testing.expectEqual(sqrtf(0x1.A1D748p-112), 0x1.470EFCp-56);625 try std.testing.expectEqual(sqrt_f32(0x1.A1D748p-112), 0x1.470EFCp-56);
613 try std.testing.expectEqual(sqrtf(0x1.E626C2p18), 0x1.60C80Ep9);626 try std.testing.expectEqual(sqrt_f32(0x1.E626C2p18), 0x1.60C80Ep9);
614 try std.testing.expectEqual(sqrtf(0x1.E80E66p-29), 0x1.F3E282p-15);627 try std.testing.expectEqual(sqrt_f32(0x1.E80E66p-29), 0x1.F3E282p-15);
615 try std.testing.expectEqual(sqrtf(0x1.B47204p89), 0x1.D8B732p44);628 try std.testing.expectEqual(sqrt_f32(0x1.B47204p89), 0x1.D8B732p44);
616 try std.testing.expectEqual(sqrtf(0x1.77F45p15), 0x1.B6BC3Ap7);629 try std.testing.expectEqual(sqrt_f32(0x1.77F45p15), 0x1.B6BC3Ap7);
617 try std.testing.expectEqual(sqrtf(0x1.AD5F5p-48), 0x1.4B8A72p-24);630 try std.testing.expectEqual(sqrt_f32(0x1.AD5F5p-48), 0x1.4B8A72p-24);
618 try std.testing.expectEqual(sqrtf(0x1.91A39p-76), 0x1.40A7A8p-38);631 try std.testing.expectEqual(sqrt_f32(0x1.91A39p-76), 0x1.40A7A8p-38);
619 try std.testing.expectEqual(sqrtf(0x1.DAE088p79), 0x1.ED16DCp39);632 try std.testing.expectEqual(sqrt_f32(0x1.DAE088p79), 0x1.ED16DCp39);
620}633}
621634
622test "sqrt" {635test "sqrt_f64" {
623 // sqrt(±0) is ±0636 // sqrt(±0) is ±0
624 try std.testing.expectEqual(sqrt(0x0.0p0), 0x0.0p0);637 try std.testing.expectEqual(sqrt_f64(0x0.0p0), 0x0.0p0);
625 try std.testing.expectEqual(sqrt(-0x0.0p0), -0x0.0p0);638 try std.testing.expectEqual(sqrt_f64(-0x0.0p0), -0x0.0p0);
626 // sqrt(+max) is finite639 // 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);
628 // sqrt(4)=2641 // sqrt(4)=2
629 try std.testing.expectEqual(sqrt(0x1p2), 0x1p1);642 try std.testing.expectEqual(sqrt_f64(0x1p2), 0x1p1);
630 // sqrt(x) for x=1, 1±ulp643 // sqrt(x) for x=1, 1±ulp
631 try std.testing.expectEqual(sqrt(0x1p0), 0x1p0);644 try std.testing.expectEqual(sqrt_f64(0x1p0), 0x1p0);
632 try std.testing.expectEqual(sqrt(0x1p0 + math.floatEps(f64)), 0x1p0);645 try std.testing.expectEqual(sqrt_f64(0x1p0 + math.floatEps(f64)), 0x1p0);
633 try std.testing.expectEqual(sqrt(0x1p0 - math.floatEps(f64)), 0x1.FFFFFFFFFFFFFp-1);646 try std.testing.expectEqual(sqrt_f64(0x1p0 - math.floatEps(f64)), 0x1.FFFFFFFFFFFFFp-1);
634 // sqrt(+min) is non-zero647 // 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);
636 // sqrt(min subnormal) is non-zero649 // 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);
638 // sqrt(inf) is inf651 // 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))));
640 // sqrt(nan) is nan653 // 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))));
642 // sqrt(-ve) is nan655 // sqrt(-ve) is nan
643 try std.testing.expect(math.isNan(sqrt(-0x1p-1074)));656 try std.testing.expect(math.isNan(sqrt_f64(-0x1p-1074)));
644 try std.testing.expect(math.isNan(sqrt(-0x1p0)));657 try std.testing.expect(math.isNan(sqrt_f64(-0x1p0)));
645 try std.testing.expect(math.isNan(sqrt(-math.inf(f64))));658 try std.testing.expect(math.isNan(sqrt_f64(-math.inf(f64))));
646 // random arguments659 // random arguments
647 try std.testing.expectEqual(sqrt(0x1.27D3510D4789Bp471), 0x1.852E97E58CFB7p235);660 try std.testing.expectEqual(sqrt_f64(0x1.27D3510D4789Bp471), 0x1.852E97E58CFB7p235);
648 try std.testing.expectEqual(sqrt(0x1.8C4FCD5A07846p791), 0x1.C27504E56D938p395);661 try std.testing.expectEqual(sqrt_f64(0x1.8C4FCD5A07846p791), 0x1.C27504E56D938p395);
649 try std.testing.expectEqual(sqrt(0x1.B1B69324F96E7p-137), 0x1.D73BD0414D8BFp-69);662 try std.testing.expectEqual(sqrt_f64(0x1.B1B69324F96E7p-137), 0x1.D73BD0414D8BFp-69);
650 try std.testing.expectEqual(sqrt(0x1.1CBD179A811FEp278), 0x1.0DFCB9A114A61p139);663 try std.testing.expectEqual(sqrt_f64(0x1.1CBD179A811FEp278), 0x1.0DFCB9A114A61p139);
651 try std.testing.expectEqual(sqrt(0x1.1D0C7EFB04A56p917), 0x1.7E0708A25DDCDp458);664 try std.testing.expectEqual(sqrt_f64(0x1.1D0C7EFB04A56p917), 0x1.7E0708A25DDCDp458);
652 try std.testing.expectEqual(sqrt(0x1.21B355DA8C94Bp-249), 0x1.8121CBE2608E3p-125);665 try std.testing.expectEqual(sqrt_f64(0x1.21B355DA8C94Bp-249), 0x1.8121CBE2608E3p-125);
653 try std.testing.expectEqual(sqrt(0x1.63024D4C5E987p487), 0x1.AA56AEA589DCDp243);666 try std.testing.expectEqual(sqrt_f64(0x1.63024D4C5E987p487), 0x1.AA56AEA589DCDp243);
654 try std.testing.expectEqual(sqrt(0x1.45AC3BE941F6Ep339), 0x1.9857F3F453E2Dp169);667 try std.testing.expectEqual(sqrt_f64(0x1.45AC3BE941F6Ep339), 0x1.9857F3F453E2Dp169);
655 try std.testing.expectEqual(sqrt(0x1.3B719C733AA24p267), 0x1.91E12E3AC8F71p133);668 try std.testing.expectEqual(sqrt_f64(0x1.3B719C733AA24p267), 0x1.91E12E3AC8F71p133);
656 try std.testing.expectEqual(sqrt(0x1.0B150433A2275p357), 0x1.71CAB87F8277Cp178);669 try std.testing.expectEqual(sqrt_f64(0x1.0B150433A2275p357), 0x1.71CAB87F8277Cp178);
657}670}
658671
659test "__sqrtx" {672test "__sqrtx" {
660 // sqrt(±0) is ±0673 // sqrt(±0) is ±0
661 try std.testing.expectEqual(__sqrtx(0x0.0p0), 0x0.0p0);674 try std.testing.expectEqual(sqrt_f80(0x0.0p0), 0x0.0p0);
662 try std.testing.expectEqual(__sqrtx(-0x0.0p0), -0x0.0p0);675 try std.testing.expectEqual(sqrt_f80(-0x0.0p0), -0x0.0p0);
663 // sqrt(+max) is finite676 // 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);
665 // sqrt(4)=2678 // sqrt(4)=2
666 try std.testing.expectEqual(__sqrtx(0x1p2), 0x1p1);679 try std.testing.expectEqual(sqrt_f80(0x1p2), 0x1p1);
667 // sqrt(x) for x=1, 1±ulp680 // sqrt(x) for x=1, 1±ulp
668 try std.testing.expectEqual(__sqrtx(0x1p0), 0x1p0);681 try std.testing.expectEqual(sqrt_f80(0x1p0), 0x1p0);
669 try std.testing.expectEqual(__sqrtx(0x1p0 + math.floatEps(f80)), 0x1p0);682 try std.testing.expectEqual(sqrt_f80(0x1p0 + math.floatEps(f80)), 0x1p0);
670 try std.testing.expectEqual(__sqrtx(0x1p0 - math.floatEps(f80)), 0x1.FFFFFFFFFFFFFFFEp-1);683 try std.testing.expectEqual(sqrt_f80(0x1p0 - math.floatEps(f80)), 0x1.FFFFFFFFFFFFFFFEp-1);
671 // sqrt(+min) is non-zero684 // 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);
673 // sqrt(min subnormal) is non-zero686 // 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);
675 // sqrt(inf) is inf688 // 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))));
677 // sqrt(nan) is nan690 // 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))));
679 // sqrt(-ve) is nan692 // sqrt(-ve) is nan
680 try std.testing.expect(math.isNan(__sqrtx(-0x1p-16442)));693 try std.testing.expect(math.isNan(sqrt_f80(-0x1p-16442)));
681 try std.testing.expect(math.isNan(__sqrtx(-0x1p0)));694 try std.testing.expect(math.isNan(sqrt_f80(-0x1p0)));
682 try std.testing.expect(math.isNan(__sqrtx(-math.inf(f80))));695 try std.testing.expect(math.isNan(sqrt_f80(-math.inf(f80))));
683 // random arguments696 // random arguments
684 try std.testing.expectEqual(__sqrtx(0x1.087F3953486918A4p15482), 0x1.0436BBE03D02F32p7741);697 try std.testing.expectEqual(sqrt_f80(0x1.087F3953486918A4p15482), 0x1.0436BBE03D02F32p7741);
685 try std.testing.expectEqual(__sqrtx(0x1.530CF9E2AE84D8Fp-6330), 0x1.269CFEF51933BE58p-3165);698 try std.testing.expectEqual(sqrt_f80(0x1.530CF9E2AE84D8Fp-6330), 0x1.269CFEF51933BE58p-3165);
686 try std.testing.expectEqual(__sqrtx(0x1.3F971515EADD574Ap5713), 0x1.9483232AB780B006p2856);699 try std.testing.expectEqual(sqrt_f80(0x1.3F971515EADD574Ap5713), 0x1.9483232AB780B006p2856);
687 try std.testing.expectEqual(__sqrtx(0x1.4CC0DC7379222954p864), 0x1.23DD4D0A4758C2Cp432);700 try std.testing.expectEqual(sqrt_f80(0x1.4CC0DC7379222954p864), 0x1.23DD4D0A4758C2Cp432);
688 try std.testing.expectEqual(__sqrtx(0x1.920E5649559A839Ep-3181), 0x1.C5B5BC0F98DD83D2p-1591);701 try std.testing.expectEqual(sqrt_f80(0x1.920E5649559A839Ep-3181), 0x1.C5B5BC0F98DD83D2p-1591);
689 try std.testing.expectEqual(__sqrtx(0x1.2E59726F87CD1746p-629), 0x1.8973327E95CB350Cp-315);702 try std.testing.expectEqual(sqrt_f80(0x1.2E59726F87CD1746p-629), 0x1.8973327E95CB350Cp-315);
690 try std.testing.expectEqual(__sqrtx(0x1.D3A16391F57B4D64p-9034), 0x1.59FF08B7DEEF5DB2p-4517);703 try std.testing.expectEqual(sqrt_f80(0x1.D3A16391F57B4D64p-9034), 0x1.59FF08B7DEEF5DB2p-4517);
691 try std.testing.expectEqual(__sqrtx(0x1.E7053D8DAA49BCEEp-11411), 0x1.F35AA3EA5E18E344p-5706);704 try std.testing.expectEqual(sqrt_f80(0x1.E7053D8DAA49BCEEp-11411), 0x1.F35AA3EA5E18E344p-5706);
692 try std.testing.expectEqual(__sqrtx(0x1.797ED0B05DD4A984p7521), 0x1.B7A22E40C6A7867Ap3760);705 try std.testing.expectEqual(sqrt_f80(0x1.797ED0B05DD4A984p7521), 0x1.B7A22E40C6A7867Ap3760);
693 try std.testing.expectEqual(__sqrtx(0x1.FC50806445C7226Ap15371), 0x1.FE2766142653F5BEp7685);706 try std.testing.expectEqual(sqrt_f80(0x1.FC50806445C7226Ap15371), 0x1.FE2766142653F5BEp7685);
694}707}
695708
696test "sqrtq" {709test "sqrt_f128" {
697 // sqrt(±0) is ±0710 // sqrt(±0) is ±0
698 try std.testing.expectEqual(sqrtq(0x0.0p0), 0x0.0p0);711 try std.testing.expectEqual(sqrt_f128(0x0.0p0), 0x0.0p0);
699 try std.testing.expectEqual(sqrtq(-0x0.0p0), -0x0.0p0);712 try std.testing.expectEqual(sqrt_f128(-0x0.0p0), -0x0.0p0);
700 // sqrt(+max) is finite713 // 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);
702 // sqrt(4)=2715 // sqrt(4)=2
703 try std.testing.expectEqual(sqrtq(0x1p2), 0x1p1);716 try std.testing.expectEqual(sqrt_f128(0x1p2), 0x1p1);
704 // sqrt(x) for x=1, 1±ulp717 // sqrt(x) for x=1, 1±ulp
705 try std.testing.expectEqual(sqrtq(0x1p0), 0x1p0);718 try std.testing.expectEqual(sqrt_f128(0x1p0), 0x1p0);
706 try std.testing.expectEqual(sqrtq(0x1p0 + math.floatEps(f128)), 0x1p0);719 try std.testing.expectEqual(sqrt_f128(0x1p0 + math.floatEps(f128)), 0x1p0);
707 try std.testing.expectEqual(sqrtq(0x1p0 - math.floatEps(f128)), 0x1.FFFFFFFFFFFFFFFFFFFFFFFFFFFFp-1);720 try std.testing.expectEqual(sqrt_f128(0x1p0 - math.floatEps(f128)), 0x1.FFFFFFFFFFFFFFFFFFFFFFFFFFFFp-1);
708 // sqrt(+min) is non-zero721 // 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);
710 // sqrt(min subnormal) is non-zero723 // 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);
712 // sqrt(inf) is inf725 // 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))));
714 // sqrt(nan) is nan727 // 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))));
716 // sqrt(-ve) is nan729 // sqrt(-ve) is nan
717 try std.testing.expect(math.isNan(sqrtq(-0x1p-16442)));730 try std.testing.expect(math.isNan(sqrt_f128(-0x1p-16442)));
718 try std.testing.expect(math.isNan(sqrtq(-0x1p0)));731 try std.testing.expect(math.isNan(sqrt_f128(-0x1p0)));
719 try std.testing.expect(math.isNan(sqrtq(-math.inf(f128))));732 try std.testing.expect(math.isNan(sqrt_f128(-math.inf(f128))));
720 // random arguments733 // random arguments
721 try std.testing.expectEqual(sqrtq(0x1.B6942D29A331751600C9F3AF7E5Fp3363), 0x1.D9DE9AFEF0F2D25586A50CA39D4Dp1681);734 try std.testing.expectEqual(sqrt_f128(0x1.B6942D29A331751600C9F3AF7E5Fp3363), 0x1.D9DE9AFEF0F2D25586A50CA39D4Dp1681);
722 try std.testing.expectEqual(sqrtq(0x1.5E65C405F84D471A8070ADD7A42Dp11765), 0x1.A78F7F9452B4D9EC2403C81D9D42p5882);735 try std.testing.expectEqual(sqrt_f128(0x1.5E65C405F84D471A8070ADD7A42Dp11765), 0x1.A78F7F9452B4D9EC2403C81D9D42p5882);
723 try std.testing.expectEqual(sqrtq(0x1.B42334D68F8016D8AE6F5E22B044p-5624), 0x1.4E247A7F2FF2A325E9377BB09C8p-2812);736 try std.testing.expectEqual(sqrt_f128(0x1.B42334D68F8016D8AE6F5E22B044p-5624), 0x1.4E247A7F2FF2A325E9377BB09C8p-2812);
724 try std.testing.expectEqual(sqrtq(0x1.E61715047F80F2E0B9382B38E06Bp10062), 0x1.60C25D9DFDC0116B78EF5AFDE0E9p5031);737 try std.testing.expectEqual(sqrt_f128(0x1.E61715047F80F2E0B9382B38E06Bp10062), 0x1.60C25D9DFDC0116B78EF5AFDE0E9p5031);
725 try std.testing.expectEqual(sqrtq(0x1.2ED0B53B494CB55A7B04E653D40Ep-1026), 0x1.166CE78D658D2453D700B04C5748p-513);738 try std.testing.expectEqual(sqrt_f128(0x1.2ED0B53B494CB55A7B04E653D40Ep-1026), 0x1.166CE78D658D2453D700B04C5748p-513);
726 try std.testing.expectEqual(sqrtq(0x1.1BA756B9790E78A4E6F0B083AA89p1835), 0x1.7D1767EA3303DB7A46940033988p917);739 try std.testing.expectEqual(sqrt_f128(0x1.1BA756B9790E78A4E6F0B083AA89p1835), 0x1.7D1767EA3303DB7A46940033988p917);
727 try std.testing.expectEqual(sqrtq(0x1.5B6C574319C1120335C8E1609704p4512), 0x1.2A3A8A415BB1648C548FBA2A4182p2256);740 try std.testing.expectEqual(sqrt_f128(0x1.5B6C574319C1120335C8E1609704p4512), 0x1.2A3A8A415BB1648C548FBA2A4182p2256);
728 try std.testing.expectEqual(sqrtq(0x1.FF91E8CDEE1552A2B74E77B602Ep14953), 0x1.FFC8F171267D4FE75CBE7AB4D851p7476);741 try std.testing.expectEqual(sqrt_f128(0x1.FF91E8CDEE1552A2B74E77B602Ep14953), 0x1.FFC8F171267D4FE75CBE7AB4D851p7476);
729 try std.testing.expectEqual(sqrtq(0x1.9B1837CFC629A1B6B1BB97099E7Dp2892), 0x1.4468511B909EAF8641BD59105A6Bp1446);742 try std.testing.expectEqual(sqrt_f128(0x1.9B1837CFC629A1B6B1BB97099E7Dp2892), 0x1.4468511B909EAF8641BD59105A6Bp1446);
730 try std.testing.expectEqual(sqrtq(0x1.0E2115475E64A92340914E7F7B37p-13951), 0x1.73E536F82F414134012F55BA5368p-6976);743 try std.testing.expectEqual(sqrt_f128(0x1.0E2115475E64A92340914E7F7B37p-13951), 0x1.73E536F82F414134012F55BA5368p-6976);
731}744}
lib/compiler_rt/ssp.zig+2-2
...@@ -17,7 +17,7 @@ const compiler_rt = @import("../compiler_rt.zig");...@@ -17,7 +17,7 @@ const compiler_rt = @import("../compiler_rt.zig");
17const symbol = compiler_rt.symbol;17const symbol = compiler_rt.symbol;
18const builtin = @import("builtin");18const 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;
21extern fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, n: usize) callconv(.c) ?[*]u8;21extern fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, n: usize) callconv(.c) ?[*]u8;
22extern fn memmove(dest: ?[*]u8, src: ?[*]const u8, n: usize) callconv(.c) ?[*]u8;22extern 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...@@ -138,7 +138,7 @@ fn __memmove_chk(dest: ?[*]u8, src: ?[*]const u8, n: usize, dest_n: usize) callc
138 return memmove(dest, src, n);138 return memmove(dest, src, n);
139}139}
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 {
142 if (dest_n < n) __chk_fail();142 if (dest_n < n) __chk_fail();
143 return memset(dest, c, n);143 return memset(dest, c, n);
144}144}
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 @@...@@ -1,5 +1,6 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const testing = @import("std").testing;1const testing = @import("std").testing;
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
34
4comptime {5comptime {
5 symbol(&__subvdi3, "__subvdi3");6 symbol(&__subvdi3, "__subvdi3");
...@@ -9,7 +10,7 @@ pub fn __subvdi3(a: i64, b: i64) callconv(.c) i64 {...@@ -9,7 +10,7 @@ pub fn __subvdi3(a: i64, b: i64) callconv(.c) i64 {
9 const sum = a -% b;10 const sum = a -% b;
10 // Overflow occurred iff the operands have opposite signs, and the sign of the11 // Overflow occurred iff the operands have opposite signs, and the sign of the
11 // sum is the opposite of the lhs sign.12 // 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");
13 return sum;14 return sum;
14}15}
1516
lib/compiler_rt/subvsi3.zig+1-1
...@@ -10,7 +10,7 @@ pub fn __subvsi3(a: i32, b: i32) callconv(.c) i32 {...@@ -10,7 +10,7 @@ pub fn __subvsi3(a: i32, b: i32) callconv(.c) i32 {
10 const sum = a -% b;10 const sum = a -% b;
11 // Overflow occurred iff the operands have opposite signs, and the sign of the11 // Overflow occurred iff the operands have opposite signs, and the sign of the
12 // sum is the opposite of the lhs sign.12 // 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");
14 return sum;14 return sum;
15}15}
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;...@@ -21,26 +21,29 @@ const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l;
2121
22const arch = builtin.cpu.arch;22const arch = builtin.cpu.arch;
23const compiler_rt = @import("../compiler_rt.zig");23const compiler_rt = @import("../compiler_rt.zig");
24const symbol = @import("../compiler_rt.zig").symbol;24const symbol = compiler_rt.symbol;
2525
26comptime {26comptime {
27 symbol(&tanh, "__tanh");27 symbol(&__tanh, "__tanh");
28 symbol(&tanf, "tanf");28 symbol(&tanf, "tanf");
29 symbol(&tan, "tan");29 symbol(&tan, "tan");
30 symbol(&tanx, "__tanx");30 symbol(&__tanx, "__tanx");
31 if (compiler_rt.want_ppc_abi) {31 symbol(&tanq, "tanf128");
32 symbol(&tanq, "tanf128");
33 }
34 symbol(&tanq, "tanq");
35 symbol(&tanl, "tanl");32 symbol(&tanl, "tanl");
36}33}
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 {
39 // TODO: more efficient implementation39 // TODO: more efficient implementation
40 return @floatCast(tanf(x));40 return @floatCast(tan_f32(x));
41}41}
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 {
44 // Small multiples of pi/2 rounded to double precision.47 // Small multiples of pi/2 rounded to double precision.
45 const t1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D1848 const t1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18
46 const t2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D1849 const t2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18
...@@ -90,7 +93,10 @@ pub fn tanf(x: f32) callconv(.c) f32 {...@@ -90,7 +93,10 @@ pub fn tanf(x: f32) callconv(.c) f32 {
90 return kernel.tandf(y, n & 1 != 0);93 return kernel.tandf(y, n & 1 != 0);
91}94}
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 {
94 var ix = @as(u64, @bitCast(x)) >> 32;100 var ix = @as(u64, @bitCast(x)) >> 32;
95 ix &= 0x7fffffff;101 ix &= 0x7fffffff;
96102
...@@ -120,7 +126,10 @@ pub fn tan(x: f64) callconv(.c) f64 {...@@ -120,7 +126,10 @@ pub fn tan(x: f64) callconv(.c) f64 {
120 return kernel.tan(y[0], y[1], n & 1 != 0);126 return kernel.tan(y[0], y[1], n & 1 != 0);
121}127}
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 {
124 const se = ld.signExponent(x) & 0x7fff;133 const se = ld.signExponent(x) & 0x7fff;
125 if (se == 0x7fff) {134 if (se == 0x7fff) {
126 return x - x;135 return x - x;
...@@ -141,7 +150,10 @@ pub fn tanx(x: f80) callconv(.c) f80 {...@@ -141,7 +150,10 @@ pub fn tanx(x: f80) callconv(.c) f80 {
141 return kernel.tanx(y[0], y[1], n & 1);150 return kernel.tanx(y[0], y[1], n & 1);
142}151}
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 {
145 const se = ld.signExponent(x) & 0x7fff;157 const se = ld.signExponent(x) & 0x7fff;
146 if (se == 0x7fff) {158 if (se == 0x7fff) {
147 return x - x;159 return x - x;
...@@ -164,18 +176,21 @@ pub fn tanq(x: f128) callconv(.c) f128 {...@@ -164,18 +176,21 @@ pub fn tanq(x: f128) callconv(.c) f128 {
164176
165pub fn tanl(x: c_longdouble) callconv(.c) c_longdouble {177pub fn tanl(x: c_longdouble) callconv(.c) c_longdouble {
166 switch (@typeInfo(c_longdouble).float.bits) {178 switch (@typeInfo(c_longdouble).float.bits) {
167 64 => return tan(x),179 64 => return tan_f64(x),
168 80 => return tanx(x),180 80 => return tan_f80(x),
169 128 => return tanq(x),181 128 => return tan_f128(x),
170 else => @compileError("unreachable"),182 else => comptime unreachable,
171 }183 }
172}184}
173185
174fn testTanNormal(comptime T: type) !void {186fn testTanNormal(comptime T: type) !void {
175 const f = switch (T) {187 const f = switch (T) {
176 f32 => tanf,188 f16 => tan_f16,
177 f64 => tan,189 f32 => tan_f32,
178 else => @compileError("unimplemented"),190 f64 => tan_f64,
191 f80 => tan_f80,
192 f128 => tan_f128,
193 else => comptime unreachable,
179 };194 };
180 const epsilon = 0.00001;195 const epsilon = 0.00001;
181196
...@@ -189,11 +204,12 @@ fn testTanNormal(comptime T: type) !void {...@@ -189,11 +204,12 @@ fn testTanNormal(comptime T: type) !void {
189204
190fn testTanSpecial(comptime T: type) !void {205fn testTanSpecial(comptime T: type) !void {
191 const f = switch (T) {206 const f = switch (T) {
192 f32 => tanf,207 f16 => tan_f16,
193 f64 => tan,208 f32 => tan_f32,
194 f80 => tanx,209 f64 => tan_f64,
195 f128 => tanq,210 f80 => tan_f80,
196 else => @compileError("unimplemented"),211 f128 => tan_f128,
212 else => comptime unreachable,
197 };213 };
198214
199 try expect(math.isPositiveZero(f(0.0)));215 try expect(math.isPositiveZero(f(0.0)));
...@@ -214,23 +230,23 @@ test "tan64.normal" {...@@ -214,23 +230,23 @@ test "tan64.normal" {
214test "tan80.normal" {230test "tan80.normal" {
215 const epsilon = math.floatEps(f80);231 const epsilon = math.floatEps(f80);
216232
217 try expectApproxEqAbs(@as(f80, 0.0), tanx(0.0), epsilon);233 try expectApproxEqAbs(@as(f80, 0.0), tan_f80(0.0), epsilon);
218 try expectApproxEqAbs(@as(f80, 0.2027100355086724833213582716475345), tanx(0.2), epsilon);234 try expectApproxEqAbs(@as(f80, 0.2027100355086724833213582716475345), tan_f80(0.2), epsilon);
219 try expectApproxEqAbs(@as(f80, 1.2404217445497097995561220131857544), tanx(0.8923), epsilon);235 try expectApproxEqAbs(@as(f80, 1.2404217445497097995561220131857544), tan_f80(0.8923), epsilon);
220 try expectApproxEqAbs(@as(f80, 14.10141994717171938764), tanx(1.5), epsilon);236 try expectApproxEqAbs(@as(f80, 14.10141994717171938764), tan_f80(1.5), epsilon);
221 try expectApproxEqAbs(@as(f80, -0.25439607116885656232), tanx(37.45), epsilon);237 try expectApproxEqAbs(@as(f80, -0.25439607116885656232), tan_f80(37.45), epsilon);
222 try expectApproxEqAbs(@as(f80, 2.2858376251355320963), tanx(89.123), epsilon);238 try expectApproxEqAbs(@as(f80, 2.2858376251355320963), tan_f80(89.123), epsilon);
223}239}
224240
225test "tan128.normal" {241test "tan128.normal" {
226 const epsilon = math.floatEps(f128);242 const epsilon = math.floatEps(f128);
227243
228 try expectApproxEqAbs(@as(f128, 0.0), tanq(0.0), epsilon);244 try expectApproxEqAbs(@as(f128, 0.0), tan_f128(0.0), epsilon);
229 try expectApproxEqAbs(@as(f128, 0.2027100355086724833213582716475345), tanq(0.2), epsilon);245 try expectApproxEqAbs(@as(f128, 0.2027100355086724833213582716475345), tan_f128(0.2), epsilon);
230 try expectApproxEqAbs(@as(f128, 1.2404217445497097995561220131857544), tanq(0.8923), epsilon);246 try expectApproxEqAbs(@as(f128, 1.2404217445497097995561220131857544), tan_f128(0.8923), epsilon);
231 try expectApproxEqAbs(@as(f128, 14.101419947171719387646083651987755), tanq(1.5), epsilon);247 try expectApproxEqAbs(@as(f128, 14.101419947171719387646083651987755), tan_f128(1.5), epsilon);
232 try expectApproxEqAbs(@as(f128, -0.2543960711688565630469573224504774), tanq(37.45), epsilon);248 try expectApproxEqAbs(@as(f128, -0.2543960711688565630469573224504774), tan_f128(37.45), epsilon);
233 try expectApproxEqAbs(@as(f128, 2.2858376251355321074066028114094292), tanq(89.123), epsilon);249 try expectApproxEqAbs(@as(f128, 2.2858376251355321074066028114094292), tan_f128(89.123), epsilon);
234}250}
235251
236test "tan32.special" {252test "tan32.special" {
lib/compiler_rt/trunc.zig+77-47
...@@ -17,19 +17,22 @@ comptime {...@@ -17,19 +17,22 @@ comptime {
17 symbol(&truncf, "truncf");17 symbol(&truncf, "truncf");
18 symbol(&trunc, "trunc");18 symbol(&trunc, "trunc");
19 symbol(&__truncx, "__truncx");19 symbol(&__truncx, "__truncx");
20 if (compiler_rt.want_ppc_abi) {20 symbol(&truncq, "truncf128");
21 symbol(&truncq, "truncf128");
22 }
23 symbol(&truncq, "truncq");
24 symbol(&truncl, "truncl");21 symbol(&truncl, "truncl");
25}22}
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 {
28 // TODO: more efficient implementation28 // TODO: more efficient implementation
29 return @floatCast(truncf(x));29 return @floatCast(trunc_f32(x));
30}30}
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 {
33 const u: u32 = @bitCast(x);36 const u: u32 = @bitCast(x);
34 var e = @as(i32, @intCast(((u >> 23) & 0xFF))) - 0x7F + 9;37 var e = @as(i32, @intCast(((u >> 23) & 0xFF))) - 0x7F + 9;
35 var m: u32 = undefined;38 var m: u32 = undefined;
...@@ -50,7 +53,10 @@ pub fn truncf(x: f32) callconv(.c) f32 {...@@ -50,7 +53,10 @@ pub fn truncf(x: f32) callconv(.c) f32 {
50 }53 }
51}54}
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 {
54 const u: u64 = @bitCast(x);60 const u: u64 = @bitCast(x);
55 var e = @as(i32, @intCast(((u >> 52) & 0x7FF))) - 0x3FF + 12;61 var e = @as(i32, @intCast(((u >> 52) & 0x7FF))) - 0x3FF + 12;
56 var m: u64 = undefined;62 var m: u64 = undefined;
...@@ -71,12 +77,18 @@ pub fn trunc(x: f64) callconv(.c) f64 {...@@ -71,12 +77,18 @@ pub fn trunc(x: f64) callconv(.c) f64 {
71 }77 }
72}78}
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 {
75 // TODO: more efficient implementation84 // TODO: more efficient implementation
76 return @floatCast(truncq(x));85 return @floatCast(trunc_f128(x));
77}86}
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 {
80 const u: u128 = @bitCast(x);92 const u: u128 = @bitCast(x);
81 var e = @as(i32, @intCast(((u >> 112) & 0x7FFF))) - 0x3FFF + 16;93 var e = @as(i32, @intCast(((u >> 112) & 0x7FFF))) - 0x3FFF + 16;
82 var m: u128 = undefined;94 var m: u128 = undefined;
...@@ -99,51 +111,69 @@ pub fn truncq(x: f128) callconv(.c) f128 {...@@ -99,51 +111,69 @@ pub fn truncq(x: f128) callconv(.c) f128 {
99111
100pub fn truncl(x: c_longdouble) callconv(.c) c_longdouble {112pub fn truncl(x: c_longdouble) callconv(.c) c_longdouble {
101 switch (@typeInfo(c_longdouble).float.bits) {113 switch (@typeInfo(c_longdouble).float.bits) {
102 64 => return trunc(x),114 64 => return trunc_f64(x),
103 80 => return __truncx(x),115 80 => return trunc_f80(x),
104 128 => return truncq(x),116 128 => return trunc_f128(x),
105 else => @compileError("unreachable"),117 else => comptime unreachable,
106 }118 }
107}119}
108120
109test "trunc32" {121test trunc_f16 {
110 try expect(truncf(1.3) == 1.0);122 try expect(trunc_f16(1.3) == 1.0);
111 try expect(truncf(-1.3) == -1.0);123 try expect(trunc_f16(-1.3) == -1.0);
112 try expect(truncf(0.2) == 0.0);124 try expect(math.isPositiveZero(trunc_f16(0.2)));
113}125 try expect(math.isNegativeZero(trunc_f16(-0.2)));
114126 try expect(math.isPositiveZero(trunc_f16(0.0)));
115test "trunc64" {127 try expect(math.isNegativeZero(trunc_f16(-0.0)));
116 try expect(trunc(1.3) == 1.0);128 try expect(math.isPositiveInf(trunc_f16(math.inf(f32))));
117 try expect(trunc(-1.3) == -1.0);129 try expect(math.isNegativeInf(trunc_f16(-math.inf(f32))));
118 try expect(trunc(0.2) == 0.0);130 try expect(math.isNan(trunc_f16(math.nan(f32))));
119}131}
120132
121test "trunc128" {133test trunc_f32 {
122 try expect(truncq(1.3) == 1.0);134 try expect(trunc_f32(1.3) == 1.0);
123 try expect(truncq(-1.3) == -1.0);135 try expect(trunc_f32(-1.3) == -1.0);
124 try expect(truncq(0.2) == 0.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))));
125}143}
126144
127test "trunc32.special" {145test trunc_f64 {
128 try expect(truncf(0.0) == 0.0); // 0x3F800000146 try expect(trunc_f64(1.3) == 1.0);
129 try expect(truncf(-0.0) == -0.0);147 try expect(trunc_f64(-1.3) == -1.0);
130 try expect(math.isPositiveInf(truncf(math.inf(f32))));148 try expect(math.isPositiveZero(trunc_f64(0.2)));
131 try expect(math.isNegativeInf(truncf(-math.inf(f32))));149 try expect(math.isNegativeZero(trunc_f64(-0.2)));
132 try expect(math.isNan(truncf(math.nan(f32))));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))));
133}155}
134156
135test "trunc64.special" {157test trunc_f80 {
136 try expect(trunc(0.0) == 0.0);158 try expect(trunc_f80(1.3) == 1.0);
137 try expect(trunc(-0.0) == -0.0);159 try expect(trunc_f80(-1.3) == -1.0);
138 try expect(math.isPositiveInf(trunc(math.inf(f64))));160 try expect(math.isPositiveZero(trunc_f80(0.2)));
139 try expect(math.isNegativeInf(trunc(-math.inf(f64))));161 try expect(math.isNegativeZero(trunc_f80(-0.2)));
140 try expect(math.isNan(trunc(math.nan(f64))));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))));
141}167}
142168
143test "trunc128.special" {169test trunc_f128 {
144 try expect(truncq(0.0) == 0.0);170 try expect(trunc_f128(1.3) == 1.0);
145 try expect(truncq(-0.0) == -0.0);171 try expect(trunc_f128(-1.3) == -1.0);
146 try expect(math.isPositiveInf(truncq(math.inf(f128))));172 try expect(math.isPositiveZero(trunc_f128(0.2)));
147 try expect(math.isNegativeInf(truncq(-math.inf(f128))));173 try expect(math.isNegativeZero(trunc_f128(-0.2)));
148 try expect(math.isNan(truncq(math.nan(f128))));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))));
149}179}
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 @@...@@ -1,6 +1,204 @@
1const std = @import("std");1const 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 {
4 const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits);202 const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits);
5 const dst_rep_t = @Int(.unsigned, @typeInfo(dst_t).float.bits);203 const dst_rep_t = @Int(.unsigned, @typeInfo(dst_t).float.bits);
6 const srcSigBits = std.math.floatMantissaBits(src_t);204 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...@@ -99,7 +297,7 @@ pub inline fn truncf(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t
99 return @bitCast(result);297 return @bitCast(result);
100}298}
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 {
103 const dst_rep_t = @Int(.unsigned, @typeInfo(dst_t).float.bits);301 const dst_rep_t = @Int(.unsigned, @typeInfo(dst_t).float.bits);
104 const src_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit302 const src_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit
105 const dst_sig_bits = std.math.floatMantissaBits(dst_t);303 const dst_sig_bits = std.math.floatMantissaBits(dst_t);
lib/compiler_rt/truncf_test.zig+160-174
...@@ -1,79 +1,82 @@...@@ -1,79 +1,82 @@
1const std = @import("std");1const std = @import("std");
2const testing = std.testing;2const testing = std.testing;
33
4const __truncsfhf2 = @import("truncsfhf2.zig").__truncsfhf2;4const impl = @import("truncf.zig");
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 }
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);
20}23}
2124
22test "truncsfhf2" {25test f16_floatCast_f32 {
23 try test__truncsfhf2(0x7fc00000, 0x7e00); // qNaN26 try test_f16_floatCast_f32(0x7fc00000, 0x7e00); // qNaN
24 try test__truncsfhf2(0x7fe00000, 0x7f00); // sNaN27 try test_f16_floatCast_f32(0x7fe00000, 0x7f00); // sNaN
2528
26 try test__truncsfhf2(0, 0); // 029 try test_f16_floatCast_f32(0, 0); // 0
27 try test__truncsfhf2(0x80000000, 0x8000); // -030 try test_f16_floatCast_f32(0x80000000, 0x8000); // -0
2831
29 try test__truncsfhf2(0x7f800000, 0x7c00); // inf32 try test_f16_floatCast_f32(0x7f800000, 0x7c00); // inf
30 try test__truncsfhf2(0xff800000, 0xfc00); // -inf33 try test_f16_floatCast_f32(0xff800000, 0xfc00); // -inf
3134
32 try test__truncsfhf2(0x477ff000, 0x7c00); // 65520 -> inf35 try test_f16_floatCast_f32(0x477ff000, 0x7c00); // 65520 -> inf
33 try test__truncsfhf2(0xc77ff000, 0xfc00); // -65520 -> -inf36 try test_f16_floatCast_f32(0xc77ff000, 0xfc00); // -65520 -> -inf
3437
35 try test__truncsfhf2(0x71cc3892, 0x7c00); // 0x1.987124876876324p+100 -> inf38 try test_f16_floatCast_f32(0x71cc3892, 0x7c00); // 0x1.987124876876324p+100 -> inf
36 try test__truncsfhf2(0xf1cc3892, 0xfc00); // -0x1.987124876876324p+100 -> -inf39 try test_f16_floatCast_f32(0xf1cc3892, 0xfc00); // -0x1.987124876876324p+100 -> -inf
3740
38 try test__truncsfhf2(0x38800000, 0x0400); // normal (min), 2**-1441 try test_f16_floatCast_f32(0x38800000, 0x0400); // normal (min), 2**-14
39 try test__truncsfhf2(0xb8800000, 0x8400); // normal (min), -2**-1442 try test_f16_floatCast_f32(0xb8800000, 0x8400); // normal (min), -2**-14
4043
41 try test__truncsfhf2(0x477fe000, 0x7bff); // normal (max), 6550444 try test_f16_floatCast_f32(0x477fe000, 0x7bff); // normal (max), 65504
42 try test__truncsfhf2(0xc77fe000, 0xfbff); // normal (max), -6550445 try test_f16_floatCast_f32(0xc77fe000, 0xfbff); // normal (max), -65504
4346
44 try test__truncsfhf2(0x477fe100, 0x7bff); // normal, 65505 -> 6550447 try test_f16_floatCast_f32(0x477fe100, 0x7bff); // normal, 65505 -> 65504
45 try test__truncsfhf2(0xc77fe100, 0xfbff); // normal, -65505 -> -6550448 try test_f16_floatCast_f32(0xc77fe100, 0xfbff); // normal, -65505 -> -65504
4649
47 try test__truncsfhf2(0x477fef00, 0x7bff); // normal, 65519 -> 6550450 try test_f16_floatCast_f32(0x477fef00, 0x7bff); // normal, 65519 -> 65504
48 try test__truncsfhf2(0xc77fef00, 0xfbff); // normal, -65519 -> -6550451 try test_f16_floatCast_f32(0xc77fef00, 0xfbff); // normal, -65519 -> -65504
4952
50 try test__truncsfhf2(0x3f802000, 0x3c01); // normal, 1 + 2**-1053 try test_f16_floatCast_f32(0x3f802000, 0x3c01); // normal, 1 + 2**-10
51 try test__truncsfhf2(0xbf802000, 0xbc01); // normal, -1 - 2**-1054 try test_f16_floatCast_f32(0xbf802000, 0xbc01); // normal, -1 - 2**-10
5255
53 try test__truncsfhf2(0x3eaaa000, 0x3555); // normal, approx. 1/356 try test_f16_floatCast_f32(0x3eaaa000, 0x3555); // normal, approx. 1/3
54 try test__truncsfhf2(0xbeaaa000, 0xb555); // normal, approx. -1/357 try test_f16_floatCast_f32(0xbeaaa000, 0xb555); // normal, approx. -1/3
5558
56 try test__truncsfhf2(0x40490fdb, 0x4248); // normal, 3.141592653559 try test_f16_floatCast_f32(0x40490fdb, 0x4248); // normal, 3.1415926535
57 try test__truncsfhf2(0xc0490fdb, 0xc248); // normal, -3.141592653560 try test_f16_floatCast_f32(0xc0490fdb, 0xc248); // normal, -3.1415926535
5861
59 try test__truncsfhf2(0x45cc3892, 0x6e62); // normal, 0x1.987124876876324p+1262 try test_f16_floatCast_f32(0x45cc3892, 0x6e62); // normal, 0x1.987124876876324p+12
6063
61 try test__truncsfhf2(0x3f800000, 0x3c00); // normal, 164 try test_f16_floatCast_f32(0x3f800000, 0x3c00); // normal, 1
62 try test__truncsfhf2(0x38800000, 0x0400); // normal, 0x1.0p-1465 try test_f16_floatCast_f32(0x38800000, 0x0400); // normal, 0x1.0p-14
6366
64 try test__truncsfhf2(0x33800000, 0x0001); // denormal (min), 2**-2467 try test_f16_floatCast_f32(0x33800000, 0x0001); // denormal (min), 2**-24
65 try test__truncsfhf2(0xb3800000, 0x8001); // denormal (min), -2**-2468 try test_f16_floatCast_f32(0xb3800000, 0x8001); // denormal (min), -2**-24
6669
67 try test__truncsfhf2(0x387fc000, 0x03ff); // denormal (max), 2**-14 - 2**-2470 try test_f16_floatCast_f32(0x387fc000, 0x03ff); // denormal (max), 2**-14 - 2**-24
68 try test__truncsfhf2(0xb87fc000, 0x83ff); // denormal (max), -2**-14 + 2**-2471 try test_f16_floatCast_f32(0xb87fc000, 0x83ff); // denormal (max), -2**-14 + 2**-24
6972
70 try test__truncsfhf2(0x35800000, 0x0010); // denormal, 0x1.0p-2073 try test_f16_floatCast_f32(0x35800000, 0x0010); // denormal, 0x1.0p-20
71 try test__truncsfhf2(0x33280000, 0x0001); // denormal, 0x1.5p-25 -> 0x1.0p-2474 try test_f16_floatCast_f32(0x33280000, 0x0001); // denormal, 0x1.5p-25 -> 0x1.0p-24
72 try test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero75 try test_f16_floatCast_f32(0x33000000, 0x0000); // 0x1.0p-25 -> zero
73}76}
7477
75fn test__truncdfhf2(a: f64, expected: u16) void {78fn test_f16_floatCast_f64(a: f64, expected: u16) !void {
76 const rep: u16 = @bitCast(__truncdfhf2(a));79 const rep: u16 = @bitCast(f16_floatCast_f64(a));
7780
78 if (rep == expected) {81 if (rep == expected) {
79 return;82 return;
...@@ -84,62 +87,56 @@ fn test__truncdfhf2(a: f64, expected: u16) void {...@@ -84,62 +87,56 @@ fn test__truncdfhf2(a: f64, expected: u16) void {
84 return;87 return;
85 }88 }
86 }89 }
8790 return error.TestFailure;
88 @panic("__truncdfhf2 test failure");
89}91}
9092
91fn test__truncdfhf2_raw(a: u64, expected: u16) void {93fn test_f16_floatCast_f64_raw(a: u64, expected: u16) !void {
92 const actual: u16 = @bitCast(__truncdfhf2(@bitCast(a)));94 const actual: u16 = @bitCast(f16_floatCast_f64(@bitCast(a)));
9395 try testing.expect(actual == expected);
94 if (actual == expected) {
95 return;
96 }
97
98 @panic("__truncdfhf2 test failure");
99}96}
10097
101test "truncdfhf2" {98test f16_floatCast_f64 {
102 test__truncdfhf2_raw(0x7ff8000000000000, 0x7e00); // qNaN99 try test_f16_floatCast_f64_raw(0x7ff8000000000000, 0x7e00); // qNaN
103 test__truncdfhf2_raw(0x7ff0000000008000, 0x7e00); // NaN100 try test_f16_floatCast_f64_raw(0x7ff0000000008000, 0x7e00); // NaN
104101
105 test__truncdfhf2_raw(0x7ff0000000000000, 0x7c00); //inf102 try test_f16_floatCast_f64_raw(0x7ff0000000000000, 0x7c00); //inf
106 test__truncdfhf2_raw(0xfff0000000000000, 0xfc00); // -inf103 try test_f16_floatCast_f64_raw(0xfff0000000000000, 0xfc00); // -inf
107104
108 test__truncdfhf2(0.0, 0x0); // zero105 try test_f16_floatCast_f64(0.0, 0x0); // zero
109 test__truncdfhf2_raw(0x80000000 << 32, 0x8000); // -zero106 try test_f16_floatCast_f64_raw(0x80000000 << 32, 0x8000); // -zero
110107
111 test__truncdfhf2(3.1415926535, 0x4248);108 try test_f16_floatCast_f64(3.1415926535, 0x4248);
112 test__truncdfhf2(-3.1415926535, 0xc248);109 try test_f16_floatCast_f64(-3.1415926535, 0xc248);
113110
114 test__truncdfhf2(0x1.987124876876324p+1000, 0x7c00);111 try test_f16_floatCast_f64(0x1.987124876876324p+1000, 0x7c00);
115 test__truncdfhf2(0x1.987124876876324p+12, 0x6e62);112 try test_f16_floatCast_f64(0x1.987124876876324p+12, 0x6e62);
116 test__truncdfhf2(0x1.0p+0, 0x3c00);113 try test_f16_floatCast_f64(0x1.0p+0, 0x3c00);
117 test__truncdfhf2(0x1.0p-14, 0x0400);114 try test_f16_floatCast_f64(0x1.0p-14, 0x0400);
118115
119 // denormal116 // denormal
120 test__truncdfhf2(0x1.0p-20, 0x0010);117 try test_f16_floatCast_f64(0x1.0p-20, 0x0010);
121 test__truncdfhf2(0x1.0p-24, 0x0001);118 try test_f16_floatCast_f64(0x1.0p-24, 0x0001);
122 test__truncdfhf2(-0x1.0p-24, 0x8001);119 try test_f16_floatCast_f64(-0x1.0p-24, 0x8001);
123 test__truncdfhf2(0x1.5p-25, 0x0001);120 try test_f16_floatCast_f64(0x1.5p-25, 0x0001);
124121
125 // and back to zero122 // and back to zero
126 test__truncdfhf2(0x1.0p-25, 0x0000);123 try test_f16_floatCast_f64(0x1.0p-25, 0x0000);
127 test__truncdfhf2(-0x1.0p-25, 0x8000);124 try test_f16_floatCast_f64(-0x1.0p-25, 0x8000);
128125
129 // max (precise)126 // max (precise)
130 test__truncdfhf2(65504.0, 0x7bff);127 try test_f16_floatCast_f64(65504.0, 0x7bff);
131128
132 // max (rounded)129 // max (rounded)
133 test__truncdfhf2(65519.0, 0x7bff);130 try test_f16_floatCast_f64(65519.0, 0x7bff);
134131
135 // max (to +inf)132 // max (to +inf)
136 test__truncdfhf2(65520.0, 0x7c00);133 try test_f16_floatCast_f64(65520.0, 0x7c00);
137 test__truncdfhf2(-65520.0, 0xfc00);134 try test_f16_floatCast_f64(-65520.0, 0xfc00);
138 test__truncdfhf2(65536.0, 0x7c00);135 try test_f16_floatCast_f64(65536.0, 0x7c00);
139}136}
140137
141fn test__trunctfsf2(a: f128, expected: u32) void {138fn test_f32_floatCast_f128(a: f128, expected: u32) !void {
142 const x = __trunctfsf2(a);139 const x = f32_floatCast_f128(a);
143140
144 const rep: u32 = @bitCast(x);141 const rep: u32 = @bitCast(x);
145 if (rep == expected) {142 if (rep == expected) {
...@@ -151,28 +148,27 @@ fn test__trunctfsf2(a: f128, expected: u32) void {...@@ -151,28 +148,27 @@ fn test__trunctfsf2(a: f128, expected: u32) void {
151 return;148 return;
152 }149 }
153 }150 }
154151 return error.TestFailure;
155 @panic("__trunctfsf2 test failure");
156}152}
157153
158test "trunctfsf2" {154test f32_floatCast_f128 {
159 // qnan155 // qnan
160 test__trunctfsf2(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7fc00000);156 try test_f32_floatCast_f128(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7fc00000);
161 // nan157 // 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);
163 // inf159 // inf
164 test__trunctfsf2(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7f800000);160 try test_f32_floatCast_f128(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7f800000);
165 // zero161 // zero
166 test__trunctfsf2(0.0, 0x0);162 try test_f32_floatCast_f128(0.0, 0x0);
167163
168 test__trunctfsf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x4211d156);164 try test_f32_floatCast_f128(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x4211d156);
169 test__trunctfsf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x3b71e9e2);165 try test_f32_floatCast_f128(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x3b71e9e2);
170 test__trunctfsf2(0x1.234eebb5faa678f4488693abcdefp+4534, 0x7f800000);166 try test_f32_floatCast_f128(0x1.234eebb5faa678f4488693abcdefp+4534, 0x7f800000);
171 test__trunctfsf2(0x1.edcba9bb8c76a5a43dd21f334634p-435, 0x0);167 try test_f32_floatCast_f128(0x1.edcba9bb8c76a5a43dd21f334634p-435, 0x0);
172}168}
173169
174fn test__trunctfdf2(a: f128, expected: u64) void {170fn test_f64_floatCast_f128(a: f128, expected: u64) !void {
175 const x = __trunctfdf2(a);171 const x = f64_floatCast_f128(a);
176172
177 const rep: u64 = @bitCast(x);173 const rep: u64 = @bitCast(x);
178 if (rep == expected) {174 if (rep == expected) {
...@@ -184,28 +180,27 @@ fn test__trunctfdf2(a: f128, expected: u64) void {...@@ -184,28 +180,27 @@ fn test__trunctfdf2(a: f128, expected: u64) void {
184 return;180 return;
185 }181 }
186 }182 }
187183 return error.TestFailure;
188 @panic("__trunctfsf2 test failure");
189}184}
190185
191test "trunctfdf2" {186test f64_floatCast_f128 {
192 // qnan187 // qnan
193 test__trunctfdf2(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7ff8000000000000);188 try test_f64_floatCast_f128(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7ff8000000000000);
194 // nan189 // 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);
196 // inf191 // inf
197 test__trunctfdf2(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7ff0000000000000);192 try test_f64_floatCast_f128(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7ff0000000000000);
198 // zero193 // zero
199 test__trunctfdf2(0.0, 0x0);194 try test_f64_floatCast_f128(0.0, 0x0);
200195
201 test__trunctfdf2(0x1.af23456789bbaaab347645365cdep+5, 0x404af23456789bbb);196 try test_f64_floatCast_f128(0x1.af23456789bbaaab347645365cdep+5, 0x404af23456789bbb);
202 test__trunctfdf2(0x1.dedafcff354b6ae9758763545432p-9, 0x3f6dedafcff354b7);197 try test_f64_floatCast_f128(0x1.dedafcff354b6ae9758763545432p-9, 0x3f6dedafcff354b7);
203 test__trunctfdf2(0x1.2f34dd5f437e849b4baab754cdefp+4534, 0x7ff0000000000000);198 try test_f64_floatCast_f128(0x1.2f34dd5f437e849b4baab754cdefp+4534, 0x7ff0000000000000);
204 test__trunctfdf2(0x1.edcbff8ad76ab5bf46463233214fp-435, 0x24cedcbff8ad76ab);199 try test_f64_floatCast_f128(0x1.edcbff8ad76ab5bf46463233214fp-435, 0x24cedcbff8ad76ab);
205}200}
206201
207fn test__truncdfsf2(a: f64, expected: u32) void {202fn test_f32_floatCast_f64(a: f64, expected: u32) !void {
208 const x = __truncdfsf2(a);203 const x = f32_floatCast_f64(a);
209204
210 const rep: u32 = @bitCast(x);205 const rep: u32 = @bitCast(x);
211 if (rep == expected) {206 if (rep == expected) {
...@@ -217,90 +212,81 @@ fn test__truncdfsf2(a: f64, expected: u32) void {...@@ -217,90 +212,81 @@ fn test__truncdfsf2(a: f64, expected: u32) void {
217 return;212 return;
218 }213 }
219 }214 }
220215 return error.TestFailure;
221 std.debug.print("got 0x{x} wanted 0x{x}\n", .{ rep, expected });
222
223 @panic("__trunctfsf2 test failure");
224}216}
225217
226test "truncdfsf2" {218test f32_floatCast_f64 {
227 // nan & qnan219 // nan & qnan
228 test__truncdfsf2(@bitCast(@as(u64, 0x7ff8000000000000)), 0x7fc00000);220 try test_f32_floatCast_f64(@bitCast(@as(u64, 0x7ff8000000000000)), 0x7fc00000);
229 test__truncdfsf2(@bitCast(@as(u64, 0x7ff0000000000001)), 0x7fc00000);221 try test_f32_floatCast_f64(@bitCast(@as(u64, 0x7ff0000000000001)), 0x7fc00000);
230 // inf222 // inf
231 test__truncdfsf2(@bitCast(@as(u64, 0x7ff0000000000000)), 0x7f800000);223 try test_f32_floatCast_f64(@bitCast(@as(u64, 0x7ff0000000000000)), 0x7f800000);
232 test__truncdfsf2(@bitCast(@as(u64, 0xfff0000000000000)), 0xff800000);224 try test_f32_floatCast_f64(@bitCast(@as(u64, 0xfff0000000000000)), 0xff800000);
233225
234 test__truncdfsf2(0.0, 0x0);226 try test_f32_floatCast_f64(0.0, 0x0);
235 test__truncdfsf2(1.0, 0x3f800000);227 try test_f32_floatCast_f64(1.0, 0x3f800000);
236 test__truncdfsf2(-1.0, 0xbf800000);228 try test_f32_floatCast_f64(-1.0, 0xbf800000);
237229
238 // huge number becomes inf230 // huge number becomes inf
239 test__truncdfsf2(340282366920938463463374607431768211456.0, 0x7f800000);231 try test_f32_floatCast_f64(340282366920938463463374607431768211456.0, 0x7f800000);
240}232}
241233
242fn test__trunctfhf2(a: f128, expected: u16) void {234fn test_f16_floatCast_f128(a: f128, expected: u16) !void {
243 const x = __trunctfhf2(a);235 const x = f16_floatCast_f128(a);
244236
245 const rep: u16 = @bitCast(x);237 const rep: u16 = @bitCast(x);
246 if (rep == expected) {238 try testing.expect(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");
253}239}
254240
255test "trunctfhf2" {241test f16_floatCast_f128 {
256 // qNaN242 // qNaN
257 test__trunctfhf2(@bitCast(@as(u128, 0x7fff8000000000000000000000000000)), 0x7e00);243 try test_f16_floatCast_f128(@bitCast(@as(u128, 0x7fff8000000000000000000000000000)), 0x7e00);
258 // NaN244 // NaN
259 test__trunctfhf2(@bitCast(@as(u128, 0x7fff0000000000000000000000000001)), 0x7e00);245 try test_f16_floatCast_f128(@bitCast(@as(u128, 0x7fff0000000000000000000000000001)), 0x7e00);
260 // inf246 // inf
261 test__trunctfhf2(@bitCast(@as(u128, 0x7fff0000000000000000000000000000)), 0x7c00);247 try test_f16_floatCast_f128(@bitCast(@as(u128, 0x7fff0000000000000000000000000000)), 0x7c00);
262 test__trunctfhf2(-@as(f128, @bitCast(@as(u128, 0x7fff0000000000000000000000000000))), 0xfc00);248 try test_f16_floatCast_f128(-@as(f128, @bitCast(@as(u128, 0x7fff0000000000000000000000000000))), 0xfc00);
263 // zero249 // zero
264 test__trunctfhf2(0.0, 0x0);250 try test_f16_floatCast_f128(0.0, 0x0);
265 test__trunctfhf2(-0.0, 0x8000);251 try test_f16_floatCast_f128(-0.0, 0x8000);
266252
267 test__trunctfhf2(3.1415926535, 0x4248);253 try test_f16_floatCast_f128(3.1415926535, 0x4248);
268 test__trunctfhf2(-3.1415926535, 0xc248);254 try test_f16_floatCast_f128(-3.1415926535, 0xc248);
269 test__trunctfhf2(0x1.987124876876324p+100, 0x7c00);255 try test_f16_floatCast_f128(0x1.987124876876324p+100, 0x7c00);
270 test__trunctfhf2(0x1.987124876876324p+12, 0x6e62);256 try test_f16_floatCast_f128(0x1.987124876876324p+12, 0x6e62);
271 test__trunctfhf2(0x1.0p+0, 0x3c00);257 try test_f16_floatCast_f128(0x1.0p+0, 0x3c00);
272 test__trunctfhf2(0x1.0p-14, 0x0400);258 try test_f16_floatCast_f128(0x1.0p-14, 0x0400);
273 // denormal259 // denormal
274 test__trunctfhf2(0x1.0p-20, 0x0010);260 try test_f16_floatCast_f128(0x1.0p-20, 0x0010);
275 test__trunctfhf2(0x1.0p-24, 0x0001);261 try test_f16_floatCast_f128(0x1.0p-24, 0x0001);
276 test__trunctfhf2(-0x1.0p-24, 0x8001);262 try test_f16_floatCast_f128(-0x1.0p-24, 0x8001);
277 test__trunctfhf2(0x1.5p-25, 0x0001);263 try test_f16_floatCast_f128(0x1.5p-25, 0x0001);
278 // and back to zero264 // and back to zero
279 test__trunctfhf2(0x1.0p-25, 0x0000);265 try test_f16_floatCast_f128(0x1.0p-25, 0x0000);
280 test__trunctfhf2(-0x1.0p-25, 0x8000);266 try test_f16_floatCast_f128(-0x1.0p-25, 0x8000);
281 // max (precise)267 // max (precise)
282 test__trunctfhf2(65504.0, 0x7bff);268 try test_f16_floatCast_f128(65504.0, 0x7bff);
283 // max (rounded)269 // max (rounded)
284 test__trunctfhf2(65519.0, 0x7bff);270 try test_f16_floatCast_f128(65519.0, 0x7bff);
285 // max (to +inf)271 // max (to +inf)
286 test__trunctfhf2(65520.0, 0x7c00);272 try test_f16_floatCast_f128(65520.0, 0x7c00);
287 test__trunctfhf2(65536.0, 0x7c00);273 try test_f16_floatCast_f128(65536.0, 0x7c00);
288 test__trunctfhf2(-65520.0, 0xfc00);274 try test_f16_floatCast_f128(-65520.0, 0xfc00);
289275
290 test__trunctfhf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x508f);276 try test_f16_floatCast_f128(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x508f);
291 test__trunctfhf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x1b8f);277 try test_f16_floatCast_f128(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x1b8f);
292 test__trunctfhf2(0x1.234eebb5faa678f4488693abcdefp+453, 0x7c00);278 try test_f16_floatCast_f128(0x1.234eebb5faa678f4488693abcdefp+453, 0x7c00);
293 test__trunctfhf2(0x1.edcba9bb8c76a5a43dd21f334634p-43, 0x0);279 try test_f16_floatCast_f128(0x1.edcba9bb8c76a5a43dd21f334634p-43, 0x0);
294}280}
295281
296test "trunctfxf2" {282fn test_f80_floatCast_f128(a: f128, expected: f80) !void {
297 try test__trunctfxf2(1.5, 1.5);283 const x = f80_floatCast_f128(a);
298 try test__trunctfxf2(2.5, 2.5);284 try testing.expect(x == expected);
299 try test__trunctfxf2(-2.5, -2.5);
300 try test__trunctfxf2(0.0, 0.0);
301}285}
302286
303fn test__trunctfxf2(a: f128, expected: f80) !void {287test f80_floatCast_f128 {
304 const x = __trunctfxf2(a);288 try test_f80_floatCast_f128(1.5, 1.5);
305 try testing.expect(x == expected);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);
306}292}
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;...@@ -6,7 +6,7 @@ const shr = std.math.shr;
6const shl = std.math.shl;6const shl = std.math.shl;
77
8const compiler_rt = @import("../compiler_rt.zig");8const compiler_rt = @import("../compiler_rt.zig");
9const symbol = @import("../compiler_rt.zig").symbol;9const symbol = compiler_rt.symbol;
1010
11const max_limbs = @divCeil(65535, 32); // max supported type is u6553511const 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(...@@ -62,7 +62,7 @@ pub fn fileSourceHtml(
62 var cursor: usize = ast.tokenStart(start_token);62 var cursor: usize = ast.tokenStart(start_token);
6363
64 var indent: usize = 0;64 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| {
66 for (ast.source[newline_index + 1 .. cursor]) |c| {66 for (ast.source[newline_index + 1 .. cursor]) |c| {
67 if (c == ' ') {67 if (c == ' ') {
68 indent += 1;68 indent += 1;
lib/docs/wasm/main.zig+3-3
...@@ -153,11 +153,11 @@ fn query_exec_fallible(query: []const u8, ignore_case: bool) !void {...@@ -153,11 +153,11 @@ fn query_exec_fallible(query: []const u8, ignore_case: bool) !void {
153 continue;153 continue;
154 }154 }
155 // substring, case insensitive match of full decl path155 // 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) {
157 points += 2;157 points += 2;
158 continue;158 continue;
159 }159 }
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) {
161 points += 1;161 points += 1;
162 continue;162 continue;
163 }163 }
...@@ -803,7 +803,7 @@ fn unpackInner(tar_bytes: []u8) !void {...@@ -803,7 +803,7 @@ fn unpackInner(tar_bytes: []u8) !void {
803 if (std.mem.endsWith(u8, tar_file.name, ".zig")) {803 if (std.mem.endsWith(u8, tar_file.name, ".zig")) {
804 log.debug("found file: '{s}'", .{tar_file.name});804 log.debug("found file: '{s}'", .{tar_file.name});
805 const file_name = try gpa.dupe(u8, tar_file.name);805 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| {
807 const pkg_name = file_name[0..pkg_name_end];807 const pkg_name = file_name[0..pkg_name_end];
808 const gop = try Walk.modules.getOrPut(gpa, pkg_name);808 const gop = try Walk.modules.getOrPut(gpa, pkg_name);
809 const file: Walk.File.Index = @fromBackingInt(@intCast(Walk.files.entries.len));809 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 {...@@ -108,7 +108,7 @@ pub const Node = struct {
108 // In Debug and ReleaseSafe builds, there may be hidden extra fields108 // In Debug and ReleaseSafe builds, there may be hidden extra fields
109 // included for safety checks. Without such safety checks enabled,109 // included for safety checks. Without such safety checks enabled,
110 // we always want this union to be 8 bytes.110 // 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) {
112 assert(@sizeOf(Data) == 8);112 assert(@sizeOf(Data) == 8);
113 }113 }
114 }114 }
lib/docs/wasm/markdown/Parser.zig+21-21
...@@ -159,7 +159,7 @@ const Block = struct {...@@ -159,7 +159,7 @@ const Block = struct {
159 .heading => null,159 .heading => null,
160 .code_block => code_block: {160 .code_block => code_block: {
161 const trimmed = mem.trimEnd(u8, unindented, " \t");161 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) {
163 const effective_indent = @min(indent, b.data.code_block.indent);163 const effective_indent = @min(indent, b.data.code_block.indent);
164 break :code_block line[effective_indent..];164 break :code_block line[effective_indent..];
165 } else {165 } else {
...@@ -209,7 +209,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void {...@@ -209,7 +209,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void {
209 } else p.pending_blocks.items.len;209 } else p.pending_blocks.items.len;
210210
211 const in_code_block = p.pending_blocks.items.len > 0 and211 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;
213 const code_block_end = in_code_block and213 const code_block_end = in_code_block and
214 first_unmatched + 1 == p.pending_blocks.items.len;214 first_unmatched + 1 == p.pending_blocks.items.len;
215 // New blocks cannot be started if we are actively inside a code block or215 // 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 {...@@ -225,7 +225,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void {
225 if (maybe_block_start == null and225 if (maybe_block_start == null and
226 !isBlank(rest_line) and226 !isBlank(rest_line) and
227 p.pending_blocks.items.len > 0 and227 p.pending_blocks.items.len > 0 and
228 p.pending_blocks.getLast().?.tag == .paragraph)228 p.pending_blocks.last().?.tag == .paragraph)
229 {229 {
230 try p.addScratchStringLine(mem.trimStart(u8, rest_line, " \t"));230 try p.addScratchStringLine(mem.trimStart(u8, rest_line, " \t"));
231 return;231 return;
...@@ -236,7 +236,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void {...@@ -236,7 +236,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void {
236 // paragraphs.236 // paragraphs.
237 if (maybe_block_start != null and237 if (maybe_block_start != null and
238 p.pending_blocks.items.len > 0 and238 p.pending_blocks.items.len > 0 and
239 p.pending_blocks.getLast().?.tag == .paragraph)239 p.pending_blocks.last().?.tag == .paragraph)
240 {240 {
241 try p.closeLastBlock();241 try p.closeLastBlock();
242 }242 }
...@@ -259,7 +259,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void {...@@ -259,7 +259,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void {
259 // Do not append the end of a code block (```) as textual content.259 // Do not append the end of a code block (```) as textual content.
260 if (code_block_end) return;260 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|
263 last_pending_block.canAccept()263 last_pending_block.canAccept()
264 else264 else
265 .blocks;265 .blocks;
...@@ -273,7 +273,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void {...@@ -273,7 +273,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void {
273 // loose, since we might just be looking at a blank line after the273 // loose, since we might just be looking at a blank line after the
274 // end of the last item in the list. The final determination will be274 // end of the last item in the list. The final determination will be
275 // made when appending the next child of the list or list item.275 // 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)
277 p.pending_blocks.items.len - 2277 p.pending_blocks.items.len - 2
278 else278 else
279 null;279 null;
...@@ -368,7 +368,7 @@ const BlockStart = struct {...@@ -368,7 +368,7 @@ const BlockStart = struct {
368};368};
369369
370fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {370fn 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| {
372 // Close the last block if it is a list and the new block is not a list item372 // Close the last block if it is a list and the new block is not a list item
373 // or not of the same marker type.373 // or not of the same marker type.
374 const should_close_list = last_pending_block.tag == .list and374 const should_close_list = last_pending_block.tag == .list and
...@@ -383,7 +383,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {...@@ -383,7 +383,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {
383 }383 }
384 }384 }
385385
386 if (p.pending_blocks.getLast()) |last_pending_block| {386 if (p.pending_blocks.last()) |last_pending_block| {
387 // If the last block is a list or list item, check for tightness based387 // If the last block is a list or list item, check for tightness based
388 // on the last line.388 // on the last line.
389 const maybe_containing_list = switch (last_pending_block.tag) {389 const maybe_containing_list = switch (last_pending_block.tag) {
...@@ -401,7 +401,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {...@@ -401,7 +401,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {
401 // Start a new list if the new block is a list item and there is no401 // Start a new list if the new block is a list item and there is no
402 // containing list yet.402 // containing list yet.
403 if (block_start.tag == .list_item and403 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))
405 {405 {
406 try p.pending_blocks.append(p.allocator, .{406 try p.pending_blocks.append(p.allocator, .{
407 .tag = .list,407 .tag = .list,
...@@ -417,7 +417,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {...@@ -417,7 +417,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {
417417
418 if (block_start.tag == .table_row) {418 if (block_start.tag == .table_row) {
419 // Likewise, table rows start a table implicitly.419 // 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) {
421 try p.pending_blocks.append(p.allocator, .{421 try p.pending_blocks.append(p.allocator, .{
422 .tag = .table,422 .tag = .table,
423 .data = .{ .table = .{423 .data = .{ .table = .{
...@@ -429,7 +429,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {...@@ -429,7 +429,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {
429 });429 });
430 }430 }
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;
433 if (current_row <= 1) {433 if (current_row <= 1) {
434 var buffer: [max_table_columns]Node.TableCellAlignment = undefined;434 var buffer: [max_table_columns]Node.TableCellAlignment = undefined;
435 const table_row = &block_start.data.table_row;435 const table_row = &block_start.data.table_row;
...@@ -441,7 +441,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {...@@ -441,7 +441,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {
441 // We need to go back and mark the header row and its column441 // We need to go back and mark the header row and its column
442 // alignments.442 // alignments.
443 const datas = p.nodes.items(.data);443 const datas = p.nodes.items(.data);
444 const header_data = datas[p.scratch_extra.getLast().?];444 const header_data = datas[p.scratch_extra.last().?];
445 for (p.extraChildren(header_data.container.children), 0..) |header_cell, i| {445 for (p.extraChildren(header_data.container.children), 0..) |header_cell, i| {
446 const alignment = if (i < alignments.len) alignments[i] else .unset;446 const alignment = if (i < alignments.len) alignments[i] else .unset;
447 const cell_data = &datas[@backingInt(header_cell)].table_cell;447 const cell_data = &datas[@backingInt(header_cell)].table_cell;
...@@ -594,7 +594,7 @@ fn startListItem(unindented_line: []const u8) ?ListItemStart {...@@ -594,7 +594,7 @@ fn startListItem(unindented_line: []const u8) ?ListItemStart {
594 };594 };
595 }595 }
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;
598 const after_number = unindented_line[number_end..];598 const after_number = unindented_line[number_end..];
599 const marker: Block.Data.ListMarker = if (mem.startsWith(u8, after_number, ". "))599 const marker: Block.Data.ListMarker = if (mem.startsWith(u8, after_number, ". "))
600 .number_dot600 .number_dot
...@@ -639,10 +639,10 @@ fn startTableRow(unindented_line: []const u8) ?TableRowStart {...@@ -639,10 +639,10 @@ fn startTableRow(unindented_line: []const u8) ?TableRowStart {
639 // Ignoring pipes in code spans allows table cells to contain639 // Ignoring pipes in code spans allows table cells to contain
640 // code using ||, for example.640 // code using ||, for example.
641 const open_start = i;641 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;
643 const open_len = i - open_start;643 const open_len = i - open_start;
644 while (mem.indexOfScalarPos(u8, table_row_content, i, '`')) |close_start| {644 while (mem.findScalarPos(u8, table_row_content, i, '`')) |close_start| {
645 i = mem.indexOfNonePos(u8, table_row_content, close_start, "`") orelse return null;645 i = mem.findNonePos(u8, table_row_content, close_start, "`") orelse return null;
646 const close_len = i - close_start;646 const close_len = i - close_start;
647 if (close_len == open_len) break;647 if (close_len == open_len) break;
648 } else return null;648 } else return null;
...@@ -794,7 +794,7 @@ fn startCodeBlock(p: *Parser, unindented_line: []const u8) !?CodeBlockStart {...@@ -794,7 +794,7 @@ fn startCodeBlock(p: *Parser, unindented_line: []const u8) !?CodeBlockStart {
794 } else "";794 } else "";
795 // Code block tags may not contain backticks, since that would create795 // Code block tags may not contain backticks, since that would create
796 // potential confusion with inline code spans.796 // 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;
798 return .{798 return .{
799 .tag = try p.addString(mem.trim(u8, tag_bytes, " ")),799 .tag = try p.addString(mem.trim(u8, tag_bytes, " ")),
800 .fence_len = fence_len,800 .fence_len = fence_len,
...@@ -1382,12 +1382,12 @@ const InlineParser = struct {...@@ -1382,12 +1382,12 @@ const InlineParser = struct {
1382 /// parsing.1382 /// parsing.
1383 fn parseCodeSpan(ip: *InlineParser) !void {1383 fn parseCodeSpan(ip: *InlineParser) !void {
1384 const opener_start = ip.pos;1384 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;
1386 const opener_len = ip.pos - opener_start;1386 const opener_len = ip.pos - opener_start;
13871387
1388 const start = ip.pos;1388 const start = ip.pos;
1389 const end = while (mem.indexOfScalarPos(u8, ip.content, ip.pos, '`')) |closer_start| {1389 const end = while (mem.findScalarPos(u8, ip.content, ip.pos, '`')) |closer_start| {
1390 ip.pos = mem.indexOfNonePos(u8, ip.content, closer_start, "`") orelse ip.content.len;1390 ip.pos = mem.findNonePos(u8, ip.content, closer_start, "`") orelse ip.content.len;
1391 const closer_len = ip.pos - closer_start;1391 const closer_len = ip.pos - closer_start;
13921392
1393 if (closer_len == opener_len) break closer_start;1393 if (closer_len == opener_len) break closer_start;
...@@ -1627,7 +1627,7 @@ fn addScratchStringLine(p: *Parser, line: []const u8) !void {...@@ -1627,7 +1627,7 @@ fn addScratchStringLine(p: *Parser, line: []const u8) !void {
1627}1627}
16281628
1629fn isBlank(line: []const u8) bool {1629fn isBlank(line: []const u8) bool {
1630 return mem.indexOfNone(u8, line, " \t") == null;1630 return mem.findNone(u8, line, " \t") == null;
1631}1631}
16321632
1633fn isPunctuation(c: u8) bool {1633fn isPunctuation(c: u8) bool {
lib/fuzzer.zig+4-4
...@@ -41,8 +41,8 @@ fn logOverride(...@@ -41,8 +41,8 @@ fn logOverride(
4141
42var safe_allocator: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{});42var safe_allocator: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{});
43const gpa = switch (builtin.mode) {43const gpa = switch (builtin.mode) {
44 .Debug, .ReleaseSafe => safe_allocator.allocator(),44 .debug, .safe => safe_allocator.allocator(),
45 .ReleaseFast, .ReleaseSmall => std.heap.smp_allocator,45 .fast, .small => std.heap.smp_allocator,
46};46};
4747
48// Seperate from `exec` to allow initialization before `exec` is.48// Seperate from `exec` to allow initialization before `exec` is.
...@@ -1085,7 +1085,7 @@ const Fuzzer = struct {...@@ -1085,7 +1085,7 @@ const Fuzzer = struct {
1085 fn removeBest(f: *Fuzzer, i: Input.Index, best_i: u32) void {1085 fn removeBest(f: *Fuzzer, i: Input.Index, best_i: u32) void {
1086 const t = &f.tests[f.test_i];1086 const t = &f.tests[f.test_i];
1087 const ref = &t.corpus.items(.ref)[@backingInt(i)];1087 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).?;
1089 ref.best_i_len -= 1;1089 ref.best_i_len -= 1;
1090 ref.best_i_buf[list_i] = ref.best_i_buf[ref.best_i_len];1090 ref.best_i_buf[list_i] = ref.best_i_buf[ref.best_i_len];
10911091
...@@ -1209,7 +1209,7 @@ const Fuzzer = struct {...@@ -1209,7 +1209,7 @@ const Fuzzer = struct {
1209 f.req_bytes = @intCast(f.input_builder.bytes_table.items.len);1209 f.req_bytes = @intCast(f.input_builder.bytes_table.items.len);
1210 const quality: Input.Best.Quality = .{1210 const quality: Input.Best.Quality = .{
1211 .n_pcs = n_pcs: {1211 .n_pcs = n_pcs: {
1212 @setRuntimeSafety(builtin.mode == .Debug); // Necessary for vectorization1212 @setRuntimeSafety(builtin.mode == .debug); // Necessary for vectorization
1213 var n: u32 = 0;1213 var n: u32 = 0;
1214 for (exec.pc_counters) |c| {1214 for (exec.pc_counters) |c| {
1215 n += @intFromBool(c != 0);1215 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...@@ -798,7 +798,8 @@ typedef struct
798#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */798#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */
799#define NT_X86_SHSTK 0x204 /* x86 SHSTK state */799#define NT_X86_SHSTK 0x204 /* x86 SHSTK state */
800#define NT_X86_XSAVE_LAYOUT 0x205 /* XSAVE layout description. */800#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. */
802#define NT_S390_TIMER 0x301 /* s390 timer register */803#define NT_S390_TIMER 0x301 /* s390 timer register */
803#define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */804#define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */
804#define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */805#define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */
...@@ -846,6 +847,7 @@ typedef struct...@@ -846,6 +847,7 @@ typedef struct
846#define NT_RISCV_VECTOR 0x901 /* RISC-V vector registers */847#define NT_RISCV_VECTOR 0x901 /* RISC-V vector registers */
847#define NT_RISCV_TAGGED_ADDR_CTRL 0x902 /* RISC-V tagged848#define NT_RISCV_TAGGED_ADDR_CTRL 0x902 /* RISC-V tagged
848 address control */849 address control */
850#define NT_RISCV_USER_CFI 0x903 /* RISC-V shadow stack state */
849#define NT_LOONGARCH_CPUCFG 0xa00 /* LoongArch CPU config registers. */851#define NT_LOONGARCH_CPUCFG 0xa00 /* LoongArch CPU config registers. */
850#define NT_LOONGARCH_CSR 0xa01 /* LoongArch control and852#define NT_LOONGARCH_CSR 0xa01 /* LoongArch control and
851 status registers. */853 status registers. */
...@@ -3470,7 +3472,9 @@ enum...@@ -3470,7 +3472,9 @@ enum
34703472
3471/* Valid values for the e_flags field. */3473/* 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
3475/* Additional s390 relocs */3479/* Additional s390 relocs */
34763480
lib/libc/glibc/include/libc-symbols.h+2-1
...@@ -113,6 +113,7 @@...@@ -113,6 +113,7 @@
113#define HAVE_LIBINTL_H 1113#define HAVE_LIBINTL_H 1
114#define HAVE_WCTYPE_H 1114#define HAVE_WCTYPE_H 1
115#define HAVE_ISWCTYPE 1115#define HAVE_ISWCTYPE 1
116#define HAVE_MEMPCPY 1
116#define ENABLE_NLS 1117#define ENABLE_NLS 1
117118
118/* The symbols in all the user (non-_) macros are C symbols. */119/* The symbols in all the user (non-_) macros are C symbols. */
...@@ -682,7 +683,7 @@ for linking")...@@ -682,7 +683,7 @@ for linking")
682683
683/* Helper / base macros for indirect function symbols. */684/* Helper / base macros for indirect function symbols. */
684#define __ifunc_resolver(type_name, name, expr, init, classifier, ...) \685#define __ifunc_resolver(type_name, name, expr, init, classifier, ...) \
685 classifier inhibit_stack_protector \686 classifier \
686 __typeof (type_name) *name##_ifunc (__VA_ARGS__) \687 __typeof (type_name) *name##_ifunc (__VA_ARGS__) \
687 { \688 { \
688 init (); \689 init (); \
lib/libc/glibc/sysdeps/aarch64/sysdep.h+28-4
...@@ -43,7 +43,6 @@...@@ -43,7 +43,6 @@
43#define FEATURE_1_PAC 243#define FEATURE_1_PAC 2
44#define FEATURE_1_GCS 444#define FEATURE_1_GCS 4
4545
46/* Add a NT_GNU_PROPERTY_TYPE_0 note. */
47#define GNU_PROPERTY(type, value) \46#define GNU_PROPERTY(type, value) \
48 .section .note.gnu.property, "a"; \47 .section .note.gnu.property, "a"; \
49 .p2align 3; \48 .p2align 3; \
...@@ -57,9 +56,34 @@...@@ -57,9 +56,34 @@
57 .word 0; \56 .word 0; \
58 .text57 .text
5958
60/* Add GNU property note with the supported features to all asm code59#ifdef __ARM_BUILDATTR64_FV
61 where sysdep.h is included. */60/* Add AArch64 feature bits build attributes. */
62GNU_PROPERTY (FEATURE_1_AND, FEATURE_1_BTI|FEATURE_1_PAC|FEATURE_1_GCS)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
64/* Define an entry point visible from C. */88/* Define an entry point visible from C. */
65#define ENTRY(name) \89#define ENTRY(name) \
lib/libc/glibc/sysdeps/arm/start.S+27
...@@ -90,6 +90,7 @@ _start:...@@ -90,6 +90,7 @@ _start:
90 push { a1 }90 push { a1 }
9191
92#ifdef PIC92#ifdef PIC
93# ifdef SHARED
93 ldr sl, .L_GOT94 ldr sl, .L_GOT
94 adr a4, .L_GOT95 adr a4, .L_GOT
95 add sl, sl, a496 add sl, sl, a4
...@@ -103,6 +104,16 @@ _start:...@@ -103,6 +104,16 @@ _start:
103 /* __libc_start_main (main, argc, argv, init, fini, rtld_fini, stack_end) */104 /* __libc_start_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
104 /* Let the libc call main and exit with its return code. */105 /* Let the libc call main and exit with its return code. */
105 bl __libc_start_main(PLT)106 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 */
106#else117#else
107118
108 mov a4, #0 /* Used to init. */119 mov a4, #0 /* Used to init. */
...@@ -119,14 +130,30 @@ _start:...@@ -119,14 +130,30 @@ _start:
119130
120#ifdef PIC131#ifdef PIC
121 .align 2132 .align 2
133# ifdef SHARED
122.L_GOT:134.L_GOT:
123 .word _GLOBAL_OFFSET_TABLE_ - .L_GOT135 .word _GLOBAL_OFFSET_TABLE_ - .L_GOT
124 .word main(GOT)136 .word main(GOT)
137# else
138.L_main_rel:
139 .word __wrap_main - .L_main_rel
140# endif
125#endif141#endif
126142
127 .cantunwind143 .cantunwind
128 .fnend144 .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
130/* Define a symbol for the first piece of initialized data. */157/* Define a symbol for the first piece of initialized data. */
131 .data158 .data
132 .globl __data_start159 .globl __data_start
lib/libc/glibc/sysdeps/htl/libc-lockP.h+14
...@@ -21,6 +21,20 @@...@@ -21,6 +21,20 @@
2121
22#include <pthread.h>22#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
24/* If we check for a weakly referenced symbol and then perform a38/* If we check for a weakly referenced symbol and then perform a
25 normal jump to it te code generated for some platforms in case of39 normal jump to it te code generated for some platforms in case of
26 PIC is unnecessarily slow. What would happen is that the function40 PIC is unnecessarily slow. What would happen is that the function
lib/libc/glibc/sysdeps/loongarch/start.S+18-8
...@@ -36,6 +36,7 @@...@@ -36,6 +36,7 @@
36#define __ASSEMBLY__ 136#define __ASSEMBLY__ 1
37#include <entry.h>37#include <entry.h>
38#include <sys/asm.h>38#include <sys/asm.h>
39#include <sysdep.h>
3940
40/* The entry point's job is to call __libc_start_main. Per the ABI,41/* The entry point's job is to call __libc_start_main. Per the ABI,
41 a0 contains the address of a function to be passed to atexit.42 a0 contains the address of a function to be passed to atexit.
...@@ -57,23 +58,32 @@ ENTRY (ENTRY_POINT)...@@ -57,23 +58,32 @@ ENTRY (ENTRY_POINT)
57/* Terminate call stack by noting ra is undefined. Use a dummy58/* Terminate call stack by noting ra is undefined. Use a dummy
58 .cfi_label to force starting the FDE. */59 .cfi_label to force starting the FDE. */
59 .cfi_label .Ldummy60 .cfi_label .Ldummy
60 cfi_undefined (1)61 cfi_undefined (1)
61 or a5, a0, zero /* rtld_fini */62 or a5, a0, zero /* rtld_fini */
6263
63 la.pcrel a0, t0, main64#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
64 REG_L a1, sp, 072 REG_L a1, sp, 0
65 ADDI a2, sp, SZREG73 ADDI a2, sp, SZREG
6674
67 /* Adjust $sp for 16-aligned */75 /* Adjust $sp for 16-bytes aligned */
68 BSTRINS sp, zero, 3, 076 REG_ALIGN_ASM (sp, 4)
6977
70 move a3, zero /* used to be init */78 move a3, zero /* used to be init */
71 move a4, zero /* used to be fini */79 move a4, zero /* used to be fini */
72 or a6, sp, zero /* stack_end */80 or a6, sp, zero /* stack_end */
7381
74 la.pcrel ra, t0, __libc_start_main82 CALL (__libc_start_main)
75 jirl ra, ra, 083 CALL (abort)
7684
77 la.pcrel ra, t0, abort85#if defined PIC && !defined SHARED
78 jirl ra, ra, 086__wrap_main:
87 TAIL (main)
88#endif
79END (ENTRY_POINT)89END (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;...@@ -145,16 +145,16 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
145#define __rtld_lock_unlock_recursive(NAME) \145#define __rtld_lock_unlock_recursive(NAME) \
146 __libc_lock_unlock_recursive (NAME)146 __libc_lock_unlock_recursive (NAME)
147147
148/* XXX for now */148/* XXX for now, waiting for a futex-based pthread_rwlock implementation */
149#define __libc_rwlock_define __libc_lock_define149#define __mach_rwlock_define __libc_lock_define
150#define __libc_rwlock_define_initialized __libc_lock_define_initialized150#define __mach_rwlock_define_initialized __libc_lock_define_initialized
151#define __libc_rwlock_init __libc_lock_init151#define __mach_rwlock_init __libc_lock_init
152#define __libc_rwlock_fini __libc_lock_fini152#define __mach_rwlock_fini __libc_lock_fini
153#define __libc_rwlock_rdlock __libc_lock_lock153#define __mach_rwlock_rdlock __libc_lock_lock
154#define __libc_rwlock_wrlock __libc_lock_lock154#define __mach_rwlock_wrlock __libc_lock_lock
155#define __libc_rwlock_tryrdlock __libc_lock_trylock155#define __mach_rwlock_tryrdlock __libc_lock_trylock
156#define __libc_rwlock_trywrlock __libc_lock_trylock156#define __mach_rwlock_trywrlock __libc_lock_trylock
157#define __libc_rwlock_unlock __libc_lock_unlock157#define __mach_rwlock_unlock __libc_lock_unlock
158158
159struct __libc_cleanup_frame159struct __libc_cleanup_frame
160{160{
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 @@...@@ -155,7 +155,7 @@
155 similar to kernel:155 similar to kernel:
156156
157 - __ASSUME_CLONE_BACKWARDS: for variant 1.157 - __ASSUME_CLONE_BACKWARDS: for variant 1.
158 - __ASSUME_CLONE_BACKWARDS2: for variant 2 (s390).158 - __ASSUME_CLONE_BACKWARDS2: for variant 2 (s390x).
159 - __ASSUME_CLONE_BACKWARDS3: for variant 3 (microblaze).159 - __ASSUME_CLONE_BACKWARDS3: for variant 3 (microblaze).
160 - __ASSUME_CLONE_DEFAULT: for variant 4.160 - __ASSUME_CLONE_DEFAULT: for variant 4.
161 */161 */
...@@ -266,4 +266,9 @@...@@ -266,4 +266,9 @@
266/* zig patch: don't assume kernel version */266/* zig patch: don't assume kernel version */
267#define __ASSUME_MSEAL 0267#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
269#endif /* kernel-features.h */274#endif /* kernel-features.h */
lib/libc/glibc/sysdeps/unix/sysv/linux/loongarch/sysdep.h+25-6
...@@ -19,6 +19,7 @@...@@ -19,6 +19,7 @@
19#ifndef _LINUX_LOONGARCH_SYSDEP_H19#ifndef _LINUX_LOONGARCH_SYSDEP_H
20#define _LINUX_LOONGARCH_SYSDEP_H 120#define _LINUX_LOONGARCH_SYSDEP_H 1
2121
22#include <sysdeps/loongarch/sysdep.h>
22#include <sysdeps/unix/sysv/linux/sysdep.h>23#include <sysdeps/unix/sysv/linux/sysdep.h>
23#include <sysdeps/unix/sysdep.h>24#include <sysdeps/unix/sysdep.h>
24#include <tls.h>25#include <tls.h>
...@@ -34,9 +35,9 @@...@@ -34,9 +35,9 @@
34#undef PSEUDO35#undef PSEUDO
35#define PSEUDO(name, syscall_name, args) \36#define PSEUDO(name, syscall_name, args) \
36 ENTRY (name); \37 ENTRY (name); \
37 li.d a7, SYS_ify (syscall_name); \38 LI a7, SYS_ify (syscall_name); \
38 syscall 0; \39 syscall 0; \
39 li.d a7, -4096; \40 LI a7, -4096; \
40 bltu a7, a0, .Lsyscall_error##name;41 bltu a7, a0, .Lsyscall_error##name;
4142
42#undef PSEUDO_END43#undef PSEUDO_END
...@@ -52,16 +53,16 @@...@@ -52,16 +53,16 @@
52 .Lsyscall_error##name : la t0, rtld_errno; \53 .Lsyscall_error##name : la t0, rtld_errno; \
53 sub.w a0, zero, a0; \54 sub.w a0, zero, a0; \
54 st.w a0, t0, 0; \55 st.w a0, t0, 0; \
55 li.d a0, -1;56 LI a0, -1;
5657
57#else58#else
5859
59#define SYSCALL_ERROR_HANDLER(name) \60#define SYSCALL_ERROR_HANDLER(name) \
60 .Lsyscall_error##name : la.tls.ie t0, errno; \61 .Lsyscall_error##name : la.tls.ie t0, errno; \
61 add.d t0, tp, t0; \62 ADD t0, tp, t0; \
62 sub.w a0, zero, a0; \63 sub.w a0, zero, a0; \
63 st.w a0, t0, 0; \64 st.w a0, t0, 0; \
64 li.d a0, -1;65 LI a0, -1;
6566
66#endif67#endif
67#else68#else
...@@ -74,7 +75,7 @@...@@ -74,7 +75,7 @@
74#undef PSEUDO_NEORRNO75#undef PSEUDO_NEORRNO
75#define PSEUDO_NOERRNO(name, syscall_name, args) \76#define PSEUDO_NOERRNO(name, syscall_name, args) \
76 ENTRY (name); \77 ENTRY (name); \
77 li.d a7, SYS_ify (syscall_name); \78 LI a7, SYS_ify (syscall_name); \
78 syscall 0;79 syscall 0;
7980
80#undef PSEUDO_END_NOERRNO81#undef PSEUDO_END_NOERRNO
...@@ -85,11 +86,17 @@...@@ -85,11 +86,17 @@
8586
86/* Performs a system call, returning the error code. */87/* Performs a system call, returning the error code. */
87#undef PSEUDO_ERRVAL88#undef PSEUDO_ERRVAL
89#if __loongarch_grlen == 64
88#define PSEUDO_ERRVAL(name, syscall_name, args) \90#define PSEUDO_ERRVAL(name, syscall_name, args) \
89 PSEUDO_NOERRNO (name, syscall_name, args); \91 PSEUDO_NOERRNO (name, syscall_name, args); \
90 slli.d a0, a0, 32; \92 slli.d a0, a0, 32; \
91 srai.d a0, a0, 32; /* sign_ext */ \93 srai.d a0, a0, 32; /* sign_ext */ \
92 sub.d a0, zero, a0;94 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
94#undef PSEUDO_END_ERRVAL101#undef PSEUDO_END_ERRVAL
95#define PSEUDO_END_ERRVAL(name) END (name);102#define PSEUDO_END_ERRVAL(name) END (name);
...@@ -109,6 +116,18 @@...@@ -109,6 +116,18 @@
109#undef SYS_ify116#undef SYS_ify
110#define SYS_ify(syscall_name) __NR_##syscall_name117#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
112#ifndef __ASSEMBLER__131#ifndef __ASSEMBLER__
113132
114#define VDSO_NAME "LINUX_5.10"133#define VDSO_NAME "LINUX_5.10"
lib/libc/glibc/sysdeps/unix/sysv/linux/s390/bits/typesizes.h+14-22
...@@ -57,42 +57,34 @@...@@ -57,42 +57,34 @@
57#define __TIMER_T_TYPE void *57#define __TIMER_T_TYPE void *
58#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE58#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE
59#define __FSID_T_TYPE struct { int __val[2]; }59#define __FSID_T_TYPE struct { int __val[2]; }
60#if defined __GNUC__ && __GNUC__ <= 260
61/* Compatibility with g++ 2.95.x. */61/* With s390-32, __SSIZE_T_TYPE was __SWORD_TYPE for compatibility with
62#define __SSIZE_T_TYPE __SWORD_TYPE62 g++ 2.95.x. Afterwards __SLONGWORD_TYPE was needed as size_t was
63#else63 unsigned long int on s390-32.
64/* size_t is unsigned long int on s390 -m31. */64 Now as only s390-64 exists, __SWORD_TYPE can be used as also used in the
65#define __SSIZE_T_TYPE __SLONGWORD_TYPE65 generic version as both types result in long int. */
66#endif66#define __SSIZE_T_TYPE __SWORD_TYPE
67
67#define __SYSCALL_SLONG_TYPE __SLONGWORD_TYPE68#define __SYSCALL_SLONG_TYPE __SLONGWORD_TYPE
68#define __SYSCALL_ULONG_TYPE __ULONGWORD_TYPE69#define __SYSCALL_ULONG_TYPE __ULONGWORD_TYPE
69#define __CPU_MASK_TYPE __ULONGWORD_TYPE70#define __CPU_MASK_TYPE __ULONGWORD_TYPE
7071
71#ifdef __s390x__
72/* Tell the libc code that off_t and off64_t are actually the same type72/* Tell the libc code that off_t and off64_t are actually the same type
73 for all ABI purposes, even if possibly expressed as different base types73 for all ABI purposes, even if possibly expressed as different base types
74 for C type-checking purposes. */74 for C type-checking purposes. */
75# define __OFF_T_MATCHES_OFF64_T 175#define __OFF_T_MATCHES_OFF64_T 1
7676
77/* Same for ino_t and ino64_t. */77/* Same for ino_t and ino64_t. */
78# define __INO_T_MATCHES_INO64_T 178#define __INO_T_MATCHES_INO64_T 1
7979
80/* And for __rlim_t and __rlim64_t. */80/* And for __rlim_t and __rlim64_t. */
81# define __RLIM_T_MATCHES_RLIM64_T 181#define __RLIM_T_MATCHES_RLIM64_T 1
8282
83/* And for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t. */83/* And for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t. */
84# define __STATFS_MATCHES_STATFS64 184#define __STATFS_MATCHES_STATFS64 1
8585
86/* And for getitimer, setitimer and rusage */86/* And for getitimer, setitimer and rusage */
87# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 187#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
9688
97/* Number of descriptors that can fit in an `fd_set'. */89/* Number of descriptors that can fit in an `fd_set'. */
98#define __FD_SETSIZE 102490#define __FD_SETSIZE 1024
lib/libc/glibc/sysdeps/unix/sysv/linux/s390/kernel-features.h-3
...@@ -47,9 +47,6 @@...@@ -47,9 +47,6 @@
47# undef __ASSUME_DIRECT_SYSVIPC_SYSCALLS47# undef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
48# undef __ASSUME_SYSVIPC_DEFAULT_IPC_6448# undef __ASSUME_SYSVIPC_DEFAULT_IPC_64
49#endif49#endif
50#ifndef __s390x__
51# define __ASSUME_SYSVIPC_BROKEN_MODE_T
52#endif
5350
54#undef __ASSUME_CLONE_DEFAULT51#undef __ASSUME_CLONE_DEFAULT
55#define __ASSUME_CLONE_BACKWARDS252#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,5 +1,5 @@
1/* Syscall definitions, Linux s390 version.1/* Assembler macros for 64 bit S/390.
2 Copyright (C) 2019-2026 Free Software Foundation, Inc.2 Copyright (C) 2001-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.3 This file is part of the GNU C Library.
44
5 The GNU C Library is free software; you can redistribute it and/or5 The GNU C Library is free software; you can redistribute it and/or
...@@ -14,15 +14,163 @@...@@ -14,15 +14,163 @@
1414
15 You should have received a copy of the GNU Lesser General Public15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see16 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
21#undef SYS_ify35#undef SYS_ify
22#define SYS_ify(syscall_name) __NR_##syscall_name36#define SYS_ify(syscall_name) __NR_##syscall_name
2337
24#undef INTERNAL_SYSCALL_NCS38#ifdef __ASSEMBLER__
25#define INTERNAL_SYSCALL_NCS(no, nr, args...) \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...) \
26 ({ \174 ({ \
27 DECLARGS_##nr(args) \175 DECLARGS_##nr(args) \
28 register unsigned long int _nr __asm__("1") = (unsigned long int)(no); \176 register unsigned long int _nr __asm__("1") = (unsigned long int)(no); \
...@@ -34,51 +182,52 @@...@@ -34,51 +182,52 @@
34 : "memory" ); \182 : "memory" ); \
35 _ret; })183 _ret; })
36184
37#undef INTERNAL_SYSCALL185# undef INTERNAL_SYSCALL
38#define INTERNAL_SYSCALL(name, nr, args...) \186# define INTERNAL_SYSCALL(name, nr, args...) \
39 INTERNAL_SYSCALL_NCS(__NR_##name, nr, args)187 INTERNAL_SYSCALL_NCS(__NR_##name, nr, args)
40188
41#define DECLARGS_0()189# define DECLARGS_0()
42#define DECLARGS_1(arg1) \190# define DECLARGS_1(arg1) \
43 register unsigned long int gpr2 __asm__ ("2") = (unsigned long int)(arg1);191 register unsigned long int gpr2 __asm__ ("2") = (unsigned long int)(arg1);
44#define DECLARGS_2(arg1, arg2) \192# define DECLARGS_2(arg1, arg2) \
45 DECLARGS_1(arg1) \193 DECLARGS_1(arg1) \
46 register unsigned long int gpr3 __asm__ ("3") = (unsigned long int)(arg2);194 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) \
48 DECLARGS_2(arg1, arg2) \196 DECLARGS_2(arg1, arg2) \
49 register unsigned long int gpr4 __asm__ ("4") = (unsigned long int)(arg3);197 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) \
51 DECLARGS_3(arg1, arg2, arg3) \199 DECLARGS_3(arg1, arg2, arg3) \
52 register unsigned long int gpr5 __asm__ ("5") = (unsigned long int)(arg4);200 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) \
54 DECLARGS_4(arg1, arg2, arg3, arg4) \202 DECLARGS_4(arg1, arg2, arg3, arg4) \
55 register unsigned long int gpr6 __asm__ ("6") = (unsigned long int)(arg5);203 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) \
57 DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \205 DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \
58 register unsigned long int gpr7 __asm__ ("7") = (unsigned long int)(arg6);206 register unsigned long int gpr7 __asm__ ("7") = (unsigned long int)(arg6);
59207
60#define ASMFMT_0208# define ASMFMT_0
61#define ASMFMT_1 , "0" (gpr2)209# define ASMFMT_1 , "0" (gpr2)
62#define ASMFMT_2 , "0" (gpr2), "d" (gpr3)210# define ASMFMT_2 , "0" (gpr2), "d" (gpr3)
63#define ASMFMT_3 , "0" (gpr2), "d" (gpr3), "d" (gpr4)211# define ASMFMT_3 , "0" (gpr2), "d" (gpr3), "d" (gpr4)
64#define ASMFMT_4 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5)212# 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)213# 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)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"216# define VDSO_NAME "LINUX_2.6.29"
69#define VDSO_HASH 123718585217# define VDSO_HASH 123718585
70218
71/* List of system calls which are supported as vsyscalls. */219/* List of system calls which are supported as vsyscalls. */
72#ifdef __s390x__220# define HAVE_CLOCK_GETRES64_VSYSCALL "__kernel_clock_getres"
73#define HAVE_CLOCK_GETRES64_VSYSCALL "__kernel_clock_getres"221# define HAVE_CLOCK_GETTIME64_VSYSCALL "__kernel_clock_gettime"
74#define HAVE_CLOCK_GETTIME64_VSYSCALL "__kernel_clock_gettime"222# define HAVE_GETRANDOM_VSYSCALL "__kernel_getrandom"
75#define HAVE_GETRANDOM_VSYSCALL "__kernel_getrandom"223# define HAVE_GETTIMEOFDAY_VSYSCALL "__kernel_gettimeofday"
76#else224# define HAVE_GETCPU_VSYSCALL "__kernel_getcpu"
77#define HAVE_CLOCK_GETRES_VSYSCALL "__kernel_clock_getres"225
78#define HAVE_CLOCK_GETTIME_VSYSCALL "__kernel_clock_gettime"226# define HAVE_CLONE3_WRAPPER 1
79#endif227
80#define HAVE_GETTIMEOFDAY_VSYSCALL "__kernel_gettimeofday"228# undef HAVE_INTERNAL_BRK_ADDR_SYMBOL
81#define HAVE_GETCPU_VSYSCALL "__kernel_getcpu"229# define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1
82230
83#define HAVE_CLONE3_WRAPPER 1231#endif /* __ASSEMBLER__ */
84#endif232
233#endif /* _LINUX_S390_SYSDEP_H */
lib/libc/glibc/sysdeps/unix/sysv/linux/s390/xstatver.h+6-15
...@@ -1,19 +1,10 @@...@@ -1,19 +1,10 @@
1/* Versions of the 'struct stat' data structure used in compatibility xstat1/* Versions of the 'struct stat' data structure used in compatibility xstat
2 functions. */2 functions. */
33#define _STAT_VER_KERNEL 0
4#include <bits/wordsize.h>4#define _STAT_VER_LINUX 1
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
18#define _STAT_VER _STAT_VER_LINUX5#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
19#define _MKNOD_VER _MKNOD_VER_LINUX10#define _MKNOD_VER _MKNOD_VER_LINUX
lib/libc/include/aarch64-linux-gnu/bits/hwcap.h+18-1
...@@ -55,6 +55,21 @@...@@ -55,6 +55,21 @@
55#define HWCAP_PACA (1 << 30)55#define HWCAP_PACA (1 << 30)
56#define HWCAP_PACG (1UL << 31)56#define HWCAP_PACG (1UL << 31)
57#define HWCAP_GCS (1UL << 32)57#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
59#define HWCAP2_DCPODP (1 << 0)74#define HWCAP2_DCPODP (1 << 0)
60#define HWCAP2_SVE2 (1 << 1)75#define HWCAP2_SVE2 (1 << 1)
...@@ -122,4 +137,6 @@...@@ -122,4 +137,6 @@
122#define HWCAP2_POE (1UL << 63)137#define HWCAP2_POE (1UL << 63)
123138
124#define HWCAP3_MTE_FAR (1UL << 0)139#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 @@...@@ -157,6 +157,10 @@
157# define __DECL_SIMD_pow __DECL_SIMD_aarch64157# define __DECL_SIMD_pow __DECL_SIMD_aarch64
158# undef __DECL_SIMD_powf158# undef __DECL_SIMD_powf
159# define __DECL_SIMD_powf __DECL_SIMD_aarch64159# 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
160# undef __DECL_SIMD_rsqrt164# undef __DECL_SIMD_rsqrt
161# define __DECL_SIMD_rsqrt __DECL_SIMD_aarch64165# define __DECL_SIMD_rsqrt __DECL_SIMD_aarch64
162# undef __DECL_SIMD_rsqrtf166# undef __DECL_SIMD_rsqrtf
...@@ -243,6 +247,7 @@ __vpcs __f32x4_t _ZGVnN4v_log2f (__f32x4_t);...@@ -243,6 +247,7 @@ __vpcs __f32x4_t _ZGVnN4v_log2f (__f32x4_t);
243__vpcs __f32x4_t _ZGVnN4v_log2p1f (__f32x4_t);247__vpcs __f32x4_t _ZGVnN4v_log2p1f (__f32x4_t);
244__vpcs __f32x4_t _ZGVnN4v_logp1f (__f32x4_t);248__vpcs __f32x4_t _ZGVnN4v_logp1f (__f32x4_t);
245__vpcs __f32x4_t _ZGVnN4vv_powf (__f32x4_t, __f32x4_t);249__vpcs __f32x4_t _ZGVnN4vv_powf (__f32x4_t, __f32x4_t);
250__vpcs __f32x4_t _ZGVnN4vv_powrf (__f32x4_t, __f32x4_t);
246__vpcs __f32x4_t _ZGVnN4v_rsqrtf (__f32x4_t);251__vpcs __f32x4_t _ZGVnN4v_rsqrtf (__f32x4_t);
247__vpcs __f32x4_t _ZGVnN4v_sinf (__f32x4_t);252__vpcs __f32x4_t _ZGVnN4v_sinf (__f32x4_t);
248__vpcs __f32x4_t _ZGVnN4v_sinhf (__f32x4_t);253__vpcs __f32x4_t _ZGVnN4v_sinhf (__f32x4_t);
...@@ -283,6 +288,7 @@ __vpcs __f64x2_t _ZGVnN2v_log2 (__f64x2_t);...@@ -283,6 +288,7 @@ __vpcs __f64x2_t _ZGVnN2v_log2 (__f64x2_t);
283__vpcs __f64x2_t _ZGVnN2v_log2p1 (__f64x2_t);288__vpcs __f64x2_t _ZGVnN2v_log2p1 (__f64x2_t);
284__vpcs __f64x2_t _ZGVnN2v_logp1 (__f64x2_t);289__vpcs __f64x2_t _ZGVnN2v_logp1 (__f64x2_t);
285__vpcs __f64x2_t _ZGVnN2vv_pow (__f64x2_t, __f64x2_t);290__vpcs __f64x2_t _ZGVnN2vv_pow (__f64x2_t, __f64x2_t);
291__vpcs __f64x2_t _ZGVnN2vv_powr (__f64x2_t, __f64x2_t);
286__vpcs __f64x2_t _ZGVnN2v_rsqrt (__f64x2_t);292__vpcs __f64x2_t _ZGVnN2v_rsqrt (__f64x2_t);
287__vpcs __f64x2_t _ZGVnN2v_sin (__f64x2_t);293__vpcs __f64x2_t _ZGVnN2v_sin (__f64x2_t);
288__vpcs __f64x2_t _ZGVnN2v_sinh (__f64x2_t);294__vpcs __f64x2_t _ZGVnN2v_sinh (__f64x2_t);
...@@ -328,6 +334,7 @@ __sv_f32_t _ZGVsMxv_log2f (__sv_f32_t, __sv_bool_t);...@@ -328,6 +334,7 @@ __sv_f32_t _ZGVsMxv_log2f (__sv_f32_t, __sv_bool_t);
328__sv_f32_t _ZGVsMxv_log2p1f (__sv_f32_t, __sv_bool_t);334__sv_f32_t _ZGVsMxv_log2p1f (__sv_f32_t, __sv_bool_t);
329__sv_f32_t _ZGVsMxv_logp1f (__sv_f32_t, __sv_bool_t);335__sv_f32_t _ZGVsMxv_logp1f (__sv_f32_t, __sv_bool_t);
330__sv_f32_t _ZGVsMxvv_powf (__sv_f32_t, __sv_f32_t, __sv_bool_t);336__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);
331__sv_f32_t _ZGVsMxv_rsqrtf (__sv_f32_t, __sv_bool_t);338__sv_f32_t _ZGVsMxv_rsqrtf (__sv_f32_t, __sv_bool_t);
332__sv_f32_t _ZGVsMxv_sinf (__sv_f32_t, __sv_bool_t);339__sv_f32_t _ZGVsMxv_sinf (__sv_f32_t, __sv_bool_t);
333__sv_f32_t _ZGVsMxv_sinhf (__sv_f32_t, __sv_bool_t);340__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);...@@ -368,6 +375,7 @@ __sv_f64_t _ZGVsMxv_log2 (__sv_f64_t, __sv_bool_t);
368__sv_f64_t _ZGVsMxv_log2p1 (__sv_f64_t, __sv_bool_t);375__sv_f64_t _ZGVsMxv_log2p1 (__sv_f64_t, __sv_bool_t);
369__sv_f64_t _ZGVsMxv_logp1 (__sv_f64_t, __sv_bool_t);376__sv_f64_t _ZGVsMxv_logp1 (__sv_f64_t, __sv_bool_t);
370__sv_f64_t _ZGVsMxvv_pow (__sv_f64_t, __sv_f64_t, __sv_bool_t);377__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);
371__sv_f64_t _ZGVsMxv_rsqrt (__sv_f64_t, __sv_bool_t);379__sv_f64_t _ZGVsMxv_rsqrt (__sv_f64_t, __sv_bool_t);
372__sv_f64_t _ZGVsMxv_sin (__sv_f64_t, __sv_bool_t);380__sv_f64_t _ZGVsMxv_sin (__sv_f64_t, __sv_bool_t);
373__sv_f64_t _ZGVsMxv_sinh (__sv_f64_t, __sv_bool_t);381__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 @@...@@ -16,81 +16,83 @@
16! License along with the GNU C Library; if not, see16! License along with the GNU C Library; if not, see
17! <https://www.gnu.org/licenses/>.17! <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 @@...@@ -24,4 +24,5 @@
24#define LIBRESOLV_SO "libresolv.so.2"24#define LIBRESOLV_SO "libresolv.so.2"
25#define LIBRT_SO "librt.so.1"25#define LIBRT_SO "librt.so.1"
26#define LIBTHREAD_DB_SO "libthread_db.so.1"26#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
27#define LIBUTIL_SO "libutil.so.1"28#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 @@...@@ -24,4 +24,5 @@
24#define LIBRESOLV_SO "libresolv.so.2"24#define LIBRESOLV_SO "libresolv.so.2"
25#define LIBRT_SO "librt.so.1"25#define LIBRT_SO "librt.so.1"
26#define LIBTHREAD_DB_SO "libthread_db.so.1"26#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
27#define LIBUTIL_SO "libutil.so.1"28#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 @@...@@ -25,6 +25,7 @@
25#define LIBRESOLV_SO "libresolv.so.2"25#define LIBRESOLV_SO "libresolv.so.2"
26#define LIBRT_SO "librt.so.1"26#define LIBRT_SO "librt.so.1"
27#define LIBTHREAD_DB_SO "libthread_db.so.1"27#define LIBTHREAD_DB_SO "libthread_db.so.1"
28#define LIBUNWIND_SO "libunwind.so.1"
28#define LIBUTIL_SO "libutil.so.1"29#define LIBUTIL_SO "libutil.so.1"
2930
30#endif /* gnu/lib-names.h */31#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 @@...@@ -31,6 +31,7 @@
31#define LIBRESOLV_SO "libresolv.so.2"31#define LIBRESOLV_SO "libresolv.so.2"
32#define LIBRT_SO "librt.so.1"32#define LIBRT_SO "librt.so.1"
33#define LIBTHREAD_DB_SO "libthread_db.so.1"33#define LIBTHREAD_DB_SO "libthread_db.so.1"
34#define LIBUNWIND_SO "libunwind.so.1"
34#define LIBUTIL_SO "libutil.so.1"35#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 @@...@@ -52,13 +52,12 @@
52 comma in the initializer list, can be passed to assert. This52 comma in the initializer list, can be passed to assert. This
53 depends on support for variadic macros (added in C99 and GCC 2.95),53 depends on support for variadic macros (added in C99 and GCC 2.95),
54 and on support for _Bool (added in C99 and GCC 3.0) in order to54 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,55 validate that only a single expression is passed as an argument. */
56 and is currently implemented only for C. */56#if ((__GLIBC_USE (ISOC23) \
57#if (__GLIBC_USE (ISOC23) \57 && (defined __GNUC__ \
58 && (defined __GNUC__ \58 ? __GNUC_PREREQ (3, 0) \
59 ? __GNUC_PREREQ (3, 0) \59 : defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)) \
60 : defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) \60 || (defined __cplusplus && __cplusplus > 202302L))
61 && !defined __cplusplus)
62# define __ASSERT_VARIADIC 161# define __ASSERT_VARIADIC 1
63#else62#else
64# define __ASSERT_VARIADIC 063# define __ASSERT_VARIADIC 0
...@@ -108,7 +107,7 @@ extern void __assert (const char *__assertion, const char *__file, int __line)...@@ -108,7 +107,7 @@ extern void __assert (const char *__assertion, const char *__file, int __line)
108 __THROW __attribute__ ((__noreturn__)) __COLD;107 __THROW __attribute__ ((__noreturn__)) __COLD;
109108
110109
111# if __ASSERT_VARIADIC110# if __ASSERT_VARIADIC && !defined __cplusplus
112/* This function is not defined and is not called outside of an111/* This function is not defined and is not called outside of an
113 unevaluated sizeof, but serves to verify that the argument to112 unevaluated sizeof, but serves to verify that the argument to
114 assert is a single expression. */113 assert is a single expression. */
...@@ -131,11 +130,22 @@ __END_DECLS...@@ -131,11 +130,22 @@ __END_DECLS
131# define __ASSERT_FILE __FILE__130# define __ASSERT_FILE __FILE__
132# define __ASSERT_LINE __LINE__131# define __ASSERT_LINE __LINE__
133# endif132# 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) \
135 (static_cast <bool> (expr) \144 (static_cast <bool> (expr) \
136 ? void (0) \145 ? void (0) \
137 : __assert_fail (#expr, __ASSERT_FILE, __ASSERT_LINE, \146 : __assert_fail (#expr, __ASSERT_FILE, __ASSERT_LINE, \
138 __ASSERT_FUNCTION))147 __ASSERT_FUNCTION))
148# endif
139# elif !defined __GNUC__ || defined __STRICT_ANSI__149# elif !defined __GNUC__ || defined __STRICT_ANSI__
140# if __ASSERT_VARIADIC150# if __ASSERT_VARIADIC
141# define assert(...) \151# 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 @@...@@ -81,9 +81,7 @@
81#ifndef __O_NOFOLLOW81#ifndef __O_NOFOLLOW
82# define __O_NOFOLLOW 040000082# define __O_NOFOLLOW 0400000
83#endif83#endif
84#ifndef __O_CLOEXEC84#include <bits/cloexec.h>
85# define __O_CLOEXEC 02000000
86#endif
87#ifndef __O_DIRECT85#ifndef __O_DIRECT
88# define __O_DIRECT 04000086# define __O_DIRECT 040000
89#endif87#endif
...@@ -176,8 +174,8 @@...@@ -176,8 +174,8 @@
176#endif174#endif
177175
178#if defined __USE_UNIX98 || defined __USE_XOPEN2K8176#if defined __USE_UNIX98 || defined __USE_XOPEN2K8
179# define F_SETOWN __F_SETOWN /* Get owner (process receiving SIGIO). */177# define F_SETOWN __F_SETOWN /* Set owner (process receiving SIGIO). */
180# define F_GETOWN __F_GETOWN /* Set owner (process receiving SIGIO). */178# define F_GETOWN __F_GETOWN /* Get owner (process receiving SIGIO). */
181#endif179#endif
182180
183#ifndef __F_SETSIG181#ifndef __F_SETSIG
...@@ -185,15 +183,15 @@...@@ -185,15 +183,15 @@
185# define __F_GETSIG 11 /* Get number of signal to be sent. */183# define __F_GETSIG 11 /* Get number of signal to be sent. */
186#endif184#endif
187#ifndef __F_SETOWN_EX185#ifndef __F_SETOWN_EX
188# define __F_SETOWN_EX 15 /* Get owner (thread receiving SIGIO). */186# define __F_SETOWN_EX 15 /* Set owner (thread receiving SIGIO). */
189# define __F_GETOWN_EX 16 /* Set owner (thread receiving SIGIO). */187# define __F_GETOWN_EX 16 /* Get owner (thread receiving SIGIO). */
190#endif188#endif
191189
192#ifdef __USE_GNU190#ifdef __USE_GNU
193# define F_SETSIG __F_SETSIG /* Set number of signal to be sent. */191# define F_SETSIG __F_SETSIG /* Set number of signal to be sent. */
194# define F_GETSIG __F_GETSIG /* Get number of signal to be sent. */192# 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). */193# define F_SETOWN_EX __F_SETOWN_EX /* Set owner (thread receiving SIGIO). */
196# define F_GETOWN_EX __F_GETOWN_EX /* Set owner (thread receiving SIGIO). */194# define F_GETOWN_EX __F_GETOWN_EX /* Get owner (thread receiving SIGIO). */
197#endif195#endif
198196
199#ifdef __USE_GNU197#ifdef __USE_GNU
...@@ -203,7 +201,7 @@...@@ -203,7 +201,7 @@
203# define F_DUPFD_QUERY 1027 /* Compare two file descriptors for sameness. */201# define F_DUPFD_QUERY 1027 /* Compare two file descriptors for sameness. */
204# define F_CREATED_QUERY 1028 /* Was the file just created? */202# define F_CREATED_QUERY 1028 /* Was the file just created? */
205# define F_SETPIPE_SZ 1031 /* Set pipe page size array. */203# 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. */
207# define F_ADD_SEALS 1033 /* Add seals to file. */205# define F_ADD_SEALS 1033 /* Add seals to file. */
208# define F_GET_SEALS 1034 /* Get seals for file. */206# define F_GET_SEALS 1034 /* Get seals for file. */
209/* Set / get write life time hints. */207/* Set / get write life time hints. */
...@@ -211,6 +209,8 @@...@@ -211,6 +209,8 @@
211# define F_SET_RW_HINT 1036209# define F_SET_RW_HINT 1036
212# define F_GET_FILE_RW_HINT 1037210# define F_GET_FILE_RW_HINT 1037
213# define F_SET_FILE_RW_HINT 1038211# define F_SET_FILE_RW_HINT 1038
212# define F_GETDELEG 1039 /* Get delegation. */
213# define F_SETDELEG 1040 /* Set delegation. */
214#endif214#endif
215#ifdef __USE_XOPEN2K8215#ifdef __USE_XOPEN2K8
216# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with216# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with
...@@ -221,6 +221,7 @@...@@ -221,6 +221,7 @@
221#define FD_CLOEXEC 1 /* Actually anything with low bit set goes */221#define FD_CLOEXEC 1 /* Actually anything with low bit set goes */
222#ifdef __USE_GNU222#ifdef __USE_GNU
223# define FD_PIDFS_ROOT -10002 /* Root of the pidfs filesystem */223# define FD_PIDFS_ROOT -10002 /* Root of the pidfs filesystem */
224# define FD_NSFS_ROOT -10003 /* Root of the nsfs filesystem */
224#endif225#endif
225226
226#ifndef F_RDLCK227#ifndef F_RDLCK
lib/libc/include/generic-glibc/bits/libm-simd-decl-stubs.h+11
...@@ -99,6 +99,17 @@...@@ -99,6 +99,17 @@
99#define __DECL_SIMD_powf64x99#define __DECL_SIMD_powf64x
100#define __DECL_SIMD_powf128x100#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
102#define __DECL_SIMD_acos113#define __DECL_SIMD_acos
103#define __DECL_SIMD_acosf114#define __DECL_SIMD_acosf
104#define __DECL_SIMD_acosl115#define __DECL_SIMD_acosl
lib/libc/include/generic-glibc/bits/long-double.h+3-6
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1/* Properties of long double type. MIPS version.1/* Properties of long double type. ldbl-128 version.
2 Copyright (C) 2016-2026 Free Software Foundation, Inc.2 Copyright (C) 2016-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.3 This file is part of the GNU C Library.
44
...@@ -16,9 +16,6 @@...@@ -16,9 +16,6 @@
16 License along with the GNU C Library; if not, see16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */17 <https://www.gnu.org/licenses/>. */
1818
19#include <sgidefs.h>19/* long double is distinct from double, so there is nothing to
2020 define here. */
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 021#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));...@@ -197,6 +197,7 @@ __MATHCALL (compoundn,, (_Mdouble_ __x, long long int __y));
197__MATHCALL (pown,, (_Mdouble_ __x, long long int __y));197__MATHCALL (pown,, (_Mdouble_ __x, long long int __y));
198198
199/* Return X to the Y power. */199/* Return X to the Y power. */
200__MATHCALL_VEC (powr,, (_Mdouble_ __x, _Mdouble_ __y));
200__MATHCALL (powr,, (_Mdouble_ __x, _Mdouble_ __y));201__MATHCALL (powr,, (_Mdouble_ __x, _Mdouble_ __y));
201202
202/* Return the Yth root of X. */203/* 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 @@...@@ -54,6 +54,9 @@
54#define SCHED_FLAG_UTIL_CLAMP \54#define SCHED_FLAG_UTIL_CLAMP \
55 (SCHED_FLAG_UTIL_CLAMP_MIN | SCHED_FLAG_UTIL_CLAMP_MAX)55 (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
57/* Use "" to work around incorrect macro expansion of the60/* Use "" to work around incorrect macro expansion of the
58 __has_include argument (GCC PR 80005). */61 __has_include argument (GCC PR 80005). */
59# ifdef __has_include62# ifdef __has_include
lib/libc/include/generic-glibc/bits/struct_stat.h+54-164
...@@ -23,215 +23,105 @@...@@ -23,215 +23,105 @@
23#ifndef _BITS_STRUCT_STAT_H23#ifndef _BITS_STRUCT_STAT_H
24#define _BITS_STRUCT_STAT_H 124#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. */
30struct stat44struct stat
31 {45 {
32# ifdef __USE_TIME64_REDIRECTS46 __dev_t st_dev; /* Device. */
33# include <bits/struct_stat_time64_helper.h>47 __field64(__ino_t, __ino64_t, st_ino); /* File serial number. */
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. */48 __mode_t st_mode; /* File mode. */
43 __nlink_t st_nlink; /* Link count. */49 __nlink_t st_nlink; /* Link count. */
44 __uid_t st_uid; /* User ID of the file's owner. */50 __uid_t st_uid; /* User ID of the file's owner. */
45 __gid_t st_gid; /* Group ID of the file's group.*/51 __gid_t st_gid; /* Group ID of the file's group.*/
46 unsigned long int st_rdev; /* Device number, if device. */52 __dev_t st_rdev; /* Device number, if device. */
47# ifndef __USE_FILE_OFFSET6453 __dev_t __pad1;
48 long int st_pad2[2];54 __field64(__off_t, __off64_t, st_size); /* Size of file, in bytes. */
49 __off_t st_size; /* Size of file, in bytes. */55 __blksize_t st_blksize; /* Optimal block size for I/O. */
50 /* SVR4 added this extra long to allow for expansion of off_t. */56 int __pad2;
51 long int st_pad3;57 __field64(__blkcnt_t, __blkcnt64_t, st_blocks); /* 512-byte blocks */
52# else58#ifdef __USE_XOPEN2K8
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 format59 /* Nanosecond resolution timestamps are stored in a format
58 equivalent to 'struct timespec'. This is the type used60 equivalent to 'struct timespec'. This is the type used
59 whenever possible but the Unix namespace rules do not allow the61 whenever possible but the Unix namespace rules do not allow the
60 identifier 'timespec' to appear in the <sys/stat.h> header.62 identifier 'timespec' to appear in the <sys/stat.h> header.
61 Therefore we have to handle the use of this header in strictly63 Therefore we have to handle the use of this header in strictly
62 standard-compliant sources special. */64 standard-compliant sources special. */
63 struct timespec st_atim; /* Time of last access. */65 struct timespec st_atim; /* Time of last access. */
64 struct timespec st_mtim; /* Time of last modification. */66 struct timespec st_mtim; /* Time of last modification. */
65 struct timespec st_ctim; /* Time of last status change. */67 struct timespec st_ctim; /* Time of last status change. */
66# define st_atime st_atim.tv_sec /* Backward compatibility. */68# define st_atime st_atim.tv_sec /* Backward compatibility. */
67# define st_mtime st_mtim.tv_sec69# define st_mtime st_mtim.tv_sec
68# define st_ctime st_ctim.tv_sec70# define st_ctime st_ctim.tv_sec
69# else71#else
70 __time_t st_atime; /* Time of last access. */72 __time_t st_atime; /* Time of last access. */
71 unsigned long int st_atimensec; /* Nscecs of last access. */73 unsigned long int st_atimensec; /* Nscecs of last access. */
72 __time_t st_mtime; /* Time of last modification. */74 __time_t st_mtime; /* Time of last modification. */
73 unsigned long int st_mtimensec; /* Nsecs of last modification. */75 unsigned long int st_mtimensec; /* Nsecs of last modification. */
74 __time_t st_ctime; /* Time of last status change. */76 __time_t st_ctime; /* Time of last status change. */
75 unsigned long int st_ctimensec; /* Nsecs of last status change. */77 unsigned long int st_ctimensec; /* Nsecs of last status change. */
76# endif78#endif
77 __blksize_t st_blksize; /* Optimal block size for I/O. */79 int __glibc_reserved[2];
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 };80 };
8781
88# ifdef __USE_LARGEFILE6482#undef __field64
83
84#ifdef __USE_LARGEFILE64
89struct stat6485struct stat64
90 {86 {
91# ifdef __USE_TIME64_REDIRECTS87 __dev_t st_dev; /* Device. */
92# include <bits/struct_stat_time64_helper.h>88 __ino64_t st_ino; /* File serial number. */
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. */89 __mode_t st_mode; /* File mode. */
98 __nlink_t st_nlink; /* Link count. */90 __nlink_t st_nlink; /* Link count. */
99 __uid_t st_uid; /* User ID of the file's owner. */91 __uid_t st_uid; /* User ID of the file's owner. */
100 __gid_t st_gid; /* Group ID of the file's group.*/92 __gid_t st_gid; /* Group ID of the file's group.*/
101 unsigned long int st_rdev; /* Device number, if device. */93 __dev_t st_rdev; /* Device number, if device. */
102 long int st_pad2[3];94 __dev_t __pad1;
103 __off64_t st_size; /* Size of file, in bytes. */95 __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. */96 __blksize_t st_blksize; /* Optimal block size for I/O. */
123 long int st_pad3;97 int __pad2;
124 __blkcnt64_t st_blocks; /* Number of 512-byte blocks allocated. */98 __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */
125 long int st_pad4[14];99#ifdef __USE_XOPEN2K8
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 format100 /* Nanosecond resolution timestamps are stored in a format
159 equivalent to 'struct timespec'. This is the type used101 equivalent to 'struct timespec'. This is the type used
160 whenever possible but the Unix namespace rules do not allow the102 whenever possible but the Unix namespace rules do not allow the
161 identifier 'timespec' to appear in the <sys/stat.h> header.103 identifier 'timespec' to appear in the <sys/stat.h> header.
162 Therefore we have to handle the use of this header in strictly104 Therefore we have to handle the use of this header in strictly
163 standard-compliant sources special. */105 standard-compliant sources special. */
164 struct timespec st_atim; /* Time of last access. */106 struct timespec st_atim; /* Time of last access. */
165 struct timespec st_mtim; /* Time of last modification. */107 struct timespec st_mtim; /* Time of last modification. */
166 struct timespec st_ctim; /* Time of last status change. */108 struct timespec st_ctim; /* Time of last status change. */
167# define st_atime st_atim.tv_sec /* Backward compatibility. */109#else
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. */110 __time_t st_atime; /* Time of last access. */
172 unsigned long int st_atimensec; /* Nscecs of last access. */111 unsigned long int st_atimensec; /* Nscecs of last access. */
173 __time_t st_mtime; /* Time of last modification. */112 __time_t st_mtime; /* Time of last modification. */
174 unsigned long int st_mtimensec; /* Nsecs of last modification. */113 unsigned long int st_mtimensec; /* Nsecs of last modification. */
175 __time_t st_ctime; /* Time of last status change. */114 __time_t st_ctime; /* Time of last status change. */
176 unsigned long int st_ctimensec; /* Nsecs of last status change. */115 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#endif116#endif
230117 int __glibc_reserved[2];
118 };
231#endif119#endif
232120
233/* Tell code we have these members. */121/* Tell code we have these members. */
234#define _STATBUF_ST_BLKSIZE122#define _STATBUF_ST_BLKSIZE
235#define _STATBUF_ST_RDEV123#define _STATBUF_ST_RDEV
124/* Nanosecond resolution time values are supported. */
125#define _STATBUF_ST_NSEC
236126
237#endif /* _BITS_STRUCT_STAT_H */127#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 @@...@@ -1,11 +1,11 @@
1/* Generated at libc build time from syscall list. */1/* 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
4#ifndef _SYSCALL_H4#ifndef _SYSCALL_H
5# error "Never use <bits/syscall.h> directly; include <sys/syscall.h> instead."5# error "Never use <bits/syscall.h> directly; include <sys/syscall.h> instead."
6#endif6#endif
77
8#define __GLIBC_LINUX_VERSION_CODE 3975688#define __GLIBC_LINUX_VERSION_CODE 459008
99
10#ifdef __NR_FAST_atomic_update10#ifdef __NR_FAST_atomic_update
11# define SYS_FAST_atomic_update __NR_FAST_atomic_update11# define SYS_FAST_atomic_update __NR_FAST_atomic_update
...@@ -883,6 +883,10 @@...@@ -883,6 +883,10 @@
883# define SYS_listmount __NR_listmount883# define SYS_listmount __NR_listmount
884#endif884#endif
885885
886#ifdef __NR_listns
887# define SYS_listns __NR_listns
888#endif
889
886#ifdef __NR_listxattr890#ifdef __NR_listxattr
887# define SYS_listxattr __NR_listxattr891# define SYS_listxattr __NR_listxattr
888#endif892#endif
...@@ -1899,6 +1903,10 @@...@@ -1899,6 +1903,10 @@
1899# define SYS_rseq __NR_rseq1903# define SYS_rseq __NR_rseq
1900#endif1904#endif
19011905
1906#ifdef __NR_rseq_slice_yield
1907# define SYS_rseq_slice_yield __NR_rseq_slice_yield
1908#endif
1909
1902#ifdef __NR_rt_sigaction1910#ifdef __NR_rt_sigaction
1903# define SYS_rt_sigaction __NR_rt_sigaction1911# define SYS_rt_sigaction __NR_rt_sigaction
1904#endif1912#endif
...@@ -2551,6 +2559,10 @@...@@ -2551,6 +2559,10 @@
2551# define SYS_unshare __NR_unshare2559# define SYS_unshare __NR_unshare
2552#endif2560#endif
25532561
2562#ifdef __NR_uprobe
2563# define SYS_uprobe __NR_uprobe
2564#endif
2565
2554#ifdef __NR_uretprobe2566#ifdef __NR_uretprobe
2555# define SYS_uretprobe __NR_uretprobe2567# define SYS_uretprobe __NR_uretprobe
2556#endif2568#endif
lib/libc/include/generic-glibc/bits/timesize.h+3-5
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1/* Bit size of the time_t type at glibc build time, Linux/MIPS.1/* Bit size of the time_t type at glibc build time, general case.
2 Copyright (C) 2021-2026 Free Software Foundation, Inc.2 Copyright (C) 2018-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.3 This file is part of the GNU C Library.
44
5 The GNU C Library is free software; you can redistribute it and/or5 The GNU C Library is free software; you can redistribute it and/or
...@@ -16,7 +16,5 @@...@@ -16,7 +16,5 @@
16 License along with the GNU C Library; if not, see16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */17 <https://www.gnu.org/licenses/>. */
1818
19#include <bits/wordsize.h>
20
21/* Size in bits of the 'time_t' type of the default ABI. */19/* 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,...@@ -51,6 +51,7 @@ extern ssize_t process_vm_writev (pid_t __pid, const struct iovec *__lvec,
51#define RWF_ATOMIC 0x00000040 /* Write is to be issued with torn-write51#define RWF_ATOMIC 0x00000040 /* Write is to be issued with torn-write
52 prevention. */52 prevention. */
53#define RWF_DONTCACHE 0x00000080 /* Uncached buffered IO. */53#define RWF_DONTCACHE 0x00000080 /* Uncached buffered IO. */
54#define RWF_NOSIGNAL 0x00000100 /* Do not generate SIGPIPE on error. */
5455
55__END_DECLS56__END_DECLS
5657
lib/libc/include/generic-glibc/dlfcn.h+6-1
...@@ -167,7 +167,12 @@ enum...@@ -167,7 +167,12 @@ enum
167 the number of program headers in the array. */167 the number of program headers in the array. */
168 RTLD_DI_PHDR = 11,168 RTLD_DI_PHDR = 11,
169169
170 RTLD_DI_MAX = 11170 /* 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
171 };176 };
172177
173178
lib/libc/include/generic-glibc/elf.h+6-2
...@@ -798,7 +798,8 @@ typedef struct...@@ -798,7 +798,8 @@ typedef struct
798#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */798#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */
799#define NT_X86_SHSTK 0x204 /* x86 SHSTK state */799#define NT_X86_SHSTK 0x204 /* x86 SHSTK state */
800#define NT_X86_XSAVE_LAYOUT 0x205 /* XSAVE layout description. */800#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. */
802#define NT_S390_TIMER 0x301 /* s390 timer register */803#define NT_S390_TIMER 0x301 /* s390 timer register */
803#define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */804#define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */
804#define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */805#define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */
...@@ -846,6 +847,7 @@ typedef struct...@@ -846,6 +847,7 @@ typedef struct
846#define NT_RISCV_VECTOR 0x901 /* RISC-V vector registers */847#define NT_RISCV_VECTOR 0x901 /* RISC-V vector registers */
847#define NT_RISCV_TAGGED_ADDR_CTRL 0x902 /* RISC-V tagged848#define NT_RISCV_TAGGED_ADDR_CTRL 0x902 /* RISC-V tagged
848 address control */849 address control */
850#define NT_RISCV_USER_CFI 0x903 /* RISC-V shadow stack state */
849#define NT_LOONGARCH_CPUCFG 0xa00 /* LoongArch CPU config registers. */851#define NT_LOONGARCH_CPUCFG 0xa00 /* LoongArch CPU config registers. */
850#define NT_LOONGARCH_CSR 0xa01 /* LoongArch control and852#define NT_LOONGARCH_CSR 0xa01 /* LoongArch control and
851 status registers. */853 status registers. */
...@@ -3470,7 +3472,9 @@ enum...@@ -3470,7 +3472,9 @@ enum
34703472
3471/* Valid values for the e_flags field. */3473/* 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
3475/* Additional s390 relocs */3479/* Additional s390 relocs */
34763480
lib/libc/include/generic-glibc/features.h+2-2
...@@ -162,7 +162,7 @@...@@ -162,7 +162,7 @@
162#undef __GLIBC_USE_DEPRECATED_SCANF162#undef __GLIBC_USE_DEPRECATED_SCANF
163#undef __GLIBC_USE_C23_STRTOL163#undef __GLIBC_USE_C23_STRTOL
164164
165/* Suppress kernel-name space pollution unless user expressedly asks165/* Suppress kernel-name space pollution unless user explicitly asks
166 for it. */166 for it. */
167#ifndef _LOOSE_KERNEL_NAMES167#ifndef _LOOSE_KERNEL_NAMES
168# define __KERNEL_STRICT_NAMES168# define __KERNEL_STRICT_NAMES
...@@ -580,4 +580,4 @@...@@ -580,4 +580,4 @@
580#include <gnu/stubs.h>580#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 @@...@@ -52,7 +52,29 @@
5252
53#include <features.h>53#include <features.h>
54#include <sys/types.h>54#include <sys/types.h>
5555#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
57typedef struct {79typedef struct {
58 struct _ftsent *fts_cur; /* current node */80 struct _ftsent *fts_cur; /* current node */
...@@ -73,11 +95,106 @@ typedef struct {...@@ -73,11 +95,106 @@ typedef struct {
73#define FTS_SEEDOT 0x0020 /* return dot and dot-dot */95#define FTS_SEEDOT 0x0020 /* return dot and dot-dot */
74#define FTS_XDEV 0x0040 /* don't cross devices */96#define FTS_XDEV 0x0040 /* don't cross devices */
75#define FTS_WHITEOUT 0x0080 /* return whiteout information */97#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
78#define FTS_NAMEONLY 0x0100 /* (private) child names only */155#define FTS_NAMEONLY 0x0100 /* (private) child names only */
79#define FTS_STOP 0x0200 /* (private) unrecoverable error */156#define FTS_STOP 0x0200 /* (private) unrecoverable error */
157
80 int fts_options; /* fts_open options, global flags */158 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;
81} FTS;198} FTS;
82199
83#ifdef __USE_LARGEFILE64200#ifdef __USE_LARGEFILE64
...@@ -92,6 +209,13 @@ typedef struct {...@@ -92,6 +209,13 @@ typedef struct {
92 int fts_nitems; /* elements in the sort array */209 int fts_nitems; /* elements in the sort array */
93 int (*fts_compar) (const void *, const void *); /* compare fn */210 int (*fts_compar) (const void *, const void *); /* compare fn */
94 int fts_options; /* fts_open options, global flags */211 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;
95} FTS64;219} FTS64;
96#endif220#endif
97221
lib/libc/include/generic-glibc/gnu/lib-names-32.h+1
...@@ -24,4 +24,5 @@...@@ -24,4 +24,5 @@
24#define LIBRESOLV_SO "libresolv.so.2"24#define LIBRESOLV_SO "libresolv.so.2"
25#define LIBRT_SO "librt.so.1"25#define LIBRT_SO "librt.so.1"
26#define LIBTHREAD_DB_SO "libthread_db.so.1"26#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
27#define LIBUTIL_SO "libutil.so.1"28#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 @@...@@ -24,4 +24,5 @@
24#define LIBRESOLV_SO "libresolv.so.2"24#define LIBRESOLV_SO "libresolv.so.2"
25#define LIBRT_SO "librt.so.1"25#define LIBRT_SO "librt.so.1"
26#define LIBTHREAD_DB_SO "libthread_db.so.1"26#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
27#define LIBUTIL_SO "libutil.so.1"28#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 @@...@@ -23,4 +23,5 @@
23#define LIBRESOLV_SO "libresolv.so.2"23#define LIBRESOLV_SO "libresolv.so.2"
24#define LIBRT_SO "librt.so.1"24#define LIBRT_SO "librt.so.1"
25#define LIBTHREAD_DB_SO "libthread_db.so.1"25#define LIBTHREAD_DB_SO "libthread_db.so.1"
26#define LIBUNWIND_SO "libunwind.so.1"
26#define LIBUTIL_SO "libutil.so.1"27#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 @@...@@ -23,4 +23,5 @@
23#define LIBRESOLV_SO "libresolv.so.2"23#define LIBRESOLV_SO "libresolv.so.2"
24#define LIBRT_SO "librt.so.1"24#define LIBRT_SO "librt.so.1"
25#define LIBTHREAD_DB_SO "libthread_db.so.1"25#define LIBTHREAD_DB_SO "libthread_db.so.1"
26#define LIBUNWIND_SO "libunwind.so.1"
26#define LIBUTIL_SO "libutil.so.1"27#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 @@...@@ -23,4 +23,5 @@
23#define LIBRESOLV_SO "libresolv.so.2"23#define LIBRESOLV_SO "libresolv.so.2"
24#define LIBRT_SO "librt.so.1"24#define LIBRT_SO "librt.so.1"
25#define LIBTHREAD_DB_SO "libthread_db.so.1"25#define LIBTHREAD_DB_SO "libthread_db.so.1"
26#define LIBUNWIND_SO "libunwind.so.1"
26#define LIBUTIL_SO "libutil.so.1"27#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 @@...@@ -23,4 +23,5 @@
23#define LIBRESOLV_SO "libresolv.so.2"23#define LIBRESOLV_SO "libresolv.so.2"
24#define LIBRT_SO "librt.so.1"24#define LIBRT_SO "librt.so.1"
25#define LIBTHREAD_DB_SO "libthread_db.so.1"25#define LIBTHREAD_DB_SO "libthread_db.so.1"
26#define LIBUNWIND_SO "libunwind.so.1"
26#define LIBUTIL_SO "libutil.so.1"27#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 @@...@@ -24,4 +24,5 @@
24#define LIBRESOLV_SO "libresolv.so.2"24#define LIBRESOLV_SO "libresolv.so.2"
25#define LIBRT_SO "librt.so.1"25#define LIBRT_SO "librt.so.1"
26#define LIBTHREAD_DB_SO "libthread_db.so.1"26#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
27#define LIBUTIL_SO "libutil.so.1"28#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...@@ -91,6 +91,8 @@ enum
91#define IPPROTO_MPLS IPPROTO_MPLS91#define IPPROTO_MPLS IPPROTO_MPLS
92 IPPROTO_ETHERNET = 143, /* Ethernet-within-IPv6 Encapsulation. */92 IPPROTO_ETHERNET = 143, /* Ethernet-within-IPv6 Encapsulation. */
93#define IPPROTO_ETHERNET IPPROTO_ETHERNET93#define IPPROTO_ETHERNET IPPROTO_ETHERNET
94 IPPROTO_AGGFRAG = 144, /* AGGFRAG in ESP (RFC 9347). */
95#define IPPROTO_AGGFRAG IPPROTO_AGGFRAG
94 IPPROTO_RAW = 255, /* Raw IP packets. */96 IPPROTO_RAW = 255, /* Raw IP packets. */
95#define IPPROTO_RAW IPPROTO_RAW97#define IPPROTO_RAW IPPROTO_RAW
96 IPPROTO_SMC = 256, /* Shared Memory Communications. */98 IPPROTO_SMC = 256, /* Shared Memory Communications. */
lib/libc/include/generic-glibc/netinet/tcp.h+25-2
...@@ -80,6 +80,9 @@...@@ -80,6 +80,9 @@
80 as a cmsg on read. */80 as a cmsg on read. */
81#define TCP_CM_INQ TCP_INQ81#define TCP_CM_INQ TCP_INQ
82#define TCP_TX_DELAY 37 /* Delay outgoing packets by XX usec. */82#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
84#define TCP_REPAIR_ON 187#define TCP_REPAIR_ON 1
85#define TCP_REPAIR_OFF 088#define TCP_REPAIR_OFF 0
...@@ -226,6 +229,24 @@ enum tcp_ca_state...@@ -226,6 +229,24 @@ enum tcp_ca_state
226 TCP_CA_Loss = 4229 TCP_CA_Loss = 4
227};230};
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
229struct tcp_info250struct tcp_info
230{251{
231 uint8_t tcpi_state;252 uint8_t tcpi_state;
...@@ -319,8 +340,10 @@ struct tcp_info...@@ -319,8 +340,10 @@ struct tcp_info
319 uint32_t tcpi_received_e1_bytes;340 uint32_t tcpi_received_e1_bytes;
320 uint32_t tcpi_received_e0_bytes;341 uint32_t tcpi_received_e0_bytes;
321 uint32_t tcpi_received_ce_bytes;342 uint32_t tcpi_received_ce_bytes;
322 uint16_t tcpi_accecn_fail_mode;343 uint32_t tcpi_ecn_mode:2,
323 uint16_t tcpi_accecn_opt_seen;344 tcpi_accecn_opt_seen:2,
345 tcpi_accecn_fail_mode:4,
346 tcpi_options2:24;
324};347};
325348
326/* Netlink attributes types for SCM_TIMESTAMPING_OPT_STATS */349/* 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;...@@ -74,7 +74,7 @@ typedef unsigned long int reg_syntax_t;
74#ifdef __USE_GNU74#ifdef __USE_GNU
75/* If this bit is not set, then \ inside a bracket expression is literal.75/* If this bit is not set, then \ inside a bracket expression is literal.
76 If set, then such a \ quotes the following character. */76 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
79/* If this bit is not set, then + and ? are operators, and \+ and \? are79/* If this bit is not set, then + and ? are operators, and \+ and \? are
80 literals.80 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 *...@@ -200,6 +200,26 @@ extern int posix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t *
200 int __fd, int __newfd)200 int __fd, int __newfd)
201 __THROW __nonnull ((1));201 __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
203#ifdef __USE_MISC223#ifdef __USE_MISC
204/* Add an action changing the directory to PATH during spawn. This224/* Add an action changing the directory to PATH during spawn. This
205 affects the subsequent file actions. */225 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);...@@ -1225,4 +1225,4 @@ extern size_t memalignment (const void *__p);
12251225
1226__END_DECLS1226__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 @@...@@ -21,7 +21,6 @@
21#ifndef _SYS_MOUNT_H21#ifndef _SYS_MOUNT_H
22#define _SYS_MOUNT_H 122#define _SYS_MOUNT_H 1
2323
24#include <fcntl.h>
25#include <features.h>24#include <features.h>
26#include <stdint.h>25#include <stdint.h>
27#include <stddef.h>26#include <stddef.h>
...@@ -190,6 +189,11 @@ enum...@@ -190,6 +189,11 @@ enum
190189
191/* fsmount flags. */190/* fsmount flags. */
192#define FSMOUNT_CLOEXEC 0x00000001191#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
194/* mount attributes used on fsmount. */198/* mount attributes used on fsmount. */
195#define MOUNT_ATTR_RDONLY 0x00000001 /* Mount read-only. */199#define MOUNT_ATTR_RDONLY 0x00000001 /* Mount read-only. */
...@@ -267,10 +271,20 @@ enum fsconfig_command...@@ -267,10 +271,20 @@ enum fsconfig_command
267#define FSOPEN_CLOEXEC 0x00000001271#define FSOPEN_CLOEXEC 0x00000001
268272
269/* open_tree flags. */273/* open_tree flags. */
270#define OPEN_TREE_CLONE 1 /* Clone the target tree and attach the clone */274#ifndef OPEN_TREE_CLONE
271#define OPEN_TREE_CLOEXEC O_CLOEXEC /* Close the file on execve() */275# define OPEN_TREE_CLONE 1 /* Clone the target tree and attach the clone */
272276#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
273#endif282#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
275__BEGIN_DECLS289__BEGIN_DECLS
276290
lib/libc/include/generic-glibc/sys/pidfd.h+26
...@@ -64,6 +64,15 @@...@@ -64,6 +64,15 @@
64#define PIDFD_INFO_EXIT (1UL << 3)64#define PIDFD_INFO_EXIT (1UL << 3)
65/* Only returned if requested. */65/* Only returned if requested. */
66#define PIDFD_INFO_COREDUMP (1UL << 4)66#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
69/* Value for coredump_mask in pidfd_info. Only valid if PIDFD_INFO_COREDUMP78/* Value for coredump_mask in pidfd_info. Only valid if PIDFD_INFO_COREDUMP
...@@ -95,11 +104,28 @@ struct pidfd_info...@@ -95,11 +104,28 @@ struct pidfd_info
95 __uint32_t fsgid;104 __uint32_t fsgid;
96 __int32_t exit_code;105 __int32_t exit_code;
97 __uint32_t coredump_mask;106 __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
98 __uint32_t __spare1;114 __uint32_t __spare1;
115#endif /* (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 44) || __GLIBC__ > 2 */
99};116};
100117
101/* sizeof first published struct */118/* sizeof first published struct */
102#define PIDFD_INFO_SIZE_VER0 64119#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
104#define PIDFD_GET_INFO _IOWR(PIDFS_IOCTL_MAGIC, 11, struct pidfd_info)130#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,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
3/*-3/*-
4 * Copyright (c) 1983, 1990, 19934 * Copyright (c) 1983, 1990, 1993
...@@ -121,6 +121,9 @@...@@ -121,6 +121,9 @@
121#if defined(_NETBSD_SOURCE)121#if defined(_NETBSD_SOURCE)
122#define O_NOSIGPIPE 0x01000000 /* don't deliver sigpipe */122#define O_NOSIGPIPE 0x01000000 /* don't deliver sigpipe */
123#define O_REGULAR 0x02000000 /* fail if not a regular file */123#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)
124#define O_EXEC 0x04000000 /* open for executing only */127#define O_EXEC 0x04000000 /* open for executing only */
125#endif128#endif
126#if (_POSIX_C_SOURCE - 0) >= 202405L || (_XOPEN_SOURCE - 0 >= 800) || \129#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,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
3/*-3/*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
...@@ -40,6 +40,7 @@...@@ -40,6 +40,7 @@
40#define _UC_CLRSTACK _UC_MD_BIT1740#define _UC_CLRSTACK _UC_MD_BIT17
41#define _UC_VM _UC_MD_BIT1841#define _UC_VM _UC_MD_BIT18
42#define _UC_TLSBASE _UC_MD_BIT1942#define _UC_TLSBASE _UC_MD_BIT19
43#define _UC_XSAVE _UC_MD_BIT20
4344
44/*45/*
45 * Layout of mcontext_t according to the System V Application Binary Interface,46 * Layout of mcontext_t according to the System V Application Binary Interface,
...@@ -85,6 +86,27 @@ typedef struct {...@@ -85,6 +86,27 @@ typedef struct {
85 char __fp_xmm[512];86 char __fp_xmm[512];
86 } __fp_xmm_state; /* x87 and xmm regs in fxsave format */87 } __fp_xmm_state; /* x87 and xmm regs in fxsave format */
87 int __fp_fpregs[128];88 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;
88 } __fp_reg_set;110 } __fp_reg_set;
89 int __fp_pad[33]; /* Historic padding */111 int __fp_pad[33]; /* Historic padding */
90} __fpregset_t;112} __fpregset_t;
lib/libc/include/generic-netbsd/i386/wchar_limits.h+1-1
...@@ -44,4 +44,4 @@...@@ -44,4 +44,4 @@
44#define WINT_MIN (-0x7fffffff-1) /* wint_t */44#define WINT_MIN (-0x7fffffff-1) /* wint_t */
45#define WINT_MAX 0x7fffffff /* wint_t */45#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,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
3/*3/*
4 * Copyright (c) 2014, 2019, 2021 The NetBSD Foundation, Inc.4 * Copyright (c) 2014, 2019, 2021 The NetBSD Foundation, Inc.
...@@ -139,6 +139,12 @@ pte_modified_p(pt_entry_t pte)...@@ -139,6 +139,12 @@ pte_modified_p(pt_entry_t pte)
139 return (pte & PTE_D) != 0;139 return (pte & PTE_D) != 0;
140}140}
141141
142static inline bool
143pte_referenced_p(pt_entry_t pte)
144{
145 return (pte & PTE_A) != 0;
146}
147
142static inline bool148static inline bool
143pte_cached_p(pt_entry_t pte)149pte_cached_p(pt_entry_t pte)
144{150{
...@@ -177,9 +183,15 @@ pte_nv_entry(bool kernel_p)...@@ -177,9 +183,15 @@ pte_nv_entry(bool kernel_p)
177}183}
178184
179static inline pt_entry_t185static 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)
181{193{
182 return pte & ~PTE_W;194 return pte & ~PTE_A;
183}195}
184196
185static inline pt_entry_t197static inline pt_entry_t
...@@ -237,28 +249,29 @@ pte_make_enter(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot,...@@ -237,28 +249,29 @@ pte_make_enter(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot,
237 pte |= pte_prot_bits(mdpg, prot, kernel_p);249 pte |= pte_prot_bits(mdpg, prot, kernel_p);
238 pte |= pte_enter_flags_to_pbmt(flags);250 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 &&260 if (mdpg != NULL) {
243 ((flags & VM_PROT_WRITE) != 0 || VM_PAGEMD_MODIFIED_P(mdpg))) {261 if ((prot & VM_PROT_WRITE) != 0 && VM_PAGEMD_MODIFIED_P(mdpg)) {
244 /*262 /*
245 * This is a writable mapping, and the page's mod state263 * This is a writable mapping, and the page's mod state
246 * indicates it has already been modified. No need for264 * indicates it has already been modified. No need for
247 * modified emulation.265 * reference or modified emulation.
248 */266 */
249 pte |= PTE_A | PTE_D;267 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)) {
251 /*269 /*
252 * - The access type indicates that we don't need to do270 * The physical page has already been referenced so no need
253 * referenced emulation.271 * to re-do referenced emulation here.
254 * OR272 */
255 * - The physical page has already been referenced so no need
256 * to re-do referenced emulation here.
257 */
258 pte |= PTE_A;273 pte |= PTE_A;
259 }274 }
260 } else {
261 pte |= PTE_A | PTE_D;
262 }275 }
263276
264 return pte;277 return pte;
lib/libc/include/generic-netbsd/machine/vmparam.h+21-9
...@@ -1,4 +1,4 @@...@@ -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
3/*-3/*-
4 * Copyright (c) 2014, 2020 The NetBSD Foundation, Inc.4 * Copyright (c) 2014, 2020 The NetBSD Foundation, Inc.
...@@ -50,6 +50,25 @@...@@ -50,6 +50,25 @@
50#define PAGE_SIZE (1 << PAGE_SHIFT)50#define PAGE_SIZE (1 << PAGE_SHIFT)
51#define PAGE_MASK (PAGE_SIZE - 1)51#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
53/*72/*
54 * USRSTACK is the top (end) of the user stack.73 * USRSTACK is the top (end) of the user stack.
55 *74 *
...@@ -125,12 +144,6 @@...@@ -125,12 +144,6 @@
125#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)0xffffffd000000000)144#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)0xffffffd000000000)
126145
127#else /* Sv32 */146#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
135/*148/*
136 * kernel virtual space layout without direct map (common case)149 * kernel virtual space layout without direct map (common case)
...@@ -154,13 +167,12 @@...@@ -154,13 +167,12 @@
154 *167 *
155 */168 */
156169
157
158
159#define VM_MAXUSER_ADDRESS ((vaddr_t)-0x7fffffff-1)/* 0xffff_ffff_8000_0000 */170#define VM_MAXUSER_ADDRESS ((vaddr_t)-0x7fffffff-1)/* 0xffff_ffff_8000_0000 */
160#define VM_MIN_KERNEL_ADDRESS ((vaddr_t)-0x7fffffff-1)/* 0xffff_ffff_8000_0000 */171#define VM_MIN_KERNEL_ADDRESS ((vaddr_t)-0x7fffffff-1)/* 0xffff_ffff_8000_0000 */
161#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)-0x10000000) /* 0xffff_ffff_f000_0000 */172#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)-0x10000000) /* 0xffff_ffff_f000_0000 */
162173
163#endif174#endif
175
164#define VM_KERNEL_BASE VM_MIN_KERNEL_ADDRESS176#define VM_KERNEL_BASE VM_MIN_KERNEL_ADDRESS
165#define VM_KERNEL_SIZE 0x2000000 /* 32 MiB (8 / 16 megapages) */177#define VM_KERNEL_SIZE 0x2000000 /* 32 MiB (8 / 16 megapages) */
166#define VM_KERNEL_DTB_BASE (VM_KERNEL_BASE + VM_KERNEL_SIZE)178#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,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
3/*-3/*-
4 * Copyright (c) 1997 The NetBSD Foundation, Inc.4 * Copyright (c) 1997 The NetBSD Foundation, Inc.
...@@ -269,6 +269,12 @@ pte_modified_p(pt_entry_t pte)...@@ -269,6 +269,12 @@ pte_modified_p(pt_entry_t pte)
269 return (pte & MIPS_MMU(PG_D)) != 0;269 return (pte & MIPS_MMU(PG_D)) != 0;
270}270}
271271
272static inline bool
273pte_referenced_p(pt_entry_t pte)
274{
275 return false;
276}
277
272static inline bool278static inline bool
273pte_global_p(pt_entry_t pte)279pte_global_p(pt_entry_t pte)
274{280{
...@@ -340,11 +346,17 @@ pte_prot_downgrade(pt_entry_t pte, vm_prot_t prot)...@@ -340,11 +346,17 @@ pte_prot_downgrade(pt_entry_t pte, vm_prot_t prot)
340}346}
341347
342static inline pt_entry_t348static inline pt_entry_t
343pte_prot_nowrite(pt_entry_t pte)349pte_clear_modify(pt_entry_t pte)
344{350{
345 return pte & ~MIPS_MMU(PG_D);351 return pte & ~MIPS_MMU(PG_D);
346}352}
347353
354static inline pt_entry_t
355pte_clear_reference(pt_entry_t pte)
356{
357 return pte;
358}
359
348static inline pt_entry_t360static inline pt_entry_t
349pte_cached_change(pt_entry_t pte, bool cached)361pte_cached_change(pt_entry_t pte, bool cached)
350{362{
lib/libc/include/generic-netbsd/netinet/tcp_timer.h+2-2
...@@ -1,4 +1,4 @@...@@ -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
3/*-3/*-
4 * Copyright (c) 2001, 2005 The NetBSD Foundation, Inc.4 * Copyright (c) 2001, 2005 The NetBSD Foundation, Inc.
...@@ -119,7 +119,7 @@...@@ -119,7 +119,7 @@
119#define TCPTV_MSL ( 30*PR_SLOWHZ) /* max seg lifetime (hah!) */119#define TCPTV_MSL ( 30*PR_SLOWHZ) /* max seg lifetime (hah!) */
120#define TCPTV_SRTTBASE 0 /* base roundtrip time;120#define TCPTV_SRTTBASE 0 /* base roundtrip time;
121 if 0, no idea yet */121 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
124#define TCPTV_PERSMIN ( 5*PR_SLOWHZ) /* retransmit persistance */124#define TCPTV_PERSMIN ( 5*PR_SLOWHZ) /* retransmit persistance */
125#define TCPTV_PERSMAX ( 60*PR_SLOWHZ) /* maximum persist interval */125#define TCPTV_PERSMAX ( 60*PR_SLOWHZ) /* maximum persist interval */
lib/libc/include/generic-netbsd/nfs/nfs.h+3-1
...@@ -1,4 +1,4 @@...@@ -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 $ */
2/*2/*
3 * Copyright (c) 1989, 1993, 19953 * Copyright (c) 1989, 1993, 1995
4 * The Regents of the University of California. All rights reserved.4 * The Regents of the University of California. All rights reserved.
...@@ -451,6 +451,8 @@ struct nfssvc_sock {...@@ -451,6 +451,8 @@ struct nfssvc_sock {
451 int ns_sflags; /* b: */451 int ns_sflags; /* b: */
452 int ns_cc; /* b: */452 int ns_cc; /* b: */
453 int ns_reclen; /* b: */453 int ns_reclen; /* b: */
454 int ns_frag_count; /* b: */
455 int ns_streamlen; /* b: */
454 int ns_numuids;456 int ns_numuids;
455 u_int32_t ns_sref; /* g: */457 u_int32_t ns_sref; /* g: */
456 SIMPLEQ_HEAD(, nfsrv_descript) ns_sendq; /* s: send reply list */458 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,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
3/*3/*
4 * Copyright (c) 1989, 19934 * Copyright (c) 1989, 1993
...@@ -92,13 +92,15 @@ struct nfs_args {...@@ -92,13 +92,15 @@ struct nfs_args {
92#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */92#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
93#define NFSMNT_XLATECOOKIE 0x00040000 /* 32<->64 dir cookie xlation */93#define NFSMNT_XLATECOOKIE 0x00040000 /* 32<->64 dir cookie xlation */
94#define NFSMNT_NOAC 0x00080000 /* Turn off attribute cache */94#define NFSMNT_NOAC 0x00080000 /* Turn off attribute cache */
95#define NFSMNT_NOWCCMSG 0x00100000 /* Turn off attribute wcc messages */
9596
96#define NFSMNT_BITS "\177\20" \97#define NFSMNT_BITS "\177\20" \
97 "b\00soft\0b\01wsize\0b\02rsize\0b\03timeo\0" \98 "b\00soft\0b\01wsize\0b\02rsize\0b\03timeo\0" \
98 "b\04retrans\0b\05maxgrps\0b\06intr\0b\07noconn\0" \99 "b\04retrans\0b\05maxgrps\0b\06intr\0b\07noconn\0" \
99 "b\10nqnfs\0b\11nfsv3\0b\12kerb\0b\13dumbtimr\0" \100 "b\10nqnfs\0b\11nfsv3\0b\12kerb\0b\13dumbtimr\0" \
100 "b\14leaseterm\0b\15readahead\0b\16deadthresh\0b\17resvport\0" \101 "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
103/*105/*
104 * NFS internal flags (nm_iflag) */106 * NFS internal flags (nm_iflag) */
lib/libc/include/generic-netbsd/pthread.h+1-1
...@@ -461,4 +461,4 @@ __END_DECLS...@@ -461,4 +461,4 @@ __END_DECLS
461461
462#endif /* __LIBPTHREAD_SOURCE__ */462#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,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
3/*3/*
4 * Copyright (c) 2014, 2019, 2021 The NetBSD Foundation, Inc.4 * Copyright (c) 2014, 2019, 2021 The NetBSD Foundation, Inc.
...@@ -139,6 +139,12 @@ pte_modified_p(pt_entry_t pte)...@@ -139,6 +139,12 @@ pte_modified_p(pt_entry_t pte)
139 return (pte & PTE_D) != 0;139 return (pte & PTE_D) != 0;
140}140}
141141
142static inline bool
143pte_referenced_p(pt_entry_t pte)
144{
145 return (pte & PTE_A) != 0;
146}
147
142static inline bool148static inline bool
143pte_cached_p(pt_entry_t pte)149pte_cached_p(pt_entry_t pte)
144{150{
...@@ -177,9 +183,15 @@ pte_nv_entry(bool kernel_p)...@@ -177,9 +183,15 @@ pte_nv_entry(bool kernel_p)
177}183}
178184
179static inline pt_entry_t185static 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)
181{193{
182 return pte & ~PTE_W;194 return pte & ~PTE_A;
183}195}
184196
185static inline pt_entry_t197static inline pt_entry_t
...@@ -237,28 +249,29 @@ pte_make_enter(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot,...@@ -237,28 +249,29 @@ pte_make_enter(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot,
237 pte |= pte_prot_bits(mdpg, prot, kernel_p);249 pte |= pte_prot_bits(mdpg, prot, kernel_p);
238 pte |= pte_enter_flags_to_pbmt(flags);250 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 &&260 if (mdpg != NULL) {
243 ((flags & VM_PROT_WRITE) != 0 || VM_PAGEMD_MODIFIED_P(mdpg))) {261 if ((prot & VM_PROT_WRITE) != 0 && VM_PAGEMD_MODIFIED_P(mdpg)) {
244 /*262 /*
245 * This is a writable mapping, and the page's mod state263 * This is a writable mapping, and the page's mod state
246 * indicates it has already been modified. No need for264 * indicates it has already been modified. No need for
247 * modified emulation.265 * reference or modified emulation.
248 */266 */
249 pte |= PTE_A | PTE_D;267 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)) {
251 /*269 /*
252 * - The access type indicates that we don't need to do270 * The physical page has already been referenced so no need
253 * referenced emulation.271 * to re-do referenced emulation here.
254 * OR272 */
255 * - The physical page has already been referenced so no need
256 * to re-do referenced emulation here.
257 */
258 pte |= PTE_A;273 pte |= PTE_A;
259 }274 }
260 } else {
261 pte |= PTE_A | PTE_D;
262 }275 }
263276
264 return pte;277 return pte;
lib/libc/include/generic-netbsd/riscv/vmparam.h+21-9
...@@ -1,4 +1,4 @@...@@ -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
3/*-3/*-
4 * Copyright (c) 2014, 2020 The NetBSD Foundation, Inc.4 * Copyright (c) 2014, 2020 The NetBSD Foundation, Inc.
...@@ -50,6 +50,25 @@...@@ -50,6 +50,25 @@
50#define PAGE_SIZE (1 << PAGE_SHIFT)50#define PAGE_SIZE (1 << PAGE_SHIFT)
51#define PAGE_MASK (PAGE_SIZE - 1)51#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
53/*72/*
54 * USRSTACK is the top (end) of the user stack.73 * USRSTACK is the top (end) of the user stack.
55 *74 *
...@@ -125,12 +144,6 @@...@@ -125,12 +144,6 @@
125#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)0xffffffd000000000)144#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)0xffffffd000000000)
126145
127#else /* Sv32 */146#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
135/*148/*
136 * kernel virtual space layout without direct map (common case)149 * kernel virtual space layout without direct map (common case)
...@@ -154,13 +167,12 @@...@@ -154,13 +167,12 @@
154 *167 *
155 */168 */
156169
157
158
159#define VM_MAXUSER_ADDRESS ((vaddr_t)-0x7fffffff-1)/* 0xffff_ffff_8000_0000 */170#define VM_MAXUSER_ADDRESS ((vaddr_t)-0x7fffffff-1)/* 0xffff_ffff_8000_0000 */
160#define VM_MIN_KERNEL_ADDRESS ((vaddr_t)-0x7fffffff-1)/* 0xffff_ffff_8000_0000 */171#define VM_MIN_KERNEL_ADDRESS ((vaddr_t)-0x7fffffff-1)/* 0xffff_ffff_8000_0000 */
161#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)-0x10000000) /* 0xffff_ffff_f000_0000 */172#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)-0x10000000) /* 0xffff_ffff_f000_0000 */
162173
163#endif174#endif
175
164#define VM_KERNEL_BASE VM_MIN_KERNEL_ADDRESS176#define VM_KERNEL_BASE VM_MIN_KERNEL_ADDRESS
165#define VM_KERNEL_SIZE 0x2000000 /* 32 MiB (8 / 16 megapages) */177#define VM_KERNEL_SIZE 0x2000000 /* 32 MiB (8 / 16 megapages) */
166#define VM_KERNEL_DTB_BASE (VM_KERNEL_BASE + VM_KERNEL_SIZE)178#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,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
3/*-3/*-
4 * Copyright (c) 1983, 1990, 19934 * Copyright (c) 1983, 1990, 1993
...@@ -121,6 +121,9 @@...@@ -121,6 +121,9 @@
121#if defined(_NETBSD_SOURCE)121#if defined(_NETBSD_SOURCE)
122#define O_NOSIGPIPE 0x01000000 /* don't deliver sigpipe */122#define O_NOSIGPIPE 0x01000000 /* don't deliver sigpipe */
123#define O_REGULAR 0x02000000 /* fail if not a regular file */123#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)
124#define O_EXEC 0x04000000 /* open for executing only */127#define O_EXEC 0x04000000 /* open for executing only */
125#endif128#endif
126#if (_POSIX_C_SOURCE - 0) >= 202405L || (_XOPEN_SOURCE - 0 >= 800) || \129#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,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
3/*3/*
4 * Copyright (c) 2014 by Lourival Vieira Neto <lneto@NetBSD.org>.4 * Copyright (c) 2014 by Lourival Vieira Neto <lneto@NetBSD.org>.
...@@ -33,7 +33,9 @@...@@ -33,7 +33,9 @@
33#define _SYS_LUA_H_33#define _SYS_LUA_H_
3434
35#include <sys/param.h>35#include <sys/param.h>
36
36#include <sys/ioccom.h>37#include <sys/ioccom.h>
38#include <sys/stdbool.h>
3739
38#include <lua.h> /* for lua_State */40#include <lua.h> /* for lua_State */
3941
lib/libc/include/generic-netbsd/sys/param.h+2-2
...@@ -1,4 +1,4 @@...@@ -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
3/*-3/*-
4 * Copyright (c) 1982, 1986, 1989, 19934 * Copyright (c) 1982, 1986, 1989, 1993
...@@ -566,4 +566,4 @@ extern size_t coherency_unit;...@@ -566,4 +566,4 @@ extern size_t coherency_unit;
566#endif566#endif
567#endif /* !__ASSEMBLER__ */567#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,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
3#ifndef _X86_CPU_EXTENDED_STATE_H_3#ifndef _X86_CPU_EXTENDED_STATE_H_
4#define _X86_CPU_EXTENDED_STATE_H_4#define _X86_CPU_EXTENDED_STATE_H_
...@@ -142,6 +142,8 @@ struct xsave_header {...@@ -142,6 +142,8 @@ struct xsave_header {
142};142};
143__CTASSERT(sizeof(struct xsave_header) == 512 + 64);143__CTASSERT(sizeof(struct xsave_header) == 512 + 64);
144144
145#define XSAVE_ALIGN 64
146
145/*147/*
146 * The ymm save area actually follows the xsave_header.148 * The ymm save area actually follows the xsave_header.
147 */149 */
lib/libc/include/generic-netbsd/x86/fpu.h+7-1
...@@ -1,4 +1,4 @@...@@ -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
3#ifndef _X86_FPU_H_3#ifndef _X86_FPU_H_
4#define _X86_FPU_H_4#define _X86_FPU_H_
...@@ -46,6 +46,12 @@ int process_read_xstate(struct lwp *, struct xstate *);...@@ -46,6 +46,12 @@ int process_read_xstate(struct lwp *, struct xstate *);
46int process_verify_xstate(const struct xstate *);46int process_verify_xstate(const struct xstate *);
47int process_write_xstate(struct lwp *, const struct xstate *);47int 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
49#endif55#endif
5056
51#endif /* _X86_FPU_H_ */57#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,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
3/*3/*
4 * Copyright (c) 2014-2020 The NetBSD Foundation, Inc.4 * Copyright (c) 2014-2020 The NetBSD Foundation, Inc.
...@@ -183,16 +183,82 @@...@@ -183,16 +183,82 @@
183 "\0"183 "\0"
184184
185/*185/*
186 * Known FPU bits, only these get enabled. The save area is sized for all the186 * XCR0_FPU: Known FPU bits, only these get enabled. The save area is
187 * fields below.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
188 */239 */
189#if defined __i386__ || defined XENPV /* XXX XENPV PR kern/59371 */240#if defined __i386__ || defined XENPV /* XXX XENPV PR kern/59371 */
190#define XCR0_FPU (XCR0_X87 | XCR0_SSE | XCR0_YMM_Hi128 | \241#define XCR0_FPU (XCR0_X87 | XCR0_SSE | XCR0_YMM_Hi128 | \
191 XCR0_Opmask | XCR0_ZMM_Hi256 | XCR0_Hi16_ZMM)242 XCR0_Opmask | XCR0_ZMM_Hi256 | XCR0_Hi16_ZMM)
192#else243#else
193#define XCR0_FPU (XCR0_X87 | XCR0_SSE | XCR0_YMM_Hi128 | \244#define XCR0_FPU (XCR0_X87 | XCR0_SSE | XCR0_YMM_Hi128 | \
194 XCR0_Opmask | XCR0_ZMM_Hi256 | XCR0_Hi16_ZMM | \245 XCR0_Opmask | XCR0_ZMM_Hi256 | XCR0_Hi16_ZMM)
195 XCR0_TILECFG | XCR0_TILEDATA)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)))
196#endif262#endif
197263
198/*264/*
lib/libc/include/loongarch-linux-gnu/bits/hwcap.h+3-1
...@@ -36,4 +36,6 @@...@@ -36,4 +36,6 @@
36#define HWCAP_LOONGARCH_LBT_ARM (1 << 11)36#define HWCAP_LOONGARCH_LBT_ARM (1 << 11)
37#define HWCAP_LOONGARCH_LBT_MIPS (1 << 12)37#define HWCAP_LOONGARCH_LBT_MIPS (1 << 12)
38#define HWCAP_LOONGARCH_PTW (1 << 13)38#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 @@...@@ -15,5 +15,16 @@
15 License along with the GNU C Library; if not, see15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */16 <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;...@@ -94,6 +94,15 @@ extern void __loongarch_fpu_setcw (fpu_control_t) __THROW;
94#define _FPU_GETCW(cw) __asm__ volatile ("movfcsr2gr %0,$fcsr0" : "=r"(cw))94#define _FPU_GETCW(cw) __asm__ volatile ("movfcsr2gr %0,$fcsr0" : "=r"(cw))
95#define _FPU_SETCW(cw) __asm__ volatile ("movgr2fcsr $fcsr0,%0" : : "r"(cw))95#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
97/* Default control word set at startup. */106/* Default control word set at startup. */
98extern fpu_control_t __fpu_control;107extern 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 @@...@@ -24,4 +24,5 @@
24#define LIBRESOLV_SO "libresolv.so.2"24#define LIBRESOLV_SO "libresolv.so.2"
25#define LIBRT_SO "librt.so.1"25#define LIBRT_SO "librt.so.1"
26#define LIBTHREAD_DB_SO "libthread_db.so.1"26#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
27#define LIBUTIL_SO "libutil.so.1"28#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 @@...@@ -24,4 +24,5 @@
24#define LIBRESOLV_SO "libresolv.so.2"24#define LIBRESOLV_SO "libresolv.so.2"
25#define LIBRT_SO "librt.so.1"25#define LIBRT_SO "librt.so.1"
26#define LIBTHREAD_DB_SO "libthread_db.so.1"26#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
27#define LIBUTIL_SO "libutil.so.1"28#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 @@...@@ -6,6 +6,12 @@
66
7#include <bits/wordsize.h>7#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
9#if __WORDSIZE == 64 && defined __loongarch_soft_float15#if __WORDSIZE == 64 && defined __loongarch_soft_float
10# include <gnu/lib-names-lp64s.h>16# include <gnu/lib-names-lp64s.h>
11#endif17#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 @@...@@ -4,6 +4,12 @@
44
5#include <bits/wordsize.h>5#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
7#if __WORDSIZE == 64 && defined __loongarch_soft_float13#if __WORDSIZE == 64 && defined __loongarch_soft_float
8# include <gnu/stubs-lp64s.h>14# include <gnu/stubs-lp64s.h>
9#endif15#endif
lib/libc/include/loongarch-linux-gnu/sys/asm.h+32-6
...@@ -23,10 +23,8 @@...@@ -23,10 +23,8 @@
23#include <sysdeps/generic/sysdep.h>23#include <sysdeps/generic/sysdep.h>
2424
25/* Macros to handle different pointer/register sizes for 32/64-bit code. */25/* Macros to handle different pointer/register sizes for 32/64-bit code. */
26#if __loongarch_grlen == 64
26#define SZREG 827#define SZREG 8
27#define SZFREG 8
28#define SZVREG 16
29#define SZXREG 32
30#define REG_L ld.d28#define REG_L ld.d
31#define REG_S st.d29#define REG_S st.d
32#define SRLI srli.d30#define SRLI srli.d
...@@ -34,10 +32,38 @@...@@ -34,10 +32,38 @@
34#define ADDI addi.d32#define ADDI addi.d
35#define ADD add.d33#define ADD add.d
36#define SUB sub.d34#define SUB sub.d
37#define BSTRINS bstrins.d
38#define LI li.d35#define LI li.d
39#define FREG_L fld.d36#define BSTRINS bstrins.d
40#define FREG_S fst.d37
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
42/* Declare leaf routine.68/* Declare leaf routine.
43 The usage of macro LEAF/ENTRY is as follows:69 The usage of macro LEAF/ENTRY is as follows:
lib/libc/include/m68k-linux-gnu/gnu/lib-names.h+1
...@@ -24,6 +24,7 @@...@@ -24,6 +24,7 @@
24#define LIBRESOLV_SO "libresolv.so.2"24#define LIBRESOLV_SO "libresolv.so.2"
25#define LIBRT_SO "librt.so.1"25#define LIBRT_SO "librt.so.1"
26#define LIBTHREAD_DB_SO "libthread_db.so.1"26#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
27#define LIBUTIL_SO "libutil.so.1"28#define LIBUTIL_SO "libutil.so.1"
2829
29#endif /* gnu/lib-names.h */30#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 @@...@@ -1,5 +1,5 @@
1/* Properties of long double type. ldbl-opt version.1/* 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.
3 This file is part of the GNU C Library.3 This file is part of the GNU C Library.
44
5 The GNU C Library is free software; you can redistribute it and/or5 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...@@ -59,4 +59,4 @@ struct __pthread_mutex_s
59 0, 0, 0, __kind, 0, { { 0, 0 } }59 0, 0, 0, __kind, 0, { { 0, 0 } }
60#endif60#endif
6161
62#endif62#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 @@...@@ -24,4 +24,5 @@
24#define LIBRESOLV_SO "libresolv.so.2"24#define LIBRESOLV_SO "libresolv.so.2"
25#define LIBRT_SO "librt.so.1"25#define LIBRT_SO "librt.so.1"
26#define LIBTHREAD_DB_SO "libthread_db.so.1"26#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
27#define LIBUTIL_SO "libutil.so.1"28#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,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
3/*-3/*-
4 * Copyright (C) 1995, 1996 Wolfgang Solfrank.4 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
...@@ -122,11 +122,13 @@ __BEGIN_DECLS...@@ -122,11 +122,13 @@ __BEGIN_DECLS
122#include <sys/systm.h>122#include <sys/systm.h>
123123
124/*124/*
125 * For OEA and OEA64_BRIDGE, we guarantee that pa below USER_ADDR125 * Physical memory below PMAP_DIRECT_MAPPED_LEN is direct-mapped
126 * (== 3GB < VM_MIN_KERNEL_ADDRESS) 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.
127 */129 */
128#if defined(PPC_OEA) || defined(PPC_OEA64_BRIDGE)130#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)
130#define PMAP_DIRECT_MAPPED_LEN \132#define PMAP_DIRECT_MAPPED_LEN \
131 ((vaddr_t)SEGMENT_LENGTH * (PMAP_DIRECT_MAPPED_SR + 1))133 ((vaddr_t)SEGMENT_LENGTH * (PMAP_DIRECT_MAPPED_SR + 1))
132#endif134#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 @@...@@ -24,4 +24,5 @@
24#define LIBRESOLV_SO "libresolv.so.2"24#define LIBRESOLV_SO "libresolv.so.2"
25#define LIBRT_SO "librt.so.1"25#define LIBRT_SO "librt.so.1"
26#define LIBTHREAD_DB_SO "libthread_db.so.1"26#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
27#define LIBUTIL_SO "libutil.so.1"28#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 @@...@@ -24,4 +24,5 @@
24#define LIBRESOLV_SO "libresolv.so.2"24#define LIBRESOLV_SO "libresolv.so.2"
25#define LIBRT_SO "librt.so.1"25#define LIBRT_SO "librt.so.1"
26#define LIBTHREAD_DB_SO "libthread_db.so.1"26#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
27#define LIBUTIL_SO "libutil.so.1"28#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 @@...@@ -27,11 +27,6 @@
2727
28#define __ELF_NATIVE_CLASS __WORDSIZE28#define __ELF_NATIVE_CLASS __WORDSIZE
2929
30#if __WORDSIZE == 64
31/* 64 bit Linux for S/390 is exceptional as it has .hash section with30/* 64 bit Linux for S/390 is exceptional as it has .hash section with
32 64 bit entries. */31 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 @@...@@ -22,29 +22,20 @@
2222
23#include <bits/wordsize.h>23#include <bits/wordsize.h>
2424
25#if __WORDSIZE == 64
26/* Not necessary, files are always with 64bit off_t. */25/* Not necessary, files are always with 64bit off_t. */
27# define __O_LARGEFILE 026#define __O_LARGEFILE 0
28#endif
2927
30#if __WORDSIZE == 64
31/* Not necessary, we always have 64-bit offsets. */28/* Not necessary, we always have 64-bit offsets. */
32# define F_GETLK64 5 /* Get record locking info. */29#define F_GETLK64 5 /* Get record locking info. */
33# define F_SETLK64 6 /* Set record locking info (non-blocking). */30#define F_SETLK64 6 /* Set record locking info (non-blocking). */
34# define F_SETLKW64 7 /* Set record locking info (blocking). */31#define F_SETLKW64 7 /* Set record locking info (blocking). */
35#endif
3632
37struct flock33struct flock
38 {34 {
39 short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */35 short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */
40 short int l_whence; /* Where `l_start' is relative to (like `lseek'). */36 short int l_whence; /* Where `l_start' is relative to (like `lseek'). */
41#if __WORDSIZE == 64 || !defined __USE_FILE_OFFSET64
42 __off_t l_start; /* Offset where the lock begins. */37 __off_t l_start; /* Offset where the lock begins. */
43 __off_t l_len; /* Size of the locked area; zero means until EOF. */38 __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
48 __pid_t l_pid; /* Process holding the lock. */39 __pid_t l_pid; /* Process holding the lock. */
49 };40 };
5041
...@@ -59,13 +50,8 @@ struct flock64...@@ -59,13 +50,8 @@ struct flock64
59 };50 };
60#endif51#endif
6152
62#if __WORDSIZE == 6453#define __POSIX_FADV_DONTNEED 6 /* Don't need these pages. */
63# define __POSIX_FADV_DONTNEED 6 /* Don't need these pages. */54#define __POSIX_FADV_NOREUSE 7 /* Data will be accessed once. */
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
6955
70/* Include generic Linux declarations. */56/* Include generic Linux declarations. */
71#include <bits/fcntl-linux.h>57#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...@@ -77,9 +77,9 @@ typedef struct
77{77{
78 fexcept_t __fpc;78 fexcept_t __fpc;
79 void *__glibc_reserved;79 void *__glibc_reserved;
80 /* The field __unused (formerly __ieee_instruction_pointer) is a relict from80 /* The field __glibc_reserved (formerly __ieee_instruction_pointer) is a
81 commit "Remove PTRACE_PEEKUSER" (87b9b50f0d4b92248905e95a06a13c513dc45e59)81 relict from commit "Remove PTRACE_PEEKUSER"
82 and isn't used anymore. */82 (87b9b50f0d4b92248905e95a06a13c513dc45e59) and isn't used anymore. */
83} fenv_t;83} fenv_t;
8484
85/* If the default argument is used we use this value. */85/* If the default argument is used we use this value. */
...@@ -96,4 +96,4 @@ typedef unsigned int femode_t;...@@ -96,4 +96,4 @@ typedef unsigned int femode_t;
9696
97/* Default floating-point control modes. */97/* Default floating-point control modes. */
98# define FE_DFL_MODE ((const femode_t *) -1L)98# define FE_DFL_MODE ((const femode_t *) -1L)
99#endif99#endif
\ No newline at end of file
lib/libc/include/s390x-linux-gnu/bits/link.h+1-61
...@@ -23,64 +23,6 @@...@@ -23,64 +23,6 @@
23typedef char La_s390_vr[16];23typedef char La_s390_vr[16];
24#endif24#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
84/* Registers for entry into PLT on s390-64. */26/* Registers for entry into PLT on s390-64. */
85typedef struct La_s390_64_regs27typedef struct La_s390_64_regs
86{28{
...@@ -134,6 +76,4 @@ extern unsigned int la_s390_64_gnu_pltexit (Elf64_Sym *__sym,...@@ -134,6 +76,4 @@ extern unsigned int la_s390_64_gnu_pltexit (Elf64_Sym *__sym,
134 La_s390_64_retval *__outregs,76 La_s390_64_retval *__outregs,
135 const char *__symname);77 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...@@ -33,13 +33,7 @@ typedef struct __s390_jmp_buf
33 /* We save registers 6-15. */33 /* We save registers 6-15. */
34 long int __gregs[10];34 long int __gregs[10];
3535
36# if __WORDSIZE == 64
37 /* We save fpu registers f8 - f15. */
38 long __fpregs[8];36 long __fpregs[8];
39# else
40 /* We save fpu registers 4 and 6. */
41 long __fpregs[4];
42# endif
43} __jmp_buf[1];37} __jmp_buf[1];
4438
45#endif39#endif
lib/libc/include/s390x-linux-gnu/bits/sigaction.h+1-34
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1/* Definitions for 31 & 64 bit S/390 sigaction.1/* Definitions for 64 bit S/390 sigaction.
2 Copyright (C) 2001-2026 Free Software Foundation, Inc.2 Copyright (C) 2001-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.3 This file is part of the GNU C Library.
44
...@@ -23,9 +23,6 @@...@@ -23,9 +23,6 @@
23# error "Never include <bits/sigaction.h> directly; use <signal.h> instead."23# error "Never include <bits/sigaction.h> directly; use <signal.h> instead."
24#endif24#endif
2525
26#include <bits/wordsize.h>
27
28#if __WORDSIZE == 64
29/* Structure describing the action to be taken when a signal arrives. */26/* Structure describing the action to be taken when a signal arrives. */
30struct sigaction27struct sigaction
31 {28 {
...@@ -55,36 +52,6 @@ struct sigaction...@@ -55,36 +52,6 @@ struct sigaction
55 /* Additional set of signals to be blocked. */52 /* Additional set of signals to be blocked. */
56 __sigset_t sa_mask;53 __sigset_t sa_mask;
57 };54 };
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
89/* Bits in `sa_flags'. */56/* Bits in `sa_flags'. */
90#define SA_NOCLDSTOP 1 /* Don't send SIGCHLD when children stop. */57#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...@@ -24,39 +24,17 @@ struct __pthread_mutex_s
24 int __lock;24 int __lock;
25 unsigned int __count;25 unsigned int __count;
26 int __owner;26 int __owner;
27#if __WORDSIZE == 64
28 unsigned int __nusers;27 unsigned int __nusers;
29#endif
30 /* KIND must stay at this position in the structure to maintain28 /* KIND must stay at this position in the structure to maintain
31 binary compatibility with static initializers. */29 binary compatibility with static initializers. */
32 int __kind;30 int __kind;
33#if __WORDSIZE == 64
34 short __spins;31 short __spins;
35 short __glibc_reserved;32 short __glibc_reserved;
36 __pthread_list_t __list;33 __pthread_list_t __list;
37# define __PTHREAD_MUTEX_HAVE_PREV 134# 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
52};35};
5336
54#if __WORDSIZE == 6437#define __PTHREAD_MUTEX_INITIALIZER(__kind) \
55# define __PTHREAD_MUTEX_INITIALIZER(__kind) \
56 0, 0, 0, 0, __kind, 0, 0, { 0, 0 }38 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#endif40#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...@@ -28,7 +28,6 @@ struct __pthread_rwlock_arch_t
28 unsigned int __writers_futex;28 unsigned int __writers_futex;
29 unsigned int __pad3;29 unsigned int __pad3;
30 unsigned int __pad4;30 unsigned int __pad4;
31#if __WORDSIZE == 64
32 int __cur_writer;31 int __cur_writer;
33 int __shared;32 int __shared;
34 unsigned long int __pad1;33 unsigned long int __pad1;
...@@ -36,23 +35,9 @@ struct __pthread_rwlock_arch_t...@@ -36,23 +35,9 @@ struct __pthread_rwlock_arch_t
36 /* FLAGS must stay at this position in the structure to maintain35 /* FLAGS must stay at this position in the structure to maintain
37 binary compatibility. */36 binary compatibility. */
38 unsigned int __flags;37 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
48};38};
4939
50#if __WORDSIZE == 6440#define __PTHREAD_RWLOCK_INITIALIZER(__flags) \
51# define __PTHREAD_RWLOCK_INITIALIZER(__flags) \
52 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, __flags41 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
58#endif43#endif
\ No newline at end of file
lib/libc/include/s390x-linux-gnu/bits/struct_stat.h+6-114
...@@ -25,7 +25,6 @@...@@ -25,7 +25,6 @@
2525
26#include <bits/wordsize.h>26#include <bits/wordsize.h>
2727
28#if __WORDSIZE == 64
29struct stat28struct stat
30 {29 {
31 __dev_t st_dev; /* Device. */30 __dev_t st_dev; /* Device. */
...@@ -62,70 +61,8 @@ struct stat...@@ -62,70 +61,8 @@ struct stat
62 __blkcnt_t st_blocks; /* Nr. 512-byte blocks allocated. */61 __blkcnt_t st_blocks; /* Nr. 512-byte blocks allocated. */
63 long int __glibc_reserved[3];62 long int __glibc_reserved[3];
64 };63 };
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
127#ifdef __USE_LARGEFILE6465#ifdef __USE_LARGEFILE64
128# if __WORDSIZE == 64
129/* Note stat64 is the same shape as stat. */66/* Note stat64 is the same shape as stat. */
130struct stat6467struct stat64
131 {68 {
...@@ -138,7 +75,7 @@ struct stat64...@@ -138,7 +75,7 @@ struct stat64
138 int __glibc_reserved0;75 int __glibc_reserved0;
139 __dev_t st_rdev; /* Device number, if device. */76 __dev_t st_rdev; /* Device number, if device. */
140 __off_t st_size; /* Size of file, in bytes. */77 __off_t st_size; /* Size of file, in bytes. */
141# ifdef __USE_XOPEN2K878# ifdef __USE_XOPEN2K8
142 /* Nanosecond resolution timestamps are stored in a format79 /* Nanosecond resolution timestamps are stored in a format
143 equivalent to 'struct timespec'. This is the type used80 equivalent to 'struct timespec'. This is the type used
144 whenever possible but the Unix namespace rules do not allow the81 whenever possible but the Unix namespace rules do not allow the
...@@ -148,66 +85,21 @@ struct stat64...@@ -148,66 +85,21 @@ struct stat64
148 struct timespec st_atim; /* Time of last access. */85 struct timespec st_atim; /* Time of last access. */
149 struct timespec st_mtim; /* Time of last modification. */86 struct timespec st_mtim; /* Time of last modification. */
150 struct timespec st_ctim; /* Time of last status change. */87 struct timespec st_ctim; /* Time of last status change. */
151# define st_atime st_atim.tv_sec /* Backward compatibility. */88# define st_atime st_atim.tv_sec /* Backward compatibility. */
152# define st_mtime st_mtim.tv_sec89# define st_mtime st_mtim.tv_sec
153# define st_ctime st_ctim.tv_sec90# define st_ctime st_ctim.tv_sec
154# else91# else
155 __time_t st_atime; /* Time of last access. */92 __time_t st_atime; /* Time of last access. */
156 unsigned long int st_atimensec; /* Nscecs of last access. */93 unsigned long int st_atimensec; /* Nscecs of last access. */
157 __time_t st_mtime; /* Time of last modification. */94 __time_t st_mtime; /* Time of last modification. */
158 unsigned long int st_mtimensec; /* Nsecs of last modification. */95 unsigned long int st_mtimensec; /* Nsecs of last modification. */
159 __time_t st_ctime; /* Time of last status change. */96 __time_t st_ctime; /* Time of last status change. */
160 unsigned long int st_ctimensec; /* Nsecs of last status change. */97 unsigned long int st_ctimensec; /* Nsecs of last status change. */
161# endif98# endif
162 __blksize_t st_blksize; /* Optimal block size for I/O. */99 __blksize_t st_blksize; /* Optimal block size for I/O. */
163 __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */100 __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */
164 long int __glibc_reserved[3];101 long int __glibc_reserved[3];
165 };102 };
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
211#endif103#endif
212104
213/* Tell code we have these members. */105/* 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 @@...@@ -57,42 +57,34 @@
57#define __TIMER_T_TYPE void *57#define __TIMER_T_TYPE void *
58#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE58#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE
59#define __FSID_T_TYPE struct { int __val[2]; }59#define __FSID_T_TYPE struct { int __val[2]; }
60#if defined __GNUC__ && __GNUC__ <= 260
61/* Compatibility with g++ 2.95.x. */61/* With s390-32, __SSIZE_T_TYPE was __SWORD_TYPE for compatibility with
62#define __SSIZE_T_TYPE __SWORD_TYPE62 g++ 2.95.x. Afterwards __SLONGWORD_TYPE was needed as size_t was
63#else63 unsigned long int on s390-32.
64/* size_t is unsigned long int on s390 -m31. */64 Now as only s390-64 exists, __SWORD_TYPE can be used as also used in the
65#define __SSIZE_T_TYPE __SLONGWORD_TYPE65 generic version as both types result in long int. */
66#endif66#define __SSIZE_T_TYPE __SWORD_TYPE
67
67#define __SYSCALL_SLONG_TYPE __SLONGWORD_TYPE68#define __SYSCALL_SLONG_TYPE __SLONGWORD_TYPE
68#define __SYSCALL_ULONG_TYPE __ULONGWORD_TYPE69#define __SYSCALL_ULONG_TYPE __ULONGWORD_TYPE
69#define __CPU_MASK_TYPE __ULONGWORD_TYPE70#define __CPU_MASK_TYPE __ULONGWORD_TYPE
7071
71#ifdef __s390x__
72/* Tell the libc code that off_t and off64_t are actually the same type72/* Tell the libc code that off_t and off64_t are actually the same type
73 for all ABI purposes, even if possibly expressed as different base types73 for all ABI purposes, even if possibly expressed as different base types
74 for C type-checking purposes. */74 for C type-checking purposes. */
75# define __OFF_T_MATCHES_OFF64_T 175#define __OFF_T_MATCHES_OFF64_T 1
7676
77/* Same for ino_t and ino64_t. */77/* Same for ino_t and ino64_t. */
78# define __INO_T_MATCHES_INO64_T 178#define __INO_T_MATCHES_INO64_T 1
7979
80/* And for __rlim_t and __rlim64_t. */80/* And for __rlim_t and __rlim64_t. */
81# define __RLIM_T_MATCHES_RLIM64_T 181#define __RLIM_T_MATCHES_RLIM64_T 1
8282
83/* And for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t. */83/* And for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t. */
84# define __STATFS_MATCHES_STATFS64 184#define __STATFS_MATCHES_STATFS64 1
8585
86/* And for getitimer, setitimer and rusage */86/* And for getitimer, setitimer and rusage */
87# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 187#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
9688
97/* Number of descriptors that can fit in an `fd_set'. */89/* Number of descriptors that can fit in an `fd_set'. */
98#define __FD_SETSIZE 102490#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,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 The GNU C Library is free software; you can redistribute it and/or
4# define __WORDSIZE 645 modify it under the terms of the GNU Lesser General Public
5#else6 License as published by the Free Software Foundation; either
6# define __WORDSIZE 327 version 2.1 of the License, or (at your option) any later version.
7# define __WORDSIZE32_SIZE_ULONG 1
8# define __WORDSIZE32_PTRDIFF_LONG 0
9#endif
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 @@...@@ -4,13 +4,28 @@
4#ifndef __GNU_LIB_NAMES_H4#ifndef __GNU_LIB_NAMES_H
5#define __GNU_LIB_NAMES_H 15#define __GNU_LIB_NAMES_H 1
66
7#include <bits/wordsize.h>7#define LD64_SO "ld64.so.1"
88#define LD_SO "ld64.so.1"
9#if __WORDSIZE == 329#define LIBANL_SO "libanl.so.1"
10# include <gnu/lib-names-32.h>10#define LIBBROKENLOCALE_SO "libBrokenLocale.so.1"
11#endif11#define LIBC_MALLOC_DEBUG_SO "libc_malloc_debug.so.0"
12#if __WORDSIZE == 6412#define LIBC_SO "libc.so.6"
13# include <gnu/lib-names-64.h>13#define LIBDL_SO "libdl.so.2"
14#endif14#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
16#endif /* gnu/lib-names.h */31#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 @@...@@ -1,12 +1,16 @@
1/* This file is automatically generated.1/* This file is automatically generated.
2 This file selects the right generated file of `__stub_FUNCTION' macros2 It defines a symbol `__stub_FUNCTION' for each function
3 based on the architecture being compiled for. */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#ifdef _LIBC
67 #error Applications may not define the macro _LIBC
7#if __WORDSIZE == 32
8# include <gnu/stubs-32.h>
9#endif8#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;...@@ -45,11 +45,7 @@ typedef unsigned long greg_t;
45 the register set is an array, we make gregset_t a simple array45 the register set is an array, we make gregset_t a simple array
46 that has the same size as s390_regs. This is needed for the46 that has the same size as s390_regs. This is needed for the
47 elf_prstatus structure. */47 elf_prstatus structure. */
48#if __WORDSIZE == 6448#define __NGREG 27
49# define __NGREG 27
50#else
51# define __NGREG 36
52#endif
53#ifdef __USE_MISC49#ifdef __USE_MISC
54# define NGREG __NGREG50# define NGREG __NGREG
55#endif51#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 @@...@@ -24,4 +24,5 @@
24#define LIBRESOLV_SO "libresolv.so.2"24#define LIBRESOLV_SO "libresolv.so.2"
25#define LIBRT_SO "librt.so.1"25#define LIBRT_SO "librt.so.1"
26#define LIBTHREAD_DB_SO "libthread_db.so.1"26#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
27#define LIBUTIL_SO "libutil.so.1"28#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...@@ -59,4 +59,4 @@ struct __pthread_mutex_s
59 0, 0, 0, __kind, 0, { { 0, 0 } }59 0, 0, 0, __kind, 0, { { 0, 0 } }
60#endif60#endif
6161
62#endif62#endif
\ No newline at end of file
lib/libc/include/x86-linux-gnu/gnu/lib-names-64.h+1
...@@ -24,4 +24,5 @@...@@ -24,4 +24,5 @@
24#define LIBRESOLV_SO "libresolv.so.2"24#define LIBRESOLV_SO "libresolv.so.2"
25#define LIBRT_SO "librt.so.1"25#define LIBRT_SO "librt.so.1"
26#define LIBTHREAD_DB_SO "libthread_db.so.1"26#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
27#define LIBUTIL_SO "libutil.so.1"28#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 @@...@@ -24,4 +24,5 @@
24#define LIBRESOLV_SO "libresolv.so.2"24#define LIBRESOLV_SO "libresolv.so.2"
25#define LIBRT_SO "librt.so.1"25#define LIBRT_SO "librt.so.1"
26#define LIBTHREAD_DB_SO "libthread_db.so.1"26#define LIBTHREAD_DB_SO "libthread_db.so.1"
27#define LIBUNWIND_SO "libunwind.so.1"
27#define LIBUTIL_SO "libutil.so.1"28#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,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
3/*-3/*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
...@@ -40,6 +40,7 @@...@@ -40,6 +40,7 @@
40#define _UC_CLRSTACK _UC_MD_BIT1740#define _UC_CLRSTACK _UC_MD_BIT17
41#define _UC_VM _UC_MD_BIT1841#define _UC_VM _UC_MD_BIT18
42#define _UC_TLSBASE _UC_MD_BIT1942#define _UC_TLSBASE _UC_MD_BIT19
43#define _UC_XSAVE _UC_MD_BIT20
4344
44/*45/*
45 * Layout of mcontext_t according to the System V Application Binary Interface,46 * Layout of mcontext_t according to the System V Application Binary Interface,
...@@ -85,6 +86,27 @@ typedef struct {...@@ -85,6 +86,27 @@ typedef struct {
85 char __fp_xmm[512];86 char __fp_xmm[512];
86 } __fp_xmm_state; /* x87 and xmm regs in fxsave format */87 } __fp_xmm_state; /* x87 and xmm regs in fxsave format */
87 int __fp_fpregs[128];88 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;
88 } __fp_reg_set;110 } __fp_reg_set;
89 int __fp_pad[33]; /* Historic padding */111 int __fp_pad[33]; /* Historic padding */
90} __fpregset_t;112} __fpregset_t;
lib/libc/include/x86_64-netbsd-none/amd64/mcontext.h+31-2
...@@ -1,4 +1,4 @@...@@ -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
3/*-3/*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
...@@ -56,7 +56,28 @@ typedef __greg_t __gregset_t[_NGREG];...@@ -56,7 +56,28 @@ typedef __greg_t __gregset_t[_NGREG];
56 * which requires 16 byte alignment. However the mcontext version56 * which requires 16 byte alignment. However the mcontext version
57 * is never directly accessed.57 * is never directly accessed.
58 */58 */
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
61typedef struct {82typedef struct {
62 __gregset_t __gregs;83 __gregset_t __gregs;
...@@ -75,6 +96,7 @@ typedef struct {...@@ -75,6 +96,7 @@ typedef struct {
75#define _UC_MACHINE_SET_PC(uc, pc) _UC_MACHINE_PC(uc) = (pc)96#define _UC_MACHINE_SET_PC(uc, pc) _UC_MACHINE_PC(uc) = (pc)
7697
77#define _UC_TLSBASE _UC_MD_BIT1998#define _UC_TLSBASE _UC_MD_BIT19
99#define _UC_XSAVE _UC_MD_BIT20
78100
79/*101/*
80 * mcontext extensions to handle signal delivery.102 * mcontext extensions to handle signal delivery.
...@@ -127,6 +149,13 @@ typedef struct {...@@ -127,6 +149,13 @@ typedef struct {
127 struct {149 struct {
128 char __fp_xmm[512];150 char __fp_xmm[512];
129 } __fp_xmm_state;151 } __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;
130 } __fp_reg_set;159 } __fp_reg_set;
131 int __fp_pad[33]; /* Historic padding */160 int __fp_pad[33]; /* Historic padding */
132} __fpregset32_t;161} __fpregset32_t;
lib/libc/include/x86_64-netbsd-none/machine/mcontext.h+31-2
...@@ -1,4 +1,4 @@...@@ -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
3/*-3/*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
...@@ -56,7 +56,28 @@ typedef __greg_t __gregset_t[_NGREG];...@@ -56,7 +56,28 @@ typedef __greg_t __gregset_t[_NGREG];
56 * which requires 16 byte alignment. However the mcontext version56 * which requires 16 byte alignment. However the mcontext version
57 * is never directly accessed.57 * is never directly accessed.
58 */58 */
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
61typedef struct {82typedef struct {
62 __gregset_t __gregs;83 __gregset_t __gregs;
...@@ -75,6 +96,7 @@ typedef struct {...@@ -75,6 +96,7 @@ typedef struct {
75#define _UC_MACHINE_SET_PC(uc, pc) _UC_MACHINE_PC(uc) = (pc)96#define _UC_MACHINE_SET_PC(uc, pc) _UC_MACHINE_PC(uc) = (pc)
7697
77#define _UC_TLSBASE _UC_MD_BIT1998#define _UC_TLSBASE _UC_MD_BIT19
99#define _UC_XSAVE _UC_MD_BIT20
78100
79/*101/*
80 * mcontext extensions to handle signal delivery.102 * mcontext extensions to handle signal delivery.
...@@ -127,6 +149,13 @@ typedef struct {...@@ -127,6 +149,13 @@ typedef struct {
127 struct {149 struct {
128 char __fp_xmm[512];150 char __fp_xmm[512];
129 } __fp_xmm_state;151 } __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;
130 } __fp_reg_set;159 } __fp_reg_set;
131 int __fp_pad[33]; /* Historic padding */160 int __fp_pad[33]; /* Historic padding */
132} __fpregset32_t;161} __fpregset32_t;
lib/std/Build.zig+48-44
...@@ -45,17 +45,6 @@ debug_log_scopes: []const []const u8 = &.{},...@@ -45,17 +45,6 @@ debug_log_scopes: []const []const u8 = &.{},
45/// Set to 0 to disable stack collection.45/// Set to 0 to disable stack collection.
46debug_stack_frames_count: u8 = 8,46debug_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
59dep_prefix: []const u8 = "",48dep_prefix: []const u8 = "",
6049
61modules: std.array_hash_map.String(*Module),50modules: std.array_hash_map.String(*Module),
...@@ -388,11 +377,6 @@ fn createChild(...@@ -388,11 +377,6 @@ fn createChild(
388 .default_step = undefined,377 .default_step = undefined,
389 .top_level_steps = .{},378 .top_level_steps = .{},
390 .debug_log_scopes = parent.debug_log_scopes,379 .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,
396 .dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }),380 .dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }),
397 .modules = .empty,381 .modules = .empty,
398 .named_writefiles = .empty,382 .named_writefiles = .empty,
...@@ -830,7 +814,7 @@ pub fn addTest(b: *Build, options: TestOptions) *Step.Compile {...@@ -830,7 +814,7 @@ pub fn addTest(b: *Build, options: TestOptions) *Step.Compile {
830 .kind = if (options.emit_object) .test_obj else .@"test",814 .kind = if (options.emit_object) .test_obj else .@"test",
831 .root_module = options.root_module,815 .root_module = options.root_module,
832 .max_rss = options.max_rss,816 .max_rss = options.max_rss,
833 .filters = b.dupeStrings(options.filters),817 .filters = b.graph.dupeStrings(options.filters),
834 .test_runner = options.test_runner,818 .test_runner = options.test_runner,
835 .use_llvm = options.use_llvm,819 .use_llvm = options.use_llvm,
836 .use_lld = options.use_lld,820 .use_lld = options.use_lld,
...@@ -1125,7 +1109,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw...@@ -1125,7 +1109,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw
1125 const type_id = comptime typeToEnum(T);1109 const type_id = comptime typeToEnum(T);
1126 const enum_options = if (type_id == .@"enum" or type_id == .enum_list) blk: {1110 const enum_options = if (type_id == .@"enum" or type_id == .enum_list) blk: {
1127 const EnumType = if (type_id == .enum_list) @typeInfo(T).pointer.child else T;1111 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;
1129 var options = std.array_list.Managed([]const u8).initCapacity(b.allocator, field_names.len) catch @panic("OOM");1113 var options = std.array_list.Managed([]const u8).initCapacity(b.allocator, field_names.len) catch @panic("OOM");
11301114
1131 inline for (field_names) |field_name| {1115 inline for (field_names) |field_name| {
...@@ -1210,13 +1194,16 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw...@@ -1210,13 +1194,16 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw
1210 return null;1194 return null;
1211 },1195 },
1212 .scalar => |s| {1196 .scalar => |s| {
1213 if (std.meta.stringToEnum(T, s)) |enum_lit| {1197 if (T == std.lang.Optimize) {
1214 return enum_lit;1198 if (std.lang.Optimize.fromString(s)) |tag| {
1215 } else {1199 return tag;
1216 log.err("expected -D{s} to be of type {s}", .{ name, @typeName(T) });1200 }
1217 b.markInvalidUserInput();1201 } else if (std.meta.stringToEnum(T, s)) |tag| {
1218 return null;1202 return tag;
1219 }1203 }
1204 log.err("expected -D{s} to be of type {q}", .{ name, @typeName(T) });
1205 b.markInvalidUserInput();
1206 return null;
1220 },1207 },
1221 },1208 },
1222 .string => switch (option_ptr.value) {1209 .string => switch (option_ptr.value) {
...@@ -1262,23 +1249,36 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw...@@ -1262,23 +1249,36 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw
1262 },1249 },
1263 .scalar => |s| {1250 .scalar => |s| {
1264 const Child = @typeInfo(T).pointer.child;1251 const Child = @typeInfo(T).pointer.child;
1265 const value = std.meta.stringToEnum(Child, s) orelse {1252 if (Child == std.lang.Optimize) {
1266 log.err("expected -D{s} to be of type {s}", .{ name, @typeName(Child) });1253 if (std.lang.Optimize.fromString(s)) |tag| {
1267 b.markInvalidUserInput();1254 return arena.dupe(Child, &.{tag}) catch @panic("OOM");
1268 return null;1255 }
1269 };1256 } else {
1270 return arena.dupe(Child, &[_]Child{value}) catch @panic("OOM");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;
1271 },1264 },
1272 .list => |lst| {1265 .list => |lst| {
1273 const Child = @typeInfo(T).pointer.child;1266 const Child = @typeInfo(T).pointer.child;
1274 const new_list = graph.alloc(Child, lst.items.len);1267 const new_list = graph.alloc(Child, lst.items.len);
1275 for (new_list, lst.items) |*new_item, str| {1268 for (new_list, lst.items) |*new_item, str| {
1276 new_item.* = std.meta.stringToEnum(Child, str) orelse {1269 if (Child == std.lang.Optimize) {
1277 log.err("expected -D{s} to be of type {s}", .{ name, @typeName(Child) });1270 if (std.lang.Optimize.fromString(str)) |tag| {
1278 b.markInvalidUserInput();1271 new_item.* = tag;
1279 arena.free(new_list);1272 continue;
1280 return null;1273 }
1281 };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;
1282 }1282 }
1283 return new_list;1283 return new_list;
1284 },1284 },
...@@ -1359,14 +1359,14 @@ pub fn standardOptimizeOption(b: *Build, options: StandardOptimizeOptionOptions)...@@ -1359,14 +1359,14 @@ pub fn standardOptimizeOption(b: *Build, options: StandardOptimizeOptionOptions)
1359 }1359 }
13601360
1361 return switch (graph.release_mode) {1361 return switch (graph.release_mode) {
1362 .off => .Debug,1362 .off => .debug,
1363 .any => {1363 .any => {
1364 std.debug.print("the project does not declare a preferred optimization mode. choose: --release=fast, --release=safe, or --release=small\n", .{});1364 std.debug.print("the project does not declare a preferred optimization mode. choose: --release=fast, --release=safe, or --release=small\n", .{});
1365 process.exit(1);1365 process.exit(1);
1366 },1366 },
1367 .fast => .ReleaseFast,1367 .fast => .fast,
1368 .safe => .ReleaseSafe,1368 .safe => .safe,
1369 .small => .ReleaseSmall,1369 .small => .small,
1370 };1370 };
1371}1371}
13721372
...@@ -1420,7 +1420,7 @@ pub fn parseTargetQuery(options: std.Target.Query.ParseOptions) error{ParseFaile...@@ -1420,7 +1420,7 @@ pub fn parseTargetQuery(options: std.Target.Query.ParseOptions) error{ParseFaile
1420 \\available operating systems:1420 \\available operating systems:
1421 \\1421 \\
1422 , .{diags.os_name.?});1422 , .{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| {
1424 std.debug.print(" {s}\n", .{field_name});1424 std.debug.print(" {s}\n", .{field_name});
1425 }1425 }
1426 return error.ParseFailed;1426 return error.ParseFailed;
...@@ -2144,7 +2144,7 @@ pub fn dependencyLazy(b: *Build, name: []const u8, args: anytype) error{LazyDepe...@@ -2144,7 +2144,7 @@ pub fn dependencyLazy(b: *Build, name: []const u8, args: anytype) error{LazyDepe
2144 return dependencyResolved(b, name, entry, userInputOptionsFromArgs(b.graph.arena, args));2144 return dependencyResolved(b, name, entry, userInputOptionsFromArgs(b.graph.arena, args));
2145}2145}
21462146
2147const PackageEntry = struct {2147pub const PackageEntry = struct {
2148 hash: []const u8,2148 hash: []const u8,
2149 available: bool,2149 available: bool,
2150 build_root: []const u8,2150 build_root: []const u8,
...@@ -2152,7 +2152,8 @@ const PackageEntry = struct {...@@ -2152,7 +2152,8 @@ const PackageEntry = struct {
2152 run_build: ?*const fn (*Build) void,2152 run_build: ?*const fn (*Build) void,
2153};2153};
21542154
2155const package_map: std.StaticStringMap(PackageEntry) = blk: {2155/// Build system implementation detail.
2156pub const package_map: std.StaticStringMap(PackageEntry) = blk: {
2156 const deps = @import("root").dependencies;2157 const deps = @import("root").dependencies;
2157 const decl_names = @typeInfo(deps.packages).@"struct".decl_names;2158 const decl_names = @typeInfo(deps.packages).@"struct".decl_names;
2158 var kvs: [decl_names.len]struct { []const u8, PackageEntry } = undefined;2159 var kvs: [decl_names.len]struct { []const u8, PackageEntry } = undefined;
...@@ -2632,7 +2633,10 @@ pub const LazyPath = union(enum) {...@@ -2632,7 +2633,10 @@ pub const LazyPath = union(enum) {
26322633
2633 fn dupeInner(lazy_path: LazyPath, arena: Allocator) LazyPath {2634 fn dupeInner(lazy_path: LazyPath, arena: Allocator) LazyPath {
2634 return switch (lazy_path) {2635 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 } },
2636 .cwd_relative => |p| .{ .cwd_relative = Graph.dupePathInner(arena, p) },2640 .cwd_relative => |p| .{ .cwd_relative = Graph.dupePathInner(arena, p) },
2637 .relative => |r| .{ .relative = r },2641 .relative => |r| .{ .relative = r },
2638 .generated => |gen| .{ .generated = .{2642 .generated => |gen| .{ .generated = .{
lib/std/Build/Configuration.zig+77-334
...@@ -15,6 +15,8 @@ unlazy_deps: []String,...@@ -15,6 +15,8 @@ unlazy_deps: []String,
15system_integrations: []SystemIntegration,15system_integrations: []SystemIntegration,
16available_options: []AvailableOption,16available_options: []AvailableOption,
17search_prefixes: []String,17search_prefixes: []String,
18/// Index 0 always exists and is the root package.
19packages: []Package,
18extra: []u32,20extra: []u32,
19default_step: Step.Index,21default_step: Step.Index,
20generated_files_len: u32,22generated_files_len: u32,
...@@ -30,6 +32,7 @@ pub const Header = extern struct {...@@ -30,6 +32,7 @@ pub const Header = extern struct {
30 system_integrations_len: u32,32 system_integrations_len: u32,
31 available_options_len: u32,33 available_options_len: u32,
32 search_prefixes_len: u32,34 search_prefixes_len: u32,
35 packages_len: u32,
33 extra_len: u32,36 extra_len: u32,
3437
35 default_step: Step.Index,38 default_step: Step.Index,
...@@ -58,6 +61,7 @@ pub const Wip = struct {...@@ -58,6 +61,7 @@ pub const Wip = struct {
58 steps: std.ArrayList(Step) = .empty,61 steps: std.ArrayList(Step) = .empty,
59 path_deps: std.ArrayList(PathDep) = .empty,62 path_deps: std.ArrayList(PathDep) = .empty,
60 search_prefixes: std.ArrayList(String) = .empty,63 search_prefixes: std.ArrayList(String) = .empty,
64 packages: std.ArrayList(Package) = .empty,
61 extra: std.ArrayList(u32) = .empty,65 extra: std.ArrayList(u32) = .empty,
62 next_generated_file_index: u32 = 0,66 next_generated_file_index: u32 = 0,
63 cache_poison: bool = false,67 cache_poison: bool = false,
...@@ -121,7 +125,7 @@ pub const Wip = struct {...@@ -121,7 +125,7 @@ pub const Wip = struct {
121 }125 }
122126
123 pub fn hash(_: @This(), adapted_key: []const u8) u64 {127 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);
125 return std.hash_map.hashString(adapted_key);129 return std.hash_map.hashString(adapted_key);
126 }130 }
127 };131 };
...@@ -139,6 +143,7 @@ pub const Wip = struct {...@@ -139,6 +143,7 @@ pub const Wip = struct {
139 wip.steps.deinit(gpa);143 wip.steps.deinit(gpa);
140 wip.path_deps.deinit(gpa);144 wip.path_deps.deinit(gpa);
141 wip.search_prefixes.deinit(gpa);145 wip.search_prefixes.deinit(gpa);
146 wip.packages.deinit(gpa);
142 wip.extra.deinit(gpa);147 wip.extra.deinit(gpa);
143 wip.* = undefined;148 wip.* = undefined;
144 }149 }
...@@ -158,6 +163,7 @@ pub const Wip = struct {...@@ -158,6 +163,7 @@ pub const Wip = struct {
158 .system_integrations_len = @intCast(wip.system_integrations.items.len),163 .system_integrations_len = @intCast(wip.system_integrations.items.len),
159 .available_options_len = @intCast(wip.available_options.items.len),164 .available_options_len = @intCast(wip.available_options.items.len),
160 .search_prefixes_len = @intCast(wip.search_prefixes.items.len),165 .search_prefixes_len = @intCast(wip.search_prefixes.items.len),
166 .packages_len = @intCast(wip.packages.items.len),
161 .extra_len = @intCast(wip.extra.items.len),167 .extra_len = @intCast(wip.extra.items.len),
162168
163 .default_step = static.default_step,169 .default_step = static.default_step,
...@@ -175,6 +181,7 @@ pub const Wip = struct {...@@ -175,6 +181,7 @@ pub const Wip = struct {
175 @ptrCast(wip.system_integrations.items),181 @ptrCast(wip.system_integrations.items),
176 @ptrCast(wip.available_options.items),182 @ptrCast(wip.available_options.items),
177 @ptrCast(wip.search_prefixes.items),183 @ptrCast(wip.search_prefixes.items),
184 @ptrCast(wip.packages.items),
178 @ptrCast(wip.extra.items),185 @ptrCast(wip.extra.items),
179 };186 };
180 try w.writeVecAll(&buffers);187 try w.writeVecAll(&buffers);
...@@ -182,7 +189,7 @@ pub const Wip = struct {...@@ -182,7 +189,7 @@ pub const Wip = struct {
182189
183 pub fn addString(wip: *Wip, bytes: []const u8) Allocator.Error!String {190 pub fn addString(wip: *Wip, bytes: []const u8) Allocator.Error!String {
184 const gpa = wip.gpa;191 const gpa = wip.gpa;
185 assert(std.mem.indexOfScalar(u8, bytes, 0) == null);192 assert(std.mem.findScalar(u8, bytes, 0) == null);
186 const gop = try wip.string_table.getOrPutContextAdapted(193 const gop = try wip.string_table.getOrPutContextAdapted(
187 gpa,194 gpa,
188 @as([]const u8, bytes),195 @as([]const u8, bytes),
...@@ -439,7 +446,7 @@ pub const Wip = struct {...@@ -439,7 +446,7 @@ pub const Wip = struct {
439 /// Returned slice expires upon next append to the configuration.446 /// Returned slice expires upon next append to the configuration.
440 pub fn stringSlice(wip: *const Wip, s: String) [:0]const u8 {447 pub fn stringSlice(wip: *const Wip, s: String) [:0]const u8 {
441 const start_slice = wip.string_bytes.items[@backingInt(s)..];448 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];
443 }450 }
444};451};
445452
...@@ -569,8 +576,7 @@ pub const Step = extern struct {...@@ -569,8 +576,7 @@ pub const Step = extern struct {
569 flags2: Flags2,576 flags2: Flags2,
570 args: Storage.LengthPrefixedList(Arg.Index),577 args: Storage.LengthPrefixedList(Arg.Index),
571 cwd: Storage.FlagOptional(.flags, .cwd, LazyPath.Index),578 cwd: Storage.FlagOptional(.flags, .cwd, LazyPath.Index),
572 preopen_names: Storage.LengthPrefixedList(String),579 preopens: Storage.FlagLengthPrefixedList(.flags, .preopens, Preopen),
573 preopen_paths: Storage.LengthPrefixedList(LazyPath.Index),
574 captured_stdout: Storage.FlagOptional(.flags, .captured_stdout, CapturedStream),580 captured_stdout: Storage.FlagOptional(.flags, .captured_stdout, CapturedStream),
575 captured_stderr: Storage.FlagOptional(.flags, .captured_stderr, CapturedStream),581 captured_stderr: Storage.FlagOptional(.flags, .captured_stderr, CapturedStream),
576 file_inputs: Storage.LengthPrefixedList(LazyPath.Index),582 file_inputs: Storage.LengthPrefixedList(LazyPath.Index),
...@@ -627,6 +633,13 @@ pub const Step = extern struct {...@@ -627,6 +633,13 @@ pub const Step = extern struct {
627 output_file,633 output_file,
628 output_directory,634 output_directory,
629 passthru,635 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,
630 };643 };
631644
632 pub const Index = IndexType(@This());645 pub const Index = IndexType(@This());
...@@ -646,6 +659,11 @@ pub const Step = extern struct {...@@ -646,6 +659,11 @@ pub const Step = extern struct {
646 manual,659 manual,
647 };660 };
648661
662 pub const Preopen = extern struct {
663 name: String,
664 path: LazyPath.Index,
665 };
666
649 pub const StdIn = union(@This().Tag) {667 pub const StdIn = union(@This().Tag) {
650 none: void,668 none: void,
651 bytes: Bytes,669 bytes: Bytes,
...@@ -676,7 +694,8 @@ pub const Step = extern struct {...@@ -676,7 +694,8 @@ pub const Step = extern struct {
676 captured_stdout: bool,694 captured_stdout: bool,
677 captured_stderr: bool,695 captured_stderr: bool,
678 environ_map: bool,696 environ_map: bool,
679 _: u4 = 0,697 preopens: bool,
698 _: u3 = 0,
680 };699 };
681700
682 pub const Flags2 = packed struct(u32) {701 pub const Flags2 = packed struct(u32) {
...@@ -979,8 +998,6 @@ pub const Step = extern struct {...@@ -979,8 +998,6 @@ pub const Step = extern struct {
979 };998 };
980999
981 pub const Flags3 = packed struct(u32) {1000 pub const Flags3 = packed struct(u32) {
982 is_linking_libc: bool,
983 is_linking_libcpp: bool,
984 version: bool,1001 version: bool,
985 initial_memory: bool,1002 initial_memory: bool,
986 max_memory: bool,1003 max_memory: bool,
...@@ -998,6 +1015,7 @@ pub const Step = extern struct {...@@ -998,6 +1015,7 @@ pub const Step = extern struct {
998 entry: Entry,1015 entry: Entry,
999 lto: Lto,1016 lto: Lto,
1000 subsystem: Subsystem,1017 subsystem: Subsystem,
1018 _: u2 = 0,
1001 };1019 };
10021020
1003 pub const Flags4 = packed struct(u32) {1021 pub const Flags4 = packed struct(u32) {
...@@ -1076,6 +1094,7 @@ pub const Step = extern struct {...@@ -1076,6 +1094,7 @@ pub const Step = extern struct {
1076 autoconf_undef,1094 autoconf_undef,
1077 autoconf_at,1095 autoconf_at,
1078 cmake,1096 cmake,
1097 meson,
1079 blank,1098 blank,
1080 nasm,1099 nasm,
10811100
...@@ -1084,6 +1103,7 @@ pub const Step = extern struct {...@@ -1084,6 +1103,7 @@ pub const Step = extern struct {
1084 .autoconf_undef => .autoconf_undef,1103 .autoconf_undef => .autoconf_undef,
1085 .autoconf_at => .autoconf_at,1104 .autoconf_at => .autoconf_at,
1086 .cmake => .cmake,1105 .cmake => .cmake,
1106 .meson => .meson,
1087 .blank => .blank,1107 .blank => .blank,
1088 .nasm => .nasm,1108 .nasm => .nasm,
1089 };1109 };
...@@ -1589,30 +1609,28 @@ pub const OptionalGeneratedFileIndex = enum(u32) {...@@ -1589,30 +1609,28 @@ pub const OptionalGeneratedFileIndex = enum(u32) {
1589 }1609 }
1590};1610};
15911611
1592pub const Package = struct {1612pub const Package = extern struct {
1593 dep_prefix: String,1613 dep_prefix: String,
1594 hash: String,1614 hash: String,
1595 root_path: String,1615 root_path: String,
1616 deps: Dep.List.Index,
15961617
1597 pub const Index = enum(u32) {1618 pub const Index = enum(u32) {
1598 root = max_u32,1619 root,
1599 _,1620 _,
16001621
1601 /// Returns `null` for root package.1622 pub fn ptr(i: @This(), c: *const Configuration) *const Package {
1602 pub fn get(i: @This(), c: *const Configuration) ?Package {1623 return &c.packages[@backingInt(i)];
1603 if (i == .root) return null;
1604 return extraData(c, Package, @backingInt(i));
1605 }1624 }
16061625
1607 pub fn depPrefixSlice(i: @This(), c: *const Configuration) [:0]const u8 {1626 pub fn depPrefixSlice(i: @This(), c: *const Configuration) [:0]const u8 {
1608 const package = get(i, c) orelse return "";1627 return ptr(i, c).dep_prefix.slice(c);
1609 return package.dep_prefix.slice(c);
1610 }1628 }
1611 };1629 };
16121630
1613 pub const OptionalIndex = enum(u32) {1631 pub const OptionalIndex = enum(u32) {
1614 none = max_u32 - 1,1632 root,
1615 root = max_u32,1633 none = max_u32,
1616 _,1634 _,
16171635
1618 pub fn init(i: Index) OptionalIndex {1636 pub fn init(i: Index) OptionalIndex {
...@@ -1629,6 +1647,28 @@ pub const Package = struct {...@@ -1629,6 +1647,28 @@ pub const Package = struct {
1629 };1647 };
1630 }1648 }
1631 };1649 };
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 };
1632};1672};
16331673
1634pub const Module = struct {1674pub const Module = struct {
...@@ -1655,10 +1695,10 @@ pub const Module = struct {...@@ -1655,10 +1695,10 @@ pub const Module = struct {
16551695
1656 pub fn init(o: ?std.builtin.OptimizeMode) Optimize {1696 pub fn init(o: ?std.builtin.OptimizeMode) Optimize {
1657 return switch (o orelse return .default) {1697 return switch (o orelse return .default) {
1658 .Debug => .debug,1698 .debug => .debug,
1659 .ReleaseSafe => .safe,1699 .safe => .safe,
1660 .ReleaseFast => .fast,1700 .fast => .fast,
1661 .ReleaseSmall => .small,1701 .small => .small,
1662 };1702 };
1663 }1703 }
1664 };1704 };
...@@ -1946,7 +1986,7 @@ pub const String = enum(u32) {...@@ -1946,7 +1986,7 @@ pub const String = enum(u32) {
19461986
1947 pub fn slice(index: String, c: *const Configuration) [:0]const u8 {1987 pub fn slice(index: String, c: *const Configuration) [:0]const u8 {
1948 const start_slice = c.string_bytes[@backingInt(index)..];1988 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];
1950 }1990 }
1951};1991};
19521992
...@@ -2113,27 +2153,18 @@ pub const OptionalCSourceLanguage = enum(u3) {...@@ -2113,27 +2153,18 @@ pub const OptionalCSourceLanguage = enum(u3) {
2113 objective_cpp,2153 objective_cpp,
2114 assembly,2154 assembly,
2115 assembly_with_preprocessor,2155 assembly_with_preprocessor,
2156
2116 default,2157 default,
21172158
2118 pub fn init(x: ?std.Build.Module.CSourceLanguage) @This() {2159 pub fn init(x: ?std.Build.Module.CSourceLanguage) @This() {
2119 return switch (x orelse return .default) {2160 return switch (x orelse return .default) {
2120 .c => .c,2161 inline else => |tag| @field(@This(), @tagName(tag)),
2121 .cpp => .cpp,
2122 .objective_c => .objective_c,
2123 .objective_cpp => .objective_cpp,
2124 .assembly => .assembly,
2125 .assembly_with_preprocessor => .assembly_with_preprocessor,
2126 };2162 };
2127 }2163 }
21282164
2129 pub fn get(this: @This()) ?std.Build.Module.CSourceLanguage {2165 pub fn get(this: @This()) ?std.Build.Module.CSourceLanguage {
2130 return switch (this) {2166 return switch (this) {
2131 .c => .c,2167 inline else => |tag| @field(std.Build.Module.CSourceLanguage, @tagName(tag)),
2132 .cpp => .cpp,
2133 .objective_c => .objective_c,
2134 .objective_cpp => .objective_cpp,
2135 .assembly => .assembly,
2136 .assembly_with_preprocessor => .assembly_with_preprocessor,
2137 .default => null,2168 .default => null,
2138 };2169 };
2139 }2170 }
...@@ -2261,10 +2292,7 @@ pub const TargetQuery = struct {...@@ -2261,10 +2292,7 @@ pub const TargetQuery = struct {
22612292
2262 pub fn init(x: std.Target.Query.CpuModel) @This() {2293 pub fn init(x: std.Target.Query.CpuModel) @This() {
2263 return switch (x) {2294 return switch (x) {
2264 .native => .native,2295 inline else => |_, tag| @field(@This(), @tagName(tag)),
2265 .baseline => .baseline,
2266 .determined_by_arch_os => .determined_by_arch_os,
2267 .explicit => .explicit,
2268 };2296 };
2269 }2297 }
2270 };2298 };
...@@ -2322,71 +2350,13 @@ pub const TargetQuery = struct {...@@ -2322,71 +2350,13 @@ pub const TargetQuery = struct {
23222350
2323 pub fn init(x: ?std.Target.Abi) @This() {2351 pub fn init(x: ?std.Target.Abi) @This() {
2324 return switch (x orelse return .default) {2352 return switch (x orelse return .default) {
2325 .none => .none,2353 inline else => |tag| @field(@This(), @tagName(tag)),
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,
2355 };2354 };
2356 }2355 }
23572356
2358 pub fn unwrap(this: @This()) ?std.Target.Abi {2357 pub fn unwrap(this: @This()) ?std.Target.Abi {
2359 return switch (this) {2358 return switch (this) {
2360 .none => .none,2359 inline else => |tag| @field(std.Target.Abi, @tagName(tag)),
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,
2390 .default => null,2360 .default => null,
2391 };2361 };
2392 }2362 }
...@@ -2458,132 +2428,13 @@ pub const TargetQuery = struct {...@@ -2458,132 +2428,13 @@ pub const TargetQuery = struct {
24582428
2459 pub fn init(x: ?std.Target.Cpu.Arch) @This() {2429 pub fn init(x: ?std.Target.Cpu.Arch) @This() {
2460 return switch (x orelse return .default) {2430 return switch (x orelse return .default) {
2461 .aarch64 => .aarch64,2431 inline else => |tag| @field(@This(), @tagName(tag)),
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,
2521 };2432 };
2522 }2433 }
25232434
2524 pub fn unwrap(this: @This()) ?std.Target.Cpu.Arch {2435 pub fn unwrap(this: @This()) ?std.Target.Cpu.Arch {
2525 return switch (this) {2436 return switch (this) {
2526 .aarch64 => .aarch64,2437 inline else => |tag| @field(std.Target.Cpu.Arch, @tagName(tag)),
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
2587 .default => null,2438 .default => null,
2588 };2439 };
2589 }2440 }
...@@ -2642,106 +2493,13 @@ pub const TargetQuery = struct {...@@ -2642,106 +2493,13 @@ pub const TargetQuery = struct {
26422493
2643 pub fn init(x: ?std.Target.Os.Tag) @This() {2494 pub fn init(x: ?std.Target.Os.Tag) @This() {
2644 return switch (x orelse return .default) {2495 return switch (x orelse return .default) {
2645 .freestanding => .freestanding,2496 inline else => |tag| @field(@This(), @tagName(tag)),
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,
2692 };2497 };
2693 }2498 }
26942499
2695 pub fn unwrap(this: @This()) ?std.Target.Os.Tag {2500 pub fn unwrap(this: @This()) ?std.Target.Os.Tag {
2696 return switch (this) {2501 return switch (this) {
2697 .freestanding => .freestanding,2502 inline else => |tag| @field(std.Target.Os.Tag, @tagName(tag)),
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
2745 .default => null,2503 .default => null,
2746 };2504 };
2747 }2505 }
...@@ -2762,30 +2520,13 @@ pub const TargetQuery = struct {...@@ -2762,30 +2520,13 @@ pub const TargetQuery = struct {
27622520
2763 pub fn init(x: ?std.Target.ObjectFormat) @This() {2521 pub fn init(x: ?std.Target.ObjectFormat) @This() {
2764 return switch (x orelse return .default) {2522 return switch (x orelse return .default) {
2765 .c => .c,2523 inline else => |tag| @field(@This(), @tagName(tag)),
2766 .coff => .coff,
2767 .elf => .elf,
2768 .hex => .hex,
2769 .macho => .macho,
2770 .plan9 => .plan9,
2771 .raw => .raw,
2772 .spirv => .spirv,
2773 .wasm => .wasm,
2774 };2524 };
2775 }2525 }
27762526
2777 pub fn unwrap(this: @This()) ?std.Target.ObjectFormat {2527 pub fn unwrap(this: @This()) ?std.Target.ObjectFormat {
2778 return switch (this) {2528 return switch (this) {
2779 .c => .c,2529 inline else => |tag| @field(std.Target.ObjectFormat, @tagName(tag)),
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
2789 .default => null,2530 .default => null,
2790 };2531 };
2791 }2532 }
...@@ -3462,6 +3203,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {...@@ -3462,6 +3203,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {
3462 .system_integrations = try arena.alloc(SystemIntegration, header.system_integrations_len),3203 .system_integrations = try arena.alloc(SystemIntegration, header.system_integrations_len),
3463 .available_options = try arena.alloc(AvailableOption, header.available_options_len),3204 .available_options = try arena.alloc(AvailableOption, header.available_options_len),
3464 .search_prefixes = try arena.alloc(String, header.search_prefixes_len),3205 .search_prefixes = try arena.alloc(String, header.search_prefixes_len),
3206 .packages = try arena.alloc(Package, header.packages_len),
3465 .extra = try arena.alloc(u32, header.extra_len),3207 .extra = try arena.alloc(u32, header.extra_len),
3466 .default_step = header.default_step,3208 .default_step = header.default_step,
3467 .generated_files_len = header.generated_files_len,3209 .generated_files_len = header.generated_files_len,
...@@ -3475,6 +3217,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {...@@ -3475,6 +3217,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {
3475 @ptrCast(result.system_integrations),3217 @ptrCast(result.system_integrations),
3476 @ptrCast(result.available_options),3218 @ptrCast(result.available_options),
3477 @ptrCast(result.search_prefixes),3219 @ptrCast(result.search_prefixes),
3220 @ptrCast(result.packages),
3478 @ptrCast(result.extra),3221 @ptrCast(result.extra),
3479 };3222 };
3480 try reader.readVecAll(&vecs);3223 try reader.readVecAll(&vecs);
lib/std/Build/Module.zig+2-2
...@@ -402,8 +402,8 @@ pub fn addCSourceFiles(m: *Module, options: AddCSourceFilesOptions) void {...@@ -402,8 +402,8 @@ pub fn addCSourceFiles(m: *Module, options: AddCSourceFilesOptions) void {
402 const c_source_files = arena.create(CSourceFiles) catch @panic("OOM");402 const c_source_files = arena.create(CSourceFiles) catch @panic("OOM");
403 c_source_files.* = .{403 c_source_files.* = .{
404 .root = options.root orelse b.path(""),404 .root = options.root orelse b.path(""),
405 .files = b.dupeStrings(options.files),405 .files = b.graph.dupeStrings(options.files),
406 .flags = b.dupeStrings(options.flags),406 .flags = b.graph.dupeStrings(options.flags),
407 .language = options.language,407 .language = options.language,
408 };408 };
409 m.link_objects.append(arena, .{ .c_source_files = c_source_files }) catch @panic("OOM");409 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;...@@ -10,7 +10,8 @@ const log = std.log;
10arena: Allocator,10arena: Allocator,
11wc: *Configuration.Wip,11wc: *Configuration.Wip,
12module_map: std.array_hash_map.Auto(*std.Build.Module, Configuration.Module.Index) = .empty,12module_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,
14/// Index corresponds to `Configuration.steps` index.15/// Index corresponds to `Configuration.steps` index.
15step_map: std.array_hash_map.Auto(*Step, void) = .empty,16step_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...@@ -21,6 +22,10 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
2122
22 var s: Serialize = .{ .wc = wc, .arena = arena };23 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
24 try wc.path_deps.ensureTotalCapacityPrecise(gpa, graph.configure_dependencies.items.len);29 try wc.path_deps.ensureTotalCapacityPrecise(gpa, graph.configure_dependencies.items.len);
25 for (30 for (
26 graph.configure_dependencies.items,31 graph.configure_dependencies.items,
...@@ -44,10 +49,10 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi...@@ -44,10 +49,10 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
44 .relative => |r| try wc.addString(r.sub_path),49 .relative => |r| try wc.addString(r.sub_path),
45 },50 },
46 .pkg = switch (src.lazy_path) {51 .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)),
48 .generated => unreachable,53 .generated => unreachable,
49 .cwd_relative, .relative => .none,54 .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)),
51 },56 },
52 };57 };
53 }58 }
...@@ -84,7 +89,7 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi...@@ -84,7 +89,7 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
84 try wc.steps.ensureTotalCapacity(gpa, s.step_map.entries.capacity);89 try wc.steps.ensureTotalCapacity(gpa, s.step_map.entries.capacity);
85 wc.steps.appendAssumeCapacity(.{90 wc.steps.appendAssumeCapacity(.{
86 .name = try wc.addString(step.name),91 .name = try wc.addString(step.name),
87 .owner = try s.builderToPackage(step.owner),92 .owner = s.packageFromHash(step.owner.pkg_hash),
88 .deps = deps,93 .deps = deps,
89 .max_rss = .fromBytes(step.max_rss),94 .max_rss = .fromBytes(step.max_rss),
90 .extended = @fromBackingInt(@intCast(switch (step.tag) {95 .extended = @fromBackingInt(@intCast(switch (step.tag) {
...@@ -168,8 +173,6 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi...@@ -168,8 +173,6 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
168 .linkage = .init(c.linkage),173 .linkage = .init(c.linkage),
169 },174 },
170 .flags3 = .{175 .flags3 = .{
171 .is_linking_libc = c.is_linking_libc,
172 .is_linking_libcpp = c.is_linking_libcpp,
173 .version = c.version != null,176 .version = c.version != null,
174 .compress_debug_sections = c.compress_debug_sections,177 .compress_debug_sections = c.compress_debug_sections,
175 .initial_memory = c.initial_memory != null,178 .initial_memory = c.initial_memory != null,
...@@ -454,6 +457,13 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi...@@ -454,6 +457,13 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
454 },457 },
455 else => {},458 else => {},
456 }459 }
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
458 break :e try wc.addExtraErased(Configuration.Step.Run, .{468 break :e try wc.addExtraErased(Configuration.Step.Run, .{
459 .flags = .{469 .flags = .{
...@@ -482,6 +492,7 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi...@@ -482,6 +492,7 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
482 .captured_stdout = run.captured_stdout != null,492 .captured_stdout = run.captured_stdout != null,
483 .captured_stderr = run.captured_stderr != null,493 .captured_stderr = run.captured_stderr != null,
484 .environ_map = run.environ_map != null,494 .environ_map = run.environ_map != null,
495 .preopens = run.preopens.count() > 0,
485 },496 },
486 .flags2 = .{497 .flags2 = .{
487 .expect_stderr_exact = expect_stderr_exact != null,498 .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...@@ -496,8 +507,7 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
496 .file_inputs = .{ .slice = try s.initLazyPathList(run.file_inputs.items) },507 .file_inputs = .{ .slice = try s.initLazyPathList(run.file_inputs.items) },
497 .args = .{ .slice = try s.initArgsList(run.argv.items) },508 .args = .{ .slice = try s.initArgsList(run.argv.items) },
498 .cwd = .{ .value = try s.addOptionalLazyPath(run.cwd) },509 .cwd = .{ .value = try s.addOptionalLazyPath(run.cwd) },
499 .preopen_names = .{ .slice = try s.initStringList(run.preopens.keys()) },510 .preopens = .{ .slice = preopens },
500 .preopen_paths = .{ .slice = try s.initLazyPathList(run.preopens.values()) },
501 .captured_stdout = .{ .value = if (run.captured_stdout) |cs| .{511 .captured_stdout = .{ .value = if (run.captured_stdout) |cs| .{
502 .basename = try wc.addString(cs.basename),512 .basename = try wc.addString(cs.basename),
503 .generated_file = cs.generated_file,513 .generated_file = cs.generated_file,
...@@ -717,19 +727,64 @@ pub fn packageOptions(b: *std.Build, wc: *Configuration.Wip) Allocator.Error!voi...@@ -717,19 +727,64 @@ pub fn packageOptions(b: *std.Build, wc: *Configuration.Wip) Allocator.Error!voi
717 }727 }
718}728}
719729
720fn builderToPackage(s: *Serialize, b: *std.Build) !Configuration.Package.Index {730fn addRootPackage(s: *Serialize, b: *std.Build) Allocator.Error!void {
721 if (b.pkg_hash.len == 0) return .root;
722 const arena = s.arena;731 const arena = s.arena;
723 const wc = s.wc;732 const wc = s.wc;
724 const gop = try s.package_map.getOrPut(arena, b);733
725 if (!gop.found_existing) {734 try wc.packages.append(wc.gpa, .{
726 gop.value_ptr.* = try wc.addExtra(Configuration.Package, .{735 .dep_prefix = .empty,
727 .hash = try wc.addString(b.pkg_hash),736 .hash = .empty,
728 .dep_prefix = try wc.addString(b.dep_prefix),737 .root_path = try wc.addString(try b.root.toString(arena)),
729 .root_path = try wc.addString(try b.root.toString(arena)),738 .deps = undefined,
730 });739 });
731 }740
732 return gop.value_ptr.*;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});
733}788}
734789
735fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuration.LazyPath.OptionalIndex {790fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuration.LazyPath.OptionalIndex {
...@@ -738,7 +793,7 @@ fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuratio...@@ -738,7 +793,7 @@ fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuratio
738 .src_path => |src_path| i: {793 .src_path => |src_path| i: {
739 const sub_path = try wc.addString(src_path.sub_path);794 const sub_path = try wc.addString(src_path.sub_path);
740 break :i try wc.addExtraErased(Configuration.LazyPath.SourcePath, .{795 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),
742 .sub_path = sub_path,797 .sub_path = sub_path,
743 });798 });
744 },799 },
...@@ -766,7 +821,7 @@ fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuratio...@@ -766,7 +821,7 @@ fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuratio
766 .dependency => |dependency| i: {821 .dependency => |dependency| i: {
767 const sub_path = try wc.addString(dependency.sub_path);822 const sub_path = try wc.addString(dependency.sub_path);
768 break :i try wc.addExtraErased(Configuration.LazyPath.SourcePath, .{823 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),
770 .sub_path = sub_path,825 .sub_path = sub_path,
771 });826 });
772 },827 },
...@@ -1012,6 +1067,101 @@ fn initArgsList(s: *Serialize, args: []const Step.Run.Arg) ![]const Configuratio...@@ -1012,6 +1067,101 @@ fn initArgsList(s: *Serialize, args: []const Step.Run.Arg) ![]const Configuratio
1012 .producer = .{ .value = null },1067 .producer = .{ .value = null },
1013 .generated = .{ .value = null },1068 .generated = .{ .value = null },
1014 },1069 },
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 },
1015 });1165 });
1016 }1166 }
1017 return result;1167 return result;
...@@ -1131,7 +1281,7 @@ fn addModule(s: *Serialize, m: *std.Build.Module) !Configuration.Module.Index {...@@ -1131,7 +1281,7 @@ fn addModule(s: *Serialize, m: *std.Build.Module) !Configuration.Module.Index {
1131 .link_libcpp = .init(m.link_libcpp),1281 .link_libcpp = .init(m.link_libcpp),
1132 .no_builtin = .init(m.no_builtin),1282 .no_builtin = .init(m.no_builtin),
1133 },1283 },
1134 .owner = try s.builderToPackage(m.owner),1284 .owner = s.packageFromHash(m.owner.pkg_hash),
1135 .root_source_file = try s.addOptionalLazyPathEnum(m.root_source_file),1285 .root_source_file = try s.addOptionalLazyPathEnum(m.root_source_file),
1136 .import_table = .invalid,1286 .import_table = .invalid,
1137 .resolved_target = try addOptionalResolvedTarget(wc, m.resolved_target),1287 .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,...@@ -101,7 +101,7 @@ each_lib_rpath: ?bool = null,
101/// This option overrides the CLI argument passed to `zig build`.101/// This option overrides the CLI argument passed to `zig build`.
102build_id: ?std.zig.BuildId = null,102build_id: ?std.zig.BuildId = null,
103103
104/// Create a .eh_frame_hdr section and a PT_GNU_EH_FRAME segment in the ELF104/// Create a .eh_frame_hdr section and a PT.GNU_EH_FRAME segment in the ELF
105/// file.105/// file.
106link_eh_frame_hdr: bool = false,106link_eh_frame_hdr: bool = false,
107link_emit_relocs: bool = false,107link_emit_relocs: bool = false,
...@@ -220,11 +220,6 @@ expect_errors: ?ExpectedCompileErrors = null,...@@ -220,11 +220,6 @@ expect_errors: ?ExpectedCompileErrors = null,
220/// `std.math.maxInt(u16)`. Overrides the argument passed to `zig build`.220/// `std.math.maxInt(u16)`. Overrides the argument passed to `zig build`.
221error_limit: ?u32 = null,221error_limit: ?u32 = null,
222222
223/// Computed during make().
224is_linking_libc: bool = false,
225/// Computed during make().
226is_linking_libcpp: bool = false,
227
228/// Enables coverage instrumentation that is only useful if you are using third223/// Enables coverage instrumentation that is only useful if you are using third
229/// party fuzzers that depend on it. Otherwise, slows down the instrumented224/// party fuzzers that depend on it. Otherwise, slows down the instrumented
230/// binary with unnecessary function calls.225/// binary with unnecessary function calls.
...@@ -375,7 +370,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {...@@ -375,7 +370,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
375 const graph = owner.graph;370 const graph = owner.graph;
376 const arena = graph.arena;371 const arena = graph.arena;
377372
378 const name = owner.dupe(options.name);373 const name = owner.graph.dupeString(options.name);
379 if (mem.find(u8, name, "/") != null or mem.find(u8, name, "\\") != null) {374 if (mem.find(u8, name, "/") != null or mem.find(u8, name, "\\") != null) {
380 panic("invalid name: '{s}'. It looks like a file path, but it is supposed to be the library or application name.", .{name});375 panic("invalid name: '{s}'. It looks like a file path, but it is supposed to be the library or application name.", .{name});
381 }376 }
...@@ -390,7 +385,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {...@@ -390,7 +385,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
390 @tagName(options.kind)385 @tagName(options.kind)
391 else386 else
392 owner.fmt("{t} {s}", .{ options.kind, name }),387 owner.fmt("{t} {s}", .{ options.kind, name }),
393 @tagName(options.root_module.optimize orelse .Debug),388 @tagName(options.root_module.optimize orelse .debug),
394 resolved_target.query.zigTriple(arena) catch @panic("OOM"),389 resolved_target.query.zigTriple(arena) catch @panic("OOM"),
395 });390 });
396391
...@@ -645,7 +640,7 @@ pub fn producesPdbFile(compile: *Compile) bool {...@@ -645,7 +640,7 @@ pub fn producesPdbFile(compile: *Compile) bool {
645 if (target.ofmt == .c) return false;640 if (target.ofmt == .c) return false;
646 if (compile.use_llvm == false) return false;641 if (compile.use_llvm == false) return false;
647 if (compile.root_module.strip == true or642 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))
649 {644 {
650 return false;645 return false;
651 }646 }
lib/std/Build/Step/ConfigHeader.zig+4-1
...@@ -27,6 +27,9 @@ pub const Style = union(enum) {...@@ -27,6 +27,9 @@ pub const Style = union(enum) {
27 /// The configure format supported by CMake. It uses `@FOO@`, `${}` and27 /// The configure format supported by CMake. It uses `@FOO@`, `${}` and
28 /// `#cmakedefine` for template substitution.28 /// `#cmakedefine` for template substitution.
29 cmake: std.Build.LazyPath,29 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,
30 /// Instead of starting with an input file, start with nothing.33 /// Instead of starting with an input file, start with nothing.
31 blank,34 blank,
32 /// Start with nothing, like blank, and output a nasm .asm file.35 /// Start with nothing, like blank, and output a nasm .asm file.
...@@ -34,7 +37,7 @@ pub const Style = union(enum) {...@@ -34,7 +37,7 @@ pub const Style = union(enum) {
3437
35 pub fn getPath(style: Style) ?std.Build.LazyPath {38 pub fn getPath(style: Style) ?std.Build.LazyPath {
36 switch (style) {39 switch (style) {
37 .autoconf_undef, .autoconf_at, .cmake => |s| return s,40 .autoconf_undef, .autoconf_at, .cmake, .meson => |s| return s,
38 .blank, .nasm => return null,41 .blank, .nasm => return null,
39 }42 }
40 }43 }
lib/std/Build/Step/Run.zig+58-2
...@@ -28,7 +28,7 @@ environ_map: ?*EnvMap,...@@ -28,7 +28,7 @@ environ_map: ?*EnvMap,
2828
29/// Named files that will be provided to the parent process.29/// Named files that will be provided to the parent process.
30/// See `std.process.Preopens`.30/// See `std.process.Preopens`.
31preopens: std.array_hash_map.String(Build.LazyPath),31preopens: std.array_hash_map.Auto(Configuration.String, Build.LazyPath),
3232
33/// Controls the `NO_COLOR` and `CLICOLOR_FORCE` environment variables.33/// Controls the `NO_COLOR` and `CLICOLOR_FORCE` environment variables.
34color: Color = .auto,34color: Color = .auto,
...@@ -68,9 +68,11 @@ rename_step_with_output_arg: bool,...@@ -68,9 +68,11 @@ rename_step_with_output_arg: bool,
68/// executed binary will not fail the build if the binary cannot be executed68/// executed binary will not fail the build if the binary cannot be executed
69/// due to being for a foreign binary to the host system which is running the69/// due to being for a foreign binary to the host system which is running the
70/// build graph.70/// build graph.
71///
71/// Command-line arguments such as -fqemu and -fwasmtime may affect whether a72/// Command-line arguments such as -fqemu and -fwasmtime may affect whether a
72/// binary is detected as foreign, as well as system configuration such as73/// binary is detected as foreign, as well as system configuration such as
73/// Rosetta (macOS) and binfmt_misc (Linux).74/// Rosetta (macOS) and binfmt_misc (Linux).
75///
74/// If this Run step is considered to have side-effects, then this flag does76/// If this Run step is considered to have side-effects, then this flag does
75/// nothing.77/// nothing.
76skip_foreign_checks: bool,78skip_foreign_checks: bool,
...@@ -149,6 +151,19 @@ pub const Arg = union(enum) {...@@ -149,6 +151,19 @@ pub const Arg = union(enum) {
149 output_directory: *Output,151 output_directory: *Output,
150 /// The arguments passed after "--" on the "zig build" CLI.152 /// The arguments passed after "--" on the "zig build" CLI.
151 passthru,153 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,
152};167};
153168
154pub const DecoratedArtifact = struct {169pub const DecoratedArtifact = struct {
...@@ -576,6 +591,46 @@ pub fn addPassthruArgs(run: *Run) void {...@@ -576,6 +591,46 @@ pub fn addPassthruArgs(run: *Run) void {
576 run.argv.append(arena, .passthru) catch @panic("OOM");591 run.argv.append(arena, .passthru) catch @panic("OOM");
577}592}
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
579pub fn setStdIn(run: *Run, stdin: StdIn) void {634pub fn setStdIn(run: *Run, stdin: StdIn) void {
580 switch (stdin) {635 switch (stdin) {
581 .lazy_path => |lazy_path| lazy_path.addStepDependencies(&run.step),636 .lazy_path => |lazy_path| lazy_path.addStepDependencies(&run.step),
...@@ -624,11 +679,12 @@ pub fn removeEnvironmentVariable(run: *Run, key: []const u8) void {...@@ -624,11 +679,12 @@ pub fn removeEnvironmentVariable(run: *Run, key: []const u8) void {
624679
625pub fn setPreopen(run: *Run, name: []const u8, resource: Build.LazyPath) void {680pub fn setPreopen(run: *Run, name: []const u8, resource: Build.LazyPath) void {
626 const graph = run.step.owner.graph;681 const graph = run.step.owner.graph;
682 const wc = &graph.wip_configuration;
627 const arena = graph.arena;683 const arena = graph.arena;
628 resource.addStepDependencies(&run.step);684 resource.addStepDependencies(&run.step);
629 run.preopens.put(685 run.preopens.put(
630 arena,686 arena,
631 graph.dupeString(name),687 wc.addString(name) catch @panic("OOM"),
632 resource.dupe(graph),688 resource.dupe(graph),
633 ) catch @panic("OOM");689 ) catch @panic("OOM");
634}690}
lib/std/Io.zig+12-6
...@@ -238,7 +238,7 @@ pub const VTable = struct {...@@ -238,7 +238,7 @@ pub const VTable = struct {
238 netSend: *const fn (?*anyopaque, net.Socket.Handle, []net.OutgoingMessage, net.SendFlags) struct { ?net.Socket.SendError, usize },238 netSend: *const fn (?*anyopaque, net.Socket.Handle, []net.OutgoingMessage, net.SendFlags) struct { ?net.Socket.SendError, usize },
239 netWrite: *const fn (?*anyopaque, dest: net.Socket.Handle, header: []const u8, data: []const []const u8, splat: usize) net.Stream.Writer.Error!usize,239 netWrite: *const fn (?*anyopaque, dest: net.Socket.Handle, header: []const u8, data: []const []const u8, splat: usize) net.Stream.Writer.Error!usize,
240 netWriteFile: *const fn (?*anyopaque, net.Socket.Handle, header: []const u8, *Io.File.Reader, Io.Limit) net.Stream.Writer.WriteFileError!usize,240 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,
242 netShutdown: *const fn (?*anyopaque, handle: net.Socket.Handle, how: net.ShutdownHow) net.ShutdownError!void,242 netShutdown: *const fn (?*anyopaque, handle: net.Socket.Handle, how: net.ShutdownHow) net.ShutdownError!void,
243 netInterfaceNameResolve: *const fn (?*anyopaque, *const net.Interface.Name) net.Interface.Name.ResolveError!net.Interface,243 netInterfaceNameResolve: *const fn (?*anyopaque, *const net.Interface.Name) net.Interface.Name.ResolveError!net.Interface,
244 netInterfaceName: *const fn (?*anyopaque, net.Interface) net.Interface.NameError!net.Interface.Name,244 netInterfaceName: *const fn (?*anyopaque, net.Interface) net.Interface.NameError!net.Interface.Name,
...@@ -467,6 +467,7 @@ pub const OperateTimeoutError = Cancelable || Timeout.Error || ConcurrentError;...@@ -467,6 +467,7 @@ pub const OperateTimeoutError = Cancelable || Timeout.Error || ConcurrentError;
467467
468/// Performs one `Operation` with provided `timeout`.468/// Performs one `Operation` with provided `timeout`.
469pub fn operateTimeout(io: Io, operation: Operation, timeout: Timeout) OperateTimeoutError!Operation.Result {469pub fn operateTimeout(io: Io, operation: Operation, timeout: Timeout) OperateTimeoutError!Operation.Result {
470 if (timeout == .none) return io.vtable.operate(io.userdata, operation);
470 var storage: [1]Operation.Storage = undefined;471 var storage: [1]Operation.Storage = undefined;
471 var batch: Batch = .init(&storage);472 var batch: Batch = .init(&storage);
472 batch.addAt(0, operation);473 batch.addAt(0, operation);
...@@ -778,10 +779,10 @@ pub const Clock = enum {...@@ -778,10 +779,10 @@ pub const Clock = enum {
778 /// * On Linux, corresponds `CLOCK_BOOTTIME`.779 /// * On Linux, corresponds `CLOCK_BOOTTIME`.
779 /// * On macOS, corresponds to `CLOCK_MONOTONIC_RAW`.780 /// * On macOS, corresponds to `CLOCK_MONOTONIC_RAW`.
780 boot,781 boot,
781 /// Tracks the amount of CPU in user or kernel mode used by the calling782 /// Tracks the amount of CPU time in user or kernel mode used by the calling
782 /// process.783 /// process.
783 cpu_process,784 cpu_process,
784 /// Tracks the amount of CPU in user or kernel mode used by the calling785 /// Tracks the amount of CPU time in user or kernel mode used by the calling
785 /// thread.786 /// thread.
786 cpu_thread,787 cpu_thread,
787788
...@@ -980,6 +981,10 @@ pub const Timestamp = struct {...@@ -980,6 +981,10 @@ pub const Timestamp = struct {
980 const now_ts = clock.now(io);981 const now_ts = clock.now(io);
981 return t.durationTo(now_ts);982 return t.durationTo(now_ts);
982 }983 }
984
985 pub fn compare(lhs: Timestamp, op: math.CompareOperator, rhs: Timestamp) bool {
986 return math.compare(lhs.nanoseconds, op, rhs.nanoseconds);
987 }
983};988};
984989
985pub const Duration = struct {990pub const Duration = struct {
...@@ -1147,6 +1152,7 @@ pub const Duration = struct {...@@ -1147,6 +1152,7 @@ pub const Duration = struct {
11471152
1148/// Declares under what conditions an operation should return `error.Timeout`.1153/// Declares under what conditions an operation should return `error.Timeout`.
1149pub const Timeout = union(enum) {1154pub const Timeout = union(enum) {
1155 /// `.none` will wait forever
1150 none,1156 none,
1151 duration: Clock.Duration,1157 duration: Clock.Duration,
1152 deadline: Clock.Timestamp,1158 deadline: Clock.Timestamp,
...@@ -2525,7 +2531,7 @@ pub fn lockStderr(io: Io, buffer: []u8, terminal_mode: ?Terminal.Mode) Cancelabl...@@ -2525,7 +2531,7 @@ pub fn lockStderr(io: Io, buffer: []u8, terminal_mode: ?Terminal.Mode) Cancelabl
25252531
2526/// Same as `lockStderr` but non-blocking.2532/// Same as `lockStderr` but non-blocking.
2527pub fn tryLockStderr(io: Io, buffer: []u8, terminal_mode: ?Terminal.Mode) Cancelable!?LockedStderr {2533pub 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;
2529 try ls.clear(buffer);2535 try ls.clear(buffer);
2530 return ls;2536 return ls;
2531}2537}
...@@ -3476,9 +3482,9 @@ pub fn failingNetWriteFile(userdata: ?*anyopaque, handle: net.Socket.Handle, hea...@@ -3476,9 +3482,9 @@ pub fn failingNetWriteFile(userdata: ?*anyopaque, handle: net.Socket.Handle, hea
3476 return error.NetworkDown;3482 return error.NetworkDown;
3477}3483}
34783484
3479pub fn unreachableNetClose(userdata: ?*anyopaque, handle: []const net.Socket.Handle) void {3485pub fn unreachableNetClose(userdata: ?*anyopaque, sockets: []const net.Socket) void {
3480 _ = userdata;3486 _ = userdata;
3481 _ = handle;3487 _ = sockets;
3482 unreachable;3488 unreachable;
3483}3489}
34843490
lib/std/Io/Dispatch.zig+9-8
...@@ -580,6 +580,7 @@ pub fn deinit(ev: *Evented) void {...@@ -580,6 +580,7 @@ pub fn deinit(ev: *Evented) void {
580 ev.stderr_mutex.deinit();580 ev.stderr_mutex.deinit();
581 for (&ev.futexes) |*futex| futex.deinit();581 for (&ev.futexes) |*futex| futex.deinit();
582 ev.exit_semaphore.as_object().release();582 ev.exit_semaphore.as_object().release();
583 ev.backing_allocator_mutex.deinit();
583 ev.backing_allocator.free(ev.main_loop_stack[0..main_loop_stack_size]);584 ev.backing_allocator.free(ev.main_loop_stack[0..main_loop_stack_size]);
584 ev.queue.as_object().release();585 ev.queue.as_object().release();
585}586}
...@@ -825,7 +826,7 @@ const Mutex = struct {...@@ -825,7 +826,7 @@ const Mutex = struct {
825 sleeper: Sleeper = undefined,826 sleeper: Sleeper = undefined,
826 cancelable: Cancelable,827 cancelable: Cancelable,
827 mutex: *Mutex,828 mutex: *Mutex,
828 node: std.DoublyLinkedList.Node = undefined,829 node: std.DoublyLinkedList.Node = .{},
829830
830 fn add(context: ?*anyopaque) callconv(.c) void {831 fn add(context: ?*anyopaque) callconv(.c) void {
831 const waiter: *Waiter = @ptrCast(@alignCast(context));832 const waiter: *Waiter = @ptrCast(@alignCast(context));
...@@ -2781,7 +2782,7 @@ fn realPath(ev: *Evented, fd: c.fd_t, out_buffer: []u8) File.RealPathError!usize...@@ -2781,7 +2782,7 @@ fn realPath(ev: *Evented, fd: c.fd_t, out_buffer: []u8) File.RealPathError!usize
2781 else => |err| return unexpectedErrno(err),2782 else => |err| return unexpectedErrno(err),
2782 }2783 }
2783 }2784 }
2784 const n = std.mem.indexOfScalar(u8, &buffer, 0) orelse buffer.len;2785 const n = std.mem.findScalar(u8, &buffer, 0) orelse buffer.len;
2785 if (n > out_buffer.len) return error.NameTooLong;2786 if (n > out_buffer.len) return error.NameTooLong;
2786 @memcpy(out_buffer[0..n], buffer[0..n]);2787 @memcpy(out_buffer[0..n], buffer[0..n]);
2787 return n;2788 return n;
...@@ -2803,7 +2804,7 @@ fn dirRealPathFile(...@@ -2803,7 +2804,7 @@ fn dirRealPathFile(
2803 while (true) {2804 while (true) {
2804 if (c.realpath(sub_path_posix, out_buffer.ptr)) |redundant_pointer| {2805 if (c.realpath(sub_path_posix, out_buffer.ptr)) |redundant_pointer| {
2805 assert(redundant_pointer == out_buffer.ptr);2806 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;
2807 }2808 }
2808 const err: c.E = @fromBackingInt(@intCast(c._errno().*));2809 const err: c.E = @fromBackingInt(@intCast(c._errno().*));
2809 switch (err) {2810 switch (err) {
...@@ -3791,7 +3792,7 @@ fn fileRealPath(userdata: ?*anyopaque, file: File, out_buffer: []u8) File.RealPa...@@ -3791,7 +3792,7 @@ fn fileRealPath(userdata: ?*anyopaque, file: File, out_buffer: []u8) File.RealPa
3791 else => |err| return unexpectedErrno(err),3792 else => |err| return unexpectedErrno(err),
3792 }3793 }
3793 }3794 }
3794 const n = std.mem.indexOfScalar(u8, &buffer, 0) orelse buffer.len;3795 const n = std.mem.findScalar(u8, &buffer, 0) orelse buffer.len;
3795 if (n > out_buffer.len) return error.NameTooLong;3796 if (n > out_buffer.len) return error.NameTooLong;
3796 @memcpy(out_buffer[0..n], buffer[0..n]);3797 @memcpy(out_buffer[0..n], buffer[0..n]);
3797 return n;3798 return n;
...@@ -3897,7 +3898,7 @@ fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void {...@@ -3897,7 +3898,7 @@ fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void {
3897 if (memory.len == 0) return;3898 if (memory.len == 0) return;
3898 switch (c.errno(c.munmap(memory.ptr, memory.len))) {3899 switch (c.errno(c.munmap(memory.ptr, memory.len))) {
3899 .SUCCESS => {},3900 .SUCCESS => {},
3900 else => |err| if (builtin.mode == .Debug)3901 else => |err| if (builtin.mode == .debug)
3901 std.log.err("failed to unmap {d} bytes at {*}: {t}", .{ memory.len, memory.ptr, err }),3902 std.log.err("failed to unmap {d} bytes at {*}: {t}", .{ memory.len, memory.ptr, err }),
3902 }3903 }
3903 mm.* = undefined;3904 mm.* = undefined;
...@@ -4714,7 +4715,7 @@ fn sleep(userdata: ?*anyopaque, timeout: Io.Timeout) Io.Cancelable!void {...@@ -4714,7 +4715,7 @@ fn sleep(userdata: ?*anyopaque, timeout: Io.Timeout) Io.Cancelable!void {
4714 return ev.yield(.{ .after = ev.timeFromTimeout(timeout) });4715 return ev.yield(.{ .after = ev.timeFromTimeout(timeout) });
4715 };4716 };
4716 var waiter: SleepWaiter = .{4717 var waiter: SleepWaiter = .{
4717 .cancelable = .{ .queue = queue, .cancel = &Futex.Waiter.canceled },4718 .cancelable = .{ .queue = queue, .cancel = &SleepWaiter.canceled },
4718 .timer = timer,4719 .timer = timer,
4719 };4720 };
4720 timer.as_object().set_context(&waiter);4721 timer.as_object().set_context(&waiter);
...@@ -4911,10 +4912,10 @@ fn netWriteFileUnavailable(...@@ -4911,10 +4912,10 @@ fn netWriteFileUnavailable(
4911 return error.Unimplemented;4912 return error.Unimplemented;
4912}4913}
49134914
4914fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void {4915fn netClose(userdata: ?*anyopaque, sockets: []const net.Socket) void {
4915 const ev: *Evented = @ptrCast(@alignCast(userdata));4916 const ev: *Evented = @ptrCast(@alignCast(userdata));
4916 _ = ev;4917 _ = ev;
4917 for (handles) |handle| closeFd(handle);4918 for (sockets) |socket| closeFd(socket.handle);
4918}4919}
49194920
4920fn netShutdownUnavailable(4921fn netShutdownUnavailable(
lib/std/Io/Kqueue.zig+3-2
...@@ -1280,10 +1280,10 @@ fn netWrite(userdata: ?*anyopaque, dest: net.Socket.Handle, header: []const u8,...@@ -1280,10 +1280,10 @@ fn netWrite(userdata: ?*anyopaque, dest: net.Socket.Handle, header: []const u8,
1280 @panic("TODO");1280 @panic("TODO");
1281}1281}
12821282
1283fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void {1283fn netClose(userdata: ?*anyopaque, sockets: []const net.Socket) void {
1284 const k: *Kqueue = @ptrCast(@alignCast(userdata));1284 const k: *Kqueue = @ptrCast(@alignCast(userdata));
1285 _ = k;1285 _ = k;
1286 _ = handles;1286 _ = sockets;
1287 @panic("TODO");1287 @panic("TODO");
1288}1288}
12891289
...@@ -1422,6 +1422,7 @@ fn posixBind(...@@ -1422,6 +1422,7 @@ fn posixBind(
1422 .INTR => continue,1422 .INTR => continue,
1423 .CANCELED => return error.Canceled,1423 .CANCELED => return error.Canceled,
14241424
1425 .ACCES => return error.AccessDenied,
1425 .ADDRINUSE => return error.AddressInUse,1426 .ADDRINUSE => return error.AddressInUse,
1426 .BADF => |err| return errnoBug(err), // File descriptor used after closed.1427 .BADF => |err| return errnoBug(err), // File descriptor used after closed.
1427 .INVAL => |err| return errnoBug(err), // invalid parameters1428 .INVAL => |err| return errnoBug(err), // invalid parameters
lib/std/Io/Reader.zig+3-5
...@@ -718,7 +718,7 @@ pub inline fn readSliceEndian(...@@ -718,7 +718,7 @@ pub inline fn readSliceEndian(
718 endian: std.builtin.Endian,718 endian: std.builtin.Endian,
719) Error!void {719) Error!void {
720 try readSliceAll(r, @ptrCast(buffer));720 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);
722}722}
723723
724pub const ReadAllocError = Error || Allocator.Error;724pub const ReadAllocError = Error || Allocator.Error;
...@@ -734,8 +734,7 @@ pub inline fn readSliceEndianAlloc(...@@ -734,8 +734,7 @@ pub inline fn readSliceEndianAlloc(
734) ReadAllocError![]Elem {734) ReadAllocError![]Elem {
735 const dest = try allocator.alloc(Elem, len);735 const dest = try allocator.alloc(Elem, len);
736 errdefer allocator.free(dest);736 errdefer allocator.free(dest);
737 try readSliceAll(r, @ptrCast(dest));737 try r.readSliceEndian(Elem, dest, endian);
738 if (native_endian != endian) for (dest) |*elem| std.mem.byteSwapAllFields(Elem, elem);
739 return dest;738 return dest;
740}739}
741740
...@@ -1227,8 +1226,7 @@ pub inline fn takeStruct(r: *Reader, comptime T: type, endian: std.builtin.Endia...@@ -1227,8 +1226,7 @@ pub inline fn takeStruct(r: *Reader, comptime T: type, endian: std.builtin.Endia
1227 .auto => @compileError("ill-defined memory layout"),1226 .auto => @compileError("ill-defined memory layout"),
1228 .@"extern" => {1227 .@"extern" => {
1229 var res: T = undefined;1228 var res: T = undefined;
1230 try r.readSliceAll(std.mem.asBytes(&res));1229 try r.readSliceEndian(T, (&res)[0..1], endian);
1231 if (native_endian != endian) std.mem.byteSwapAllFields(T, &res);
1232 return res;1230 return res;
1233 },1231 },
1234 .@"packed" => {1232 .@"packed" => {
lib/std/Io/RwLock.zig-2
...@@ -284,8 +284,6 @@ test "concurrent access" {...@@ -284,8 +284,6 @@ test "concurrent access" {
284}284}
285285
286test "lock canceling" {286test "lock canceling" {
287 if (builtin.cpu.arch.isSPARC() and builtin.os.tag == .linux) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35347
288
289 const io = testing.io;287 const io = testing.io;
290288
291 var rl: Io.RwLock = .init;289 var rl: Io.RwLock = .init;
lib/std/Io/Semaphore.zig-2
...@@ -4,8 +4,6 @@...@@ -4,8 +4,6 @@
4//! This API supports static initialization and does not require deinitialization.4//! This API supports static initialization and does not require deinitialization.
5const Semaphore = @This();5const Semaphore = @This();
66
7const builtin = @import("builtin");
8
9const std = @import("../std.zig");7const std = @import("../std.zig");
10const Io = std.Io;8const Io = std.Io;
11const testing = std.testing;9const testing = std.testing;
lib/std/Io/Threaded.zig+156-38
...@@ -4,7 +4,7 @@ const builtin = @import("builtin");...@@ -4,7 +4,7 @@ const builtin = @import("builtin");
4const native_os = builtin.os.tag;4const native_os = builtin.os.tag;
5const is_windows = native_os == .windows;5const is_windows = native_os == .windows;
6const is_darwin = native_os.isDarwin();6const is_darwin = native_os.isDarwin();
7const is_debug = builtin.mode == .Debug;7const is_debug = builtin.mode == .debug;
88
9const std = @import("../std.zig");9const std = @import("../std.zig");
10const Io = std.Io;10const Io = std.Io;
...@@ -440,12 +440,12 @@ pub const UseFchmodat2 = if (have_fchmodat2 and !have_fchmodat_flags) enum {...@@ -440,12 +440,12 @@ pub const UseFchmodat2 = if (have_fchmodat2 and !have_fchmodat_flags) enum {
440pub const apc_align = @max(default_fn_align, 2);440pub const apc_align = @max(default_fn_align, 2);
441441
442const default_fn_align = switch (builtin.mode) {442const default_fn_align = switch (builtin.mode) {
443 .Debug, .ReleaseSafe, .ReleaseFast => switch (builtin.cpu.arch) {443 .debug, .safe, .fast => switch (builtin.cpu.arch) {
444 else => |arch| @compileError("Unsupported architecture: " ++ @tagName(arch)),444 else => |arch| @compileError("Unsupported architecture: " ++ @tagName(arch)),
445 .arm, .thumb => 4,445 .arm, .thumb => 4,
446 .aarch64, .x86, .x86_64 => 16,446 .aarch64, .x86, .x86_64 => 16,
447 },447 },
448 .ReleaseSmall => 1,448 .small => 1,
449};449};
450450
451const Runnable = struct {451const Runnable = struct {
...@@ -829,6 +829,7 @@ const Thread = struct {...@@ -829,6 +829,7 @@ const Thread = struct {
829 /// Always released when `Status.cancelation` is set to `.parked`.829 /// Always released when `Status.cancelation` is set to `.parked`.
830 futex_waiter: if (use_parking_futex) ?*parking_futex.Waiter else ?noreturn,830 futex_waiter: if (use_parking_futex) ?*parking_futex.Waiter else ?noreturn,
831 unpark_flag: UnparkFlag,831 unpark_flag: UnparkFlag,
832 park_tid: if (ParkTid == std.Thread.Id) void else ParkTid,
832833
833 csprng: Csprng,834 csprng: Csprng,
834835
...@@ -1220,7 +1221,7 @@ const Thread = struct {...@@ -1220,7 +1221,7 @@ const Thread = struct {
1220 parking_futex.removeCanceledWaiter(futex_waiter);1221 parking_futex.removeCanceledWaiter(futex_waiter);
1221 }1222 }
1222 if (need_unpark_flag) setUnparkFlag(&thread.unpark_flag);1223 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);
1224 return false;1225 return false;
1225 },1226 },
12261227
...@@ -1749,6 +1750,7 @@ fn worker(t: *Threaded) void {...@@ -1749,6 +1750,7 @@ fn worker(t: *Threaded) void {
1749 .cancel_protection = .unblocked,1750 .cancel_protection = .unblocked,
1750 .futex_waiter = undefined,1751 .futex_waiter = undefined,
1751 .unpark_flag = unpark_flag_init,1752 .unpark_flag = unpark_flag_init,
1753 .park_tid = if (ParkTid == std.Thread.Id) {} else getParkTid(),
1752 .csprng = .uninitialized,1754 .csprng = .uninitialized,
1753 };1755 };
1754 Thread.current = &thread;1756 Thread.current = &thread;
...@@ -3858,7 +3860,26 @@ fn fileLength(userdata: ?*anyopaque, file: File) File.LengthError!u64 {...@@ -3858,7 +3860,26 @@ fn fileLength(userdata: ?*anyopaque, file: File) File.LengthError!u64 {
3858 }3860 }
3859 }3861 }
3860 } else if (is_windows) {3862 } 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));
3862 }3883 }
38633884
3864 const stat = try fileStat(t, file);3885 const stat = try fileStat(t, file);
...@@ -4382,7 +4403,7 @@ fn dirCreateFilePosix(...@@ -4382,7 +4403,7 @@ fn dirCreateFilePosix(
4382 }4403 }
4383 };4404 };
43844405
4385 fl_flags |= @as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK"));4406 fl_flags &= ~@as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK"));
43864407
4387 const syscall: Syscall = try .start();4408 const syscall: Syscall = try .start();
4388 while (true) {4409 while (true) {
...@@ -4978,7 +4999,7 @@ fn dirOpenFilePosix(...@@ -4978,7 +4999,7 @@ fn dirOpenFilePosix(
4978 }4999 }
4979 };5000 };
49805001
4981 fl_flags |= @as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK"));5002 fl_flags &= ~@as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK"));
49825003
4983 const syscall: Syscall = try .start();5004 const syscall: Syscall = try .start();
4984 while (true) {5005 while (true) {
...@@ -5053,7 +5074,7 @@ pub fn dirOpenFileWtf16(...@@ -5053,7 +5074,7 @@ pub fn dirOpenFileWtf16(
5053 .VALID_FLAGS,5074 .VALID_FLAGS,
5054 .OPEN,5075 .OPEN,
5055 .{5076 .{
5056 .IO = if (flags.follow_symlinks) .SYNCHRONOUS_NONALERT else .ASYNCHRONOUS,5077 .IO = .SYNCHRONOUS_NONALERT,
5057 .NON_DIRECTORY_FILE = !allow_directory,5078 .NON_DIRECTORY_FILE = !allow_directory,
5058 .OPEN_REPARSE_POINT = !flags.follow_symlinks,5079 .OPEN_REPARSE_POINT = !flags.follow_symlinks,
5059 },5080 },
...@@ -6817,7 +6838,7 @@ fn dirRealPathFilePosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, o...@@ -6817,7 +6838,7 @@ fn dirRealPathFilePosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, o
6817 if (std.c.realpath(sub_path_posix, out_buffer.ptr)) |redundant_pointer| {6838 if (std.c.realpath(sub_path_posix, out_buffer.ptr)) |redundant_pointer| {
6818 syscall.finish();6839 syscall.finish();
6819 assert(redundant_pointer == out_buffer.ptr);6840 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;
6821 }6842 }
6822 const err: posix.E = @fromBackingInt(@intCast(std.c._errno().*));6843 const err: posix.E = @fromBackingInt(@intCast(std.c._errno().*));
6823 if (err == .INTR) {6844 if (err == .INTR) {
...@@ -6961,7 +6982,7 @@ fn realPathPosix(fd: posix.fd_t, out_buffer: []u8) File.RealPathError!usize {...@@ -6961,7 +6982,7 @@ fn realPathPosix(fd: posix.fd_t, out_buffer: []u8) File.RealPathError!usize {
6961 },6982 },
6962 }6983 }
6963 }6984 }
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;
6965 if (n > out_buffer.len) return error.NameTooLong;6986 if (n > out_buffer.len) return error.NameTooLong;
6966 @memcpy(out_buffer[0..n], sufficient_buffer[0..n]);6987 @memcpy(out_buffer[0..n], sufficient_buffer[0..n]);
6967 return n;6988 return n;
...@@ -7119,9 +7140,10 @@ fn dirDeleteFileWasi(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8) Dir....@@ -7119,9 +7140,10 @@ fn dirDeleteFileWasi(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8) Dir.
7119 if (builtin.link_libc) return dirDeleteFilePosix(userdata, dir, sub_path);7140 if (builtin.link_libc) return dirDeleteFilePosix(userdata, dir, sub_path);
7120 const t: *Threaded = @ptrCast(@alignCast(userdata));7141 const t: *Threaded = @ptrCast(@alignCast(userdata));
7121 _ = t;7142 _ = t;
7143 const wasi = std.os.wasi;
7122 const syscall: Syscall = try .start();7144 const syscall: Syscall = try .start();
7123 while (true) {7145 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);
7125 switch (res) {7147 switch (res) {
7126 .SUCCESS => {7148 .SUCCESS => {
7127 syscall.finish();7149 syscall.finish();
...@@ -7131,11 +7153,35 @@ fn dirDeleteFileWasi(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8) Dir....@@ -7131,11 +7153,35 @@ fn dirDeleteFileWasi(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8) Dir.
7131 try syscall.checkCancel();7153 try syscall.checkCancel();
7132 continue;7154 continue;
7133 },7155 },
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 },
7134 else => |e| {7182 else => |e| {
7135 syscall.finish();7183 syscall.finish();
7136 switch (e) {7184 switch (e) {
7137 .ACCES => return error.AccessDenied,
7138 .PERM => return error.PermissionDenied,
7139 .BUSY => return error.FileBusy,7185 .BUSY => return error.FileBusy,
7140 .FAULT => |err| return errnoBug(err),7186 .FAULT => |err| return errnoBug(err),
7141 .IO => return error.FileSystem,7187 .IO => return error.FileSystem,
...@@ -8111,7 +8157,7 @@ fn dirReadLinkWindows(dir: Dir, sub_path: []const u8, buffer: []u8) Dir.ReadLink...@@ -8111,7 +8157,7 @@ fn dirReadLinkWindows(dir: Dir, sub_path: []const u8, buffer: []u8) Dir.ReadLink
8111 .{8157 .{
8112 .DIRECTORY_FILE = false,8158 .DIRECTORY_FILE = false,
8113 .NON_DIRECTORY_FILE = false,8159 .NON_DIRECTORY_FILE = false,
8114 .IO = .ASYNCHRONOUS,8160 .IO = .SYNCHRONOUS_NONALERT,
8115 .OPEN_REPARSE_POINT = true,8161 .OPEN_REPARSE_POINT = true,
8116 },8162 },
8117 null,8163 null,
...@@ -8177,7 +8223,7 @@ fn dirReadLinkWindows(dir: Dir, sub_path: []const u8, buffer: []u8) Dir.ReadLink...@@ -8177,7 +8223,7 @@ fn dirReadLinkWindows(dir: Dir, sub_path: []const u8, buffer: []u8) Dir.ReadLink
81778223
8178 var reparse_buf: [windows.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 align(@alignOf(windows.REPARSE_DATA_BUFFER)) = undefined;8224 var reparse_buf: [windows.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 align(@alignOf(windows.REPARSE_DATA_BUFFER)) = undefined;
8179 switch ((try deviceIoControl(&.{8225 switch ((try deviceIoControl(&.{
8180 .file = .{ .handle = result_handle, .flags = .{ .nonblocking = true } },8226 .file = .{ .handle = result_handle, .flags = .{ .nonblocking = false } },
8181 .code = .GET_REPARSE_POINT,8227 .code = .GET_REPARSE_POINT,
8182 .out = &reparse_buf,8228 .out = &reparse_buf,
8183 })).u.Status) {8229 })).u.Status) {
...@@ -8955,7 +9001,7 @@ fn isCygwinPty(file: File) Io.Cancelable!bool {...@@ -8955,7 +9001,7 @@ fn isCygwinPty(file: File) Io.Cancelable!bool {
8955 // The name we get from NtQueryInformationFile will be prefixed with a '\', e.g. \msys-1888ae32e00d56aa-pty0-to-master9001 // The name we get from NtQueryInformationFile will be prefixed with a '\', e.g. \msys-1888ae32e00d56aa-pty0-to-master
8956 return (std.mem.startsWith(u16, name_wide, &[_]u16{ '\\', 'm', 's', 'y', 's', '-' }) or9002 return (std.mem.startsWith(u16, name_wide, &[_]u16{ '\\', 'm', 's', 'y', 's', '-' }) or
8957 std.mem.startsWith(u16, name_wide, &[_]u16{ '\\', 'c', 'y', 'g', 'w', 'i', 'n', '-' })) and9003 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;
8959}9005}
89609006
8961fn fileSetLength(userdata: ?*anyopaque, file: File, length: u64) File.SetLengthError!void {9007fn fileSetLength(userdata: ?*anyopaque, file: File, length: u64) File.SetLengthError!void {
...@@ -11184,7 +11230,10 @@ fn fileWriteFileStreaming(...@@ -11184,7 +11230,10 @@ fn fileWriteFileStreaming(
11184 var off: std.os.linux.off_t = undefined;11230 var off: std.os.linux.off_t = undefined;
11185 const off_ptr: ?*std.os.linux.off_t, const count: usize = switch (file_reader.mode) {11231 const off_ptr: ?*std.os.linux.off_t, const count: usize = switch (file_reader.mode) {
11186 .positional => o: {11232 .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 };
11188 off = std.math.cast(std.os.linux.off_t, file_reader.pos) orelse return error.ReadFailed;11237 off = std.math.cast(std.os.linux.off_t, file_reader.pos) orelse return error.ReadFailed;
11189 break :o .{ &off, @min(@backingInt(limit), size - file_reader.pos, max_count) };11238 break :o .{ &off, @min(@backingInt(limit), size - file_reader.pos, max_count) };
11190 },11239 },
...@@ -11533,7 +11582,10 @@ fn fileWriteFilePositional(...@@ -11533,7 +11582,10 @@ fn fileWriteFilePositional(
11533 if (file_reader.pos != 0) break :fcf;11582 if (file_reader.pos != 0) break :fcf;
11534 if (offset != 0) break :fcf;11583 if (offset != 0) break :fcf;
11535 if (limit != .unlimited) break :fcf;11584 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 };
11537 if (header.len != 0 or reader_buffered.len != 0) {11589 if (header.len != 0 or reader_buffered.len != 0) {
11538 const n = try fileWritePositional(t, file, header, &.{limit.slice(reader_buffered)}, 1, offset);11590 const n = try fileWritePositional(t, file, header, &.{limit.slice(reader_buffered)}, 1, offset);
11539 file_reader.interface.toss(n -| header.len);11591 file_reader.interface.toss(n -| header.len);
...@@ -11725,7 +11777,6 @@ fn nowWasi(clock: Io.Clock) Io.Timestamp {...@@ -11725,7 +11777,6 @@ fn nowWasi(clock: Io.Clock) Io.Timestamp {
1172511777
11726fn sleep(userdata: ?*anyopaque, timeout: Io.Timeout) Io.Cancelable!void {11778fn sleep(userdata: ?*anyopaque, timeout: Io.Timeout) Io.Cancelable!void {
11727 const t: *Threaded = @ptrCast(@alignCast(userdata));11779 const t: *Threaded = @ptrCast(@alignCast(userdata));
11728 if (timeout == .none) return;
11729 if (use_parking_sleep) return parking_sleep.sleep(timeout);11780 if (use_parking_sleep) return parking_sleep.sleep(timeout);
11730 if (native_os == .wasi) return sleepWasi(t, timeout);11781 if (native_os == .wasi) return sleepWasi(t, timeout);
11731 if (@TypeOf(posix.system.clock_nanosleep) != void) return sleepPosix(timeout);11782 if (@TypeOf(posix.system.clock_nanosleep) != void) return sleepPosix(timeout);
...@@ -12042,6 +12093,7 @@ fn posixBind(...@@ -12042,6 +12093,7 @@ fn posixBind(
12042 else => |e| {12093 else => |e| {
12043 syscall.finish();12094 syscall.finish();
12044 switch (e) {12095 switch (e) {
12096 .ACCES => return error.AccessDenied,
12045 .ADDRINUSE => return error.AddressInUse,12097 .ADDRINUSE => return error.AddressInUse,
12046 .BADF => |err| return errnoBug(err), // File descriptor used after closed.12098 .BADF => |err| return errnoBug(err), // File descriptor used after closed.
12047 .INVAL => |err| return errnoBug(err), // invalid parameters12099 .INVAL => |err| return errnoBug(err), // invalid parameters
...@@ -12124,6 +12176,7 @@ fn posixConnectUnix(...@@ -12124,6 +12176,7 @@ fn posixConnectUnix(
12124 .NOTDIR => return error.NotDir,12176 .NOTDIR => return error.NotDir,
12125 .ROFS => return error.ReadOnlyFileSystem,12177 .ROFS => return error.ReadOnlyFileSystem,
12126 .PERM => return error.PermissionDenied,12178 .PERM => return error.PermissionDenied,
12179 .CONNREFUSED => return error.ConnectionRefused,
1212712180
12128 .BADF => |err| return errnoBug(err), // File descriptor used after closed.12181 .BADF => |err| return errnoBug(err), // File descriptor used after closed.
12129 .CONNABORTED => |err| return errnoBug(err),12182 .CONNABORTED => |err| return errnoBug(err),
...@@ -13362,13 +13415,13 @@ fn addBuf(v: []posix.iovec_const, i: *iovlen_t, bytes: []const u8) void {...@@ -13362,13 +13415,13 @@ fn addBuf(v: []posix.iovec_const, i: *iovlen_t, bytes: []const u8) void {
13362 i.* += 1;13415 i.* += 1;
13363}13416}
1336413417
13365fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void {13418fn netClose(userdata: ?*anyopaque, sockets: []const net.Socket) void {
13366 if (!have_networking) unreachable;13419 if (!have_networking) unreachable;
13367 const t: *Threaded = @ptrCast(@alignCast(userdata));13420 const t: *Threaded = @ptrCast(@alignCast(userdata));
13368 _ = t;13421 _ = t;
13369 for (handles) |handle| switch (native_os) {13422 for (sockets) |socket| switch (native_os) {
13370 .windows => windows.CloseHandle(handle),13423 .windows => windows.CloseHandle(socket.handle),
13371 else => closeFd(handle),13424 else => closeFd(socket.handle),
13372 };13425 };
13373}13426}
1337413427
...@@ -13870,9 +13923,14 @@ fn netLookupFallible(...@@ -13870,9 +13923,14 @@ fn netLookupFallible(
13870 var port_buffer: [8]u8 = undefined;13923 var port_buffer: [8]u8 = undefined;
13871 const port_c = std.fmt.bufPrintSentinel(&port_buffer, "{d}", .{options.port}, 0) catch unreachable;13924 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
13873 const hints: posix.addrinfo = .{13931 const hints: posix.addrinfo = .{
13874 .flags = .{ .CANONNAME = options.canonical_name_buffer != null, .NUMERICSERV = true },13932 .flags = .{ .CANONNAME = options.canonical_name_buffer != null, .NUMERICSERV = true },
13875 .family = posix.AF.UNSPEC,13933 .family = family,
13876 .socktype = posix.SOCK.STREAM,13934 .socktype = posix.SOCK.STREAM,
13877 .protocol = posix.IPPROTO.TCP,13935 .protocol = posix.IPPROTO.TCP,
13878 .canonname = null,13936 .canonname = null,
...@@ -15302,8 +15360,7 @@ fn childKillWindows(t: *Threaded, child: *process.Child, exit_code: windows.UINT...@@ -15302,8 +15360,7 @@ fn childKillWindows(t: *Threaded, child: *process.Child, exit_code: windows.UINT
15302 _ = windows.ntdll.RtlReportSilentProcessExit(handle, @fromBackingInt(@intCast(exit_code)));15360 _ = windows.ntdll.RtlReportSilentProcessExit(handle, @fromBackingInt(@intCast(exit_code)));
15303 switch (windows.ntdll.NtTerminateProcess(handle, @fromBackingInt(@intCast(exit_code)))) {15361 switch (windows.ntdll.NtTerminateProcess(handle, @fromBackingInt(@intCast(exit_code)))) {
15304 .SUCCESS, .PROCESS_IS_TERMINATING => {15362 .SUCCESS, .PROCESS_IS_TERMINATING => {
15305 const infinite_timeout: windows.LARGE_INTEGER = std.math.minInt(windows.LARGE_INTEGER);15363 _ = windows.ntdll.NtWaitForSingleObject(handle, .FALSE, null);
15306 _ = windows.ntdll.NtWaitForSingleObject(handle, .FALSE, &infinite_timeout);
15307 childCleanupWindows(child);15364 childCleanupWindows(child);
15308 },15365 },
15309 .ACCESS_DENIED => {15366 .ACCESS_DENIED => {
...@@ -15326,8 +15383,7 @@ fn childWaitWindows(child: *process.Child) process.Child.WaitError!process.Child...@@ -15326,8 +15383,7 @@ fn childWaitWindows(child: *process.Child) process.Child.WaitError!process.Child
15326 const handle = child.id.?;15383 const handle = child.id.?;
1532715384
15328 const alertable_syscall: AlertableSyscall = try .start();15385 const alertable_syscall: AlertableSyscall = try .start();
15329 const infinite_timeout: windows.LARGE_INTEGER = std.math.minInt(windows.LARGE_INTEGER);15386 while (true) switch (windows.ntdll.NtWaitForSingleObject(handle, .TRUE, null)) {
15330 while (true) switch (windows.ntdll.NtWaitForSingleObject(handle, .TRUE, &infinite_timeout)) {
15331 windows.NTSTATUS.WAIT_0 => break alertable_syscall.finish(),15387 windows.NTSTATUS.WAIT_0 => break alertable_syscall.finish(),
15332 .USER_APC, .ALERTED, .TIMEOUT => {15388 .USER_APC, .ALERTED, .TIMEOUT => {
15333 try alertable_syscall.checkCancel();15389 try alertable_syscall.checkCancel();
...@@ -16272,7 +16328,7 @@ fn windowsCreateProcessPathExt(...@@ -16272,7 +16328,7 @@ fn windowsCreateProcessPathExt(
1627216328
16273 const is_bat_or_cmd = bat_or_cmd: {16329 const is_bat_or_cmd = bat_or_cmd: {
16274 const app_name = app_buf.items[0..app_name_len];16330 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;
16276 const ext = app_name[ext_start..];16332 const ext = app_name[ext_start..];
16277 const ext_enum = windowsCreateProcessSupportsExtension(ext) orelse break :bat_or_cmd false;16333 const ext_enum = windowsCreateProcessSupportsExtension(ext) orelse break :bat_or_cmd false;
16278 switch (ext_enum) {16334 switch (ext_enum) {
...@@ -16308,7 +16364,7 @@ fn windowsCreateProcessPathExt(...@@ -16308,7 +16364,7 @@ fn windowsCreateProcessPathExt(
16308 // it's treated as an unrecoverable error. Otherwise, it'll be16364 // it's treated as an unrecoverable error. Otherwise, it'll be
16309 // skipped as normal.16365 // skipped as normal.
16310 const app_name = app_buf.items[0..app_name_len];16366 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;
16312 const ext = app_name[ext_start..];16368 const ext = app_name[ext_start..];
16313 if (windows.eqlIgnoreCaseWtf16(ext, std.unicode.utf8ToUtf16LeStringLiteral(".EXE"))) {16369 if (windows.eqlIgnoreCaseWtf16(ext, std.unicode.utf8ToUtf16LeStringLiteral(".EXE"))) {
16314 return error.UnrecoverableInvalidExe;16370 return error.UnrecoverableInvalidExe;
...@@ -17387,6 +17443,7 @@ const use_parking_futex = switch (native_os) {...@@ -17387,6 +17443,7 @@ const use_parking_futex = switch (native_os) {
17387 .windows => true, // RtlWaitOnAddress is a userland implementation anyway17443 .windows => true, // RtlWaitOnAddress is a userland implementation anyway
17388 .netbsd => true, // NetBSD has `futex(2)`, but it's historically been quite buggy. TODO: evaluate whether it's okay to use now.17444 .netbsd => true, // NetBSD has `futex(2)`, but it's historically been quite buggy. TODO: evaluate whether it's okay to use now.
17389 .illumos => true, // Illumos has no futex mechanism17445 .illumos => true, // Illumos has no futex mechanism
17446 .haiku => true, // Haiku has no futex mechanism
17390 else => false,17447 else => false,
17391};17448};
17392const use_parking_sleep = switch (native_os) {17449const use_parking_sleep = switch (native_os) {
...@@ -17432,7 +17489,7 @@ const parking_futex = struct {...@@ -17432,7 +17489,7 @@ const parking_futex = struct {
17432 const Waiter = struct {17489 const Waiter = struct {
17433 node: std.DoublyLinkedList.Node,17490 node: std.DoublyLinkedList.Node,
17434 address: usize,17491 address: usize,
17435 tid: std.Thread.Id,17492 tid: ParkTid,
17436 /// `thread_status.cancelation` is `.parked` while the thread is waiting. The single thread17493 /// `thread_status.cancelation` is `.parked` while the thread is waiting. The single thread
17437 /// which atomically updates it (to `.none` or `.canceling`) is responsible for:17494 /// which atomically updates it (to `.none` or `.canceling`) is responsible for:
17438 ///17495 ///
...@@ -17473,7 +17530,7 @@ const parking_futex = struct {...@@ -17473,7 +17530,7 @@ const parking_futex = struct {
1747317530
17474 // Put the threadlocal access outside of the critical section.17531 // Put the threadlocal access outside of the critical section.
17475 const opt_thread = Thread.current;17532 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
17478 var waiter: Waiter = .{17535 var waiter: Waiter = .{
17479 .node = undefined, // populated by list append17536 .node = undefined, // populated by list append
...@@ -17721,7 +17778,12 @@ const parking_sleep = struct {...@@ -17721,7 +17778,12 @@ const parking_sleep = struct {
17721 },17778 },
17722 }17779 }
17723 }17780 }
17781
17724 // Uncancelable sleep; we expect not to be manually unparked.17782 // 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();
17725 var dummy_flag: UnparkFlag = unpark_flag_init;17787 var dummy_flag: UnparkFlag = unpark_flag_init;
17726 if (park(timeout, null, if (need_unpark_flag) &dummy_flag)) {17788 if (park(timeout, null, if (need_unpark_flag) &dummy_flag)) {
17727 unreachable; // unexpected unpark17789 unreachable; // unexpected unpark
...@@ -17760,7 +17822,7 @@ const ParkingMutex = struct {...@@ -17760,7 +17822,7 @@ const ParkingMutex = struct {
17760 /// Never modified once the `Waiter` is in the linked list.17822 /// Never modified once the `Waiter` is in the linked list.
17761 next: ?*Waiter,17823 next: ?*Waiter,
17762 /// Never modified once the `Waiter` is in the linked list.17824 /// Never modified once the `Waiter` is in the linked list.
17763 tid: std.Thread.Id,17825 tid: ParkTid,
17764 };17826 };
17765 fn lock(m: *ParkingMutex) void {17827 fn lock(m: *ParkingMutex) void {
17766 state: switch (State.unlocked) { // assume 'unlocked' to optimize for uncontended case17828 state: switch (State.unlocked) { // assume 'unlocked' to optimize for uncontended case
...@@ -17776,7 +17838,7 @@ const ParkingMutex = struct {...@@ -17776,7 +17838,7 @@ const ParkingMutex = struct {
1777617838
17777 .locked_once, _ => |last_state| {17839 .locked_once, _ => |last_state| {
17778 const old_waiter = last_state.waiter();17840 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();
17780 var waiter: Waiter = .{17842 var waiter: Waiter = .{
17781 .next = old_waiter,17843 .next = old_waiter,
17782 .unpark_flag = unpark_flag_init,17844 .unpark_flag = unpark_flag_init,
...@@ -17904,9 +17966,36 @@ fn setUnparkFlag(f: *UnparkFlag) void {...@@ -17904,9 +17966,36 @@ fn setUnparkFlag(f: *UnparkFlag) void {
17904/// but it seems that someone at Microsoft forgot how big their TIDs are supposed to be.17966/// but it seems that someone at Microsoft forgot how big their TIDs are supposed to be.
17905const UnparkTid = switch (native_os) {17967const UnparkTid = switch (native_os) {
17906 .windows => usize,17968 .windows => usize,
17969 else => ParkTid,
17970};
17971
17972const ParkTid = switch (native_os) {
17973 .haiku => std.c.sem_id,
17907 else => std.Thread.Id,17974 else => std.Thread.Id,
17908};17975};
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
17910fn park(17999fn park(
17911 timeout: Io.Timeout,18000 timeout: Io.Timeout,
17912 /// This value has no semantic effect, but may allow the OS to optimize the operation.18001 /// This value has no semantic effect, but may allow the OS to optimize the operation.
...@@ -17972,6 +18061,27 @@ fn park(...@@ -17972,6 +18061,27 @@ fn park(
17972 }18061 }
17973 },18062 },
17974 .illumos => @panic("TODO: illumos lwp_park"),18063 .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 },
17975 else => comptime unreachable,18085 else => comptime unreachable,
17976 }18086 }
17977}18087}
...@@ -18014,6 +18124,14 @@ fn unpark(tids: []const UnparkTid, addr_hint: ?*const anyopaque) void {...@@ -18014,6 +18124,14 @@ fn unpark(tids: []const UnparkTid, addr_hint: ?*const anyopaque) void {
18014 }18124 }
18015 },18125 },
18016 .illumos => @panic("TODO: illumos lwp_unpark"),18126 .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 },
18017 else => comptime unreachable,18135 else => comptime unreachable,
18018 }18136 }
18019}18137}
...@@ -18171,7 +18289,7 @@ fn fileMemoryMapCreate(...@@ -18171,7 +18289,7 @@ fn fileMemoryMapCreate(
18171 error.Unseekable, error.Canceled, error.AccessDenied => |e| return e,18289 error.Unseekable, error.Canceled, error.AccessDenied => |e| return e,
18172 error.OperationUnsupported => {},18290 error.OperationUnsupported => {},
18173 else => {18291 else => {
18174 if (builtin.mode == .Debug)18292 if (builtin.mode == .debug)
18175 std.log.warn("memory mapping failed with {t}, falling back to file operations", .{err});18293 std.log.warn("memory mapping failed with {t}, falling back to file operations", .{err});
18176 },18294 },
18177 }18295 }
...@@ -18278,7 +18396,7 @@ fn createFileMap(...@@ -18278,7 +18396,7 @@ fn createFileMap(
18278 .INVALID_VIEW_SIZE => |status| return windows.statusBug(status),18396 .INVALID_VIEW_SIZE => |status| return windows.statusBug(status),
18279 else => |status| return windows.unexpectedStatus(status),18397 else => |status| return windows.unexpectedStatus(status),
18280 }18398 }
18281 if (builtin.mode == .Debug) {18399 if (builtin.mode == .debug) {
18282 const page_size = std.heap.pageSize();18400 const page_size = std.heap.pageSize();
18283 const alignment: Alignment = .fromByteUnits(page_size);18401 const alignment: Alignment = .fromByteUnits(page_size);
18284 assert(contents_len == alignment.forward(len));18402 assert(contents_len == alignment.forward(len));
...@@ -18369,7 +18487,7 @@ fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void {...@@ -18369,7 +18487,7 @@ fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void {
18369 switch (posix.errno(posix.system.munmap(memory.ptr, memory.len))) {18487 switch (posix.errno(posix.system.munmap(memory.ptr, memory.len))) {
18370 .SUCCESS => {},18488 .SUCCESS => {},
18371 else => |e| {18489 else => |e| {
18372 if (builtin.mode == .Debug)18490 if (builtin.mode == .debug)
18373 std.log.err("failed to unmap {d} bytes at {*}: {t}", .{ memory.len, memory.ptr, e });18491 std.log.err("failed to unmap {d} bytes at {*}: {t}", .{ memory.len, memory.ptr, e });
18374 },18492 },
18375 }18493 }
...@@ -18969,7 +19087,7 @@ fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!windows...@@ -18969,7 +19087,7 @@ fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!windows
18969 .{19087 .{
18970 .DIRECTORY_FILE = options.filter == .dir_only,19088 .DIRECTORY_FILE = options.filter == .dir_only,
18971 .NON_DIRECTORY_FILE = options.filter == .non_directory_only,19089 .NON_DIRECTORY_FILE = options.filter == .non_directory_only,
18972 .IO = if (options.follow_symlinks) .SYNCHRONOUS_NONALERT else .ASYNCHRONOUS,19090 .IO = .SYNCHRONOUS_NONALERT,
18973 .OPEN_REPARSE_POINT = !options.follow_symlinks,19091 .OPEN_REPARSE_POINT = !options.follow_symlinks,
18974 },19092 },
18975 null,19093 null,
lib/std/Io/Threaded/test.zig-2
...@@ -149,8 +149,6 @@ test "async with array return type" {...@@ -149,8 +149,6 @@ test "async with array return type" {
149}149}
150150
151test "cancel blocked read from pipe" {151test "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
154 const global = struct {152 const global = struct {
155 fn readFromPipe(io: Io, pipe: Io.File) !void {153 fn readFromPipe(io: Io, pipe: Io.File) !void {
156 var buf: [1]u8 = undefined;154 var buf: [1]u8 = undefined;
lib/std/Io/Uring.zig+14-8
...@@ -1135,8 +1135,9 @@ fn mainIdleEntry() callconv(.naked) void {...@@ -1135,8 +1135,9 @@ fn mainIdleEntry() callconv(.naked) void {
11351135
1136fn mainIdle(1136fn mainIdle(
1137 ev: *Evented,1137 ev: *Evented,
1138 message: *const SwitchMessage,1138 contexts: *const Io.fiber.Switch,
1139) callconv(.withStackAlign(.c, @max(@alignOf(Thread), @alignOf(Io.fiber.Context)))) noreturn {1139) callconv(.withStackAlign(.c, @max(@alignOf(Thread), @alignOf(Io.fiber.Context)))) noreturn {
1140 const message: *const SwitchMessage = @fieldParentPtr("contexts", contexts);
1140 message.handle(ev);1141 message.handle(ev);
1141 ev.idle(&ev.threads.allocated[0]);1142 ev.idle(&ev.threads.allocated[0]);
1142 ev.yield(@ptrCast(&ev.main_fiber_buffer), .nothing);1143 ev.yield(@ptrCast(&ev.main_fiber_buffer), .nothing);
...@@ -1414,8 +1415,9 @@ const AsyncClosure = struct {...@@ -1414,8 +1415,9 @@ const AsyncClosure = struct {
14141415
1415 fn call(1416 fn call(
1416 closure: *AsyncClosure,1417 closure: *AsyncClosure,
1417 message: *const SwitchMessage,1418 contexts: *const Io.fiber.Switch,
1418 ) callconv(.withStackAlign(.c, @alignOf(AsyncClosure))) noreturn {1419 ) callconv(.withStackAlign(.c, @alignOf(AsyncClosure))) noreturn {
1420 const message: *const SwitchMessage = @fieldParentPtr("contexts", contexts);
1419 const ev = closure.evented;1421 const ev = closure.evented;
1420 const fiber = closure.fiber;1422 const fiber = closure.fiber;
1421 message.handle(ev);1423 message.handle(ev);
...@@ -1779,8 +1781,9 @@ const Group = struct {...@@ -1779,8 +1781,9 @@ const Group = struct {
17791781
1780 fn call(1782 fn call(
1781 closure: *Group.AsyncClosure,1783 closure: *Group.AsyncClosure,
1782 message: *const SwitchMessage,1784 contexts: *const Io.fiber.Switch,
1783 ) callconv(.withStackAlign(.c, @alignOf(Group.AsyncClosure))) noreturn {1785 ) callconv(.withStackAlign(.c, @alignOf(Group.AsyncClosure))) noreturn {
1786 const message: *const SwitchMessage = @fieldParentPtr("contexts", contexts);
1784 const ev = closure.evented;1787 const ev = closure.evented;
1785 const fiber = closure.fiber;1788 const fiber = closure.fiber;
1786 message.handle(ev);1789 message.handle(ev);
...@@ -3558,7 +3561,7 @@ fn dirHardLink(...@@ -3558,7 +3561,7 @@ fn dirHardLink(
3558 old_sub_path_posix,3561 old_sub_path_posix,
3559 new_dir.handle,3562 new_dir.handle,
3560 new_sub_path_posix,3563 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,
3562 );3565 );
3563}3566}
35643567
...@@ -3990,7 +3993,7 @@ fn fileHardLink(...@@ -3990,7 +3993,7 @@ fn fileHardLink(
3990 "",3993 "",
3991 new_dir.handle,3994 new_dir.handle,
3992 new_sub_path_posix,3995 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),
3994 );3997 );
3995}3998}
39963999
...@@ -4050,7 +4053,7 @@ fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void {...@@ -4050,7 +4053,7 @@ fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void {
4050 if (memory.len == 0) return;4053 if (memory.len == 0) return;
4051 switch (linux.errno(linux.munmap(memory.ptr, memory.len))) {4054 switch (linux.errno(linux.munmap(memory.ptr, memory.len))) {
4052 .SUCCESS => {},4055 .SUCCESS => {},
4053 else => |err| if (builtin.mode == .Debug)4056 else => |err| if (builtin.mode == .debug)
4054 std.log.err("failed to unmap {d} bytes at {*}: {t}", .{ memory.len, memory.ptr, err }),4057 std.log.err("failed to unmap {d} bytes at {*}: {t}", .{ memory.len, memory.ptr, err }),
4055 }4058 }
4056 mm.* = undefined;4059 mm.* = undefined;
...@@ -5186,9 +5189,9 @@ fn netWriteFileUnavailable(...@@ -5186,9 +5189,9 @@ fn netWriteFileUnavailable(
5186 return error.Unimplemented;5189 return error.Unimplemented;
5187}5190}
51885191
5189fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void {5192fn netClose(userdata: ?*anyopaque, sockets: []const net.Socket) void {
5190 const ev: *Evented = @ptrCast(@alignCast(userdata));5193 const ev: *Evented = @ptrCast(@alignCast(userdata));
5191 for (handles) |handle| ev.close(handle);5194 for (sockets) |sock| ev.close(sock.handle);
5192}5195}
51935196
5194fn netShutdown(5197fn netShutdown(
...@@ -5295,6 +5298,7 @@ fn bind(...@@ -5295,6 +5298,7 @@ fn bind(
5295 switch (cancel_region.errno()) {5298 switch (cancel_region.errno()) {
5296 .SUCCESS => return,5299 .SUCCESS => return,
5297 .INTR, .CANCELED => {},5300 .INTR, .CANCELED => {},
5301 .ACCES => return error.AccessDenied,
5298 .ADDRINUSE => return error.AddressInUse,5302 .ADDRINUSE => return error.AddressInUse,
5299 .BADF => |err| return errnoBug(err), // File descriptor used after closed.5303 .BADF => |err| return errnoBug(err), // File descriptor used after closed.
5300 .INVAL => |err| return errnoBug(err), // invalid parameters5304 .INVAL => |err| return errnoBug(err), // invalid parameters
...@@ -5542,6 +5546,8 @@ fn linkat(...@@ -5542,6 +5546,8 @@ fn linkat(
5542 new_path: [*:0]const u8,5546 new_path: [*:0]const u8,
5543 flags: u32,5547 flags: u32,
5544) File.HardLinkError!void {5548) 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);
5545 while (true) {5551 while (true) {
5546 const thread = try cancel_region.awaitIoUring();5552 const thread = try cancel_region.awaitIoUring();
5547 thread.enqueue().* = .{5553 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 {...@@ -874,7 +874,7 @@ pub fn splatBytes(w: *Writer, bytes: []const u8, n: usize) Error!usize {
874}874}
875875
876/// Asserts the `buffer` was initialized with a capacity of at least `@sizeOf(T)` bytes.876/// 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 {
878 var bytes: [@divExact(@typeInfo(T).int.bits, 8)]u8 = undefined;878 var bytes: [@divExact(@typeInfo(T).int.bits, 8)]u8 = undefined;
879 std.mem.writeInt(std.math.ByteAlignedInt(@TypeOf(value)), &bytes, value, endian);879 std.mem.writeInt(std.math.ByteAlignedInt(@TypeOf(value)), &bytes, value, endian);
880 return w.writeAll(&bytes);880 return w.writeAll(&bytes);
...@@ -882,7 +882,7 @@ pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.built...@@ -882,7 +882,7 @@ pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.built
882882
883/// The function is inline to avoid the dead code in case `endian` is883/// The function is inline to avoid the dead code in case `endian` is
884/// comptime-known and matches host endianness.884/// 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 {
886 switch (@typeInfo(@TypeOf(value))) {886 switch (@typeInfo(@TypeOf(value))) {
887 .@"struct" => |info| switch (info.layout) {887 .@"struct" => |info| switch (info.layout) {
888 .auto => @compileError("ill-defined memory layout"),888 .auto => @compileError("ill-defined memory layout"),
...@@ -907,7 +907,7 @@ pub inline fn writeSliceEndian(...@@ -907,7 +907,7 @@ pub inline fn writeSliceEndian(
907 w: *Writer,907 w: *Writer,
908 Elem: type,908 Elem: type,
909 slice: []const Elem,909 slice: []const Elem,
910 endian: std.builtin.Endian,910 endian: std.lang.Endian,
911) Error!void {911) Error!void {
912 switch (@typeInfo(Elem)) {912 switch (@typeInfo(Elem)) {
913 .@"struct" => |info| comptime assert(info.layout != .auto),913 .@"struct" => |info| comptime assert(info.layout != .auto),
...@@ -2387,6 +2387,7 @@ pub fn unreachableRebase(w: *Writer, preserve: usize, capacity: usize) Error!voi...@@ -2387,6 +2387,7 @@ pub fn unreachableRebase(w: *Writer, preserve: usize, capacity: usize) Error!voi
23872387
2388pub fn fromArrayList(array_list: *ArrayList(u8)) Writer {2388pub fn fromArrayList(array_list: *ArrayList(u8)) Writer {
2389 defer array_list.* = .empty;2389 defer array_list.* = .empty;
2390 array_list.pointer_stability.assertUnlocked();
2390 return .{2391 return .{
2391 .vtable = &.{2392 .vtable = &.{
2392 .drain = fixedDrain,2393 .drain = fixedDrain,
...@@ -2402,6 +2403,7 @@ pub fn toArrayList(w: *Writer) ArrayList(u8) {...@@ -2402,6 +2403,7 @@ pub fn toArrayList(w: *Writer) ArrayList(u8) {
2402 const result: ArrayList(u8) = .{2403 const result: ArrayList(u8) = .{
2403 .items = w.buffer[0..w.end],2404 .items = w.buffer[0..w.end],
2404 .capacity = w.buffer.len,2405 .capacity = w.buffer.len,
2406 .pointer_stability = .{},
2405 };2407 };
2406 w.buffer = &.{};2408 w.buffer = &.{};
2407 w.end = 0;2409 w.end = 0;
...@@ -2651,6 +2653,7 @@ pub const Allocating = struct {...@@ -2651,6 +2653,7 @@ pub const Allocating = struct {
2651 const result: std.array_list.Aligned(u8, alignment) = .{2653 const result: std.array_list.Aligned(u8, alignment) = .{
2652 .items = @alignCast(w.buffer[0..w.end]),2654 .items = @alignCast(w.buffer[0..w.end]),
2653 .capacity = w.buffer.len,2655 .capacity = w.buffer.len,
2656 .pointer_stability = .{},
2654 };2657 };
2655 w.buffer = &.{};2658 w.buffer = &.{};
2656 w.end = 0;2659 w.end = 0;
...@@ -2742,29 +2745,26 @@ pub const Allocating = struct {...@@ -2742,29 +2745,26 @@ pub const Allocating = struct {
27422745
2743 fn drain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {2746 fn drain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
2744 const a: *Allocating = @fieldParentPtr("writer", w);2747 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;
2748 assert(data.len != 0);2748 assert(data.len != 0);
2749 for (data) |bytes| {2749 const count = countSplat(data, splat);
2750 a.ensureUnusedCapacity(bytes.len + splat_len + 1) catch return error.WriteFailed;2750 a.ensureUnusedCapacity(count + 1) catch return error.WriteFailed;
2751 for (data[0 .. data.len - 1]) |bytes| {
2751 @memcpy(a.writer.buffer[a.writer.end..][0..bytes.len], bytes);2752 @memcpy(a.writer.buffer[a.writer.end..][0..bytes.len], bytes);
2752 a.writer.end += bytes.len;2753 a.writer.end += bytes.len;
2753 }2754 }
2754 if (splat == 0) {2755 const pattern = data[data.len - 1];
2755 a.writer.end -= pattern.len;2756 switch (pattern.len) {
2756 } else switch (pattern.len) {
2757 0 => {},2757 0 => {},
2758 1 => {2758 1 => {
2759 @memset(a.writer.buffer[a.writer.end..][0 .. splat - 1], pattern[0]);2759 @memset(a.writer.buffer[a.writer.end..][0..splat], pattern[0]);
2760 a.writer.end += splat - 1;2760 a.writer.end += splat;
2761 },2761 },
2762 else => for (0..splat - 1) |_| {2762 else => for (0..splat) |_| {
2763 @memcpy(a.writer.buffer[a.writer.end..][0..pattern.len], pattern);2763 @memcpy(a.writer.buffer[a.writer.end..][0..pattern.len], pattern);
2764 a.writer.end += pattern.len;2764 a.writer.end += pattern.len;
2765 },2765 },
2766 }2766 }
2767 return a.writer.end - start_len;2767 return count;
2768 }2768 }
27692769
2770 fn sendFile(w: *Writer, file_reader: *File.Reader, limit: Limit) FileError!usize {2770 fn sendFile(w: *Writer, file_reader: *File.Reader, limit: Limit) FileError!usize {
...@@ -2817,12 +2817,12 @@ pub const Allocating = struct {...@@ -2817,12 +2817,12 @@ pub const Allocating = struct {
2817 }2817 }
28182818
2819 test Allocating {2819 test Allocating {
2820 try testAllocating(.fromByteUnits(1));2820 try testAllocating(.@"1");
2821 try testAllocating(.fromByteUnits(4));2821 try testAllocating(.@"4");
2822 try testAllocating(.fromByteUnits(8));2822 try testAllocating(.@"8");
2823 try testAllocating(.fromByteUnits(16));2823 try testAllocating(.@"16");
2824 try testAllocating(.fromByteUnits(32));2824 try testAllocating(.@"32");
2825 try testAllocating(.fromByteUnits(64));2825 try testAllocating(.@"64");
2826 }2826 }
2827};2827};
28282828
lib/std/Io/net.zig+7-2
...@@ -198,6 +198,8 @@ pub const IpAddress = union(enum) {...@@ -198,6 +198,8 @@ pub const IpAddress = union(enum) {
198 }198 }
199199
200 pub const ListenError = error{200 pub const ListenError = error{
201 /// The address is protected and the current user does not have permission to bind it.
202 AccessDenied,
201 /// The address is already taken. Can occur when bound port is 0 but203 /// The address is already taken. Can occur when bound port is 0 but
202 /// all ephemeral ports are already in use.204 /// all ephemeral ports are already in use.
203 AddressInUse,205 AddressInUse,
...@@ -254,6 +256,8 @@ pub const IpAddress = union(enum) {...@@ -254,6 +256,8 @@ pub const IpAddress = union(enum) {
254 }256 }
255257
256 pub const BindError = error{258 pub const BindError = error{
259 /// The address is protected and the current user does not have permission to bind it.
260 AccessDenied,
257 /// The address is already taken. Can occur when bound port is 0 but261 /// The address is already taken. Can occur when bound port is 0 but
258 /// all ephemeral ports are already in use.262 /// all ephemeral ports are already in use.
259 AddressInUse,263 AddressInUse,
...@@ -901,6 +905,7 @@ pub const UnixAddress = struct {...@@ -901,6 +905,7 @@ pub const UnixAddress = struct {
901 ReadOnlyFileSystem,905 ReadOnlyFileSystem,
902 WouldBlock,906 WouldBlock,
903 NetworkDown,907 NetworkDown,
908 ConnectionRefused,
904 } || Io.Cancelable || Io.UnexpectedError;909 } || Io.Cancelable || Io.UnexpectedError;
905910
906 pub fn connect(ua: *const UnixAddress, io: Io) ConnectError!Stream {911 pub fn connect(ua: *const UnixAddress, io: Io) ConnectError!Stream {
...@@ -1076,7 +1081,7 @@ pub const Socket = struct {...@@ -1076,7 +1081,7 @@ pub const Socket = struct {
10761081
1077 /// Leaves `address` in a valid state.1082 /// Leaves `address` in a valid state.
1078 pub fn close(s: *const Socket, io: Io) void {1083 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]);
1080 }1085 }
10811086
1082 pub fn closeMany(io: Io, sockets: []const Socket) void {1087 pub fn closeMany(io: Io, sockets: []const Socket) void {
...@@ -1253,7 +1258,7 @@ pub const Stream = struct {...@@ -1253,7 +1258,7 @@ pub const Stream = struct {
1253 }1258 }
12541259
1255 pub fn close(s: *const Stream, io: Io) void {1260 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]);
1257 }1262 }
12581263
1259 pub fn shutdown(s: *const Stream, io: Io, how: ShutdownHow) ShutdownError!void {1264 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" {...@@ -356,8 +356,6 @@ test "decompress compressed DNS name" {
356}356}
357357
358test "cancel accept" {358test "cancel accept" {
359 if (builtin.cpu.arch.isSPARC() and builtin.os.tag == .linux) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35347
360
361 const io = testing.io;359 const io = testing.io;
362 const localhost: net.IpAddress = .{ .ip4 = .loopback(0) };360 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 {...@@ -232,8 +232,6 @@ fn count(a: usize, b: usize, result: *usize) void {
232}232}
233233
234test "Group.cancel" {234test "Group.cancel" {
235 if (builtin.cpu.arch.isSPARC() and builtin.os.tag == .linux) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35347
236
237 const global = struct {235 const global = struct {
238 fn sleep(io: Io, result: *usize) Io.Cancelable!void {236 fn sleep(io: Io, result: *usize) Io.Cancelable!void {
239 defer result.* = 1;237 defer result.* = 1;
...@@ -326,8 +324,6 @@ test "Group materializes error.Cancel" {...@@ -326,8 +324,6 @@ test "Group materializes error.Cancel" {
326}324}
327325
328test "Group task receives cancelation unknowingly" {326test "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
331 const S = struct {327 const S = struct {
332 io: Io,328 io: Io,
333 err: ?Io.Cancelable!void,329 err: ?Io.Cancelable!void,
lib/std/Progress.zig+14-2
...@@ -442,7 +442,15 @@ pub const Node = struct {...@@ -442,7 +442,15 @@ pub const Node = struct {
442 global_progress.ipc_files[slot] = file;442 global_progress.ipc_files[slot] = file;
443 storageByIndex(index).setIpcIndex(.{ .slot = slot, .generation = generation });443 storageByIndex(index).setIpcIndex(.{ .slot = slot, .generation = generation });
444 break;444 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 }
446 }454 }
447455
448 pub fn setIpcIndex(node: Node, ipc_index: Ipc.Index) void {456 pub fn setIpcIndex(node: Node, ipc_index: Ipc.Index) void {
...@@ -452,7 +460,11 @@ pub const Node = struct {...@@ -452,7 +460,11 @@ pub const Node = struct {
452 /// Not thread-safe.460 /// Not thread-safe.
453 pub fn takeIpcIndex(node: Node) ?Ipc.Index {461 pub fn takeIpcIndex(node: Node) ?Ipc.Index {
454 const storage = storageByIndex(node.index.unwrap() orelse return null);462 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 }
456 @atomicStore(u32, &storage.estimated_total_count, 0, .monotonic);468 @atomicStore(u32, &storage.estimated_total_count, 0, .monotonic);
457 return @bitCast(storage.completed_count);469 return @bitCast(storage.completed_count);
458 }470 }
lib/std/Random/RomuTrio.zig-1
...@@ -122,7 +122,6 @@ test fill {...@@ -122,7 +122,6 @@ test fill {
122}122}
123123
124test "buf seeding test" {124test "buf seeding test" {
125 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
126 const buf0: [24]u8 = @bitCast([3]u64{ 16294208416658607535, 13964609475759908645, 4703697494102998476 });125 const buf0: [24]u8 = @bitCast([3]u64{ 16294208416658607535, 13964609475759908645, 4703697494102998476 });
127 const resulting_state = .{ .x = 16294208416658607535, .y = 13964609475759908645, .z = 4703697494102998476 };126 const resulting_state = .{ .x = 16294208416658607535, .y = 13964609475759908645, .z = 4703697494102998476 };
128 var r = RomuTrio.init(0);127 var r = RomuTrio.init(0);
lib/std/Random/Xoshiro256.zig-2
...@@ -89,8 +89,6 @@ pub fn fill(self: *Xoshiro256, buf: []u8) void {...@@ -89,8 +89,6 @@ pub fn fill(self: *Xoshiro256, buf: []u8) void {
89}89}
9090
91test "sequence" {91test "sequence" {
92 if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest;
93
94 var r = Xoshiro256.init(0);92 var r = Xoshiro256.init(0);
9593
96 const seq1 = [_]u64{94 const seq1 = [_]u64{
lib/std/Random/benchmark.zig+1-1
...@@ -122,7 +122,7 @@ fn usage() void {...@@ -122,7 +122,7 @@ fn usage() void {
122}122}
123123
124fn mode(comptime x: comptime_int) comptime_int {124fn 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;
126}126}
127127
128pub fn main(init: std.process.Init) !void {128pub 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 {...@@ -1194,9 +1194,6 @@ pub fn toCoffMachine(target: *const Target) std.coff.IMAGE.FILE.MACHINE {
1194 };1194 };
1195}1195}
11961196
1197/// Deprecated; use 'std.zig.Subsystem' instead. To be removed after 0.16.0 is tagged.
1198pub const SubSystem = std.zig.Subsystem;
1199
1200pub const Cpu = struct {1197pub const Cpu = struct {
1201 /// Architecture1198 /// Architecture
1202 arch: Arch,1199 arch: Arch,
...@@ -1796,10 +1793,12 @@ pub const Cpu = struct {...@@ -1796,10 +1793,12 @@ pub const Cpu = struct {
1796 .x86_64_regcall_v4_win,1793 .x86_64_regcall_v4_win,
1797 .x86_64_vectorcall,1794 .x86_64_vectorcall,
1798 .x86_64_interrupt,1795 .x86_64_interrupt,
1796 .x86_64_preserve_none,
1799 => &.{.x86_64},1797 => &.{.x86_64},
18001798
1801 .x86_sysv,1799 .x86_sysv,
1802 .x86_win,1800 .x86_win,
1801 .x86_mingw,
1803 .x86_stdcall,1802 .x86_stdcall,
1804 .x86_fastcall,1803 .x86_fastcall,
1805 .x86_thiscall,1804 .x86_thiscall,
...@@ -1821,6 +1820,7 @@ pub const Cpu = struct {...@@ -1821,6 +1820,7 @@ pub const Cpu = struct {
1821 .aarch64_aapcs_win,1820 .aarch64_aapcs_win,
1822 .aarch64_vfabi,1821 .aarch64_vfabi,
1823 .aarch64_vfabi_sve,1822 .aarch64_vfabi_sve,
1823 .aarch64_preserve_none,
1824 => &.{ .aarch64, .aarch64_be },1824 => &.{ .aarch64, .aarch64_be },
18251825
1826 .alpha_osf,1826 .alpha_osf,
...@@ -2081,6 +2081,7 @@ pub const Cpu = struct {...@@ -2081,6 +2081,7 @@ pub const Cpu = struct {
2081 else => generic(arch),2081 else => generic(arch),
2082 },2082 },
2083 .powerpc64 => switch (os.tag) {2083 .powerpc64 => switch (os.tag) {
2084 .linux, .freebsd => &powerpc.cpu.pwr8,
2084 .openbsd => &powerpc.cpu.pwr9,2085 .openbsd => &powerpc.cpu.pwr9,
2085 else => generic(arch),2086 else => generic(arch),
2086 },2087 },
...@@ -2660,12 +2661,26 @@ pub const DynamicLinker = struct {...@@ -2660,12 +2661,26 @@ pub const DynamicLinker = struct {
2660 else => return none,2661 else => return none,
2661 }}),2662 }}),
26622663
2663 .loongarch64 => initFmt("/lib64/ld-linux-loongarch-{s}.so.1", .{switch (abi) {2664 .loongarch32,
2664 .gnu => "lp64d",2665 .loongarch64,
2665 .gnuf32 => "lp64f",2666 => |arch| initFmt("/lib{s}/ld-linux-{s}{s}.so.1", .{
2666 .gnusf => "lp64s",2667 switch (arch) {
2667 else => return none,2668 .loongarch32 => "32",
2668 }}),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
2670 .hppa,2685 .hppa,
2671 .m68k,2686 .m68k,
...@@ -3069,9 +3084,13 @@ pub fn stackGrowth(target: *const Target) StackGrowth {...@@ -3069,9 +3084,13 @@ pub fn stackGrowth(target: *const Target) StackGrowth {
3069/// Default signedness of `char` for the native C compiler for this target3084/// Default signedness of `char` for the native C compiler for this target
3070/// Note that char signedness is implementation-defined and many compilers provide3085/// Note that char signedness is implementation-defined and many compilers provide
3071/// an option to override the default signedness e.g. GCC's -funsigned-char / -fsigned-char3086/// 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 }
3073 if (target.os.tag.isDarwin() or target.os.tag == .windows or target.os.tag == .uefi) return .signed;3093 if (target.os.tag.isDarwin() or target.os.tag == .windows or target.os.tag == .uefi) return .signed;
3074
3075 return switch (target.cpu.arch) {3094 return switch (target.cpu.arch) {
3076 .aarch64,3095 .aarch64,
3077 .aarch64_be,3096 .aarch64_be,
...@@ -3117,7 +3136,8 @@ pub const CType = enum {...@@ -3117,7 +3136,8 @@ pub const CType = enum {
3117 longdouble,3136 longdouble,
3118};3137};
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 {
3121 return switch (c_type) {3141 return switch (c_type) {
3122 .char,3142 .char,
3123 .short,3143 .short,
...@@ -3130,18 +3150,19 @@ pub fn cTypeByteSize(t: *const Target, c_type: CType) u16 {...@@ -3130,18 +3150,19 @@ pub fn cTypeByteSize(t: *const Target, c_type: CType) u16 {
3130 .ulonglong,3150 .ulonglong,
3131 .float,3151 .float,
3132 .double,3152 .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) {
3136 64 => 8,3156 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).?)),
3138 128 => 16,3158 128 => 16,
3139 else => unreachable,3159 else => unreachable,
3140 },3160 },
3141 };3161 };
3142}3162}
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 {
3145 switch (target.os.tag) {3166 switch (target.os.tag) {
3146 .freestanding,3167 .freestanding,
3147 .other,3168 .other,
...@@ -3462,15 +3483,17 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {...@@ -3462,15 +3483,17 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
3462 .longlong, .ulonglong, .longdouble => return 64,3483 .longlong, .ulonglong, .longdouble => return 64,
3463 },3484 },
34643485
3486 .opengl => return null,
3487
3465 .ps3,3488 .ps3,
3466 .contiki,3489 .contiki,
3467 .managarm,3490 .managarm,
3468 .opengl,
3469 => @panic("specify the C integer and float type sizes for this OS"),3491 => @panic("specify the C integer and float type sizes for this OS"),
3470 }3492 }
3471}3493}
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 {
3474 // Overrides for unusual alignments3497 // Overrides for unusual alignments
3475 switch (target.cpu.arch) {3498 switch (target.cpu.arch) {
3476 .avr,3499 .avr,
...@@ -3503,7 +3526,7 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 {...@@ -3503,7 +3526,7 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 {
35033526
3504 // Next-power-of-two-aligned, up to a maximum.3527 // Next-power-of-two-aligned, up to a maximum.
3505 return @min(3528 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),
3507 @as(u16, switch (target.cpu.arch) {3530 @as(u16, switch (target.cpu.arch) {
3508 .msp430,3531 .msp430,
3509 .x86_16,3532 .x86_16,
...@@ -3578,120 +3601,6 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 {...@@ -3578,120 +3601,6 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 {
3578 );3601 );
3579}3602}
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
3695pub fn cMaxIntAlignment(target: *const Target) u16 {3604pub fn cMaxIntAlignment(target: *const Target) u16 {
3696 return switch (target.cpu.arch) {3605 return switch (target.cpu.arch) {
3697 .avr,3606 .avr,
...@@ -3715,6 +3624,11 @@ pub fn cMaxIntAlignment(target: *const Target) u16 {...@@ -3715,6 +3624,11 @@ pub fn cMaxIntAlignment(target: *const Target) u16 {
3715 .xcore,3624 .xcore,
3716 => 4,3625 => 4,
37173626
3627 .x86 => switch (target.os.tag) {
3628 else => 4,
3629 .uefi, .windows => 8,
3630 },
3631
3718 .arm,3632 .arm,
3719 .armeb,3633 .armeb,
3720 .hexagon,3634 .hexagon,
...@@ -3733,7 +3647,6 @@ pub fn cMaxIntAlignment(target: *const Target) u16 {...@@ -3733,7 +3647,6 @@ pub fn cMaxIntAlignment(target: *const Target) u16 {
3733 .sparc,3647 .sparc,
3734 .thumb,3648 .thumb,
3735 .thumbeb,3649 .thumbeb,
3736 .x86,
3737 .xtensa,3650 .xtensa,
3738 .xtensaeb,3651 .xtensaeb,
3739 => 8,3652 => 8,
...@@ -3769,18 +3682,14 @@ pub fn cMaxIntAlignment(target: *const Target) u16 {...@@ -3769,18 +3682,14 @@ pub fn cMaxIntAlignment(target: *const Target) u16 {
3769pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention {3682pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention {
3770 return switch (target.cpu.arch) {3683 return switch (target.cpu.arch) {
3771 .x86_64 => switch (target.os.tag) {3684 .x86_64 => switch (target.os.tag) {
3772 .windows,3685 .windows, .uefi => .{ .x86_64_win = .{} },
3773 .uefi,
3774 => .{ .x86_64_win = .{} },
3775 else => switch (target.abi) {3686 else => switch (target.abi) {
3776 .gnux32, .muslx32, .x32 => .{ .x86_64_x32 = .{} },3687 .gnux32, .muslx32, .x32 => .{ .x86_64_x32 = .{} },
3777 else => .{ .x86_64_sysv = .{} },3688 else => .{ .x86_64_sysv = .{} },
3778 },3689 },
3779 },3690 },
3780 .x86 => switch (target.os.tag) {3691 .x86 => switch (target.os.tag) {
3781 .windows,3692 .windows, .uefi => if (target.isMinGW()) .{ .x86_mingw = .{} } else .{ .x86_win = .{} },
3782 .uefi,
3783 => .{ .x86_win = .{} },
3784 else => .{ .x86_sysv = .{} },3693 else => .{ .x86_sysv = .{} },
3785 },3694 },
3786 .x86_16 => .{ .x86_16_cdecl = .{} },3695 .x86_16 => .{ .x86_16_cdecl = .{} },
lib/std/Thread.zig+36-43
...@@ -639,8 +639,7 @@ const WindowsThreadImpl = struct {...@@ -639,8 +639,7 @@ const WindowsThreadImpl = struct {
639 }639 }
640640
641 fn join(self: Impl) void {641 fn join(self: Impl) void {
642 const infinite_timeout: windows.LARGE_INTEGER = std.math.minInt(windows.LARGE_INTEGER);642 switch (windows.ntdll.NtWaitForSingleObject(self.thread.thread_handle, .FALSE, null)) {
643 switch (windows.ntdll.NtWaitForSingleObject(self.thread.thread_handle, .FALSE, &infinite_timeout)) {
644 windows.NTSTATUS.WAIT_0 => {},643 windows.NTSTATUS.WAIT_0 => {},
645 else => |status| windows.unexpectedStatus(status) catch unreachable,644 else => |status| windows.unexpectedStatus(status) catch unreachable,
646 }645 }
...@@ -720,10 +719,9 @@ const PosixThreadImpl = struct {...@@ -720,10 +719,9 @@ const PosixThreadImpl = struct {
720 },719 },
721 .haiku => {720 .haiku => {
722 var system_info: std.c.system_info = undefined;721 var system_info: std.c.system_info = undefined;
723 const rc = std.c.get_system_info(&system_info); // always returns B_OK722 return switch (std.c.get_system_info(&system_info)) {
724 return switch (posix.errno(rc)) {723 0 => @as(usize, @intCast(system_info.cpu_count)),
725 .SUCCESS => @as(usize, @intCast(system_info.cpu_count)),724 else => error.Unexpected,
726 else => |err| posix.unexpectedErrno(err),
727 };725 };
728 },726 },
729 else => {727 else => {
...@@ -1146,6 +1144,13 @@ const LinuxThreadImpl = struct {...@@ -1146,6 +1144,13 @@ const LinuxThreadImpl = struct {
1146 parent_tid: i32 = undefined,1144 parent_tid: i32 = undefined,
1147 mapped: []align(std.heap.page_size_min) u8,1145 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
1149 /// Calls `munmap(mapped.ptr, mapped.len)` then `exit(1)` without touching the stack (which lives in `mapped.ptr`).1154 /// Calls `munmap(mapped.ptr, mapped.len)` then `exit(1)` without touching the stack (which lives in `mapped.ptr`).
1150 /// Ported over from musl libc's pthread detached implementation:1155 /// Ported over from musl libc's pthread detached implementation:
1151 /// https://github.com/ifduyue/musl/search?q=__unmapself1156 /// https://github.com/ifduyue/musl/search?q=__unmapself
...@@ -1365,51 +1370,39 @@ const LinuxThreadImpl = struct {...@@ -1365,51 +1370,39 @@ const LinuxThreadImpl = struct {
1365 [len] "{r5}" (self.mapped.len),1370 [len] "{r5}" (self.mapped.len),
1366 ),1371 ),
1367 .sparc => asm volatile (1372 .sparc => asm volatile (
1368 \\ # See sparc64 comments below.1373 \\ // See sparc64 comments below.
1369 \\ 1:1374 \\ t 0x3 // ST_FLUSH_WINDOWS
1370 \\ cmp %%fp, 01375 \\ mov %%g3, %%sp
1371 \\ beq 2f1376 \\ mov %%g1, %%o0
1372 \\ nop1377 \\ mov %%g2, %%o1
1373 \\ ba 1b1378 \\ mov 73, %%g1 // SYS_munmap
1374 \\ restore1379 \\ t 0x10
1375 \\ 2:1380 \\ mov 1, %%g1 // SYS_exit
1376 \\ mov %%g1, %%o0 // ptr1381 \\ mov 0, %%o0
1377 \\ mov %%g2, %%o1 // len1382 \\ t 0x10
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
1384 :1383 :
1385 : [ptr] "{g1}" (@intFromPtr(self.mapped.ptr)),1384 : [ptr] "{g1}" (@intFromPtr(self.mapped.ptr)),
1386 [len] "{g2}" (self.mapped.len),1385 [len] "{g2}" (self.mapped.len),
1386 [stack] "{g3}" (&sparc_exit_stack),
1387 : .{ .memory = true }),1387 : .{ .memory = true }),
1388 .sparc64 => asm volatile (1388 .sparc64 => asm volatile (
1389 \\ # SPARCs really don't like it when active stack frames1389 \\ // Ensure that the kernel only has to flush the current register window.
1390 \\ # is unmapped (it will result in a segfault), so we1390 \\ flushw
1391 \\ # force-deactivate it by running `restore` until1391 \\ // Set up a fake stack for the syscall to restore l/i registers from. Local
1392 \\ # all frames are cleared.1392 \\ // and incoming registers must be treated as effectively garbage past this
1393 \\ 1:1393 \\ // instruction!
1394 \\ cmp %%fp, 01394 \\ sub %%g3, 2047, %%sp
1395 \\ beq 2f1395 \\ mov %%g1, %%o0
1396 \\ nop1396 \\ mov %%g2, %%o1
1397 \\ ba 1b1397 \\ mov 73, %%g1 // SYS_munmap
1398 \\ restore1398 \\ t 0x6d
1399 \\ 2:1399 \\ mov 1, %%g1 // SYS_exit
1400 \\ mov %%g1, %%o0 // ptr1400 \\ mov 0, %%o0
1401 \\ mov %%g2, %%o1 // len1401 \\ t 0x6d
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
1410 :1402 :
1411 : [ptr] "{g1}" (@intFromPtr(self.mapped.ptr)),1403 : [ptr] "{g1}" (@intFromPtr(self.mapped.ptr)),
1412 [len] "{g2}" (self.mapped.len),1404 [len] "{g2}" (self.mapped.len),
1405 [stack] "{g3}" (&sparc_exit_stack),
1413 : .{ .memory = true }),1406 : .{ .memory = true }),
1414 .loongarch32, .loongarch64 => asm volatile (1407 .loongarch32, .loongarch64 => asm volatile (
1415 \\ ori $a7, $zero, 215 # SYS_munmap1408 \\ 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 {...@@ -221,16 +221,16 @@ pub fn parseAfterScheme(scheme: []const u8, text: []const u8) ParseError!Uri {
221 }221 }
222222
223 if (authority.len > start_of_host and authority[start_of_host] == '[') { // IPv6223 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;
225 end_of_host += 1;225 end_of_host += 1;
226226
227 if (std.mem.lastIndexOf(u8, authority, ":")) |index| {227 if (std.mem.findLast(u8, authority, ":")) |index| {
228 if (index >= end_of_host) { // if not part of the V6 address field228 if (index >= end_of_host) { // if not part of the V6 address field
229 end_of_host = @min(end_of_host, index);229 end_of_host = @min(end_of_host, index);
230 uri.port = std.fmt.parseInt(u16, authority[index + 1 ..], 10) catch return error.InvalidPort;230 uri.port = std.fmt.parseInt(u16, authority[index + 1 ..], 10) catch return error.InvalidPort;
231 }231 }
232 }232 }
233 } else if (std.mem.lastIndexOf(u8, authority, ":")) |index| {233 } else if (std.mem.findLast(u8, authority, ":")) |index| {
234 if (index >= start_of_host) { // if not part of the userinfo field234 if (index >= start_of_host) { // if not part of the userinfo field
235 end_of_host = @min(end_of_host, index);235 end_of_host = @min(end_of_host, index);
236 uri.port = std.fmt.parseInt(u16, authority[index + 1 ..], 10) catch return error.InvalidPort;236 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...@@ -475,7 +475,7 @@ fn merge_paths(base: Component, new: []u8, aux_buf: *[]u8) error{NoSpaceLeft}!Co
475 var aux: Writer = .fixed(aux_buf.*);475 var aux: Writer = .fixed(aux_buf.*);
476 if (!base.isEmpty()) {476 if (!base.isEmpty()) {
477 base.formatPath(&aux) catch return error.NoSpaceLeft;477 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);
479 }479 }
480 aux.print("/{s}", .{new}) catch return error.NoSpaceLeft;480 aux.print("/{s}", .{new}) catch return error.NoSpaceLeft;
481 const merged_path = remove_dot_segments(aux.buffered());481 const merged_path = remove_dot_segments(aux.buffered());
lib/std/array_hash_map.zig+7-7
...@@ -13,12 +13,12 @@ const hash_map = @This();...@@ -13,12 +13,12 @@ const hash_map = @This();
13///13///
14/// See `AutoContext` for a description of the hash and equal implementations.14/// See `AutoContext` for a description of the hash and equal implementations.
15pub fn Auto(comptime K: type, comptime V: type) type {15pub 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));
17}17}
1818
19/// An `ArrayHashMap` with strings as keys.19/// An `ArrayHashMap` with strings as keys.
20pub fn String(comptime V: type) type {20pub fn String(comptime V: type) type {
21 return ArrayHashMap([]const u8, V, StringContext, true);21 return Custom([]const u8, V, StringContext, true);
22}22}
2323
24pub const StringContext = struct {24pub const StringContext = struct {
...@@ -2130,7 +2130,7 @@ test "0 sized key and 0 sized value" {...@@ -2130,7 +2130,7 @@ test "0 sized key and 0 sized value" {
2130test "setKey storehash true" {2130test "setKey storehash true" {
2131 const gpa = std.testing.allocator;2131 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;
2134 defer map.deinit(gpa);2134 defer map.deinit(gpa);
21352135
2136 try map.put(gpa, 12, 34);2136 try map.put(gpa, 12, 34);
...@@ -2146,7 +2146,7 @@ test "setKey storehash true" {...@@ -2146,7 +2146,7 @@ test "setKey storehash true" {
2146test "setKey storehash false" {2146test "setKey storehash false" {
2147 const gpa = std.testing.allocator;2147 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;
2150 defer map.deinit(gpa);2150 defer map.deinit(gpa);
21512151
2152 try map.put(gpa, 12, 34);2152 try map.put(gpa, 12, 34);
...@@ -2162,7 +2162,7 @@ test "setKey storehash false" {...@@ -2162,7 +2162,7 @@ test "setKey storehash false" {
2162test "setKey storehash false with index" {2162test "setKey storehash false with index" {
2163 const gpa = std.testing.allocator;2163 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
2167 var map: T = .empty;2167 var map: T = .empty;
2168 defer map.deinit(gpa);2168 defer map.deinit(gpa);
...@@ -2180,9 +2180,9 @@ test "setKey storehash false with index" {...@@ -2180,9 +2180,9 @@ test "setKey storehash false with index" {
2180test "setKey storehash true with index" {2180test "setKey storehash true with index" {
2181 const gpa = std.testing.allocator;2181 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;
2186 defer map.deinit(gpa);2186 defer map.deinit(gpa);
21872187
2188 for (0..T.linear_scan_max + 1) |i| try map.put(gpa, i, i);2188 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...@@ -26,8 +26,8 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
26 ///26 ///
27 /// Pointers to elements in this slice are invalidated by various27 /// Pointers to elements in this slice are invalidated by various
28 /// functions of this ArrayList in accordance with the respective28 /// functions of this ArrayList in accordance with the respective
29 /// documentation. In all cases, "invalidated" means that the memory29 /// documentation.
30 /// has been passed to this allocator's resize or free function.30 /// An invalidated pointer may point either to valid or freed memory.
31 items: Slice,31 items: Slice,
32 /// How many T values this list can hold without allocating32 /// How many T values this list can hold without allocating
33 /// additional memory.33 /// additional memory.
...@@ -35,7 +35,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -35,7 +35,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
35 allocator: Allocator,35 allocator: Allocator,
3636
37 /// Used to detect memory safety violations.37 /// Used to detect memory safety violations.
38 pointer_stability: debug.SafetyLock = .{},38 pointer_stability: debug.SafetyLock,
3939
40 pub const Slice = if (alignment) |a| ([]align(a.toByteUnits()) T) else []T;40 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...@@ -49,6 +49,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
49 .items = &[_]T{},49 .items = &[_]T{},
50 .capacity = 0,50 .capacity = 0,
51 .allocator = gpa,51 .allocator = gpa,
52 .pointer_stability = .{},
52 };53 };
53 }54 }
5455
...@@ -94,6 +95,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -94,6 +95,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
94 .items = slice,95 .items = slice,
95 .capacity = slice.len,96 .capacity = slice.len,
96 .allocator = gpa,97 .allocator = gpa,
98 .pointer_stability = .{},
97 };99 };
98 }100 }
99101
...@@ -105,22 +107,28 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -105,22 +107,28 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
105 .items = slice,107 .items = slice,
106 .capacity = slice.len + 1,108 .capacity = slice.len + 1,
107 .allocator = gpa,109 .allocator = gpa,
110 .pointer_stability = .{},
108 };111 };
109 }112 }
110113
111 /// Initializes an ArrayList with the `items` and `capacity` fields114 /// Initializes an ArrayList with the `items` and `capacity` fields
112 /// of this ArrayList. Empties this ArrayList.115 /// of this ArrayList. Empties this ArrayList.
113 pub fn moveToUnmanaged(self: *Self) Aligned(T, alignment) {116 pub fn moveToUnmanaged(self: *Self) Aligned(T, alignment) {
114 self.pointer_stability.assertUnlocked();
115 const allocator = self.allocator;117 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 };
117 self.* = init(allocator);123 self.* = init(allocator);
118 return result;124 return result;
119 }125 }
120126
121 /// The caller owns the returned memory. Empties this ArrayList.127 /// The caller owns the returned memory. Empties this ArrayList.
122 /// Its capacity is cleared, making `deinit` safe but unnecessary to call.128 /// Its capacity is cleared, making `deinit` safe but unnecessary to call.
129 /// May invalidate element pointers if remapping memory cannot be done in place.
123 pub fn toOwnedSlice(self: *Self) Allocator.Error!Slice {130 pub fn toOwnedSlice(self: *Self) Allocator.Error!Slice {
131 self.pointer_stability.assertUnlocked();
124 const allocator = self.allocator;132 const allocator = self.allocator;
125133
126 const old_memory = self.allocatedSlice();134 const old_memory = self.allocatedSlice();
...@@ -136,6 +144,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -136,6 +144,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
136 }144 }
137145
138 /// The caller owns the returned memory. Empties this ArrayList.146 /// The caller owns the returned memory. Empties this ArrayList.
147 /// May invalidate element pointers if remapping memory cannot be done in place.
139 pub fn toOwnedSliceSentinel(self: *Self, comptime sentinel: T) Allocator.Error!SentinelSlice(sentinel) {148 pub fn toOwnedSliceSentinel(self: *Self, comptime sentinel: T) Allocator.Error!SentinelSlice(sentinel) {
140 // This addition can never overflow because `self.items` can never occupy the whole address space149 // This addition can never overflow because `self.items` can never occupy the whole address space
141 try self.ensureTotalCapacityPrecise(self.items.len + 1);150 try self.ensureTotalCapacityPrecise(self.items.len + 1);
...@@ -151,31 +160,31 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -151,31 +160,31 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
151 return cloned;160 return cloned;
152 }161 }
153162
154 /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room.163 /// Insert `item` at index `index`. Moves `list[index .. 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.164 /// If `index` is equal to the length of the list this operation is equivalent to append.
156 /// This operation is O(N).165 /// This operation is O(N).
157 /// Invalidates element pointers if additional memory is needed.166 /// Invalidates element pointers if additional memory is needed.
167 /// Invalidates pre-existing pointers to elements at and after `index`.
158 /// Asserts that the index is in bounds or equal to the length.168 /// 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 {169 pub fn insert(self: *Self, index: usize, item: T) Allocator.Error!void {
160 const dst = try self.addManyAt(i, 1);170 self.pointer_stability.assertUnlocked();
171 const dst = try self.addManyAt(index, 1);
161 dst[0] = item;172 dst[0] = item;
162 }173 }
163174
164 /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room.175 /// Insert `item` at index `index`. Moves `list[index .. list.len]` to higher indices to make room.
165 /// If `i` is equal to the length of the list this operation is176 /// If `index` is equal to the length of the list this operation is
166 /// equivalent to appendAssumeCapacity.177 /// equivalent to appendAssumeCapacity.
167 /// This operation is O(N).178 /// This operation is O(N).
179 /// Invalidates pre-existing pointers to elements at and after `index`.
168 /// Asserts that there is enough capacity for the new item.180 /// Asserts that there is enough capacity for the new item.
169 /// Asserts that the index is in bounds or equal to the length.181 /// Asserts that the index is in bounds or equal to the length.
170 pub fn insertAssumeCapacity(self: *Self, i: usize, item: T) void {182 pub fn insertAssumeCapacity(self: *Self, index: usize, item: T) void {
171 self.pointer_stability.lock();183 self.pointer_stability.assertUnlocked();
172 defer self.pointer_stability.unlock();
173
174 assert(self.items.len < self.capacity);184 assert(self.items.len < self.capacity);
175 self.items.len += 1;185 self.items.len += 1;
176186 @memmove(self.items[index + 1 .. self.items.len], self.items[index .. self.items.len - 1]);
177 @memmove(self.items[i + 1 .. self.items.len], self.items[i .. self.items.len - 1]);187 self.items[index] = item;
178 self.items[i] = item;
179 }188 }
180189
181 /// Add `count` new elements at position `index`, which have190 /// Add `count` new elements at position `index`, which have
...@@ -188,12 +197,11 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -188,12 +197,11 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
188 /// Asserts that the index is in bounds or equal to the length.197 /// Asserts that the index is in bounds or equal to the length.
189 pub fn addManyAt(self: *Self, index: usize, count: usize) Allocator.Error![]T {198 pub fn addManyAt(self: *Self, index: usize, count: usize) Allocator.Error![]T {
190 const new_len = try addOrOom(self.items.len, count);199 const new_len = try addOrOom(self.items.len, count);
200 self.pointer_stability.assertUnlocked();
191201
192 if (self.capacity >= new_len)202 if (self.capacity >= new_len)
193 return addManyAtAssumeCapacity(self, index, count);203 return addManyAtAssumeCapacity(self, index, count);
194204
195 self.pointer_stability.lock();
196 defer self.pointer_stability.unlock();
197 // Here we avoid copying allocated but unused bytes by205 // Here we avoid copying allocated but unused bytes by
198 // attempting a resize in place, and falling back to allocating206 // attempting a resize in place, and falling back to allocating
199 // a new buffer and doing our own copy. With a realloc() call,207 // 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...@@ -225,9 +233,11 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
225 /// `undefined` values. Returns a slice pointing to the newly allocated233 /// `undefined` values. Returns a slice pointing to the newly allocated
226 /// elements, which becomes invalid after various `ArrayList`234 /// elements, which becomes invalid after various `ArrayList`
227 /// operations.235 /// operations.
236 /// Invalidates pre-existing pointers to elements at and after `index`.
228 /// Asserts that there is enough capacity for the new elements.237 /// Asserts that there is enough capacity for the new elements.
229 /// Asserts that the index is in bounds or equal to the length.238 /// Asserts that the index is in bounds or equal to the length.
230 pub fn addManyAtAssumeCapacity(self: *Self, index: usize, count: usize) []T {239 pub fn addManyAtAssumeCapacity(self: *Self, index: usize, count: usize) []T {
240 self.pointer_stability.assertUnlocked();
231 const new_len = self.items.len + count;241 const new_len = self.items.len + count;
232 assert(self.capacity >= new_len);242 assert(self.capacity >= new_len);
233 const to_move = self.items[index..];243 const to_move = self.items[index..];
...@@ -238,7 +248,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -238,7 +248,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
238 return result;248 return result;
239 }249 }
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.
242 /// This operation is O(N).252 /// This operation is O(N).
243 /// Invalidates pre-existing pointers to elements at and after `index`.253 /// Invalidates pre-existing pointers to elements at and after `index`.
244 /// Invalidates all pre-existing element pointers if capacity must be254 /// 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...@@ -254,7 +264,9 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
254 }264 }
255265
256 /// Grows or shrinks the list as necessary.266 /// 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.
258 /// Asserts that the range is in bounds.270 /// Asserts that the range is in bounds.
259 pub fn replaceRange(self: *Self, start: usize, len: usize, new_items: []const T) Allocator.Error!void {271 pub fn replaceRange(self: *Self, start: usize, len: usize, new_items: []const T) Allocator.Error!void {
260 var unmanaged = self.moveToUnmanaged();272 var unmanaged = self.moveToUnmanaged();
...@@ -263,7 +275,8 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -263,7 +275,8 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
263 }275 }
264276
265 /// Grows or shrinks the list as necessary.277 /// 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.
267 /// Asserts the capacity is enough for additional items.280 /// Asserts the capacity is enough for additional items.
268 pub fn replaceRangeAssumeCapacity(self: *Self, start: usize, len: usize, new_items: []const T) void {281 pub fn replaceRangeAssumeCapacity(self: *Self, start: usize, len: usize, new_items: []const T) void {
269 var unmanaged = self.moveToUnmanaged();282 var unmanaged = self.moveToUnmanaged();
...@@ -300,10 +313,12 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -300,10 +313,12 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
300313
301 /// Removes the element at the specified index and returns it.314 /// Removes the element at the specified index and returns it.
302 /// The empty slot is filled from the end of the list.315 /// The empty slot is filled from the end of the list.
316 /// Invalidates pointers to the end of the list.
303 /// This operation is O(1).317 /// This operation is O(1).
304 /// This may not preserve item order. Use `orderedRemove` if you need to preserve order.318 /// This may not preserve item order. Use `orderedRemove` if you need to preserve order.
305 /// Asserts that the index is in bounds.319 /// Asserts that the index is in bounds.
306 pub fn swapRemove(self: *Self, i: usize) T {320 pub fn swapRemove(self: *Self, i: usize) T {
321 self.pointer_stability.assertUnlocked();
307 const val = self.items[i];322 const val = self.items[i];
308 self.items[i] = self.items[self.items.len - 1];323 self.items[i] = self.items[self.items.len - 1];
309 self.items[self.items.len - 1] = undefined;324 self.items[self.items.len - 1] = undefined;
...@@ -353,6 +368,8 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -353,6 +368,8 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
353 @memcpy(self.items[old_len..][0..items.len], items);368 @memcpy(self.items[old_len..][0..items.len], items);
354 }369 }
355370
371 /// Prints a formatted string into this list.
372 /// Invalidates element pointers if additional memory is needed.
356 pub fn print(self: *Self, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void {373 pub fn print(self: *Self, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void {
357 const gpa = self.allocator;374 const gpa = self.allocator;
358 var unmanaged = self.moveToUnmanaged();375 var unmanaged = self.moveToUnmanaged();
...@@ -404,9 +421,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -404,9 +421,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
404 /// Invalidates element pointers for the elements `items[new_len..]`.421 /// Invalidates element pointers for the elements `items[new_len..]`.
405 /// Asserts that the new length is less than or equal to the previous length.422 /// Asserts that the new length is less than or equal to the previous length.
406 pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void {423 pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void {
407 self.pointer_stability.lock();424 self.pointer_stability.assertUnlocked();
408 defer self.pointer_stability.unlock();
409
410 assert(new_len <= self.items.len);425 assert(new_len <= self.items.len);
411 @memset(self.items[new_len..], undefined);426 @memset(self.items[new_len..], undefined);
412 self.items.len = new_len;427 self.items.len = new_len;
...@@ -415,8 +430,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -415,8 +430,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
415 /// Reduce length to 0.430 /// Reduce length to 0.
416 /// Invalidates all element pointers.431 /// Invalidates all element pointers.
417 pub fn clearRetainingCapacity(self: *Self) void {432 pub fn clearRetainingCapacity(self: *Self) void {
418 self.pointer_stability.lock();433 self.pointer_stability.assertUnlocked();
419 defer self.pointer_stability.unlock();
420 @memset(self.items, undefined);434 @memset(self.items, undefined);
421 self.items.len = 0;435 self.items.len = 0;
422 }436 }
...@@ -449,18 +463,15 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -449,18 +463,15 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
449 /// modify the array so that it can hold exactly `new_capacity` items.463 /// modify the array so that it can hold exactly `new_capacity` items.
450 /// Invalidates element pointers if additional memory is needed.464 /// Invalidates element pointers if additional memory is needed.
451 pub fn ensureTotalCapacityPrecise(self: *Self, new_capacity: usize) Allocator.Error!void {465 pub fn ensureTotalCapacityPrecise(self: *Self, new_capacity: usize) Allocator.Error!void {
452 self.pointer_stability.lock();
453 defer self.pointer_stability.unlock();
454
455 if (@sizeOf(T) == 0) {466 if (@sizeOf(T) == 0) {
456 self.capacity = math.maxInt(usize);467 self.capacity = math.maxInt(usize);
457 return;468 return;
458 }469 }
459470
460 if (self.capacity >= new_capacity) return;471 if (self.capacity >= new_capacity) return;
461472 self.pointer_stability.assertUnlocked();
462 // Here we avoid copying allocated but unused bytes by473 // Here we avoid copying allocated but unused bytes by
463 // attempting a resize in place, and falling back to allocating474 // attempting a remap, and falling back to allocating
464 // a new buffer and doing our own copy. With a realloc() call,475 // a new buffer and doing our own copy. With a realloc() call,
465 // the allocator implementation would pointlessly copy our476 // the allocator implementation would pointlessly copy our
466 // extra capacity.477 // extra capacity.
...@@ -491,7 +502,8 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -491,7 +502,8 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
491 }502 }
492503
493 /// Increase length by 1, returning pointer to the new item.504 /// 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.
495 pub fn addOne(self: *Self) Allocator.Error!*T {507 pub fn addOne(self: *Self) Allocator.Error!*T {
496 // This can never overflow because `self.items` can never occupy the whole address space508 // This can never overflow because `self.items` can never occupy the whole address space
497 const newlen = self.items.len + 1;509 const newlen = self.items.len + 1;
...@@ -500,7 +512,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -500,7 +512,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
500 }512 }
501513
502 /// Increase length by 1, returning pointer to the new item.514 /// 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.
504 /// Never invalidates element pointers.516 /// Never invalidates element pointers.
505 /// Asserts that the list can hold one additional item.517 /// Asserts that the list can hold one additional item.
506 pub fn addOneAssumeCapacity(self: *Self) *T {518 pub fn addOneAssumeCapacity(self: *Self) *T {
...@@ -511,8 +523,9 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -511,8 +523,9 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
511523
512 /// Resize the array, adding `n` new elements, which have `undefined` values.524 /// Resize the array, adding `n` new elements, which have `undefined` values.
513 /// The return value is an array pointing to the newly allocated elements.525 /// 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.
515 /// Resizes list if `self.capacity` is not large enough.527 /// Resizes list if `self.capacity` is not large enough.
528 /// Invalidates element pointers if additional memory is needed.
516 pub fn addManyAsArray(self: *Self, comptime n: usize) Allocator.Error!*[n]T {529 pub fn addManyAsArray(self: *Self, comptime n: usize) Allocator.Error!*[n]T {
517 const prev_len = self.items.len;530 const prev_len = self.items.len;
518 try self.resize(try addOrOom(self.items.len, n));531 try self.resize(try addOrOom(self.items.len, n));
...@@ -522,7 +535,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -522,7 +535,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
522 /// Resize the array, adding `n` new elements, which have `undefined` values.535 /// Resize the array, adding `n` new elements, which have `undefined` values.
523 /// The return value is an array pointing to the newly allocated elements.536 /// The return value is an array pointing to the newly allocated elements.
524 /// Never invalidates element pointers.537 /// 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.
526 /// Asserts that the list can hold the additional items.539 /// Asserts that the list can hold the additional items.
527 pub fn addManyAsArrayAssumeCapacity(self: *Self, comptime n: usize) *[n]T {540 pub fn addManyAsArrayAssumeCapacity(self: *Self, comptime n: usize) *[n]T {
528 assert(self.items.len + n <= self.capacity);541 assert(self.items.len + n <= self.capacity);
...@@ -533,8 +546,9 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -533,8 +546,9 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
533546
534 /// Resize the array, adding `n` new elements, which have `undefined` values.547 /// Resize the array, adding `n` new elements, which have `undefined` values.
535 /// The return value is a slice pointing to the newly allocated elements.548 /// 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.
537 /// Resizes list if `self.capacity` is not large enough.550 /// Resizes list if `self.capacity` is not large enough.
551 /// Invalidates element pointers if additional memory is needed.
538 pub fn addManyAsSlice(self: *Self, n: usize) Allocator.Error![]T {552 pub fn addManyAsSlice(self: *Self, n: usize) Allocator.Error![]T {
539 const prev_len = self.items.len;553 const prev_len = self.items.len;
540 try self.resize(try addOrOom(self.items.len, n));554 try self.resize(try addOrOom(self.items.len, n));
...@@ -544,7 +558,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -544,7 +558,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
544 /// Resize the array, adding `n` new elements, which have `undefined` values.558 /// Resize the array, adding `n` new elements, which have `undefined` values.
545 /// The return value is a slice pointing to the newly allocated elements.559 /// The return value is a slice pointing to the newly allocated elements.
546 /// Never invalidates element pointers.560 /// 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.
548 /// Asserts that the list can hold the additional items.562 /// Asserts that the list can hold the additional items.
549 pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T {563 pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T {
550 assert(self.items.len + n <= self.capacity);564 assert(self.items.len + n <= self.capacity);
...@@ -554,11 +568,10 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -554,11 +568,10 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
554 }568 }
555569
556 /// Remove and return the last element from the list, or return `null` if list is empty.570 /// 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.
558 pub fn pop(self: *Self) ?T {572 pub fn pop(self: *Self) ?T {
559 if (self.items.len == 0) return null;573 if (self.items.len == 0) return null;
560 self.pointer_stability.lock();574 self.pointer_stability.assertUnlocked();
561 defer self.pointer_stability.unlock();
562 const val = self.items[self.items.len - 1];575 const val = self.items[self.items.len - 1];
563 self.items[self.items.len - 1] = undefined;576 self.items[self.items.len - 1] = undefined;
564 self.items.len -= 1;577 self.items.len -= 1;
...@@ -567,6 +580,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -567,6 +580,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
567580
568 /// Returns a slice of all the items plus the extra capacity, whose memory581 /// Returns a slice of all the items plus the extra capacity, whose memory
569 /// contents are `undefined`.582 /// contents are `undefined`.
583 /// The returned pointer may be invalidated by further operations to this list.
570 pub fn allocatedSlice(self: Self) Slice {584 pub fn allocatedSlice(self: Self) Slice {
571 // `items.len` is the length, not the capacity.585 // `items.len` is the length, not the capacity.
572 return self.items.ptr[0..self.capacity];586 return self.items.ptr[0..self.capacity];
...@@ -576,18 +590,29 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type...@@ -576,18 +590,29 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
576 /// This can be useful for writing directly into an ArrayList.590 /// This can be useful for writing directly into an ArrayList.
577 /// Note that such an operation must be followed up with a direct591 /// Note that such an operation must be followed up with a direct
578 /// modification of `self.items.len`.592 /// modification of `self.items.len`.
593 /// The returned pointer may be invalidated by further operations to this list.
579 pub fn unusedCapacitySlice(self: Self) []T {594 pub fn unusedCapacitySlice(self: Self) []T {
580 return self.allocatedSlice()[self.items.len..];595 return self.allocatedSlice()[self.items.len..];
581 }596 }
582597
583 /// Deprecated in favor of `getLast`598 /// Deprecated in favor of `last`
584 pub const getLastOrNull = getLast;599 pub const getLastOrNull = last;
585600
586 /// Returns the last element from the list, or `null` if the list is empty.601 /// Returns the last element from the list, or `null` if the list is
587 pub fn getLast(self: Self) ?T {602 /// empty.
603 /// Never invalidates element pointers.
604 pub fn last(self: Self) ?T {
588 if (self.items.len == 0) return null;605 if (self.items.len == 0) return null;
589 return self.items[self.items.len - 1];606 return self.items[self.items.len - 1];
590 }607 }
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 }
591 };616 };
592}617}
593618
...@@ -613,20 +638,21 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -613,20 +638,21 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
613 ///638 ///
614 /// Pointers to elements in this slice are invalidated by various639 /// Pointers to elements in this slice are invalidated by various
615 /// functions of this ArrayList in accordance with the respective640 /// functions of this ArrayList in accordance with the respective
616 /// documentation. In all cases, "invalidated" means that the memory641 /// documentation.
617 /// has been passed to an allocator's resize or free function.642 /// An invalidated pointer may point either to valid or freed memory.
618 items: Slice,643 items: Slice,
619 /// How many T values this list can hold without allocating644 /// How many T values this list can hold without allocating
620 /// additional memory.645 /// additional memory.
621 capacity: usize,646 capacity: usize,
622647
623 /// Used to detect memory safety violations.648 /// Used to detect memory safety violations.
624 pointer_stability: debug.SafetyLock = .{},649 pointer_stability: debug.SafetyLock,
625650
626 /// An ArrayList containing no elements.651 /// An ArrayList containing no elements.
627 pub const empty: Self = .{652 pub const empty: Self = .{
628 .items = &.{},653 .items = &.{},
629 .capacity = 0,654 .capacity = 0,
655 .pointer_stability = .{},
630 };656 };
631657
632 pub const Slice = if (alignment) |a| ([]align(a.toByteUnits()) T) else []T;658 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 {...@@ -652,6 +678,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
652 return .{678 return .{
653 .items = buffer[0..0],679 .items = buffer[0..0],
654 .capacity = buffer.len,680 .capacity = buffer.len,
681 .pointer_stability = .{},
655 };682 };
656 }683 }
657684
...@@ -682,7 +709,12 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -682,7 +709,12 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
682 /// Convert this list into an analogous memory-managed one.709 /// Convert this list into an analogous memory-managed one.
683 /// The returned list has ownership of the underlying memory.710 /// The returned list has ownership of the underlying memory.
684 pub fn toManaged(self: *Self, gpa: Allocator) AlignedManaged(T, alignment) {711 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 };
686 }718 }
687719
688 /// ArrayList takes ownership of the passed in slice.720 /// ArrayList takes ownership of the passed in slice.
...@@ -691,6 +723,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -691,6 +723,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
691 return Self{723 return Self{
692 .items = slice,724 .items = slice,
693 .capacity = slice.len,725 .capacity = slice.len,
726 .pointer_stability = .{},
694 };727 };
695 }728 }
696729
...@@ -700,13 +733,16 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -700,13 +733,16 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
700 return Self{733 return Self{
701 .items = slice,734 .items = slice,
702 .capacity = slice.len + 1,735 .capacity = slice.len + 1,
736 .pointer_stability = .{},
703 };737 };
704 }738 }
705739
706 /// The caller owns the returned memory. Empties this ArrayList.740 /// The caller owns the returned memory. Empties this ArrayList.
707 /// Its capacity is cleared, making deinit() safe but unnecessary to call.741 /// Its capacity is cleared, making deinit() safe but unnecessary to call.
742 /// May invalidate element pointers.
708 pub fn toOwnedSlice(self: *Self, gpa: Allocator) Allocator.Error!Slice {743 pub fn toOwnedSlice(self: *Self, gpa: Allocator) Allocator.Error!Slice {
709 const old_memory = self.allocatedSlice();744 const old_memory = self.allocatedSlice();
745 self.pointer_stability.assertUnlocked();
710 if (gpa.remap(old_memory, self.items.len)) |new_items| {746 if (gpa.remap(old_memory, self.items.len)) |new_items| {
711 self.* = .empty;747 self.* = .empty;
712 return new_items;748 return new_items;
...@@ -719,7 +755,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -719,7 +755,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
719 }755 }
720756
721 /// The caller owns the returned memory. ArrayList becomes empty.757 /// The caller owns the returned memory. ArrayList becomes empty.
758 /// May invalidate element pointers.
722 pub fn toOwnedSliceSentinel(self: *Self, gpa: Allocator, comptime sentinel: T) Allocator.Error!SentinelSlice(sentinel) {759 pub fn toOwnedSliceSentinel(self: *Self, gpa: Allocator, comptime sentinel: T) Allocator.Error!SentinelSlice(sentinel) {
760 self.pointer_stability.assertUnlocked();
723 // This addition can never overflow because `self.items` can never occupy the whole address space.761 // This addition can never overflow because `self.items` can never occupy the whole address space.
724 try self.ensureTotalCapacityPrecise(gpa, self.items.len + 1);762 try self.ensureTotalCapacityPrecise(gpa, self.items.len + 1);
725 self.appendAssumeCapacity(sentinel);763 self.appendAssumeCapacity(sentinel);
...@@ -732,6 +770,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -732,6 +770,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
732 /// Its capacity is cleared, making deinit() safe but unnecessary to call.770 /// Its capacity is cleared, making deinit() safe but unnecessary to call.
733 ///771 ///
734 /// Asserts what the capacity is equal to the length.772 /// Asserts what the capacity is equal to the length.
773 /// Never invalidates element pointers.
735 pub fn toOwnedSliceAssert(self: *Self) Slice {774 pub fn toOwnedSliceAssert(self: *Self) Slice {
736 assert(self.items.len == self.capacity);775 assert(self.items.len == self.capacity);
737 const items = self.items;776 const items = self.items;
...@@ -741,6 +780,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -741,6 +780,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
741780
742 /// The caller owns the returned memory. ArrayList becomes empty.781 /// The caller owns the returned memory. ArrayList becomes empty.
743 /// Asserts what the capacity is equal to the length + 1.782 /// Asserts what the capacity is equal to the length + 1.
783 /// Never invalidates element pointers.
744 pub fn toOwnedSliceSentinelAssert(self: *Self, comptime sentinel: T) SentinelSlice(sentinel) {784 pub fn toOwnedSliceSentinelAssert(self: *Self, comptime sentinel: T) SentinelSlice(sentinel) {
745 std.debug.assert(self.items.len + 1 == self.capacity);785 std.debug.assert(self.items.len + 1 == self.capacity);
746 self.appendAssumeCapacity(sentinel);786 self.appendAssumeCapacity(sentinel);
...@@ -755,46 +795,41 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -755,46 +795,41 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
755 return cloned;795 return cloned;
756 }796 }
757797
758 /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room.798 /// Insert `item` at index `index`. Moves `list[index .. 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.799 /// If `index` is equal to the length of the list this operation is equivalent to append.
760 /// This operation is O(N).800 /// This operation is O(N).
761 /// Invalidates element pointers if additional memory is needed.801 /// Invalidates element pointers if additional memory is needed.
802 /// Invalidates pre-existing pointers to elements at and after `index`.
762 /// Asserts that the index is in bounds or equal to the length.803 /// 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 {804 pub fn insert(self: *Self, gpa: Allocator, index: usize, item: T) Allocator.Error!void {
764 const dst = try self.addManyAt(gpa, i, 1);805 self.pointer_stability.assertUnlocked();
806 const dst = try self.addManyAt(gpa, index, 1);
765 dst[0] = item;807 dst[0] = item;
766 }808 }
767809
768 /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room.810 /// Insert `item` at index `index`. Moves `list[index .. list.len]` to higher indices to make room.
769 ///811 /// If `index` is equal to the length of the list this operation is
770 /// If `i` is equal to the length of the list this operation is equivalent to append.812 /// equivalent to appendAssumeCapacity.
771 ///
772 /// This operation is O(N).813 /// This operation is O(N).
773 ///814 /// Invalidates pre-existing pointers to elements at and after `index`.
774 /// Asserts that the list has capacity for one additional item.815 /// Asserts that the list has capacity for one additional item.
775 ///
776 /// Asserts that the index is in bounds or equal to the length.816 /// Asserts that the index is in bounds or equal to the length.
777 pub fn insertAssumeCapacity(self: *Self, i: usize, item: T) void {817 pub fn insertAssumeCapacity(self: *Self, index: usize, item: T) void {
778 self.pointer_stability.lock();818 self.pointer_stability.assertUnlocked();
779 defer self.pointer_stability.unlock();
780
781 assert(self.items.len < self.capacity);819 assert(self.items.len < self.capacity);
782 self.items.len += 1;820 self.items.len += 1;
783821 @memmove(self.items[index + 1 .. self.items.len], self.items[index .. self.items.len - 1]);
784 @memmove(self.items[i + 1 .. self.items.len], self.items[i .. self.items.len - 1]);822 self.items[index] = item;
785 self.items[i] = item;
786 }823 }
787824
788 /// Insert `item` at index `i`, moving `list[i .. list.len]` to higher indices to make room.825 /// Insert `item` at index `index`. Moves `list[index .. list.len]` to higher indices to make room.
789 ///826 /// If `index` is equal to the length of the list this operation is
790 /// If `i` is equal to the length of the list this operation is equivalent to append.827 /// equivalent to appendAssumeCapacity.
791 ///
792 /// This operation is O(N).828 /// 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.
794 /// If the list lacks unused capacity for the additional item, returns831 /// If the list lacks unused capacity for the additional item, returns
795 /// `error.OutOfMemory`.832 /// `error.OutOfMemory`.
796 ///
797 /// Asserts that the index is in bounds or equal to the length.
798 pub fn insertBounded(self: *Self, i: usize, item: T) error{OutOfMemory}!void {833 pub fn insertBounded(self: *Self, i: usize, item: T) error{OutOfMemory}!void {
799 if (self.capacity - self.items.len == 0) return error.OutOfMemory;834 if (self.capacity - self.items.len == 0) return error.OutOfMemory;
800 return insertAssumeCapacity(self, i, item);835 return insertAssumeCapacity(self, i, item);
...@@ -814,21 +849,48 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -814,21 +849,48 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
814 index: usize,849 index: usize,
815 count: usize,850 count: usize,
816 ) Allocator.Error![]T {851 ) Allocator.Error![]T {
817 var managed = self.toManaged(gpa);852 const new_len = try addOrOom(self.items.len, count);
818 defer self.* = managed.moveToUnmanaged();853 self.pointer_stability.assertUnlocked();
819 return managed.addManyAt(index, count);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];
820 }883 }
821884
822 /// Add `count` new elements at position `index`, which have885 /// Add `count` new elements at position `index`, which have
823 /// `undefined` values. Returns a slice pointing to the newly allocated886 /// `undefined` values. Returns a slice pointing to the newly allocated
824 /// elements, which becomes invalid after various `ArrayList`887 /// elements, which becomes invalid after various `ArrayList`
825 /// operations.888 /// operations.
889 /// Invalidates pre-existing pointers to elements at and after `index`.
826 /// Asserts that the list has capacity for the additional items.890 /// Asserts that the list has capacity for the additional items.
827 /// Asserts that the index is in bounds or equal to the length.891 /// Asserts that the index is in bounds or equal to the length.
828 pub fn addManyAtAssumeCapacity(self: *Self, index: usize, count: usize) []T {892 pub fn addManyAtAssumeCapacity(self: *Self, index: usize, count: usize) []T {
829 self.pointer_stability.lock();893 self.pointer_stability.assertUnlocked();
830 defer self.pointer_stability.unlock();
831
832 const new_len = self.items.len + count;894 const new_len = self.items.len + count;
833 assert(self.capacity >= new_len);895 assert(self.capacity >= new_len);
834 const to_move = self.items[index..];896 const to_move = self.items[index..];
...@@ -843,17 +905,16 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -843,17 +905,16 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
843 /// `undefined` values, returning a slice pointing to the newly905 /// `undefined` values, returning a slice pointing to the newly
844 /// allocated elements, which becomes invalid after various `ArrayList`906 /// allocated elements, which becomes invalid after various `ArrayList`
845 /// operations.907 /// operations.
846 ///908 /// Invalidates pre-existing pointers to elements at and after `index`.
847 /// If the list lacks unused capacity for the additional items, returns909 /// If the list lacks unused capacity for the additional items, returns
848 /// `error.OutOfMemory`.910 /// `error.OutOfMemory`.
849 ///
850 /// Asserts that the index is in bounds or equal to the length.911 /// Asserts that the index is in bounds or equal to the length.
851 pub fn addManyAtBounded(self: *Self, index: usize, count: usize) error{OutOfMemory}![]T {912 pub fn addManyAtBounded(self: *Self, index: usize, count: usize) error{OutOfMemory}![]T {
852 if (self.capacity - self.items.len < count) return error.OutOfMemory;913 if (self.capacity - self.items.len < count) return error.OutOfMemory;
853 return addManyAtAssumeCapacity(self, index, count);914 return addManyAtAssumeCapacity(self, index, count);
854 }915 }
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.
857 /// This operation is O(N).918 /// This operation is O(N).
858 /// Invalidates pre-existing pointers to elements at and after `index`.919 /// Invalidates pre-existing pointers to elements at and after `index`.
859 /// Invalidates all pre-existing element pointers if capacity must be920 /// 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 {...@@ -873,7 +934,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
873 @memcpy(dst, items);934 @memcpy(dst, items);
874 }935 }
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.
877 /// This operation is O(N).938 /// This operation is O(N).
878 /// Invalidates pre-existing pointers to elements at and after `index`.939 /// Invalidates pre-existing pointers to elements at and after `index`.
879 /// Asserts that the list has capacity for the additional items.940 /// 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 {...@@ -887,7 +948,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
887 @memcpy(dst, items);948 @memcpy(dst, items);
888 }949 }
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.
891 /// This operation is O(N).952 /// This operation is O(N).
892 /// Invalidates pre-existing pointers to elements at and after `index`.953 /// Invalidates pre-existing pointers to elements at and after `index`.
893 /// If the list lacks unused capacity for the additional items, returns954 /// 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 {...@@ -903,7 +964,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
903 }964 }
904965
905 /// Grows or shrinks the list as necessary.966 /// 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.
907 /// Asserts that the range is in bounds.970 /// Asserts that the range is in bounds.
908 pub fn replaceRange(971 pub fn replaceRange(
909 self: *Self,972 self: *Self,
...@@ -917,9 +980,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -917,9 +980,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
917 }980 }
918981
919 /// Grows or shrinks the list as necessary.982 /// Grows or shrinks the list as necessary.
920 ///983 /// Invalidates pointers to elements at and above index `start + len`
921 /// Never invalidates element pointers.984 /// when `len` and `new_items.len` are unequal.
922 ///
923 /// Asserts the capacity is enough for additional items.985 /// Asserts the capacity is enough for additional items.
924 pub fn replaceRangeAssumeCapacity(986 pub fn replaceRangeAssumeCapacity(
925 self: *Self,987 self: *Self,
...@@ -928,7 +990,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -928,7 +990,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
928 new_items: []const T,990 new_items: []const T,
929 ) void {991 ) void {
930 std.debug.assert(self.capacity - self.items.len >= new_items.len -| len);992 std.debug.assert(self.capacity - self.items.len >= new_items.len -| len);
931993 self.pointer_stability.assertUnlocked();
932 const tail = self.items[start + len ..];994 const tail = self.items[start + len ..];
933 const vacated = self.items[self.items.len - (len -| new_items.len) ..];995 const vacated = self.items[self.items.len - (len -| new_items.len) ..];
934 self.items.len = self.items.len - len + new_items.len;996 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 {...@@ -937,10 +999,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
937 @memset(vacated, undefined);999 @memset(vacated, undefined);
938 }1000 }
9391001
940 /// Grows or shrinks the list as necessary.1002 /// Invalidates pointers to elements at and above index `start + len`
941 ///1003 /// when `len` and `new_items.len` are unequal.
942 /// Never invalidates element pointers.
943 ///
944 /// If the unused capacity is insufficient for additional items,1004 /// If the unused capacity is insufficient for additional items,
945 /// returns `error.OutOfMemory`.1005 /// returns `error.OutOfMemory`.
946 pub fn replaceRangeBounded(1006 pub fn replaceRangeBounded(
...@@ -1003,6 +1063,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -1003,6 +1063,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
1003 ///1063 ///
1004 /// Invalidates element pointers beyond the first deleted index.1064 /// Invalidates element pointers beyond the first deleted index.
1005 pub fn orderedRemoveMany(self: *Self, sorted_indexes: []const usize) void {1065 pub fn orderedRemoveMany(self: *Self, sorted_indexes: []const usize) void {
1066 self.pointer_stability.assertUnlocked();
1006 if (sorted_indexes.len == 0) return;1067 if (sorted_indexes.len == 0) return;
1007 var shift: usize = 1;1068 var shift: usize = 1;
1008 for (sorted_indexes[0 .. sorted_indexes.len - 1], sorted_indexes[1..]) |removed, end| {1069 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 {...@@ -1025,8 +1086,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
1025 /// This operation is O(1).1086 /// This operation is O(1).
1026 /// Asserts that the index is in bounds.1087 /// Asserts that the index is in bounds.
1027 pub fn swapRemove(self: *Self, i: usize) T {1088 pub fn swapRemove(self: *Self, i: usize) T {
1028 self.pointer_stability.lock();1089 self.pointer_stability.assertUnlocked();
1029 defer self.pointer_stability.unlock();
1030 const val = self.items[i];1090 const val = self.items[i];
1031 self.items[i] = self.items[self.items.len - 1];1091 self.items[i] = self.items[self.items.len - 1];
1032 self.items[self.items.len - 1] = undefined;1092 self.items[self.items.len - 1] = undefined;
...@@ -1043,7 +1103,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -1043,7 +1103,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
1043 }1103 }
10441104
1045 /// Append the slice of items to the list.1105 /// Append the slice of items to the list.
1046 ///1106 /// Never invalidates element pointers.
1047 /// Asserts that the list can hold the additional items.1107 /// Asserts that the list can hold the additional items.
1048 pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void {1108 pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void {
1049 const old_len = self.items.len;1109 const old_len = self.items.len;
...@@ -1054,7 +1114,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -1054,7 +1114,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
1054 }1114 }
10551115
1056 /// Append the slice of items to the list.1116 /// Append the slice of items to the list.
1057 ///1117 /// Never invalidates element pointers.
1058 /// If the list lacks unused capacity for the additional items, returns `error.OutOfMemory`.1118 /// If the list lacks unused capacity for the additional items, returns `error.OutOfMemory`.
1059 pub fn appendSliceBounded(self: *Self, items: []const T) error{OutOfMemory}!void {1119 pub fn appendSliceBounded(self: *Self, items: []const T) error{OutOfMemory}!void {
1060 if (self.capacity - self.items.len < items.len) return error.OutOfMemory;1120 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 {...@@ -1074,7 +1134,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
1074 ///1134 ///
1075 /// Intended to be used only when `appendSliceAssumeCapacity` would be1135 /// Intended to be used only when `appendSliceAssumeCapacity` would be
1076 /// a compile error.1136 /// a compile error.
1077 ///1137 /// Never invalidates element pointers.
1078 /// Asserts that the list can hold the additional items.1138 /// Asserts that the list can hold the additional items.
1079 pub fn appendUnalignedSliceAssumeCapacity(self: *Self, items: []align(1) const T) void {1139 pub fn appendUnalignedSliceAssumeCapacity(self: *Self, items: []align(1) const T) void {
1080 const old_len = self.items.len;1140 const old_len = self.items.len;
...@@ -1088,7 +1148,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -1088,7 +1148,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
1088 ///1148 ///
1089 /// Intended to be used only when `appendSliceAssumeCapacity` would be1149 /// Intended to be used only when `appendSliceAssumeCapacity` would be
1090 /// a compile error.1150 /// a compile error.
1091 ///1151 /// Never invalidates element pointers.
1092 /// If the list lacks unused capacity for the additional items, returns1152 /// If the list lacks unused capacity for the additional items, returns
1093 /// `error.OutOfMemory`.1153 /// `error.OutOfMemory`.
1094 pub fn appendUnalignedSliceBounded(self: *Self, items: []align(1) const T) error{OutOfMemory}!void {1154 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 {...@@ -1096,6 +1156,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
1096 return appendUnalignedSliceAssumeCapacity(self, items);1156 return appendUnalignedSliceAssumeCapacity(self, items);
1097 }1157 }
10981158
1159 /// Prints a formatted string into this list.
1160 /// Invalidates element pointers if additional memory is needed.
1099 pub fn print(self: *Self, gpa: Allocator, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void {1161 pub fn print(self: *Self, gpa: Allocator, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void {
1100 comptime assert(T == u8);1162 comptime assert(T == u8);
1101 try self.ensureUnusedCapacity(gpa, fmt.len);1163 try self.ensureUnusedCapacity(gpa, fmt.len);
...@@ -1106,6 +1168,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -1106,6 +1168,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
1106 };1168 };
1107 }1169 }
11081170
1171 /// Prints a formatted string into this list.
1172 /// Asserts that there is enough capacity for the write.
1173 /// Never invalidates element pointers.
1109 pub fn printAssumeCapacity(self: *Self, comptime fmt: []const u8, args: anytype) void {1174 pub fn printAssumeCapacity(self: *Self, comptime fmt: []const u8, args: anytype) void {
1110 comptime assert(T == u8);1175 comptime assert(T == u8);
1111 var w: std.Io.Writer = .fixed(self.unusedCapacitySlice());1176 var w: std.Io.Writer = .fixed(self.unusedCapacitySlice());
...@@ -1113,6 +1178,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -1113,6 +1178,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
1113 self.items.len += w.end;1178 self.items.len += w.end;
1114 }1179 }
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.
1116 pub fn printBounded(self: *Self, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void {1184 pub fn printBounded(self: *Self, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void {
1117 comptime assert(T == u8);1185 comptime assert(T == u8);
1118 var w: std.Io.Writer = .fixed(self.unusedCapacitySlice());1186 var w: std.Io.Writer = .fixed(self.unusedCapacitySlice());
...@@ -1188,8 +1256,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -1188,8 +1256,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
1188 /// Asserts that the new length is less than or equal to the previous length.1256 /// Asserts that the new length is less than or equal to the previous length.
1189 /// If succeds capacity is guaranteed to be equal to the length.1257 /// If succeds capacity is guaranteed to be equal to the length.
1190 pub fn shrinkAndFreePrecise(self: *Self, gpa: Allocator, new_len: usize) Allocator.Error!void {1258 pub fn shrinkAndFreePrecise(self: *Self, gpa: Allocator, new_len: usize) Allocator.Error!void {
1191 self.pointer_stability.lock();1259 self.pointer_stability.assertUnlocked();
1192 defer self.pointer_stability.unlock();
1193 assert(new_len <= self.items.len);1260 assert(new_len <= self.items.len);
11941261
1195 if (@sizeOf(T) == 0) {1262 if (@sizeOf(T) == 0) {
...@@ -1243,8 +1310,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -1243,8 +1310,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
1243 /// Keeps capacity the same.1310 /// Keeps capacity the same.
1244 /// Asserts that the new length is less than or equal to the previous length.1311 /// Asserts that the new length is less than or equal to the previous length.
1245 pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void {1312 pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void {
1246 self.pointer_stability.lock();1313 self.pointer_stability.assertUnlocked();
1247 defer self.pointer_stability.unlock();
12481314
1249 assert(new_len <= self.items.len);1315 assert(new_len <= self.items.len);
1250 @memset(self.items[new_len..], undefined);1316 @memset(self.items[new_len..], undefined);
...@@ -1254,16 +1320,14 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -1254,16 +1320,14 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
1254 /// Reduce length to 0.1320 /// Reduce length to 0.
1255 /// Invalidates all element pointers.1321 /// Invalidates all element pointers.
1256 pub fn clearRetainingCapacity(self: *Self) void {1322 pub fn clearRetainingCapacity(self: *Self) void {
1257 self.pointer_stability.lock();1323 self.pointer_stability.assertUnlocked();
1258 defer self.pointer_stability.unlock();
1259 @memset(self.items, undefined);1324 @memset(self.items, undefined);
1260 self.items.len = 0;1325 self.items.len = 0;
1261 }1326 }
12621327
1263 /// Invalidates all element pointers.1328 /// Invalidates all element pointers.
1264 pub fn clearAndFree(self: *Self, gpa: Allocator) void {1329 pub fn clearAndFree(self: *Self, gpa: Allocator) void {
1265 self.pointer_stability.lock();1330 self.pointer_stability.assertUnlocked();
1266 defer self.pointer_stability.unlock();
1267 gpa.free(self.allocatedSlice());1331 gpa.free(self.allocatedSlice());
1268 self.items.len = 0;1332 self.items.len = 0;
1269 self.capacity = 0;1333 self.capacity = 0;
...@@ -1281,8 +1345,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -1281,8 +1345,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
1281 /// modify the array so that it can hold exactly `new_capacity` items.1345 /// modify the array so that it can hold exactly `new_capacity` items.
1282 /// Invalidates element pointers if additional memory is needed.1346 /// Invalidates element pointers if additional memory is needed.
1283 pub fn ensureTotalCapacityPrecise(self: *Self, gpa: Allocator, new_capacity: usize) Allocator.Error!void {1347 pub fn ensureTotalCapacityPrecise(self: *Self, gpa: Allocator, new_capacity: usize) Allocator.Error!void {
1284 self.pointer_stability.lock();1348 self.pointer_stability.assertUnlocked();
1285 defer self.pointer_stability.unlock();
12861349
1287 if (@sizeOf(T) == 0) {1350 if (@sizeOf(T) == 0) {
1288 self.capacity = math.maxInt(usize);1351 self.capacity = math.maxInt(usize);
...@@ -1327,7 +1390,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -1327,7 +1390,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
1327 }1390 }
13281391
1329 /// Increase length by 1, returning pointer to the new item.1392 /// 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.
1331 pub fn addOne(self: *Self, gpa: Allocator) Allocator.Error!*T {1395 pub fn addOne(self: *Self, gpa: Allocator) Allocator.Error!*T {
1332 // This can never overflow because `self.items` can never occupy the whole address space1396 // This can never overflow because `self.items` can never occupy the whole address space
1333 const newlen = self.items.len + 1;1397 const newlen = self.items.len + 1;
...@@ -1336,11 +1400,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -1336,11 +1400,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
1336 }1400 }
13371401
1338 /// Increase length by 1, returning pointer to the new item.1402 /// Increase length by 1, returning pointer to the new item.
1339 ///
1340 /// Never invalidates element pointers.1403 /// Never invalidates element pointers.
1341 ///1404 /// The returned pointer may be invalidated by further operations to this list.
1342 /// The returned element pointer becomes invalid when the list is resized.
1343 ///
1344 /// Asserts that the list can hold one additional item.1405 /// Asserts that the list can hold one additional item.
1345 pub fn addOneAssumeCapacity(self: *Self) *T {1406 pub fn addOneAssumeCapacity(self: *Self) *T {
1346 assert(self.items.len < self.capacity);1407 assert(self.items.len < self.capacity);
...@@ -1350,11 +1411,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -1350,11 +1411,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
1350 }1411 }
13511412
1352 /// Increase length by 1, returning pointer to the new item.1413 /// Increase length by 1, returning pointer to the new item.
1353 ///
1354 /// Never invalidates element pointers.1414 /// Never invalidates element pointers.
1355 ///1415 /// The returned pointer may be invalidated by further operations to this list.
1356 /// The returned element pointer becomes invalid when the list is resized.
1357 ///
1358 /// If the list lacks unused capacity for the additional item, returns `error.OutOfMemory`.1416 /// If the list lacks unused capacity for the additional item, returns `error.OutOfMemory`.
1359 pub fn addOneBounded(self: *Self) error{OutOfMemory}!*T {1417 pub fn addOneBounded(self: *Self) error{OutOfMemory}!*T {
1360 if (self.capacity - self.items.len < 1) return error.OutOfMemory;1418 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 {...@@ -1362,8 +1420,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
1362 }1420 }
13631421
1364 /// Resize the array, adding `n` new elements, which have `undefined` values.1422 /// Resize the array, adding `n` new elements, which have `undefined` values.
1423 /// Invalidates element pointers if additional memory is required.
1365 /// The return value is an array pointing to the newly allocated elements.1424 /// 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.
1367 pub fn addManyAsArray(self: *Self, gpa: Allocator, comptime n: usize) Allocator.Error!*[n]T {1426 pub fn addManyAsArray(self: *Self, gpa: Allocator, comptime n: usize) Allocator.Error!*[n]T {
1368 const prev_len = self.items.len;1427 const prev_len = self.items.len;
1369 try self.resize(gpa, try addOrOom(self.items.len, n));1428 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 {...@@ -1371,13 +1430,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
1371 }1430 }
13721431
1373 /// Resize the array, adding `n` new elements, which have `undefined` values.1432 /// Resize the array, adding `n` new elements, which have `undefined` values.
1374 ///
1375 /// The return value is an array pointing to the newly allocated elements.1433 /// The return value is an array pointing to the newly allocated elements.
1376 ///
1377 /// Never invalidates element pointers.1434 /// Never invalidates element pointers.
1378 ///1435 /// The returned pointer may be invalidated by further operations to this list.
1379 /// The returned pointer becomes invalid when the list is resized.
1380 ///
1381 /// Asserts that the list can hold the additional items.1436 /// Asserts that the list can hold the additional items.
1382 pub fn addManyAsArrayAssumeCapacity(self: *Self, comptime n: usize) *[n]T {1437 pub fn addManyAsArrayAssumeCapacity(self: *Self, comptime n: usize) *[n]T {
1383 assert(self.items.len + n <= self.capacity);1438 assert(self.items.len + n <= self.capacity);
...@@ -1387,13 +1442,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -1387,13 +1442,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
1387 }1442 }
13881443
1389 /// Resize the array, adding `n` new elements, which have `undefined` values.1444 /// Resize the array, adding `n` new elements, which have `undefined` values.
1390 ///
1391 /// The return value is an array pointing to the newly allocated elements.1445 /// The return value is an array pointing to the newly allocated elements.
1392 ///
1393 /// Never invalidates element pointers.1446 /// Never invalidates element pointers.
1394 ///1447 /// The returned pointer may be invalidated by further operations to this list.
1395 /// The returned pointer becomes invalid when the list is resized.
1396 ///
1397 /// If the list lacks unused capacity for the additional items, returns1448 /// If the list lacks unused capacity for the additional items, returns
1398 /// `error.OutOfMemory`.1449 /// `error.OutOfMemory`.
1399 pub fn addManyAsArrayBounded(self: *Self, comptime n: usize) error{OutOfMemory}!*[n]T {1450 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 {...@@ -1403,7 +1454,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
14031454
1404 /// Resize the array, adding `n` new elements, which have `undefined` values.1455 /// Resize the array, adding `n` new elements, which have `undefined` values.
1405 /// The return value is a slice pointing to the newly allocated elements.1456 /// 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.
1407 /// Resizes list if `self.capacity` is not large enough.1458 /// Resizes list if `self.capacity` is not large enough.
1408 pub fn addManyAsSlice(self: *Self, gpa: Allocator, n: usize) Allocator.Error![]T {1459 pub fn addManyAsSlice(self: *Self, gpa: Allocator, n: usize) Allocator.Error![]T {
1409 const prev_len = self.items.len;1460 const prev_len = self.items.len;
...@@ -1413,10 +1464,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -1413,10 +1464,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
14131464
1414 /// Resizes the array, adding `n` new elements, which have `undefined`1465 /// Resizes the array, adding `n` new elements, which have `undefined`
1415 /// values, returning a slice pointing to the newly allocated elements.1466 /// values, returning a slice pointing to the newly allocated elements.
1416 ///1467 /// Never invalidates element pointers.
1417 /// Never invalidates element pointers. The returned pointer becomes1468 /// The returned pointer may be invalidated by further operations to this list.
1418 /// invalid when the list is resized.
1419 ///
1420 /// Asserts that the list can hold the additional items.1469 /// Asserts that the list can hold the additional items.
1421 pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T {1470 pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T {
1422 assert(self.items.len + n <= self.capacity);1471 assert(self.items.len + n <= self.capacity);
...@@ -1427,10 +1476,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -1427,10 +1476,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
14271476
1428 /// Resizes the array, adding `n` new elements, which have `undefined`1477 /// Resizes the array, adding `n` new elements, which have `undefined`
1429 /// values, returning a slice pointing to the newly allocated elements.1478 /// values, returning a slice pointing to the newly allocated elements.
1430 ///1479 /// Never invalidates element pointers.
1431 /// Never invalidates element pointers. The returned pointer becomes1480 /// The returned pointer may be invalidated by further operations to this list.
1432 /// invalid when the list is resized.
1433 ///
1434 /// If the list lacks unused capacity for the additional items, returns1481 /// If the list lacks unused capacity for the additional items, returns
1435 /// `error.OutOfMemory`.1482 /// `error.OutOfMemory`.
1436 pub fn addManyAsSliceBounded(self: *Self, n: usize) error{OutOfMemory}![]T {1483 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 {...@@ -1443,8 +1490,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
1443 /// Invalidates pointers to last element.1490 /// Invalidates pointers to last element.
1444 pub fn pop(self: *Self) ?T {1491 pub fn pop(self: *Self) ?T {
1445 if (self.items.len == 0) return null;1492 if (self.items.len == 0) return null;
1446 self.pointer_stability.lock();1493 self.pointer_stability.assertUnlocked();
1447 defer self.pointer_stability.unlock();
14481494
1449 const val = self.items[self.items.len - 1];1495 const val = self.items[self.items.len - 1];
1450 self.items[self.items.len - 1] = undefined;1496 self.items[self.items.len - 1] = undefined;
...@@ -1454,6 +1500,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -1454,6 +1500,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
14541500
1455 /// Returns a slice of all the items plus the extra capacity, whose memory1501 /// Returns a slice of all the items plus the extra capacity, whose memory
1456 /// contents are `undefined`.1502 /// contents are `undefined`.
1503 /// The returned pointer may be invalidated by further operations to this list.
1457 pub fn allocatedSlice(self: Self) Slice {1504 pub fn allocatedSlice(self: Self) Slice {
1458 return self.items.ptr[0..self.capacity];1505 return self.items.ptr[0..self.capacity];
1459 }1506 }
...@@ -1462,19 +1509,22 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {...@@ -1462,19 +1509,22 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
1462 /// This can be useful for writing directly into an ArrayList.1509 /// This can be useful for writing directly into an ArrayList.
1463 /// Note that such an operation must be followed up with a direct1510 /// Note that such an operation must be followed up with a direct
1464 /// modification of `self.items.len`.1511 /// modification of `self.items.len`.
1512 /// The returned pointer may be invalidated by further operations to this list.
1465 pub fn unusedCapacitySlice(self: Self) []T {1513 pub fn unusedCapacitySlice(self: Self) []T {
1466 return self.allocatedSlice()[self.items.len..];1514 return self.allocatedSlice()[self.items.len..];
1467 }1515 }
14681516
1469 /// Deprecated in favor of `last`.1517 /// Returns the last element from the list, or `null` if the list is
1470 pub fn getLast(self: Self) ?T {1518 /// empty.
1519 pub fn last(self: Self) ?T {
1471 if (self.items.len == 0) return null;1520 if (self.items.len == 0) return null;
1472 return self.items[self.items.len - 1];1521 return self.items[self.items.len - 1];
1473 }1522 }
14741523
1475 /// Returns a pointer to the last element from the list, or `null` if1524 /// Returns a pointer to the last element from the list, or `null` if
1476 /// the list is empty.1525 /// 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 {
1478 if (self.items.len == 0) return null;1528 if (self.items.len == 0) return null;
1479 return &self.items[self.items.len - 1];1529 return &self.items[self.items.len - 1];
1480 }1530 }
...@@ -2441,6 +2491,10 @@ test "Managed(u0)" {...@@ -2441,6 +2491,10 @@ test "Managed(u0)" {
2441 count += 1;2491 count += 1;
2442 }2492 }
2443 try testing.expectEqual(count, 3);2493 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 });
2444}2498}
24452499
2446test "Managed(?u32).pop()" {2500test "Managed(?u32).pop()" {
...@@ -2469,7 +2523,7 @@ test "last" {...@@ -2469,7 +2523,7 @@ test "last" {
2469 try testing.expectEqual(list.last(), null);2523 try testing.expectEqual(list.last(), null);
24702524
2471 try list.append(a, 2);2525 try list.append(a, 2);
2472 try testing.expectEqual(list.last().?.*, 2);2526 try testing.expectEqual(list.last().?, 2);
2473}2527}
24742528
2475test "return OutOfMemory when capacity would exceed maximum usize integer value" {2529test "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"...@@ -2481,6 +2535,7 @@ test "return OutOfMemory when capacity would exceed maximum usize integer value"
2481 var list: ArrayList(u32) = .{2535 var list: ArrayList(u32) = .{
2482 .items = undefined,2536 .items = undefined,
2483 .capacity = math.maxInt(usize) - 1,2537 .capacity = math.maxInt(usize) - 1,
2538 .pointer_stability = .{},
2484 };2539 };
2485 list.items.len = math.maxInt(usize) - 1;2540 list.items.len = math.maxInt(usize) - 1;
24862541
...@@ -2499,6 +2554,7 @@ test "return OutOfMemory when capacity would exceed maximum usize integer value"...@@ -2499,6 +2554,7 @@ test "return OutOfMemory when capacity would exceed maximum usize integer value"
2499 .items = undefined,2554 .items = undefined,
2500 .capacity = math.maxInt(usize) - 1,2555 .capacity = math.maxInt(usize) - 1,
2501 .allocator = a,2556 .allocator = a,
2557 .pointer_stability = .{},
2502 };2558 };
2503 list.items.len = math.maxInt(usize) - 1;2559 list.items.len = math.maxInt(usize) - 1;
25042560
lib/std/ascii.zig+3-3
...@@ -511,11 +511,11 @@ pub const HexEscape = struct {...@@ -511,11 +511,11 @@ pub const HexEscape = struct {
511};511};
512512
513/// Replaces non-ASCII bytes with hex escapes.513/// Replaces non-ASCII bytes with hex escapes.
514pub fn hexEscape(bytes: []const u8, case: std.fmt.Case) std.fmt.Alt(HexEscape, HexEscape.format) {514pub fn hexEscape(bytes: []const u8, case: std.fmt.Case) HexEscape {
515 return .{ .data = .{ .bytes = bytes, .charset = switch (case) {515 return .{ .bytes = bytes, .charset = switch (case) {
516 .lower => HexEscape.lower_charset,516 .lower => HexEscape.lower_charset,
517 .upper => HexEscape.upper_charset,517 .upper => HexEscape.upper_charset,
518 } } };518 } };
519}519}
520520
521test hexEscape {521test hexEscape {
lib/std/bit_set.zig-2
...@@ -1707,8 +1707,6 @@ fn testStaticBitSet(comptime Set: type) !void {...@@ -1707,8 +1707,6 @@ fn testStaticBitSet(comptime Set: type) !void {
1707}1707}
17081708
1709test Integer {1709test Integer {
1710 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1711
1712 try testStaticBitSet(Integer(0));1710 try testStaticBitSet(Integer(0));
1713 try testStaticBitSet(Integer(1));1711 try testStaticBitSet(Integer(1));
1714 try testStaticBitSet(Integer(2));1712 try testStaticBitSet(Integer(2));
lib/std/c.zig+52-22
...@@ -2821,13 +2821,14 @@ pub const SIG = switch (native_os) {...@@ -2821,13 +2821,14 @@ pub const SIG = switch (native_os) {
2821 }2821 }
28222822
2823 pub const POLL: SIG = .IO;2823 pub const POLL: SIG = .IO;
2824 pub const IOT: SIG = .ABRT;
2825 pub const CLD: SIG = .CHLD;
28242826
2825 HUP = 1,2827 HUP = 1,
2826 INT = 2,2828 INT = 2,
2827 QUIT = 3,2829 QUIT = 3,
2828 ILL = 4,2830 ILL = 4,
2829 TRAP = 5,2831 TRAP = 5,
2830 IOT = 6,
2831 ABRT = 6,2832 ABRT = 6,
2832 EMT = 7,2833 EMT = 7,
2833 FPE = 8,2834 FPE = 8,
...@@ -2840,7 +2841,6 @@ pub const SIG = switch (native_os) {...@@ -2840,7 +2841,6 @@ pub const SIG = switch (native_os) {
2840 TERM = 15,2841 TERM = 15,
2841 USR1 = 16,2842 USR1 = 16,
2842 USR2 = 17,2843 USR2 = 17,
2843 CLD = 18,
2844 CHLD = 18,2844 CHLD = 18,
2845 PWR = 19,2845 PWR = 19,
2846 WINCH = 20,2846 WINCH = 20,
...@@ -2991,6 +2991,7 @@ pub const SIG = switch (native_os) {...@@ -2991,6 +2991,7 @@ pub const SIG = switch (native_os) {
2991 pub const UNBLOCK = 2;2991 pub const UNBLOCK = 2;
2992 pub const SETMASK = 3;2992 pub const SETMASK = 3;
29932993
2994 pub const IO: SIG = .POLL;
2994 pub const IOT: SIG = .ABRT;2995 pub const IOT: SIG = .ABRT;
29952996
2996 HUP = 1,2997 HUP = 1,
...@@ -9736,6 +9737,7 @@ pub const SS = switch (native_os) {...@@ -9736,6 +9737,7 @@ pub const SS = switch (native_os) {
97369737
9737pub const EV = switch (native_os) {9738pub const EV = switch (native_os) {
9738 .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => struct {9739 .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => struct {
9740 // https://github.com/apple-oss-distributions/xnu/blob/main/bsd/sys/event.h
9739 /// add event to kq (implies enable)9741 /// add event to kq (implies enable)
9740 pub const ADD = 0x0001;9742 pub const ADD = 0x0001;
9741 /// delete event from kq9743 /// delete event from kq
...@@ -9771,11 +9773,14 @@ pub const EV = switch (native_os) {...@@ -9771,11 +9773,14 @@ pub const EV = switch (native_os) {
9771 pub const FLAG0 = 0x1000;9773 pub const FLAG0 = 0x1000;
9772 /// filter-specific flag9774 /// filter-specific flag
9773 pub const FLAG1 = 0x2000;9775 pub const FLAG1 = 0x2000;
9774 /// EOF detected9776 /// EOF detected (return value)
9775 pub const EOF = 0x8000;9777 pub const EOF = 0x8000;
9776 /// error, data contains errno9778 /// error, data contains errno (return value)
9777 pub const ERROR = 0x4000;9779 pub const ERROR = 0x4000;
9780 /// use poll(2) semantics for EVFILT.READ
9778 pub const POLL = FLAG0;9781 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
9779 pub const OOBAND = FLAG1;9784 pub const OOBAND = FLAG1;
9780 },9785 },
9781 .dragonfly => struct {9786 .dragonfly => struct {
...@@ -9818,6 +9823,7 @@ pub const EV = switch (native_os) {...@@ -9818,6 +9823,7 @@ pub const EV = switch (native_os) {
9818 pub const EOF = 0x8000;9823 pub const EOF = 0x8000;
9819 },9824 },
9820 .freebsd => struct {9825 .freebsd => struct {
9826 // https://cgit.freebsd.org/src/tree/sys/sys/event.h
9821 /// add event to kq (implies enable)9827 /// add event to kq (implies enable)
9822 pub const ADD = 0x0001;9828 pub const ADD = 0x0001;
9823 /// delete event from kq9829 /// delete event from kq
...@@ -9826,12 +9832,14 @@ pub const EV = switch (native_os) {...@@ -9826,12 +9832,14 @@ pub const EV = switch (native_os) {
9826 pub const ENABLE = 0x0004;9832 pub const ENABLE = 0x0004;
9827 /// disable event (not reported)9833 /// disable event (not reported)
9828 pub const DISABLE = 0x0008;9834 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;
9829 /// only report one occurrence9839 /// only report one occurrence
9830 pub const ONESHOT = 0x0010;9840 pub const ONESHOT = 0x0010;
9831 /// clear event state after reporting9841 /// clear event state after reporting
9832 pub const CLEAR = 0x0020;9842 pub const CLEAR = 0x0020;
9833 /// error, event data contains errno
9834 pub const ERROR = 0x4000;
9835 /// force immediate event output9843 /// force immediate event output
9836 /// ... with or without ERROR9844 /// ... with or without ERROR
9837 /// ... use KEVENT_FLAG_ERROR_EVENTS9845 /// ... use KEVENT_FLAG_ERROR_EVENTS
...@@ -9839,6 +9847,18 @@ pub const EV = switch (native_os) {...@@ -9839,6 +9847,18 @@ pub const EV = switch (native_os) {
9839 pub const RECEIPT = 0x0040;9847 pub const RECEIPT = 0x0040;
9840 /// disable event after reporting9848 /// disable event after reporting
9841 pub const DISPATCH = 0x0080;9849 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;
9842 },9862 },
9843 .openbsd => struct {9863 .openbsd => struct {
9844 pub const ADD = 0x0001;9864 pub const ADD = 0x0001;
...@@ -9962,6 +9982,7 @@ pub const EVFILT = switch (native_os) {...@@ -9962,6 +9982,7 @@ pub const EVFILT = switch (native_os) {
9962 pub const EMPTY = 9;9982 pub const EMPTY = 9;
9963 },9983 },
9964 .freebsd => struct {9984 .freebsd => struct {
9985 // https://cgit.freebsd.org/src/tree/sys/sys/event.h
9965 pub const READ = -1;9986 pub const READ = -1;
9966 pub const WRITE = -2;9987 pub const WRITE = -2;
9967 /// attached to aio requests9988 /// attached to aio requests
...@@ -9978,12 +9999,18 @@ pub const EVFILT = switch (native_os) {...@@ -9978,12 +9999,18 @@ pub const EVFILT = switch (native_os) {
9978 pub const PROCDESC = -8;9999 pub const PROCDESC = -8;
9979 /// Filesystem events10000 /// Filesystem events
9980 pub const FS = -9;10001 pub const FS = -9;
10002 /// attached to lio requests
9981 pub const LIO = -10;10003 pub const LIO = -10;
9982 /// User events10004 /// User events
9983 pub const USER = -11;10005 pub const USER = -11;
9984 /// Sendfile events10006 /// Sendfile events
9985 pub const SENDFILE = -12;10007 pub const SENDFILE = -12;
10008 /// empty send socket buf
9986 pub const EMPTY = -13;10009 pub const EMPTY = -13;
10010 /// attached to struct prison
10011 pub const JAIL = -14;
10012 /// attached to jail descriptors
10013 pub const JAILDESC = -15;
9987 },10014 },
9988 .openbsd => struct {10015 .openbsd => struct {
9989 pub const READ = -1;10016 pub const READ = -1;
...@@ -10002,6 +10029,7 @@ pub const EVFILT = switch (native_os) {...@@ -10002,6 +10029,7 @@ pub const EVFILT = switch (native_os) {
1000210029
10003pub const NOTE = switch (native_os) {10030pub const NOTE = switch (native_os) {
10004 .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => struct {10031 .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => struct {
10032 // https://github.com/apple-oss-distributions/xnu/blob/main/bsd/sys/event.h
10005 /// On input, TRIGGER causes the event to be triggered for output.10033 /// On input, TRIGGER causes the event to be triggered for output.
10006 pub const TRIGGER = 0x01000000;10034 pub const TRIGGER = 0x01000000;
10007 /// ignore input fflags10035 /// ignore input fflags
...@@ -10033,7 +10061,7 @@ pub const NOTE = switch (native_os) {...@@ -10033,7 +10061,7 @@ pub const NOTE = switch (native_os) {
10033 pub const RENAME = 0x00000020;10061 pub const RENAME = 0x00000020;
10034 /// vnode access was revoked10062 /// vnode access was revoked
10035 pub const REVOKE = 0x00000040;10063 pub const REVOKE = 0x00000040;
10036 /// No specific vnode event: to test for EVFILT_READ activation10064 /// No specific vnode event: to test for EVFILT_READ activation
10037 pub const NONE = 0x00000080;10065 pub const NONE = 0x00000080;
10038 /// vnode was unlocked by flock(2)10066 /// vnode was unlocked by flock(2)
10039 pub const FUNLOCK = 0x00000100;10067 pub const FUNLOCK = 0x00000100;
...@@ -10045,7 +10073,7 @@ pub const NOTE = switch (native_os) {...@@ -10045,7 +10073,7 @@ pub const NOTE = switch (native_os) {
10045 pub const EXEC = 0x20000000;10073 pub const EXEC = 0x20000000;
10046 /// shared with EVFILT_SIGNAL10074 /// shared with EVFILT_SIGNAL
10047 pub const SIGNAL = 0x08000000;10075 pub const SIGNAL = 0x08000000;
10048 /// exit status to be returned, valid for child process only10076 /// exit status to be returned, valid for child process only
10049 pub const EXITSTATUS = 0x04000000;10077 pub const EXITSTATUS = 0x04000000;
10050 /// provide details on reasons for exit10078 /// provide details on reasons for exit
10051 pub const EXIT_DETAIL = 0x02000000;10079 pub const EXIT_DETAIL = 0x02000000;
...@@ -10056,11 +10084,11 @@ pub const NOTE = switch (native_os) {...@@ -10056,11 +10084,11 @@ pub const NOTE = switch (native_os) {
10056 pub const EXIT_DECRYPTFAIL = 0x00010000;10084 pub const EXIT_DECRYPTFAIL = 0x00010000;
10057 pub const EXIT_MEMORY = 0x00020000;10085 pub const EXIT_MEMORY = 0x00020000;
10058 pub const EXIT_CSERROR = 0x00040000;10086 pub const EXIT_CSERROR = 0x00040000;
10059 /// will react on memory pressure10087 /// will react on memory pressure
10060 pub const VM_PRESSURE = 0x80000000;10088 pub const VM_PRESSURE = 0x80000000;
10061 /// will quit on memory pressure, possibly after cleaning up dirty state10089 /// will quit on memory pressure, possibly after cleaning up dirty state
10062 pub const VM_PRESSURE_TERMINATE = 0x40000000;10090 pub const VM_PRESSURE_TERMINATE = 0x40000000;
10063 /// will quit immediately on memory pressure10091 /// will quit immediately on memory pressure
10064 pub const VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000;10092 pub const VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000;
10065 /// there was an error10093 /// there was an error
10066 pub const VM_ERROR = 0x10000000;10094 pub const VM_ERROR = 0x10000000;
...@@ -10078,6 +10106,9 @@ pub const NOTE = switch (native_os) {...@@ -10078,6 +10106,9 @@ pub const NOTE = switch (native_os) {
10078 pub const CRITICAL = 0x00000020;10106 pub const CRITICAL = 0x00000020;
10079 /// system does maximum timer coalescing10107 /// system does maximum timer coalescing
10080 pub const BACKGROUND = 0x00000040;10108 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
10081 pub const MACH_CONTINUOUS_TIME = 0x00000080;10112 pub const MACH_CONTINUOUS_TIME = 0x00000080;
10082 /// data is mach absolute time units10113 /// data is mach absolute time units
10083 pub const MACHTIME = 0x00000100;10114 pub const MACHTIME = 0x00000100;
...@@ -11237,31 +11268,30 @@ pub const signalfd_siginfo = illumos.signalfd_siginfo;...@@ -11237,31 +11268,30 @@ pub const signalfd_siginfo = illumos.signalfd_siginfo;
11237pub const taskid_t = illumos.taskid_t;11268pub const taskid_t = illumos.taskid_t;
11238pub const zoneid_t = illumos.zoneid_t;11269pub 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;
11240pub const DirEnt = haiku.DirEnt;11274pub const DirEnt = haiku.DirEnt;
11241pub const _get_next_area_info = haiku._get_next_area_info;11275pub const _kern_acquire_sem_etc = haiku._kern_acquire_sem_etc;
11242pub const _get_next_image_info = haiku._get_next_image_info;11276pub const _kern_create_sem = haiku._kern_create_sem;
11243pub const _get_team_info = haiku._get_team_info;11277pub const _kern_delete_sem = haiku._kern_delete_sem;
11244pub const _kern_get_current_team = haiku._kern_get_current_team;
11245pub const _kern_open_dir = haiku._kern_open_dir;11278pub const _kern_open_dir = haiku._kern_open_dir;
11246pub const _kern_read_dir = haiku._kern_read_dir;11279pub const _kern_read_dir = haiku._kern_read_dir;
11247pub const _kern_read_stat = haiku._kern_read_stat;11280pub const _kern_read_stat = haiku._kern_read_stat;
11281pub const _kern_release_sem_etc = haiku._kern_release_sem_etc;
11248pub const _kern_rewind_dir = haiku._kern_rewind_dir;11282pub const _kern_rewind_dir = haiku._kern_rewind_dir;
11249pub const readv_pos = haiku.readv_pos;
11250pub const writev_pos = haiku.writev_pos;
11251pub const area_id = haiku.area_id;11283pub 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;
11255pub const find_thread = haiku.find_thread;11284pub const find_thread = haiku.find_thread;
11256pub const get_system_info = haiku.get_system_info;11285pub const get_system_info = haiku.get_system_info;
11257pub const image_info = haiku.image_info;11286pub const on_exit_thread = haiku.on_exit_thread;
11258pub const port_id = haiku.port_id;11287pub const port_id = haiku.port_id;
11288pub const readv_pos = haiku.readv_pos;
11259pub const sem_id = haiku.sem_id;11289pub const sem_id = haiku.sem_id;
11260pub const status_t = haiku.status_t;11290pub const status_t = haiku.status_t;
11261pub const system_info = haiku.system_info;11291pub const system_info = haiku.system_info;
11262pub const team_id = haiku.team_id;11292pub const team_id = haiku.team_id;
11263pub const team_info = haiku.team_info;
11264pub const thread_id = haiku.thread_id;11293pub const thread_id = haiku.thread_id;
11294pub const writev_pos = haiku.writev_pos;
1126511295
11266pub const AUTH = openbsd.AUTH;11296pub const AUTH = openbsd.AUTH;
11267pub const BI = openbsd.BI;11297pub const BI = openbsd.BI;
lib/std/c/darwin/dispatch.zig+2-2
...@@ -44,8 +44,8 @@ pub const once_t = enum(isize) {...@@ -44,8 +44,8 @@ pub const once_t = enum(isize) {
44 once_f(predicate, context, function);44 once_f(predicate, context, function);
45 } else asm volatile ("" ::: .{ .memory = true });45 } else asm volatile ("" ::: .{ .memory = true });
46 switch (builtin.mode) {46 switch (builtin.mode) {
47 .Debug, .ReleaseSafe => {},47 .debug, .safe => {},
48 .ReleaseFast, .ReleaseSmall => if (predicate.* != .done) unreachable,48 .fast, .small => if (predicate.* != .done) unreachable,
49 }49 }
50 }50 }
51};51};
lib/std/c/haiku.zig+18-69
...@@ -1,15 +1,8 @@...@@ -1,15 +1,8 @@
1const std = @import("../std.zig");1const std = @import("../std.zig");
2const assert = std.debug.assert;
3const builtin = @import("builtin");2const builtin = @import("builtin");
4const maxInt = std.math.maxInt;3const assert = std.debug.assert;
5const iovec = std.posix.iovec;
6const iovec_const = std.posix.iovec_const;
7const socklen_t = std.c.socklen_t;
8const fd_t = std.c.fd_t;4const fd_t = std.c.fd_t;
9const off_t = std.c.off_t;5const 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;
13const dev_t = std.c.dev_t;6const dev_t = std.c.dev_t;
14const ino_t = std.c.ino_t;7const ino_t = std.c.ino_t;
158
...@@ -17,52 +10,27 @@ comptime {...@@ -17,52 +10,27 @@ comptime {
17 assert(builtin.os.tag == .haiku); // Prevent access of std.c symbols on wrong OS.10 assert(builtin.os.tag == .haiku); // Prevent access of std.c symbols on wrong OS.
18}11}
1912
20pub extern "root" fn _errnop() *i32;13pub const B_OS_NAME_LENGTH = 32;
21pub extern "root" fn find_directory(which: directory_which, volume: i32, createIt: bool, path_ptr: [*]u8, length: i32) u64;14pub const B_ABSOLUTE_TIMEOUT = 0x10;
22pub extern "root" fn find_thread(thread_name: ?*anyopaque) i32;15pub const B_TIMEOUT_REAL_TIME_BASE = 0x40;
23pub extern "root" fn get_system_info(system_info: *system_info) usize;16
24pub extern "root" fn _get_team_info(team: i32, team_info: *team_info, size: usize) i32;17pub extern "root" fn _kern_create_sem(count: c_int, name: ?[*:0]const u8) sem_id;
25pub extern "root" fn _get_next_area_info(team: i32, cookie: *i64, area_info: *area_info, size: usize) i32;18pub extern "root" fn _kern_delete_sem(id: sem_id) status_t;
26pub extern "root" fn _get_next_image_info(team: i32, cookie: *i32, image_info: *image_info, size: usize) i32;19pub extern "root" fn _kern_acquire_sem_etc(id: sem_id, count: u32, flags: u32, timeout: i64) status_t;
27pub extern "root" fn _kern_get_current_team() team_id;20pub extern "root" fn _kern_release_sem_etc(id: sem_id, count: u32, flags: u32) status_t;
28pub extern "root" fn _kern_open_dir(fd: fd_t, path: [*:0]const u8) fd_t;21pub extern "root" fn _kern_open_dir(fd: fd_t, path: [*:0]const u8) fd_t;
29pub extern "root" fn _kern_read_dir(fd: fd_t, buffer: [*]u8, bufferSize: usize, maxCount: u32) isize;22pub extern "root" fn _kern_read_dir(fd: fd_t, buffer: [*]u8, bufferSize: usize, maxCount: u32) isize;
30pub extern "root" fn _kern_rewind_dir(fd: fd_t) status_t;23pub extern "root" fn _kern_rewind_dir(fd: fd_t) status_t;
31pub extern "root" fn _kern_read_stat(fd: fd_t, path: [*:0]const u8, traverseLink: bool, stat: *std.c.Stat, statSize: usize) status_t;24pub 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 {26pub extern "root" fn on_exit_thread(callback: *const fn (?*anyopaque) callconv(.c) void, data: ?*anyopaque) status_t;
36 area: u32,27pub extern "root" fn find_thread(name: ?[*:0]const u8) thread_id;
37 name: [32]u8,28pub extern "root" fn get_system_info(info: *system_info) status_t;
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};
4829
49pub const image_info = extern struct {30pub extern "root" fn _errnop() *i32;
50 id: u32,31
51 image_type: u32,32pub extern "root" fn readv_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec, count: i32) isize;
52 sequence: i32,33pub extern "root" fn writev_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec_const, count: i32) isize;
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};
6634
67pub const system_info = extern struct {35pub const system_info = extern struct {
68 boot_time: i64,36 boot_time: i64,
...@@ -86,31 +54,12 @@ pub const system_info = extern struct {...@@ -86,31 +54,12 @@ pub const system_info = extern struct {
86 max_teams: u32,54 max_teams: u32,
87 used_teams: u32,55 used_teams: u32,
88 kernel_name: [256]u8,56 kernel_name: [256]u8,
89 kernel_build_date: [32]u8,57 kernel_build_date: [B_OS_NAME_LENGTH]u8,
90 kernel_build_time: [32]u8,58 kernel_build_time: [B_OS_NAME_LENGTH]u8,
91 kernel_version: i64,59 kernel_version: i64,
92 abi: u32,60 abi: u32,
93};61};
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
114pub const area_id = i32;63pub const area_id = i32;
115pub const port_id = i32;64pub const port_id = i32;
116pub const sem_id = i32;65pub 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...@@ -738,7 +738,7 @@ fn matchAndAddHash(c: *Compress, i: usize, h: Hash, gt: u16, max_chain: u16, goo
738738
739fn clenHlen(freqs: [19]u16) u4 {739fn clenHlen(freqs: [19]u16) u4 {
740 // Note that the first four codes (16, 17, 18, and 0) are always present.740 // 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) {
742 const V = @Vector(16, u16);742 const V = @Vector(16, u16);
743 const hlen_mul: V = comptime m: {743 const hlen_mul: V = comptime m: {
744 var hlen_mul: [16]u16 = undefined;744 var hlen_mul: [16]u16 = undefined;
lib/std/compress/flate/token.zig+3-3
...@@ -57,9 +57,9 @@ const fixed_dist = blk: {...@@ -57,9 +57,9 @@ const fixed_dist = blk: {
57};57};
5858
59// All paramters of codes can be derived matchematically, however some are faster to59// 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.60// do via lookup table. For -Osmall, we do all mathematically to save space.
61pub const LenCode = if (builtin.mode != .ReleaseSmall) LookupLenCode else ShortLenCode;61pub const LenCode = if (builtin.mode != .small) LookupLenCode else ShortLenCode;
62pub const DistCode = if (builtin.mode != .ReleaseSmall) LookupDistCode else ShortDistCode;62pub const DistCode = if (builtin.mode != .small) LookupDistCode else ShortDistCode;
63const ShortLenCode = ShortCode(u8, u2, u3, true);63const ShortLenCode = ShortCode(u8, u2, u3, true);
64const ShortDistCode = ShortCode(u15, u1, u4, false);64const ShortDistCode = ShortCode(u15, u1, u4, false);
65/// For length and distance codes, they having this format.65/// 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;...@@ -7,8 +7,8 @@ const NotSquareError = crypto.errors.NotSquareError;
77
8// Inline conditionally, when it can result in large code generation.8// Inline conditionally, when it can result in large code generation.
9const bloaty_inline: std.builtin.CallingConvention = switch (builtin.mode) {9const bloaty_inline: std.builtin.CallingConvention = switch (builtin.mode) {
10 .ReleaseSafe, .ReleaseFast => .@"inline",10 .safe, .fast => .@"inline",
11 .Debug, .ReleaseSmall => .auto,11 .debug, .small => .auto,
12};12};
1313
14pub const Fe = struct {14pub const Fe = struct {
lib/std/crypto/Certificate.zig+81-10
...@@ -175,6 +175,8 @@ pub const GeneralNameTag = enum(u5) {...@@ -175,6 +175,8 @@ pub const GeneralNameTag = enum(u5) {
175 _,175 _,
176};176};
177177
178const net = @import("../Io/net.zig");
179
178pub const Parsed = struct {180pub const Parsed = struct {
179 certificate: Certificate,181 certificate: Certificate,
180 issuer_slice: Slice,182 issuer_slice: Slice,
...@@ -315,6 +317,7 @@ pub const Parsed = struct {...@@ -315,6 +317,7 @@ pub const Parsed = struct {
315 // what to check. Otherwise, only the common name is checked.317 // what to check. Otherwise, only the common name is checked.
316 const subject_alt_name = parsed_subject.subjectAltName();318 const subject_alt_name = parsed_subject.subjectAltName();
317 if (subject_alt_name.len == 0) {319 if (subject_alt_name.len == 0) {
320 // note: checkIpAddress is intentionally omitted, as it is not permitted in the common name field anyway.
318 if (checkHostName(host_name, parsed_subject.commonName())) {321 if (checkHostName(host_name, parsed_subject.commonName())) {
319 return;322 return;
320 } else {323 } else {
...@@ -332,6 +335,10 @@ pub const Parsed = struct {...@@ -332,6 +335,10 @@ pub const Parsed = struct {
332 const dns_name = subject_alt_name[general_name.slice.start..general_name.slice.end];335 const dns_name = subject_alt_name[general_name.slice.start..general_name.slice.end];
333 if (checkHostName(host_name, dns_name)) return;336 if (checkHostName(host_name, dns_name)) return;
334 },337 },
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 },
335 else => {},342 else => {},
336 }343 }
337 }344 }
...@@ -376,6 +383,22 @@ pub const Parsed = struct {...@@ -376,6 +383,22 @@ pub const Parsed = struct {
376383
377 return false;384 return false;
378 }385 }
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 }
379};402};
380403
381test "Parsed.checkHostName RFC 6125 compliance" {404test "Parsed.checkHostName RFC 6125 compliance" {
...@@ -417,6 +440,39 @@ test "Parsed.checkHostName RFC 6125 compliance" {...@@ -417,6 +440,39 @@ test "Parsed.checkHostName RFC 6125 compliance" {
417 try expectEqual(false, Parsed.checkHostName("example.com", "*."));440 try expectEqual(false, Parsed.checkHostName("example.com", "*."));
418}441}
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
420pub const ParseError = der.Element.ParseError || ParseVersionError || ParseTimeError || ParseEnumError || ParseBitStringError;476pub const ParseError = der.Element.ParseError || ParseVersionError || ParseTimeError || ParseEnumError || ParseBitStringError;
421477
422pub fn parse(cert: Certificate) ParseError!Parsed {478pub fn parse(cert: Certificate) ParseError!Parsed {
...@@ -793,7 +849,7 @@ fn verifyRsa(...@@ -793,7 +849,7 @@ fn verifyRsa(
793 inline 128, 256, 384, 512 => |modulus_len| {849 inline 128, 256, 384, 512 => |modulus_len| {
794 const public_key = rsa.PublicKey.fromBytes(exponent, modulus) catch850 const public_key = rsa.PublicKey.fromBytes(exponent, modulus) catch
795 return error.CertificateSignatureInvalid;851 return error.CertificateSignatureInvalid;
796 rsa.PKCS1v1_5Signature.verify(modulus_len, sig[0..modulus_len].*, msg, public_key, Hash) catch852 rsa.PKCS1v1_5Signature.verify(modulus_len, sig[0..modulus_len], msg, public_key, Hash) catch
797 return error.CertificateSignatureInvalid;853 return error.CertificateSignatureInvalid;
798 },854 },
799 else => return error.CertificateSignatureUnsupportedBitCount,855 else => return error.CertificateSignatureUnsupportedBitCount,
...@@ -983,7 +1039,7 @@ pub const rsa = struct {...@@ -983,7 +1039,7 @@ pub const rsa = struct {
9831039
984 pub fn concatVerify(1040 pub fn concatVerify(
985 comptime modulus_len: usize,1041 comptime modulus_len: usize,
986 sig: [modulus_len]u8,1042 sig: *const [modulus_len]u8,
987 msg: []const []const u8,1043 msg: []const []const u8,
988 public_key: PublicKey,1044 public_key: PublicKey,
989 comptime Hash: type,1045 comptime Hash: type,
...@@ -1092,9 +1148,9 @@ pub const rsa = struct {...@@ -1092,9 +1148,9 @@ pub const rsa = struct {
1092 }1148 }
1093 var m_p_buf: [8 + Hash.digest_length + Hash.digest_length]u8 = undefined;1149 var m_p_buf: [8 + Hash.digest_length + Hash.digest_length]u8 = undefined;
1094 var m_p = m_p_buf[0 .. 8 + Hash.digest_length + sLen];1150 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)));1151 @memmove(m_p[0..8], @as(*const [8]u8, &@splat(0)));
1096 std.mem.copyForwards(u8, m_p[8..], &mHash);1152 @memmove(m_p[8..][0..Hash.digest_length], &mHash);
1097 std.mem.copyForwards(u8, m_p[(8 + Hash.digest_length)..], salt);1153 @memmove(m_p[(8 + Hash.digest_length)..], salt);
10981154
1099 // 13. Let H' = Hash(M'), an octet string of length hLen.1155 // 13. Let H' = Hash(M'), an octet string of length hLen.
1100 var h_p: [Hash.digest_length]u8 = undefined;1156 var h_p: [Hash.digest_length]u8 = undefined;
...@@ -1136,7 +1192,7 @@ pub const rsa = struct {...@@ -1136,7 +1192,7 @@ pub const rsa = struct {
11361192
1137 pub fn verify(1193 pub fn verify(
1138 comptime modulus_len: usize,1194 comptime modulus_len: usize,
1139 sig: [modulus_len]u8,1195 sig: *const [modulus_len]u8,
1140 msg: []const u8,1196 msg: []const u8,
1141 public_key: PublicKey,1197 public_key: PublicKey,
1142 comptime Hash: type,1198 comptime Hash: type,
...@@ -1146,7 +1202,7 @@ pub const rsa = struct {...@@ -1146,7 +1202,7 @@ pub const rsa = struct {
11461202
1147 pub fn concatVerify(1203 pub fn concatVerify(
1148 comptime modulus_len: usize,1204 comptime modulus_len: usize,
1149 sig: [modulus_len]u8,1205 sig: *const [modulus_len]u8,
1150 msg: []const []const u8,1206 msg: []const []const u8,
1151 public_key: PublicKey,1207 public_key: PublicKey,
1152 comptime Hash: type,1208 comptime Hash: type,
...@@ -1187,6 +1243,11 @@ pub const rsa = struct {...@@ -1187,6 +1243,11 @@ pub const rsa = struct {
1187 // DigestInfo value (see the notes below) and let tLen be the length1243 // DigestInfo value (see the notes below) and let tLen be the length
1188 // in octets of T.1244 // in octets of T.
1189 const hash_der: []const u8 = &switch (Hash) {1245 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 },
1190 crypto.hash.Sha1 => .{1251 crypto.hash.Sha1 => .{
1191 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,1252 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
1192 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14,1253 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14,
...@@ -1211,7 +1272,17 @@ pub const rsa = struct {...@@ -1211,7 +1272,17 @@ pub const rsa = struct {
1211 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,1272 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
1212 0x00, 0x04, 0x40,1273 0x00, 0x04, 0x40,
1213 },1274 },
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,
1215 };1286 };
1216 em_index -= hash_der.len;1287 em_index -= hash_der.len;
1217 @memcpy(em[em_index..][0..hash_der.len], hash_der);1288 @memcpy(em[em_index..][0..hash_der.len], hash_der);
...@@ -1292,8 +1363,8 @@ pub const rsa = struct {...@@ -1292,8 +1363,8 @@ pub const rsa = struct {
12921363
1293 const EncryptError = error{MessageTooLong};1364 const EncryptError = error{MessageTooLong};
12941365
1295 fn encrypt(comptime modulus_len: usize, msg: [modulus_len]u8, public_key: PublicKey) EncryptError![modulus_len]u8 {1366 fn encrypt(comptime modulus_len: usize, msg: *const [modulus_len]u8, public_key: PublicKey) EncryptError![modulus_len]u8 {
1296 const m = Fe.fromBytes(public_key.n, &msg, .big) catch return error.MessageTooLong;1367 const m = Fe.fromBytes(public_key.n, msg, .big) catch return error.MessageTooLong;
1297 const e = public_key.n.powPublic(m, public_key.e) catch unreachable;1368 const e = public_key.n.powPublic(m, public_key.e) catch unreachable;
1298 var res: [modulus_len]u8 = undefined;1369 var res: [modulus_len]u8 = undefined;
1299 e.toBytes(&res, .big) catch unreachable;1370 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);...@@ -6,9 +6,9 @@ const has_aesni = builtin.cpu.has(.x86, .aes);
6const has_avx = builtin.cpu.has(.x86, .avx);6const has_avx = builtin.cpu.has(.x86, .avx);
7const has_armaes = builtin.cpu.has(.aarch64, .aes);7const has_armaes = builtin.cpu.has(.aarch64, .aes);
8// C backend doesn't currently support passing vectors to inline asm.8// 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: {
10 break :impl @import("aes/aesni.zig");10 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: {
12 break :impl @import("aes/armcrypto.zig");12 break :impl @import("aes/armcrypto.zig");
13} else impl: {13} else impl: {
14 break :impl @import("aes/soft.zig");14 break :impl @import("aes/soft.zig");
lib/std/crypto/aes_ocb.zig-10
...@@ -262,8 +262,6 @@ const hexToBytes = std.fmt.hexToBytes;...@@ -262,8 +262,6 @@ const hexToBytes = std.fmt.hexToBytes;
262const testing = std.testing;262const testing = std.testing;
263263
264test "AesOcb test vector 1" {264test "AesOcb test vector 1" {
265 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
266
267 var k: [Aes128Ocb.key_length]u8 = undefined;265 var k: [Aes128Ocb.key_length]u8 = undefined;
268 var nonce: [Aes128Ocb.nonce_length]u8 = undefined;266 var nonce: [Aes128Ocb.nonce_length]u8 = undefined;
269 var tag: [Aes128Ocb.tag_length]u8 = undefined;267 var tag: [Aes128Ocb.tag_length]u8 = undefined;
...@@ -281,8 +279,6 @@ test "AesOcb test vector 1" {...@@ -281,8 +279,6 @@ test "AesOcb test vector 1" {
281}279}
282280
283test "AesOcb test vector 2" {281test "AesOcb test vector 2" {
284 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
285
286 var k: [Aes128Ocb.key_length]u8 = undefined;282 var k: [Aes128Ocb.key_length]u8 = undefined;
287 var nonce: [Aes128Ocb.nonce_length]u8 = undefined;283 var nonce: [Aes128Ocb.nonce_length]u8 = undefined;
288 var tag: [Aes128Ocb.tag_length]u8 = undefined;284 var tag: [Aes128Ocb.tag_length]u8 = undefined;
...@@ -303,8 +299,6 @@ test "AesOcb test vector 2" {...@@ -303,8 +299,6 @@ test "AesOcb test vector 2" {
303}299}
304300
305test "AesOcb test vector 3" {301test "AesOcb test vector 3" {
306 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
307
308 var k: [Aes128Ocb.key_length]u8 = undefined;302 var k: [Aes128Ocb.key_length]u8 = undefined;
309 var nonce: [Aes128Ocb.nonce_length]u8 = undefined;303 var nonce: [Aes128Ocb.nonce_length]u8 = undefined;
310 var tag: [Aes128Ocb.tag_length]u8 = undefined;304 var tag: [Aes128Ocb.tag_length]u8 = undefined;
...@@ -329,8 +323,6 @@ test "AesOcb test vector 3" {...@@ -329,8 +323,6 @@ test "AesOcb test vector 3" {
329}323}
330324
331test "AesOcb test vector 4" {325test "AesOcb test vector 4" {
332 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
333
334 var k: [Aes128Ocb.key_length]u8 = undefined;326 var k: [Aes128Ocb.key_length]u8 = undefined;
335 var nonce: [Aes128Ocb.nonce_length]u8 = undefined;327 var nonce: [Aes128Ocb.nonce_length]u8 = undefined;
336 var tag: [Aes128Ocb.tag_length]u8 = undefined;328 var tag: [Aes128Ocb.tag_length]u8 = undefined;
...@@ -356,8 +348,6 @@ test "AesOcb test vector 4" {...@@ -356,8 +348,6 @@ test "AesOcb test vector 4" {
356}348}
357349
358test "AesOcb in-place encryption-decryption" {350test "AesOcb in-place encryption-decryption" {
359 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
360
361 var k: [Aes128Ocb.key_length]u8 = undefined;351 var k: [Aes128Ocb.key_length]u8 = undefined;
362 var nonce: [Aes128Ocb.nonce_length]u8 = undefined;352 var nonce: [Aes128Ocb.nonce_length]u8 = undefined;
363 var tag: [Aes128Ocb.tag_length]u8 = undefined;353 var tag: [Aes128Ocb.tag_length]u8 = undefined;
lib/std/crypto/benchmark.zig+3-3
...@@ -454,8 +454,8 @@ fn benchmarkPwhash(...@@ -454,8 +454,8 @@ fn benchmarkPwhash(
454454
455 const strHash = ty.strHash;455 const strHash = ty.strHash;
456 const strHashFnInfo = @typeInfo(@TypeOf(strHash)).@"fn";456 const strHashFnInfo = @typeInfo(@TypeOf(strHash)).@"fn";
457 const needs_io = 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.params.len == 4 and strHashFnInfo.params[3].type != std.Io;458 const needs_salt = strHashFnInfo.param_types.len == 4 and strHashFnInfo.param_types[3].? != std.Io;
459 const salt: [16]u8 = @splat(0);459 const salt: [16]u8 = @splat(0);
460460
461 const start = benchTime(io);461 const start = benchTime(io);
...@@ -493,7 +493,7 @@ fn usage() void {...@@ -493,7 +493,7 @@ fn usage() void {
493}493}
494494
495fn mode(comptime x: comptime_int) comptime_int {495fn 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;
497}497}
498498
499pub fn main(init: std.process.Init) !void {499pub fn main(init: std.process.Init) !void {
lib/std/crypto/ecdsa.zig+6-24
...@@ -1,4 +1,3 @@...@@ -1,4 +1,3 @@
1const builtin = @import("builtin");
2const std = @import("std");1const std = @import("std");
3const crypto = std.crypto;2const crypto = std.crypto;
4const fmt = std.fmt;3const fmt = std.fmt;
...@@ -25,14 +24,17 @@ pub const EcdsaSecp256k1Sha256 = Ecdsa(crypto.ecc.Secp256k1, crypto.hash.sha2.Sh...@@ -25,14 +24,17 @@ pub const EcdsaSecp256k1Sha256 = Ecdsa(crypto.ecc.Secp256k1, crypto.hash.sha2.Sh
25pub const EcdsaSecp256k1Sha256oSha256 = Ecdsa(crypto.ecc.Secp256k1, crypto.hash.composition.Sha256oSha256);24pub const EcdsaSecp256k1Sha256oSha256 = Ecdsa(crypto.ecc.Secp256k1, crypto.hash.composition.Sha256oSha256);
2625
27/// Elliptic Curve Digital Signature Algorithm (ECDSA).26/// Elliptic Curve Digital Signature Algorithm (ECDSA).
28pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type {27pub fn Ecdsa(comptime C: type, comptime H: type) type {
29 const Prf = switch (Hash) {28 const Prf = switch (H) {
30 sha3.Shake128 => sha3.KMac128,29 sha3.Shake128 => sha3.KMac128,
31 sha3.Shake256 => sha3.KMac256,30 sha3.Shake256 => sha3.KMac256,
32 else => crypto.auth.hmac.Hmac(Hash),31 else => crypto.auth.hmac.Hmac(H),
33 };32 };
3433
35 return struct {34 return struct {
35 pub const Curve = C;
36 pub const Hash = H;
37
36 /// Length (in bytes) of optional random bytes, for non-deterministic signatures.38 /// Length (in bytes) of optional random bytes, for non-deterministic signatures.
37 pub const noise_length = Curve.scalar.encoded_length;39 pub const noise_length = Curve.scalar.encoded_length;
3840
...@@ -415,8 +417,6 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type {...@@ -415,8 +417,6 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type {
415}417}
416418
417test "Basic operations over EcdsaP384Sha384" {419test "Basic operations over EcdsaP384Sha384" {
418 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
419
420 const io = testing.io;420 const io = testing.io;
421 const Scheme = EcdsaP384Sha384;421 const Scheme = EcdsaP384Sha384;
422 const kp = Scheme.KeyPair.generate(io);422 const kp = Scheme.KeyPair.generate(io);
...@@ -432,8 +432,6 @@ test "Basic operations over EcdsaP384Sha384" {...@@ -432,8 +432,6 @@ test "Basic operations over EcdsaP384Sha384" {
432}432}
433433
434test "Basic operations over Secp256k1" {434test "Basic operations over Secp256k1" {
435 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
436
437 const io = testing.io;435 const io = testing.io;
438 const Scheme = EcdsaSecp256k1Sha256oSha256;436 const Scheme = EcdsaSecp256k1Sha256oSha256;
439 const kp = Scheme.KeyPair.generate(io);437 const kp = Scheme.KeyPair.generate(io);
...@@ -449,8 +447,6 @@ test "Basic operations over Secp256k1" {...@@ -449,8 +447,6 @@ test "Basic operations over Secp256k1" {
449}447}
450448
451test "Basic operations over EcdsaP384Sha256" {449test "Basic operations over EcdsaP384Sha256" {
452 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
453
454 const io = testing.io;450 const io = testing.io;
455 const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256);451 const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256);
456 const kp = Scheme.KeyPair.generate(io);452 const kp = Scheme.KeyPair.generate(io);
...@@ -466,8 +462,6 @@ test "Basic operations over EcdsaP384Sha256" {...@@ -466,8 +462,6 @@ test "Basic operations over EcdsaP384Sha256" {
466}462}
467463
468test "Verifying a existing signature with EcdsaP384Sha256" {464test "Verifying a existing signature with EcdsaP384Sha256" {
469 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
470
471 const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256);465 const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256);
472 // zig fmt: off466 // zig fmt: off
473 const sk_bytes = [_]u8{467 const sk_bytes = [_]u8{
...@@ -503,8 +497,6 @@ test "Verifying a existing signature with EcdsaP384Sha256" {...@@ -503,8 +497,6 @@ test "Verifying a existing signature with EcdsaP384Sha256" {
503}497}
504498
505test "Prehashed message operations" {499test "Prehashed message operations" {
506 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
507
508 const io = testing.io;500 const io = testing.io;
509501
510 const Scheme = EcdsaP256Sha256;502 const Scheme = EcdsaP256Sha256;
...@@ -539,8 +531,6 @@ const TestVector = struct {...@@ -539,8 +531,6 @@ const TestVector = struct {
539};531};
540532
541test "Test vectors from Project Wycheproof - EcdsaP256Sha256 valid" {533test "Test vectors from Project Wycheproof - EcdsaP256Sha256 valid" {
542 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
543
544 const vectors: []const TestVector = &.{534 const vectors: []const TestVector = &.{
545 // well-formed DER encoding -> expected valid535 // well-formed DER encoding -> expected valid
546 .{ .key = "042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", .msg = "313233343030", .sig = "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1802204cd60b855d442f5b3c7b11eb6c4e0ae7525fe710fab9aa7c77a67f79e6fadd76" },536 .{ .key = "042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", .msg = "313233343030", .sig = "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1802204cd60b855d442f5b3c7b11eb6c4e0ae7525fe710fab9aa7c77a67f79e6fadd76" },
...@@ -711,8 +701,6 @@ test "Test vectors from Project Wycheproof - EcdsaP256Sha256 valid" {...@@ -711,8 +701,6 @@ test "Test vectors from Project Wycheproof - EcdsaP256Sha256 valid" {
711}701}
712702
713test "Test vectors from Project Wycheproof - EcdsaP256Sha256 invalid" {703test "Test vectors from Project Wycheproof - EcdsaP256Sha256 invalid" {
714 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
715
716 const vectors: []const TestVector = &.{704 const vectors: []const TestVector = &.{
717 // S encoded with negative sign -> expected invalid705 // S encoded with negative sign -> expected invalid
718 .{ .key = "042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", .msg = "313233343030", .sig = "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180220b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db" },706 .{ .key = "042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", .msg = "313233343030", .sig = "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180220b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db" },
...@@ -1026,8 +1014,6 @@ test "Test vectors from Project Wycheproof - EcdsaP256Sha256 invalid" {...@@ -1026,8 +1014,6 @@ test "Test vectors from Project Wycheproof - EcdsaP256Sha256 invalid" {
1026}1014}
10271015
1028test "Test vectors from Project Wycheproof - EcdsaP384Sha384 valid" {1016test "Test vectors from Project Wycheproof - EcdsaP384Sha384 valid" {
1029 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1030
1031 const vectors: []const TestVector = &.{1017 const vectors: []const TestVector = &.{
1032 // canonical sign-bit padding on R; canonical sign-bit padding on S -> expected valid1018 // canonical sign-bit padding on R; canonical sign-bit padding on S -> expected valid
1033 .{ .key = "0429bdb76d5fa741bfd70233cb3a66cc7d44beb3b0663d92a8136650478bcefb61ef182e155a54345a5e8e5e88f064e5bc9a525ab7f764dad3dae1468c2b419f3b62b9ba917d5e8c4fb1ec47404a3fc76474b2713081be9db4c00e043ada9fc4a3", .msg = "4d7367", .sig = "3066023100d7143a836608b25599a7f28dec6635494c2992ad1e2bbeecb7ef601a9c01746e710ce0d9c48accb38a79ede5b9638f3402310080f9e165e8c61035bf8aa7b5533960e46dd0e211c904a064edb6de41f797c0eae4e327612ee3f816f4157272bb4fabc9" },1019 .{ .key = "0429bdb76d5fa741bfd70233cb3a66cc7d44beb3b0663d92a8136650478bcefb61ef182e155a54345a5e8e5e88f064e5bc9a525ab7f764dad3dae1468c2b419f3b62b9ba917d5e8c4fb1ec47404a3fc76474b2713081be9db4c00e043ada9fc4a3", .msg = "4d7367", .sig = "3066023100d7143a836608b25599a7f28dec6635494c2992ad1e2bbeecb7ef601a9c01746e710ce0d9c48accb38a79ede5b9638f3402310080f9e165e8c61035bf8aa7b5533960e46dd0e211c904a064edb6de41f797c0eae4e327612ee3f816f4157272bb4fabc9" },
...@@ -1243,8 +1229,6 @@ test "Test vectors from Project Wycheproof - EcdsaP384Sha384 valid" {...@@ -1243,8 +1229,6 @@ test "Test vectors from Project Wycheproof - EcdsaP384Sha384 valid" {
1243}1229}
12441230
1245test "Test vectors from Project Wycheproof - EcdsaP384Sha384 invalid" {1231test "Test vectors from Project Wycheproof - EcdsaP384Sha384 invalid" {
1246 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1247
1248 const vectors: []const TestVector = &.{1232 const vectors: []const TestVector = &.{
1249 // S encoded with negative sign -> expected invalid1233 // S encoded with negative sign -> expected invalid
1250 .{ .key = "042da57dda1089276a543f9ffdac0bff0d976cad71eb7280e7d9bfd9fee4bdb2f20f47ff888274389772d98cc5752138aa4b6d054d69dcf3e25ec49df870715e34883b1836197d76f8ad962e78f6571bbc7407b0d6091f9e4d88f014274406174f", .msg = "313233343030", .sig = "3064023012b30abef6b5476fe6b612ae557c0425661e26b44b1bfe19daf2ca28e3113083ba8e4ae4cc45a0320abd3394f1c548d70230e7bf25603e2d07076ff30b7a2abec473da8b11c572b35fc631991d5de62ddca7525aaba89325dfd04fecc47bff426f82" },1234 .{ .key = "042da57dda1089276a543f9ffdac0bff0d976cad71eb7280e7d9bfd9fee4bdb2f20f47ff888274389772d98cc5752138aa4b6d054d69dcf3e25ec49df870715e34883b1836197d76f8ad962e78f6571bbc7407b0d6091f9e4d88f014274406174f", .msg = "313233343030", .sig = "3064023012b30abef6b5476fe6b612ae557c0425661e26b44b1bfe19daf2ca28e3113083ba8e4ae4cc45a0320abd3394f1c548d70230e7bf25603e2d07076ff30b7a2abec473da8b11c572b35fc631991d5de62ddca7525aaba89325dfd04fecc47bff426f82" },
...@@ -1631,8 +1615,6 @@ fn tvTry(comptime Scheme: type, vector: TestVector) !void {...@@ -1631,8 +1615,6 @@ fn tvTry(comptime Scheme: type, vector: TestVector) !void {
1631}1615}
16321616
1633test "Sec1 encoding/decoding" {1617test "Sec1 encoding/decoding" {
1634 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1635
1636 const io = testing.io;1618 const io = testing.io;
1637 const Scheme = EcdsaP384Sha384;1619 const Scheme = EcdsaP384Sha384;
1638 const kp = Scheme.KeyPair.generate(io);1620 const kp = Scheme.KeyPair.generate(io);
lib/std/crypto/ff.zig-4
...@@ -966,8 +966,6 @@ const ct_unprotected = struct {...@@ -966,8 +966,6 @@ const ct_unprotected = struct {
966};966};
967967
968test "finite field arithmetic" {968test "finite field arithmetic" {
969 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
970
971 const M = Modulus(256);969 const M = Modulus(256);
972 const m = try M.fromPrimitive(u256, 3429938563481314093726330772853735541133072814650493833233);970 const m = try M.fromPrimitive(u256, 3429938563481314093726330772853735541133072814650493833233);
973 var x = try M.Fe.fromPrimitive(u256, m, 80169837251094269539116136208111827396136208141182357733);971 var x = try M.Fe.fromPrimitive(u256, m, 80169837251094269539116136208111827396136208141182357733);
...@@ -1066,8 +1064,6 @@ test "finite field arithmetic" {...@@ -1066,8 +1064,6 @@ test "finite field arithmetic" {
1066}1064}
10671065
1068fn testCt(ct_: anytype) !void {1066fn testCt(ct_: anytype) !void {
1069 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1070
1071 const l0: Limb = 0;1067 const l0: Limb = 0;
1072 const l1: Limb = 1;1068 const l1: Limb = 1;
1073 try testing.expectEqual(l1, ct_.select(true, l1, l0));1069 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 {...@@ -30,7 +30,7 @@ fn Hash(comptime endian: std.builtin.Endian, comptime shift_key: bool) type {
30 pub const mac_length = 16;30 pub const mac_length = 16;
31 pub const key_length = 16;31 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;
34 const agg_4_threshold = 22;34 const agg_4_threshold = 22;
35 const agg_8_threshold = 84;35 const agg_8_threshold = 84;
36 const agg_16_threshold = 328;36 const agg_16_threshold = 328;
...@@ -61,7 +61,7 @@ fn Hash(comptime endian: std.builtin.Endian, comptime shift_key: bool) type {...@@ -61,7 +61,7 @@ fn Hash(comptime endian: std.builtin.Endian, comptime shift_key: bool) type {
61 hx[0] = h;61 hx[0] = h;
62 hx[1] = reduce(clsq128(hx[0])); // h^262 hx[1] = reduce(clsq128(hx[0])); // h^2
6363
64 if (builtin.mode != .ReleaseSmall) {64 if (builtin.mode != .small) {
65 hx[2] = reduce(clmul128(hx[1], h)); // h^365 hx[2] = reduce(clmul128(hx[1], h)); // h^3
66 hx[3] = reduce(clsq128(hx[1])); // h^4 = h^2^266 hx[3] = reduce(clsq128(hx[1])); // h^4 = h^2^2
67 if (block_count >= agg_8_threshold) {67 if (block_count >= agg_8_threshold) {
...@@ -303,7 +303,7 @@ fn Hash(comptime endian: std.builtin.Endian, comptime shift_key: bool) type {...@@ -303,7 +303,7 @@ fn Hash(comptime endian: std.builtin.Endian, comptime shift_key: bool) type {
303303
304 var i: usize = 0;304 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) {
307 // 16-blocks aggregated reduction307 // 16-blocks aggregated reduction
308 while (i + 256 <= msg.len) : (i += 256) {308 while (i + 256 <= msg.len) : (i += 256) {
309 var u = clmul128(acc ^ mem.readInt(u128, msg[i..][0..16], endian), st.hx[15 - 0]);309 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 {...@@ -313,7 +313,7 @@ fn Hash(comptime endian: std.builtin.Endian, comptime shift_key: bool) type {
313 }313 }
314 acc = reduce(u);314 acc = reduce(u);
315 }315 }
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) {
317 // 8-blocks aggregated reduction317 // 8-blocks aggregated reduction
318 while (i + 128 <= msg.len) : (i += 128) {318 while (i + 128 <= msg.len) : (i += 128) {
319 var u = clmul128(acc ^ mem.readInt(u128, msg[i..][0..16], endian), st.hx[7 - 0]);319 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 {...@@ -323,7 +323,7 @@ fn Hash(comptime endian: std.builtin.Endian, comptime shift_key: bool) type {
323 }323 }
324 acc = reduce(u);324 acc = reduce(u);
325 }325 }
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) {
327 // 4-blocks aggregated reduction327 // 4-blocks aggregated reduction
328 while (i + 64 <= msg.len) : (i += 64) {328 while (i + 64 <= msg.len) : (i += 64) {
329 var u = clmul128(acc ^ mem.readInt(u128, msg[i..][0..16], endian), st.hx[3 - 0]);329 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(...@@ -885,7 +885,7 @@ fn ktMultiThreaded(
885885
886 var select_outstanding: usize = 0;886 var select_outstanding: usize = 0;
887 var select: Select = .init(io, select_buf);887 var select: Select = .init(io, select_buf);
888 defer select.cancel();888 defer select.cancelDiscard();
889 var batches_spawned: usize = 0;889 var batches_spawned: usize = 0;
890 var next_to_process: usize = 0;890 var next_to_process: usize = 0;
891891
...@@ -1398,7 +1398,7 @@ test "KT128 sequential and parallel produce same output for many random lengths"...@@ -1398,7 +1398,7 @@ test "KT128 sequential and parallel produce same output for many random lengths"
1398 var prng = std.Random.DefaultPrng.init(std.testing.random_seed);1398 var prng = std.Random.DefaultPrng.init(std.testing.random_seed);
1399 const random = prng.random();1399 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;
1402 const max_length = 250000;1402 const max_length = 250000;
14031403
1404 for (0..num_tests) |_| {1404 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...@@ -202,7 +202,7 @@ pub fn State(comptime f: u11, comptime capacity: u11, comptime rounds: u5) type
202202
203 // In debug mode, track transitions to prevent insecure ones.203 // In debug mode, track transitions to prevent insecure ones.
204 const Op = enum { uninitialized, initialized, updated, absorb, squeeze };204 const Op = enum { uninitialized, initialized, updated, absorb, squeeze };
205 const TransitionTracker = if (mode == .Debug) struct {205 const TransitionTracker = if (mode == .debug) struct {
206 op: Op = .uninitialized,206 op: Op = .uninitialized,
207207
208 fn to(tracker: *@This(), next_op: Op) void {208 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...@@ -294,7 +294,7 @@ pub fn State(comptime f: u11, comptime capacity: u11, comptime rounds: u5) type
294294
295 /// Permute the state295 /// Permute the state
296 pub fn permute(self: *Self) void {296 pub fn permute(self: *Self) void {
297 if (mode == .Debug) {297 if (mode == .debug) {
298 if (self.transition.op == .absorb and self.offset > 0) {298 if (self.transition.op == .absorb and self.offset > 0) {
299 @panic("cannot permute with pending input - call fillBlock() or pad() instead");299 @panic("cannot permute with pending input - call fillBlock() or pad() instead");
300 }300 }
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 {...@@ -110,7 +110,7 @@ fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
110/// out1: [0x0 ~> 0xffffffffffffffff]110/// out1: [0x0 ~> 0xffffffffffffffff]
111/// out2: [0x0 ~> 0xffffffffffffffff]111/// out2: [0x0 ~> 0xffffffffffffffff]
112fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {112fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
113 @setRuntimeSafety(mode == .Debug);113 @setRuntimeSafety(mode == .debug);
114114
115 const x = @as(u128, arg1) * @as(u128, arg2);115 const x = @as(u128, arg1) * @as(u128, arg2);
116 out1.* = @as(u64, @truncate(x));116 out1.* = @as(u64, @truncate(x));
...@@ -129,7 +129,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {...@@ -129,7 +129,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
129/// Output Bounds:129/// Output Bounds:
130/// out1: [0x0 ~> 0xffffffffffffffff]130/// out1: [0x0 ~> 0xffffffffffffffff]
131fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {131fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
132 @setRuntimeSafety(mode == .Debug);132 @setRuntimeSafety(mode == .debug);
133133
134 const mask = 0 -% @as(u64, arg1);134 const mask = 0 -% @as(u64, arg1);
135 out1.* = (mask & arg3) | ((~mask) & arg2);135 out1.* = (mask & arg3) | ((~mask) & arg2);
...@@ -145,7 +145,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {...@@ -145,7 +145,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
145/// 0 ≤ eval out1 < m145/// 0 ≤ eval out1 < m
146///146///
147pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {147pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
148 @setRuntimeSafety(mode == .Debug);148 @setRuntimeSafety(mode == .debug);
149149
150 const x1 = (arg1[1]);150 const x1 = (arg1[1]);
151 const x2 = (arg1[2]);151 const x2 = (arg1[2]);
...@@ -437,7 +437,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -437,7 +437,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
437/// 0 ≤ eval out1 < m437/// 0 ≤ eval out1 < m
438///438///
439pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {439pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
440 @setRuntimeSafety(mode == .Debug);440 @setRuntimeSafety(mode == .debug);
441441
442 const x1 = (arg1[1]);442 const x1 = (arg1[1]);
443 const x2 = (arg1[2]);443 const x2 = (arg1[2]);
...@@ -730,7 +730,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl...@@ -730,7 +730,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl
730/// 0 ≤ eval out1 < m730/// 0 ≤ eval out1 < m
731///731///
732pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {732pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
733 @setRuntimeSafety(mode == .Debug);733 @setRuntimeSafety(mode == .debug);
734734
735 var x1: u64 = undefined;735 var x1: u64 = undefined;
736 var x2: u1 = undefined;736 var x2: u1 = undefined;
...@@ -783,7 +783,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -783,7 +783,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
783/// 0 ≤ eval out1 < m783/// 0 ≤ eval out1 < m
784///784///
785pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {785pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
786 @setRuntimeSafety(mode == .Debug);786 @setRuntimeSafety(mode == .debug);
787787
788 var x1: u64 = undefined;788 var x1: u64 = undefined;
789 var x2: u1 = undefined;789 var x2: u1 = undefined;
...@@ -826,7 +826,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -826,7 +826,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
826/// 0 ≤ eval out1 < m826/// 0 ≤ eval out1 < m
827///827///
828pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {828pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
829 @setRuntimeSafety(mode == .Debug);829 @setRuntimeSafety(mode == .debug);
830830
831 var x1: u64 = undefined;831 var x1: u64 = undefined;
832 var x2: u1 = undefined;832 var x2: u1 = undefined;
...@@ -869,7 +869,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -869,7 +869,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
869/// 0 ≤ eval out1 < m869/// 0 ≤ eval out1 < m
870///870///
871pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {871pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
872 @setRuntimeSafety(mode == .Debug);872 @setRuntimeSafety(mode == .debug);
873873
874 const x1 = (arg1[0]);874 const x1 = (arg1[0]);
875 var x2: u64 = undefined;875 var x2: u64 = undefined;
...@@ -1022,7 +1022,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo...@@ -1022,7 +1022,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo
1022/// 0 ≤ eval out1 < m1022/// 0 ≤ eval out1 < m
1023///1023///
1024pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void {1024pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void {
1025 @setRuntimeSafety(mode == .Debug);1025 @setRuntimeSafety(mode == .debug);
10261026
1027 const x1 = (arg1[1]);1027 const x1 = (arg1[1]);
1028 const x2 = (arg1[2]);1028 const x2 = (arg1[2]);
...@@ -1297,7 +1297,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma...@@ -1297,7 +1297,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma
1297/// Output Bounds:1297/// Output Bounds:
1298/// out1: [0x0 ~> 0xffffffffffffffff]1298/// out1: [0x0 ~> 0xffffffffffffffff]
1299pub fn nonzero(out1: *u64, arg1: [4]u64) void {1299pub fn nonzero(out1: *u64, arg1: [4]u64) void {
1300 @setRuntimeSafety(mode == .Debug);1300 @setRuntimeSafety(mode == .debug);
13011301
1302 const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3]))));1302 const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3]))));
1303 out1.* = x1;1303 out1.* = x1;
...@@ -1315,7 +1315,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void {...@@ -1315,7 +1315,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void {
1315/// Output Bounds:1315/// Output Bounds:
1316/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1316/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1317pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void {1317pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void {
1318 @setRuntimeSafety(mode == .Debug);1318 @setRuntimeSafety(mode == .debug);
13191319
1320 var x1: u64 = undefined;1320 var x1: u64 = undefined;
1321 cmovznzU64(&x1, arg1, (arg2[0]), (arg3[0]));1321 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 {...@@ -1343,7 +1343,7 @@ pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void {
1343/// Output Bounds:1343/// Output Bounds:
1344/// 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]]1344/// 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]]
1345pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {1345pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {
1346 @setRuntimeSafety(mode == .Debug);1346 @setRuntimeSafety(mode == .debug);
13471347
1348 const x1 = (arg1[3]);1348 const x1 = (arg1[3]);
1349 const x2 = (arg1[2]);1349 const x2 = (arg1[2]);
...@@ -1452,7 +1452,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {...@@ -1452,7 +1452,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {
1452/// Output Bounds:1452/// Output Bounds:
1453/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1453/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1454pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {1454pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {
1455 @setRuntimeSafety(mode == .Debug);1455 @setRuntimeSafety(mode == .debug);
14561456
1457 const x1 = (@as(u64, (arg1[31])) << 56);1457 const x1 = (@as(u64, (arg1[31])) << 56);
1458 const x2 = (@as(u64, (arg1[30])) << 48);1458 const x2 = (@as(u64, (arg1[30])) << 48);
...@@ -1527,7 +1527,7 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {...@@ -1527,7 +1527,7 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {
1527/// 0 ≤ eval out1 < m1527/// 0 ≤ eval out1 < m
1528///1528///
1529pub fn setOne(out1: *MontgomeryDomainFieldElement) void {1529pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
1530 @setRuntimeSafety(mode == .Debug);1530 @setRuntimeSafety(mode == .debug);
15311531
1532 out1[0] = @as(u64, 0x1);1532 out1[0] = @as(u64, 0x1);
1533 out1[1] = 0xffffffff00000000;1533 out1[1] = 0xffffffff00000000;
...@@ -1544,7 +1544,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void {...@@ -1544,7 +1544,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
1544/// Output Bounds:1544/// Output Bounds:
1545/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1545/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1546pub fn msat(out1: *[5]u64) void {1546pub fn msat(out1: *[5]u64) void {
1547 @setRuntimeSafety(mode == .Debug);1547 @setRuntimeSafety(mode == .debug);
15481548
1549 out1[0] = 0xffffffffffffffff;1549 out1[0] = 0xffffffffffffffff;
1550 out1[1] = 0xffffffff;1550 out1[1] = 0xffffffff;
...@@ -1582,7 +1582,7 @@ pub fn msat(out1: *[5]u64) void {...@@ -1582,7 +1582,7 @@ pub fn msat(out1: *[5]u64) void {
1582/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1582/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1583/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1583/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1584pub 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 {1584pub 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
1587 var x1: u64 = undefined;1587 var x1: u64 = undefined;
1588 var x2: u1 = undefined;1588 var x2: u1 = undefined;
...@@ -1816,7 +1816,7 @@ pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[...@@ -1816,7 +1816,7 @@ pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[
1816/// Output Bounds:1816/// Output Bounds:
1817/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1817/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1818pub fn divstepPrecomp(out1: *[4]u64) void {1818pub fn divstepPrecomp(out1: *[4]u64) void {
1819 @setRuntimeSafety(mode == .Debug);1819 @setRuntimeSafety(mode == .debug);
18201820
1821 out1[0] = 0x67ffffffb8000000;1821 out1[0] = 0x67ffffffb8000000;
1822 out1[1] = 0xc000000038000000;1822 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 {...@@ -110,7 +110,7 @@ fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
110/// out1: [0x0 ~> 0xffffffffffffffff]110/// out1: [0x0 ~> 0xffffffffffffffff]
111/// out2: [0x0 ~> 0xffffffffffffffff]111/// out2: [0x0 ~> 0xffffffffffffffff]
112fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {112fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
113 @setRuntimeSafety(mode == .Debug);113 @setRuntimeSafety(mode == .debug);
114114
115 const x = @as(u128, arg1) * @as(u128, arg2);115 const x = @as(u128, arg1) * @as(u128, arg2);
116 out1.* = @as(u64, @truncate(x));116 out1.* = @as(u64, @truncate(x));
...@@ -129,7 +129,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {...@@ -129,7 +129,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
129/// Output Bounds:129/// Output Bounds:
130/// out1: [0x0 ~> 0xffffffffffffffff]130/// out1: [0x0 ~> 0xffffffffffffffff]
131fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {131fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
132 @setRuntimeSafety(mode == .Debug);132 @setRuntimeSafety(mode == .debug);
133133
134 const mask = 0 -% @as(u64, arg1);134 const mask = 0 -% @as(u64, arg1);
135 out1.* = (mask & arg3) | ((~mask) & arg2);135 out1.* = (mask & arg3) | ((~mask) & arg2);
...@@ -145,7 +145,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {...@@ -145,7 +145,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
145/// 0 ≤ eval out1 < m145/// 0 ≤ eval out1 < m
146///146///
147pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {147pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
148 @setRuntimeSafety(mode == .Debug);148 @setRuntimeSafety(mode == .debug);
149149
150 const x1 = (arg1[1]);150 const x1 = (arg1[1]);
151 const x2 = (arg1[2]);151 const x2 = (arg1[2]);
...@@ -485,7 +485,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -485,7 +485,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
485/// 0 ≤ eval out1 < m485/// 0 ≤ eval out1 < m
486///486///
487pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {487pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
488 @setRuntimeSafety(mode == .Debug);488 @setRuntimeSafety(mode == .debug);
489489
490 const x1 = (arg1[1]);490 const x1 = (arg1[1]);
491 const x2 = (arg1[2]);491 const x2 = (arg1[2]);
...@@ -826,7 +826,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl...@@ -826,7 +826,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl
826/// 0 ≤ eval out1 < m826/// 0 ≤ eval out1 < m
827///827///
828pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {828pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
829 @setRuntimeSafety(mode == .Debug);829 @setRuntimeSafety(mode == .debug);
830830
831 var x1: u64 = undefined;831 var x1: u64 = undefined;
832 var x2: u1 = undefined;832 var x2: u1 = undefined;
...@@ -879,7 +879,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -879,7 +879,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
879/// 0 ≤ eval out1 < m879/// 0 ≤ eval out1 < m
880///880///
881pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {881pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
882 @setRuntimeSafety(mode == .Debug);882 @setRuntimeSafety(mode == .debug);
883883
884 var x1: u64 = undefined;884 var x1: u64 = undefined;
885 var x2: u1 = undefined;885 var x2: u1 = undefined;
...@@ -922,7 +922,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -922,7 +922,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
922/// 0 ≤ eval out1 < m922/// 0 ≤ eval out1 < m
923///923///
924pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {924pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
925 @setRuntimeSafety(mode == .Debug);925 @setRuntimeSafety(mode == .debug);
926926
927 var x1: u64 = undefined;927 var x1: u64 = undefined;
928 var x2: u1 = undefined;928 var x2: u1 = undefined;
...@@ -965,7 +965,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -965,7 +965,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
965/// 0 ≤ eval out1 < m965/// 0 ≤ eval out1 < m
966///966///
967pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {967pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
968 @setRuntimeSafety(mode == .Debug);968 @setRuntimeSafety(mode == .debug);
969969
970 const x1 = (arg1[0]);970 const x1 = (arg1[0]);
971 var x2: u64 = undefined;971 var x2: u64 = undefined;
...@@ -1178,7 +1178,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo...@@ -1178,7 +1178,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo
1178/// 0 ≤ eval out1 < m1178/// 0 ≤ eval out1 < m
1179///1179///
1180pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void {1180pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void {
1181 @setRuntimeSafety(mode == .Debug);1181 @setRuntimeSafety(mode == .debug);
11821182
1183 const x1 = (arg1[1]);1183 const x1 = (arg1[1]);
1184 const x2 = (arg1[2]);1184 const x2 = (arg1[2]);
...@@ -1501,7 +1501,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma...@@ -1501,7 +1501,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma
1501/// Output Bounds:1501/// Output Bounds:
1502/// out1: [0x0 ~> 0xffffffffffffffff]1502/// out1: [0x0 ~> 0xffffffffffffffff]
1503pub fn nonzero(out1: *u64, arg1: [4]u64) void {1503pub fn nonzero(out1: *u64, arg1: [4]u64) void {
1504 @setRuntimeSafety(mode == .Debug);1504 @setRuntimeSafety(mode == .debug);
15051505
1506 const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3]))));1506 const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3]))));
1507 out1.* = x1;1507 out1.* = x1;
...@@ -1519,7 +1519,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void {...@@ -1519,7 +1519,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void {
1519/// Output Bounds:1519/// Output Bounds:
1520/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1520/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1521pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void {1521pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void {
1522 @setRuntimeSafety(mode == .Debug);1522 @setRuntimeSafety(mode == .debug);
15231523
1524 var x1: u64 = undefined;1524 var x1: u64 = undefined;
1525 cmovznzU64(&x1, arg1, (arg2[0]), (arg3[0]));1525 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 {...@@ -1547,7 +1547,7 @@ pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void {
1547/// Output Bounds:1547/// Output Bounds:
1548/// 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]]1548/// 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]]
1549pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {1549pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {
1550 @setRuntimeSafety(mode == .Debug);1550 @setRuntimeSafety(mode == .debug);
15511551
1552 const x1 = (arg1[3]);1552 const x1 = (arg1[3]);
1553 const x2 = (arg1[2]);1553 const x2 = (arg1[2]);
...@@ -1656,7 +1656,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {...@@ -1656,7 +1656,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {
1656/// Output Bounds:1656/// Output Bounds:
1657/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1657/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1658pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {1658pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {
1659 @setRuntimeSafety(mode == .Debug);1659 @setRuntimeSafety(mode == .debug);
16601660
1661 const x1 = (@as(u64, (arg1[31])) << 56);1661 const x1 = (@as(u64, (arg1[31])) << 56);
1662 const x2 = (@as(u64, (arg1[30])) << 48);1662 const x2 = (@as(u64, (arg1[30])) << 48);
...@@ -1731,7 +1731,7 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {...@@ -1731,7 +1731,7 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {
1731/// 0 ≤ eval out1 < m1731/// 0 ≤ eval out1 < m
1732///1732///
1733pub fn setOne(out1: *MontgomeryDomainFieldElement) void {1733pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
1734 @setRuntimeSafety(mode == .Debug);1734 @setRuntimeSafety(mode == .debug);
17351735
1736 out1[0] = 0xc46353d039cdaaf;1736 out1[0] = 0xc46353d039cdaaf;
1737 out1[1] = 0x4319055258e8617b;1737 out1[1] = 0x4319055258e8617b;
...@@ -1748,7 +1748,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void {...@@ -1748,7 +1748,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
1748/// Output Bounds:1748/// Output Bounds:
1749/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1749/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1750pub fn msat(out1: *[5]u64) void {1750pub fn msat(out1: *[5]u64) void {
1751 @setRuntimeSafety(mode == .Debug);1751 @setRuntimeSafety(mode == .debug);
17521752
1753 out1[0] = 0xf3b9cac2fc632551;1753 out1[0] = 0xf3b9cac2fc632551;
1754 out1[1] = 0xbce6faada7179e84;1754 out1[1] = 0xbce6faada7179e84;
...@@ -1786,7 +1786,7 @@ pub fn msat(out1: *[5]u64) void {...@@ -1786,7 +1786,7 @@ pub fn msat(out1: *[5]u64) void {
1786/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1786/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1787/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1787/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1788pub 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 {1788pub 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
1791 var x1: u64 = undefined;1791 var x1: u64 = undefined;
1792 var x2: u1 = undefined;1792 var x2: u1 = undefined;
...@@ -2020,7 +2020,7 @@ pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[...@@ -2020,7 +2020,7 @@ pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[
2020/// Output Bounds:2020/// Output Bounds:
2021/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]2021/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
2022pub fn divstepPrecomp(out1: *[4]u64) void {2022pub fn divstepPrecomp(out1: *[4]u64) void {
2023 @setRuntimeSafety(mode == .Debug);2023 @setRuntimeSafety(mode == .debug);
20242024
2025 out1[0] = 0xd739262fb7fcfbb5;2025 out1[0] = 0xd739262fb7fcfbb5;
2026 out1[1] = 0x8ac6f75d20074414;2026 out1[1] = 0x8ac6f75d20074414;
lib/std/crypto/pcurves/p384.zig+4-6
...@@ -56,7 +56,7 @@ pub const P384 = struct {...@@ -56,7 +56,7 @@ pub const P384 = struct {
56 }56 }
5757
58 /// Create a point from serialized affine coordinates.58 /// 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 {
60 const x = try Fe.fromBytes(xs, endian);60 const x = try Fe.fromBytes(xs, endian);
61 const y = try Fe.fromBytes(ys, endian);61 const y = try Fe.fromBytes(ys, endian);
62 return fromAffineCoordinates(.{ .x = x, .y = y });62 return fromAffineCoordinates(.{ .x = x, .y = y });
...@@ -395,7 +395,7 @@ pub const P384 = struct {...@@ -395,7 +395,7 @@ pub const P384 = struct {
395395
396 /// Multiply an elliptic curve point by a scalar.396 /// Multiply an elliptic curve point by a scalar.
397 /// Return error.IdentityElement if the result is the identity element.397 /// 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 {
399 const s = if (endian == .little) s_ else Fe.orderSwap(s_);399 const s = if (endian == .little) s_ else Fe.orderSwap(s_);
400 if (p.is_base) {400 if (p.is_base) {
401 return pcMul16(&basePointPc, s, false);401 return pcMul16(&basePointPc, s, false);
...@@ -407,7 +407,7 @@ pub const P384 = struct {...@@ -407,7 +407,7 @@ pub const P384 = struct {
407407
408 /// Multiply an elliptic curve point by a *PUBLIC* scalar *IN VARIABLE TIME*408 /// Multiply an elliptic curve point by a *PUBLIC* scalar *IN VARIABLE TIME*
409 /// This can be used for signature verification.409 /// 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 {
411 const s = if (endian == .little) s_ else Fe.orderSwap(s_);411 const s = if (endian == .little) s_ else Fe.orderSwap(s_);
412 if (p.is_base) {412 if (p.is_base) {
413 return pcMul16(&basePointPc, s, true);413 return pcMul16(&basePointPc, s, true);
...@@ -419,7 +419,7 @@ pub const P384 = struct {...@@ -419,7 +419,7 @@ pub const P384 = struct {
419419
420 /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME*420 /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME*
421 /// This can be used for signature verification.421 /// 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 {
423 const s1 = if (endian == .little) s1_ else Fe.orderSwap(s1_);423 const s1 = if (endian == .little) s1_ else Fe.orderSwap(s1_);
424 const s2 = if (endian == .little) s2_ else Fe.orderSwap(s2_);424 const s2 = if (endian == .little) s2_ else Fe.orderSwap(s2_);
425 try p1.rejectIdentity();425 try p1.rejectIdentity();
...@@ -478,7 +478,5 @@ pub const AffineCoordinates = struct {...@@ -478,7 +478,5 @@ pub const AffineCoordinates = struct {
478};478};
479479
480test {480test {
481 if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest;
482
483 _ = @import("tests/p384.zig");481 _ = @import("tests/p384.zig");
484}482}
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 {...@@ -79,7 +79,7 @@ fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
79/// out1: [0x0 ~> 0xffffffffffffffff]79/// out1: [0x0 ~> 0xffffffffffffffff]
80/// out2: [0x0 ~> 0xffffffffffffffff]80/// out2: [0x0 ~> 0xffffffffffffffff]
81fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {81fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
82 @setRuntimeSafety(mode == .Debug);82 @setRuntimeSafety(mode == .debug);
8383
84 const x = @as(u128, arg1) * @as(u128, arg2);84 const x = @as(u128, arg1) * @as(u128, arg2);
85 out1.* = @as(u64, @truncate(x));85 out1.* = @as(u64, @truncate(x));
...@@ -98,7 +98,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {...@@ -98,7 +98,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
98/// Output Bounds:98/// Output Bounds:
99/// out1: [0x0 ~> 0xffffffffffffffff]99/// out1: [0x0 ~> 0xffffffffffffffff]
100fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {100fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
101 @setRuntimeSafety(mode == .Debug);101 @setRuntimeSafety(mode == .debug);
102102
103 const mask = 0 -% @as(u64, arg1);103 const mask = 0 -% @as(u64, arg1);
104 out1.* = (mask & arg3) | ((~mask) & arg2);104 out1.* = (mask & arg3) | ((~mask) & arg2);
...@@ -114,7 +114,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {...@@ -114,7 +114,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
114/// 0 ≤ eval out1 < m114/// 0 ≤ eval out1 < m
115///115///
116pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {116pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
117 @setRuntimeSafety(mode == .Debug);117 @setRuntimeSafety(mode == .debug);
118118
119 const x1 = (arg1[1]);119 const x1 = (arg1[1]);
120 const x2 = (arg1[2]);120 const x2 = (arg1[2]);
...@@ -834,7 +834,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -834,7 +834,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
834/// 0 ≤ eval out1 < m834/// 0 ≤ eval out1 < m
835///835///
836pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {836pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
837 @setRuntimeSafety(mode == .Debug);837 @setRuntimeSafety(mode == .debug);
838838
839 const x1 = (arg1[1]);839 const x1 = (arg1[1]);
840 const x2 = (arg1[2]);840 const x2 = (arg1[2]);
...@@ -1555,7 +1555,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl...@@ -1555,7 +1555,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl
1555/// 0 ≤ eval out1 < m1555/// 0 ≤ eval out1 < m
1556///1556///
1557pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {1557pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
1558 @setRuntimeSafety(mode == .Debug);1558 @setRuntimeSafety(mode == .debug);
15591559
1560 var x1: u64 = undefined;1560 var x1: u64 = undefined;
1561 var x2: u1 = undefined;1561 var x2: u1 = undefined;
...@@ -1626,7 +1626,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -1626,7 +1626,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
1626/// 0 ≤ eval out1 < m1626/// 0 ≤ eval out1 < m
1627///1627///
1628pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {1628pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
1629 @setRuntimeSafety(mode == .Debug);1629 @setRuntimeSafety(mode == .debug);
16301630
1631 var x1: u64 = undefined;1631 var x1: u64 = undefined;
1632 var x2: u1 = undefined;1632 var x2: u1 = undefined;
...@@ -1683,7 +1683,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -1683,7 +1683,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
1683/// 0 ≤ eval out1 < m1683/// 0 ≤ eval out1 < m
1684///1684///
1685pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {1685pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
1686 @setRuntimeSafety(mode == .Debug);1686 @setRuntimeSafety(mode == .debug);
16871687
1688 var x1: u64 = undefined;1688 var x1: u64 = undefined;
1689 var x2: u1 = undefined;1689 var x2: u1 = undefined;
...@@ -1740,7 +1740,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -1740,7 +1740,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
1740/// 0 ≤ eval out1 < m1740/// 0 ≤ eval out1 < m
1741///1741///
1742pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {1742pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
1743 @setRuntimeSafety(mode == .Debug);1743 @setRuntimeSafety(mode == .debug);
17441744
1745 const x1 = (arg1[0]);1745 const x1 = (arg1[0]);
1746 var x2: u64 = undefined;1746 var x2: u64 = undefined;
...@@ -2225,7 +2225,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo...@@ -2225,7 +2225,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo
2225/// 0 ≤ eval out1 < m2225/// 0 ≤ eval out1 < m
2226///2226///
2227pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void {2227pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void {
2228 @setRuntimeSafety(mode == .Debug);2228 @setRuntimeSafety(mode == .debug);
22292229
2230 const x1 = (arg1[1]);2230 const x1 = (arg1[1]);
2231 const x2 = (arg1[2]);2231 const x2 = (arg1[2]);
...@@ -2862,7 +2862,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma...@@ -2862,7 +2862,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma
2862/// Output Bounds:2862/// Output Bounds:
2863/// out1: [0x0 ~> 0xffffffffffffffff]2863/// out1: [0x0 ~> 0xffffffffffffffff]
2864pub fn nonzero(out1: *u64, arg1: [6]u64) void {2864pub fn nonzero(out1: *u64, arg1: [6]u64) void {
2865 @setRuntimeSafety(mode == .Debug);2865 @setRuntimeSafety(mode == .debug);
28662866
2867 const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | ((arg1[3]) | ((arg1[4]) | (arg1[5]))))));2867 const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | ((arg1[3]) | ((arg1[4]) | (arg1[5]))))));
2868 out1.* = x1;2868 out1.* = x1;
...@@ -2880,7 +2880,7 @@ pub fn nonzero(out1: *u64, arg1: [6]u64) void {...@@ -2880,7 +2880,7 @@ pub fn nonzero(out1: *u64, arg1: [6]u64) void {
2880/// Output Bounds:2880/// Output Bounds:
2881/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]2881/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
2882pub fn selectznz(out1: *[6]u64, arg1: u1, arg2: [6]u64, arg3: [6]u64) void {2882pub fn selectznz(out1: *[6]u64, arg1: u1, arg2: [6]u64, arg3: [6]u64) void {
2883 @setRuntimeSafety(mode == .Debug);2883 @setRuntimeSafety(mode == .debug);
28842884
2885 var x1: u64 = undefined;2885 var x1: u64 = undefined;
2886 cmovznzU64(&x1, arg1, (arg2[0]), (arg3[0]));2886 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 {...@@ -2914,7 +2914,7 @@ pub fn selectznz(out1: *[6]u64, arg1: u1, arg2: [6]u64, arg3: [6]u64) void {
2914/// Output Bounds:2914/// Output Bounds:
2915/// 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]]2915/// 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]]
2916pub fn toBytes(out1: *[48]u8, arg1: [6]u64) void {2916pub fn toBytes(out1: *[48]u8, arg1: [6]u64) void {
2917 @setRuntimeSafety(mode == .Debug);2917 @setRuntimeSafety(mode == .debug);
29182918
2919 const x1 = (arg1[5]);2919 const x1 = (arg1[5]);
2920 const x2 = (arg1[4]);2920 const x2 = (arg1[4]);
...@@ -3069,7 +3069,7 @@ pub fn toBytes(out1: *[48]u8, arg1: [6]u64) void {...@@ -3069,7 +3069,7 @@ pub fn toBytes(out1: *[48]u8, arg1: [6]u64) void {
3069/// Output Bounds:3069/// Output Bounds:
3070/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]3070/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
3071pub fn fromBytes(out1: *[6]u64, arg1: [48]u8) void {3071pub fn fromBytes(out1: *[6]u64, arg1: [48]u8) void {
3072 @setRuntimeSafety(mode == .Debug);3072 @setRuntimeSafety(mode == .debug);
30733073
3074 const x1 = (@as(u64, (arg1[47])) << 56);3074 const x1 = (@as(u64, (arg1[47])) << 56);
3075 const x2 = (@as(u64, (arg1[46])) << 48);3075 const x2 = (@as(u64, (arg1[46])) << 48);
...@@ -3176,7 +3176,7 @@ pub fn fromBytes(out1: *[6]u64, arg1: [48]u8) void {...@@ -3176,7 +3176,7 @@ pub fn fromBytes(out1: *[6]u64, arg1: [48]u8) void {
3176/// 0 ≤ eval out1 < m3176/// 0 ≤ eval out1 < m
3177///3177///
3178pub fn setOne(out1: *MontgomeryDomainFieldElement) void {3178pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
3179 @setRuntimeSafety(mode == .Debug);3179 @setRuntimeSafety(mode == .debug);
31803180
3181 out1[0] = 0xffffffff00000001;3181 out1[0] = 0xffffffff00000001;
3182 out1[1] = 0xffffffff;3182 out1[1] = 0xffffffff;
...@@ -3195,7 +3195,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void {...@@ -3195,7 +3195,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
3195/// Output Bounds:3195/// Output Bounds:
3196/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]3196/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
3197pub fn msat(out1: *[7]u64) void {3197pub fn msat(out1: *[7]u64) void {
3198 @setRuntimeSafety(mode == .Debug);3198 @setRuntimeSafety(mode == .debug);
31993199
3200 out1[0] = 0xffffffff;3200 out1[0] = 0xffffffff;
3201 out1[1] = 0xffffffff00000000;3201 out1[1] = 0xffffffff00000000;
...@@ -3235,7 +3235,7 @@ pub fn msat(out1: *[7]u64) void {...@@ -3235,7 +3235,7 @@ pub fn msat(out1: *[7]u64) void {
3235/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]3235/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
3236/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]3236/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
3237pub 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 {3237pub 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
3240 var x1: u64 = undefined;3240 var x1: u64 = undefined;
3241 var x2: u1 = undefined;3241 var x2: u1 = undefined;
...@@ -3561,7 +3561,7 @@ pub fn divstep(out1: *u64, out2: *[7]u64, out3: *[7]u64, out4: *[6]u64, out5: *[...@@ -3561,7 +3561,7 @@ pub fn divstep(out1: *u64, out2: *[7]u64, out3: *[7]u64, out4: *[6]u64, out5: *[
3561/// Output Bounds:3561/// Output Bounds:
3562/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]3562/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
3563pub fn divstepPrecomp(out1: *[6]u64) void {3563pub fn divstepPrecomp(out1: *[6]u64) void {
3564 @setRuntimeSafety(mode == .Debug);3564 @setRuntimeSafety(mode == .debug);
35653565
3566 out1[0] = 0xfff69400fff18fff;3566 out1[0] = 0xfff69400fff18fff;
3567 out1[1] = 0x2b7feffffd3ff;3567 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 {...@@ -79,7 +79,7 @@ fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
79/// out1: [0x0 ~> 0xffffffffffffffff]79/// out1: [0x0 ~> 0xffffffffffffffff]
80/// out2: [0x0 ~> 0xffffffffffffffff]80/// out2: [0x0 ~> 0xffffffffffffffff]
81fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {81fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
82 @setRuntimeSafety(mode == .Debug);82 @setRuntimeSafety(mode == .debug);
8383
84 const x = @as(u128, arg1) * @as(u128, arg2);84 const x = @as(u128, arg1) * @as(u128, arg2);
85 out1.* = @as(u64, @truncate(x));85 out1.* = @as(u64, @truncate(x));
...@@ -98,7 +98,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {...@@ -98,7 +98,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
98/// Output Bounds:98/// Output Bounds:
99/// out1: [0x0 ~> 0xffffffffffffffff]99/// out1: [0x0 ~> 0xffffffffffffffff]
100fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {100fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
101 @setRuntimeSafety(mode == .Debug);101 @setRuntimeSafety(mode == .debug);
102102
103 const mask = 0 -% @as(u64, arg1);103 const mask = 0 -% @as(u64, arg1);
104 out1.* = (mask & arg3) | ((~mask) & arg2);104 out1.* = (mask & arg3) | ((~mask) & arg2);
...@@ -114,7 +114,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {...@@ -114,7 +114,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
114/// 0 ≤ eval out1 < m114/// 0 ≤ eval out1 < m
115///115///
116pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {116pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
117 @setRuntimeSafety(mode == .Debug);117 @setRuntimeSafety(mode == .debug);
118118
119 const x1 = (arg1[1]);119 const x1 = (arg1[1]);
120 const x2 = (arg1[2]);120 const x2 = (arg1[2]);
...@@ -834,7 +834,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -834,7 +834,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
834/// 0 ≤ eval out1 < m834/// 0 ≤ eval out1 < m
835///835///
836pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {836pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
837 @setRuntimeSafety(mode == .Debug);837 @setRuntimeSafety(mode == .debug);
838838
839 const x1 = (arg1[1]);839 const x1 = (arg1[1]);
840 const x2 = (arg1[2]);840 const x2 = (arg1[2]);
...@@ -1555,7 +1555,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl...@@ -1555,7 +1555,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl
1555/// 0 ≤ eval out1 < m1555/// 0 ≤ eval out1 < m
1556///1556///
1557pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {1557pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
1558 @setRuntimeSafety(mode == .Debug);1558 @setRuntimeSafety(mode == .debug);
15591559
1560 var x1: u64 = undefined;1560 var x1: u64 = undefined;
1561 var x2: u1 = undefined;1561 var x2: u1 = undefined;
...@@ -1626,7 +1626,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -1626,7 +1626,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
1626/// 0 ≤ eval out1 < m1626/// 0 ≤ eval out1 < m
1627///1627///
1628pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {1628pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
1629 @setRuntimeSafety(mode == .Debug);1629 @setRuntimeSafety(mode == .debug);
16301630
1631 var x1: u64 = undefined;1631 var x1: u64 = undefined;
1632 var x2: u1 = undefined;1632 var x2: u1 = undefined;
...@@ -1683,7 +1683,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -1683,7 +1683,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
1683/// 0 ≤ eval out1 < m1683/// 0 ≤ eval out1 < m
1684///1684///
1685pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {1685pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
1686 @setRuntimeSafety(mode == .Debug);1686 @setRuntimeSafety(mode == .debug);
16871687
1688 var x1: u64 = undefined;1688 var x1: u64 = undefined;
1689 var x2: u1 = undefined;1689 var x2: u1 = undefined;
...@@ -1740,7 +1740,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -1740,7 +1740,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
1740/// 0 ≤ eval out1 < m1740/// 0 ≤ eval out1 < m
1741///1741///
1742pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {1742pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
1743 @setRuntimeSafety(mode == .Debug);1743 @setRuntimeSafety(mode == .debug);
17441744
1745 const x1 = (arg1[0]);1745 const x1 = (arg1[0]);
1746 var x2: u64 = undefined;1746 var x2: u64 = undefined;
...@@ -2225,7 +2225,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo...@@ -2225,7 +2225,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo
2225/// 0 ≤ eval out1 < m2225/// 0 ≤ eval out1 < m
2226///2226///
2227pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void {2227pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void {
2228 @setRuntimeSafety(mode == .Debug);2228 @setRuntimeSafety(mode == .debug);
22292229
2230 const x1 = (arg1[1]);2230 const x1 = (arg1[1]);
2231 const x2 = (arg1[2]);2231 const x2 = (arg1[2]);
...@@ -2916,7 +2916,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma...@@ -2916,7 +2916,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma
2916/// Output Bounds:2916/// Output Bounds:
2917/// out1: [0x0 ~> 0xffffffffffffffff]2917/// out1: [0x0 ~> 0xffffffffffffffff]
2918pub fn nonzero(out1: *u64, arg1: [6]u64) void {2918pub fn nonzero(out1: *u64, arg1: [6]u64) void {
2919 @setRuntimeSafety(mode == .Debug);2919 @setRuntimeSafety(mode == .debug);
29202920
2921 const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | ((arg1[3]) | ((arg1[4]) | (arg1[5]))))));2921 const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | ((arg1[3]) | ((arg1[4]) | (arg1[5]))))));
2922 out1.* = x1;2922 out1.* = x1;
...@@ -2934,7 +2934,7 @@ pub fn nonzero(out1: *u64, arg1: [6]u64) void {...@@ -2934,7 +2934,7 @@ pub fn nonzero(out1: *u64, arg1: [6]u64) void {
2934/// Output Bounds:2934/// Output Bounds:
2935/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]2935/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
2936pub fn selectznz(out1: *[6]u64, arg1: u1, arg2: [6]u64, arg3: [6]u64) void {2936pub fn selectznz(out1: *[6]u64, arg1: u1, arg2: [6]u64, arg3: [6]u64) void {
2937 @setRuntimeSafety(mode == .Debug);2937 @setRuntimeSafety(mode == .debug);
29382938
2939 var x1: u64 = undefined;2939 var x1: u64 = undefined;
2940 cmovznzU64(&x1, arg1, (arg2[0]), (arg3[0]));2940 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 {...@@ -2968,7 +2968,7 @@ pub fn selectznz(out1: *[6]u64, arg1: u1, arg2: [6]u64, arg3: [6]u64) void {
2968/// Output Bounds:2968/// Output Bounds:
2969/// 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]]2969/// 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]]
2970pub fn toBytes(out1: *[48]u8, arg1: [6]u64) void {2970pub fn toBytes(out1: *[48]u8, arg1: [6]u64) void {
2971 @setRuntimeSafety(mode == .Debug);2971 @setRuntimeSafety(mode == .debug);
29722972
2973 const x1 = (arg1[5]);2973 const x1 = (arg1[5]);
2974 const x2 = (arg1[4]);2974 const x2 = (arg1[4]);
...@@ -3123,7 +3123,7 @@ pub fn toBytes(out1: *[48]u8, arg1: [6]u64) void {...@@ -3123,7 +3123,7 @@ pub fn toBytes(out1: *[48]u8, arg1: [6]u64) void {
3123/// Output Bounds:3123/// Output Bounds:
3124/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]3124/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
3125pub fn fromBytes(out1: *[6]u64, arg1: [48]u8) void {3125pub fn fromBytes(out1: *[6]u64, arg1: [48]u8) void {
3126 @setRuntimeSafety(mode == .Debug);3126 @setRuntimeSafety(mode == .debug);
31273127
3128 const x1 = (@as(u64, (arg1[47])) << 56);3128 const x1 = (@as(u64, (arg1[47])) << 56);
3129 const x2 = (@as(u64, (arg1[46])) << 48);3129 const x2 = (@as(u64, (arg1[46])) << 48);
...@@ -3230,7 +3230,7 @@ pub fn fromBytes(out1: *[6]u64, arg1: [48]u8) void {...@@ -3230,7 +3230,7 @@ pub fn fromBytes(out1: *[6]u64, arg1: [48]u8) void {
3230/// 0 ≤ eval out1 < m3230/// 0 ≤ eval out1 < m
3231///3231///
3232pub fn setOne(out1: *MontgomeryDomainFieldElement) void {3232pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
3233 @setRuntimeSafety(mode == .Debug);3233 @setRuntimeSafety(mode == .debug);
32343234
3235 out1[0] = 0x1313e695333ad68d;3235 out1[0] = 0x1313e695333ad68d;
3236 out1[1] = 0xa7e5f24db74f5885;3236 out1[1] = 0xa7e5f24db74f5885;
...@@ -3249,7 +3249,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void {...@@ -3249,7 +3249,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
3249/// Output Bounds:3249/// Output Bounds:
3250/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]3250/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
3251pub fn msat(out1: *[7]u64) void {3251pub fn msat(out1: *[7]u64) void {
3252 @setRuntimeSafety(mode == .Debug);3252 @setRuntimeSafety(mode == .debug);
32533253
3254 out1[0] = 0xecec196accc52973;3254 out1[0] = 0xecec196accc52973;
3255 out1[1] = 0x581a0db248b0a77a;3255 out1[1] = 0x581a0db248b0a77a;
...@@ -3289,7 +3289,7 @@ pub fn msat(out1: *[7]u64) void {...@@ -3289,7 +3289,7 @@ pub fn msat(out1: *[7]u64) void {
3289/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]3289/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
3290/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]3290/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
3291pub 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 {3291pub 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
3294 var x1: u64 = undefined;3294 var x1: u64 = undefined;
3295 var x2: u1 = undefined;3295 var x2: u1 = undefined;
...@@ -3615,7 +3615,7 @@ pub fn divstep(out1: *u64, out2: *[7]u64, out3: *[7]u64, out4: *[6]u64, out5: *[...@@ -3615,7 +3615,7 @@ pub fn divstep(out1: *u64, out2: *[7]u64, out3: *[7]u64, out4: *[6]u64, out5: *[
3615/// Output Bounds:3615/// Output Bounds:
3616/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]3616/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
3617pub fn divstepPrecomp(out1: *[6]u64) void {3617pub fn divstepPrecomp(out1: *[6]u64) void {
3618 @setRuntimeSafety(mode == .Debug);3618 @setRuntimeSafety(mode == .debug);
36193619
3620 out1[0] = 0x49589ae0e6045b6a;3620 out1[0] = 0x49589ae0e6045b6a;
3621 out1[1] = 0x3c9a5352870040ed;3621 out1[1] = 0x3c9a5352870040ed;
lib/std/crypto/pcurves/secp256k1.zig+5-7
...@@ -51,7 +51,7 @@ pub const Secp256k1 = struct {...@@ -51,7 +51,7 @@ pub const Secp256k1 = struct {
51 };51 };
5252
53 /// Compute r1 and r2 so that k = r1 + r2*lambda (mod L).53 /// 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 {
55 const b1_neg_s = comptime s: {55 const b1_neg_s = comptime s: {
56 var buf: [32]u8 = undefined;56 var buf: [32]u8 = undefined;
57 mem.writeInt(u256, &buf, 303414439467246543595250775667605759171, .little);57 mem.writeInt(u256, &buf, 303414439467246543595250775667605759171, .little);
...@@ -109,7 +109,7 @@ pub const Secp256k1 = struct {...@@ -109,7 +109,7 @@ pub const Secp256k1 = struct {
109 }109 }
110110
111 /// Create a point from serialized affine coordinates.111 /// 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 {
113 const x = try Fe.fromBytes(xs, endian);113 const x = try Fe.fromBytes(xs, endian);
114 const y = try Fe.fromBytes(ys, endian);114 const y = try Fe.fromBytes(ys, endian);
115 return fromAffineCoordinates(.{ .x = x, .y = y });115 return fromAffineCoordinates(.{ .x = x, .y = y });
...@@ -423,7 +423,7 @@ pub const Secp256k1 = struct {...@@ -423,7 +423,7 @@ pub const Secp256k1 = struct {
423423
424 /// Multiply an elliptic curve point by a scalar.424 /// Multiply an elliptic curve point by a scalar.
425 /// Return error.IdentityElement if the result is the identity element.425 /// 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 {
427 const s = if (endian == .little) s_ else Fe.orderSwap(s_);427 const s = if (endian == .little) s_ else Fe.orderSwap(s_);
428 if (p.is_base) {428 if (p.is_base) {
429 return pcMul16(&basePointPc, s, false);429 return pcMul16(&basePointPc, s, false);
...@@ -435,7 +435,7 @@ pub const Secp256k1 = struct {...@@ -435,7 +435,7 @@ pub const Secp256k1 = struct {
435435
436 /// Multiply an elliptic curve point by a *PUBLIC* scalar *IN VARIABLE TIME*436 /// Multiply an elliptic curve point by a *PUBLIC* scalar *IN VARIABLE TIME*
437 /// This can be used for signature verification.437 /// 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 {
439 const s = if (endian == .little) s_ else Fe.orderSwap(s_);439 const s = if (endian == .little) s_ else Fe.orderSwap(s_);
440 const zero = comptime scalar.Scalar.zero.toBytes(.little);440 const zero = comptime scalar.Scalar.zero.toBytes(.little);
441 if (mem.eql(u8, &zero, &s)) {441 if (mem.eql(u8, &zero, &s)) {
...@@ -497,7 +497,7 @@ pub const Secp256k1 = struct {...@@ -497,7 +497,7 @@ pub const Secp256k1 = struct {
497497
498 /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME*498 /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME*
499 /// This can be used for signature verification.499 /// 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 {
501 const s1 = if (endian == .little) s1_ else Fe.orderSwap(s1_);501 const s1 = if (endian == .little) s1_ else Fe.orderSwap(s1_);
502 const s2 = if (endian == .little) s2_ else Fe.orderSwap(s2_);502 const s2 = if (endian == .little) s2_ else Fe.orderSwap(s2_);
503 try p1.rejectIdentity();503 try p1.rejectIdentity();
...@@ -556,7 +556,5 @@ pub const AffineCoordinates = struct {...@@ -556,7 +556,5 @@ pub const AffineCoordinates = struct {
556};556};
557557
558test {558test {
559 if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest;
560
561 _ = @import("tests/secp256k1.zig");559 _ = @import("tests/secp256k1.zig");
562}560}
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 {...@@ -79,7 +79,7 @@ fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
79/// out1: [0x0 ~> 0xffffffffffffffff]79/// out1: [0x0 ~> 0xffffffffffffffff]
80/// out2: [0x0 ~> 0xffffffffffffffff]80/// out2: [0x0 ~> 0xffffffffffffffff]
81fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {81fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
82 @setRuntimeSafety(mode == .Debug);82 @setRuntimeSafety(mode == .debug);
8383
84 const x = @as(u128, arg1) * @as(u128, arg2);84 const x = @as(u128, arg1) * @as(u128, arg2);
85 out1.* = @as(u64, @truncate(x));85 out1.* = @as(u64, @truncate(x));
...@@ -98,7 +98,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {...@@ -98,7 +98,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
98/// Output Bounds:98/// Output Bounds:
99/// out1: [0x0 ~> 0xffffffffffffffff]99/// out1: [0x0 ~> 0xffffffffffffffff]
100fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {100fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
101 @setRuntimeSafety(mode == .Debug);101 @setRuntimeSafety(mode == .debug);
102102
103 const mask = 0 -% @as(u64, arg1);103 const mask = 0 -% @as(u64, arg1);
104 out1.* = (mask & arg3) | ((~mask) & arg2);104 out1.* = (mask & arg3) | ((~mask) & arg2);
...@@ -114,7 +114,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {...@@ -114,7 +114,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
114/// 0 ≤ eval out1 < m114/// 0 ≤ eval out1 < m
115///115///
116pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {116pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
117 @setRuntimeSafety(mode == .Debug);117 @setRuntimeSafety(mode == .debug);
118118
119 const x1 = (arg1[1]);119 const x1 = (arg1[1]);
120 const x2 = (arg1[2]);120 const x2 = (arg1[2]);
...@@ -454,7 +454,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -454,7 +454,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
454/// 0 ≤ eval out1 < m454/// 0 ≤ eval out1 < m
455///455///
456pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {456pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
457 @setRuntimeSafety(mode == .Debug);457 @setRuntimeSafety(mode == .debug);
458458
459 const x1 = (arg1[1]);459 const x1 = (arg1[1]);
460 const x2 = (arg1[2]);460 const x2 = (arg1[2]);
...@@ -795,7 +795,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl...@@ -795,7 +795,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl
795/// 0 ≤ eval out1 < m795/// 0 ≤ eval out1 < m
796///796///
797pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {797pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
798 @setRuntimeSafety(mode == .Debug);798 @setRuntimeSafety(mode == .debug);
799799
800 var x1: u64 = undefined;800 var x1: u64 = undefined;
801 var x2: u1 = undefined;801 var x2: u1 = undefined;
...@@ -848,7 +848,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -848,7 +848,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
848/// 0 ≤ eval out1 < m848/// 0 ≤ eval out1 < m
849///849///
850pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {850pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
851 @setRuntimeSafety(mode == .Debug);851 @setRuntimeSafety(mode == .debug);
852852
853 var x1: u64 = undefined;853 var x1: u64 = undefined;
854 var x2: u1 = undefined;854 var x2: u1 = undefined;
...@@ -891,7 +891,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -891,7 +891,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
891/// 0 ≤ eval out1 < m891/// 0 ≤ eval out1 < m
892///892///
893pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {893pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
894 @setRuntimeSafety(mode == .Debug);894 @setRuntimeSafety(mode == .debug);
895895
896 var x1: u64 = undefined;896 var x1: u64 = undefined;
897 var x2: u1 = undefined;897 var x2: u1 = undefined;
...@@ -934,7 +934,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -934,7 +934,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
934/// 0 ≤ eval out1 < m934/// 0 ≤ eval out1 < m
935///935///
936pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {936pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
937 @setRuntimeSafety(mode == .Debug);937 @setRuntimeSafety(mode == .debug);
938938
939 const x1 = (arg1[0]);939 const x1 = (arg1[0]);
940 var x2: u64 = undefined;940 var x2: u64 = undefined;
...@@ -1167,7 +1167,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo...@@ -1167,7 +1167,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo
1167/// 0 ≤ eval out1 < m1167/// 0 ≤ eval out1 < m
1168///1168///
1169pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void {1169pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void {
1170 @setRuntimeSafety(mode == .Debug);1170 @setRuntimeSafety(mode == .debug);
11711171
1172 const x1 = (arg1[1]);1172 const x1 = (arg1[1]);
1173 const x2 = (arg1[2]);1173 const x2 = (arg1[2]);
...@@ -1430,7 +1430,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma...@@ -1430,7 +1430,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma
1430/// Output Bounds:1430/// Output Bounds:
1431/// out1: [0x0 ~> 0xffffffffffffffff]1431/// out1: [0x0 ~> 0xffffffffffffffff]
1432pub fn nonzero(out1: *u64, arg1: [4]u64) void {1432pub fn nonzero(out1: *u64, arg1: [4]u64) void {
1433 @setRuntimeSafety(mode == .Debug);1433 @setRuntimeSafety(mode == .debug);
14341434
1435 const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3]))));1435 const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3]))));
1436 out1.* = x1;1436 out1.* = x1;
...@@ -1448,7 +1448,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void {...@@ -1448,7 +1448,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void {
1448/// Output Bounds:1448/// Output Bounds:
1449/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1449/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1450pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void {1450pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void {
1451 @setRuntimeSafety(mode == .Debug);1451 @setRuntimeSafety(mode == .debug);
14521452
1453 var x1: u64 = undefined;1453 var x1: u64 = undefined;
1454 cmovznzU64(&x1, arg1, (arg2[0]), (arg3[0]));1454 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 {...@@ -1476,7 +1476,7 @@ pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void {
1476/// Output Bounds:1476/// Output Bounds:
1477/// 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]]1477/// 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]]
1478pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {1478pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {
1479 @setRuntimeSafety(mode == .Debug);1479 @setRuntimeSafety(mode == .debug);
14801480
1481 const x1 = (arg1[3]);1481 const x1 = (arg1[3]);
1482 const x2 = (arg1[2]);1482 const x2 = (arg1[2]);
...@@ -1585,7 +1585,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {...@@ -1585,7 +1585,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {
1585/// Output Bounds:1585/// Output Bounds:
1586/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1586/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1587pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {1587pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {
1588 @setRuntimeSafety(mode == .Debug);1588 @setRuntimeSafety(mode == .debug);
15891589
1590 const x1 = (@as(u64, (arg1[31])) << 56);1590 const x1 = (@as(u64, (arg1[31])) << 56);
1591 const x2 = (@as(u64, (arg1[30])) << 48);1591 const x2 = (@as(u64, (arg1[30])) << 48);
...@@ -1660,7 +1660,7 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {...@@ -1660,7 +1660,7 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {
1660/// 0 ≤ eval out1 < m1660/// 0 ≤ eval out1 < m
1661///1661///
1662pub fn setOne(out1: *MontgomeryDomainFieldElement) void {1662pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
1663 @setRuntimeSafety(mode == .Debug);1663 @setRuntimeSafety(mode == .debug);
16641664
1665 out1[0] = 0x1000003d1;1665 out1[0] = 0x1000003d1;
1666 out1[1] = 0x0;1666 out1[1] = 0x0;
...@@ -1677,7 +1677,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void {...@@ -1677,7 +1677,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
1677/// Output Bounds:1677/// Output Bounds:
1678/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1678/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1679pub fn msat(out1: *[5]u64) void {1679pub fn msat(out1: *[5]u64) void {
1680 @setRuntimeSafety(mode == .Debug);1680 @setRuntimeSafety(mode == .debug);
16811681
1682 out1[0] = 0xfffffffefffffc2f;1682 out1[0] = 0xfffffffefffffc2f;
1683 out1[1] = 0xffffffffffffffff;1683 out1[1] = 0xffffffffffffffff;
...@@ -1715,7 +1715,7 @@ pub fn msat(out1: *[5]u64) void {...@@ -1715,7 +1715,7 @@ pub fn msat(out1: *[5]u64) void {
1715/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1715/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1716/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1716/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1717pub 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 {1717pub 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
1720 var x1: u64 = undefined;1720 var x1: u64 = undefined;
1721 var x2: u1 = undefined;1721 var x2: u1 = undefined;
...@@ -1949,7 +1949,7 @@ pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[...@@ -1949,7 +1949,7 @@ pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[
1949/// Output Bounds:1949/// Output Bounds:
1950/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1950/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1951pub fn divstepPrecomp(out1: *[4]u64) void {1951pub fn divstepPrecomp(out1: *[4]u64) void {
1952 @setRuntimeSafety(mode == .Debug);1952 @setRuntimeSafety(mode == .debug);
19531953
1954 out1[0] = 0xf201a41831525e0a;1954 out1[0] = 0xf201a41831525e0a;
1955 out1[1] = 0x9953f9ddcd648d85;1955 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 {...@@ -79,7 +79,7 @@ fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
79/// out1: [0x0 ~> 0xffffffffffffffff]79/// out1: [0x0 ~> 0xffffffffffffffff]
80/// out2: [0x0 ~> 0xffffffffffffffff]80/// out2: [0x0 ~> 0xffffffffffffffff]
81fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {81fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
82 @setRuntimeSafety(mode == .Debug);82 @setRuntimeSafety(mode == .debug);
8383
84 const x = @as(u128, arg1) * @as(u128, arg2);84 const x = @as(u128, arg1) * @as(u128, arg2);
85 out1.* = @as(u64, @truncate(x));85 out1.* = @as(u64, @truncate(x));
...@@ -98,7 +98,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {...@@ -98,7 +98,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void {
98/// Output Bounds:98/// Output Bounds:
99/// out1: [0x0 ~> 0xffffffffffffffff]99/// out1: [0x0 ~> 0xffffffffffffffff]
100fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {100fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
101 @setRuntimeSafety(mode == .Debug);101 @setRuntimeSafety(mode == .debug);
102102
103 const mask = 0 -% @as(u64, arg1);103 const mask = 0 -% @as(u64, arg1);
104 out1.* = (mask & arg3) | ((~mask) & arg2);104 out1.* = (mask & arg3) | ((~mask) & arg2);
...@@ -114,7 +114,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {...@@ -114,7 +114,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void {
114/// 0 ≤ eval out1 < m114/// 0 ≤ eval out1 < m
115///115///
116pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {116pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
117 @setRuntimeSafety(mode == .Debug);117 @setRuntimeSafety(mode == .debug);
118118
119 const x1 = (arg1[1]);119 const x1 = (arg1[1]);
120 const x2 = (arg1[2]);120 const x2 = (arg1[2]);
...@@ -454,7 +454,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -454,7 +454,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
454/// 0 ≤ eval out1 < m454/// 0 ≤ eval out1 < m
455///455///
456pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {456pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
457 @setRuntimeSafety(mode == .Debug);457 @setRuntimeSafety(mode == .debug);
458458
459 const x1 = (arg1[1]);459 const x1 = (arg1[1]);
460 const x2 = (arg1[2]);460 const x2 = (arg1[2]);
...@@ -795,7 +795,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl...@@ -795,7 +795,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl
795/// 0 ≤ eval out1 < m795/// 0 ≤ eval out1 < m
796///796///
797pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {797pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
798 @setRuntimeSafety(mode == .Debug);798 @setRuntimeSafety(mode == .debug);
799799
800 var x1: u64 = undefined;800 var x1: u64 = undefined;
801 var x2: u1 = undefined;801 var x2: u1 = undefined;
...@@ -848,7 +848,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -848,7 +848,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
848/// 0 ≤ eval out1 < m848/// 0 ≤ eval out1 < m
849///849///
850pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {850pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void {
851 @setRuntimeSafety(mode == .Debug);851 @setRuntimeSafety(mode == .debug);
852852
853 var x1: u64 = undefined;853 var x1: u64 = undefined;
854 var x2: u1 = undefined;854 var x2: u1 = undefined;
...@@ -891,7 +891,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -891,7 +891,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
891/// 0 ≤ eval out1 < m891/// 0 ≤ eval out1 < m
892///892///
893pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {893pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
894 @setRuntimeSafety(mode == .Debug);894 @setRuntimeSafety(mode == .debug);
895895
896 var x1: u64 = undefined;896 var x1: u64 = undefined;
897 var x2: u1 = undefined;897 var x2: u1 = undefined;
...@@ -934,7 +934,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme...@@ -934,7 +934,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme
934/// 0 ≤ eval out1 < m934/// 0 ≤ eval out1 < m
935///935///
936pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {936pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void {
937 @setRuntimeSafety(mode == .Debug);937 @setRuntimeSafety(mode == .debug);
938938
939 const x1 = (arg1[0]);939 const x1 = (arg1[0]);
940 var x2: u64 = undefined;940 var x2: u64 = undefined;
...@@ -1167,7 +1167,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo...@@ -1167,7 +1167,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo
1167/// 0 ≤ eval out1 < m1167/// 0 ≤ eval out1 < m
1168///1168///
1169pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void {1169pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void {
1170 @setRuntimeSafety(mode == .Debug);1170 @setRuntimeSafety(mode == .debug);
11711171
1172 const x1 = (arg1[1]);1172 const x1 = (arg1[1]);
1173 const x2 = (arg1[2]);1173 const x2 = (arg1[2]);
...@@ -1490,7 +1490,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma...@@ -1490,7 +1490,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma
1490/// Output Bounds:1490/// Output Bounds:
1491/// out1: [0x0 ~> 0xffffffffffffffff]1491/// out1: [0x0 ~> 0xffffffffffffffff]
1492pub fn nonzero(out1: *u64, arg1: [4]u64) void {1492pub fn nonzero(out1: *u64, arg1: [4]u64) void {
1493 @setRuntimeSafety(mode == .Debug);1493 @setRuntimeSafety(mode == .debug);
14941494
1495 const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3]))));1495 const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3]))));
1496 out1.* = x1;1496 out1.* = x1;
...@@ -1508,7 +1508,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void {...@@ -1508,7 +1508,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void {
1508/// Output Bounds:1508/// Output Bounds:
1509/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1509/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1510pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void {1510pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void {
1511 @setRuntimeSafety(mode == .Debug);1511 @setRuntimeSafety(mode == .debug);
15121512
1513 var x1: u64 = undefined;1513 var x1: u64 = undefined;
1514 cmovznzU64(&x1, arg1, (arg2[0]), (arg3[0]));1514 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 {...@@ -1536,7 +1536,7 @@ pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void {
1536/// Output Bounds:1536/// Output Bounds:
1537/// 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]]1537/// 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]]
1538pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {1538pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {
1539 @setRuntimeSafety(mode == .Debug);1539 @setRuntimeSafety(mode == .debug);
15401540
1541 const x1 = (arg1[3]);1541 const x1 = (arg1[3]);
1542 const x2 = (arg1[2]);1542 const x2 = (arg1[2]);
...@@ -1645,7 +1645,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {...@@ -1645,7 +1645,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {
1645/// Output Bounds:1645/// Output Bounds:
1646/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1646/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1647pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {1647pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {
1648 @setRuntimeSafety(mode == .Debug);1648 @setRuntimeSafety(mode == .debug);
16491649
1650 const x1 = (@as(u64, (arg1[31])) << 56);1650 const x1 = (@as(u64, (arg1[31])) << 56);
1651 const x2 = (@as(u64, (arg1[30])) << 48);1651 const x2 = (@as(u64, (arg1[30])) << 48);
...@@ -1720,7 +1720,7 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {...@@ -1720,7 +1720,7 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {
1720/// 0 ≤ eval out1 < m1720/// 0 ≤ eval out1 < m
1721///1721///
1722pub fn setOne(out1: *MontgomeryDomainFieldElement) void {1722pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
1723 @setRuntimeSafety(mode == .Debug);1723 @setRuntimeSafety(mode == .debug);
17241724
1725 out1[0] = 0x402da1732fc9bebf;1725 out1[0] = 0x402da1732fc9bebf;
1726 out1[1] = 0x4551231950b75fc4;1726 out1[1] = 0x4551231950b75fc4;
...@@ -1737,7 +1737,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void {...@@ -1737,7 +1737,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void {
1737/// Output Bounds:1737/// Output Bounds:
1738/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1738/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1739pub fn msat(out1: *[5]u64) void {1739pub fn msat(out1: *[5]u64) void {
1740 @setRuntimeSafety(mode == .Debug);1740 @setRuntimeSafety(mode == .debug);
17411741
1742 out1[0] = 0xbfd25e8cd0364141;1742 out1[0] = 0xbfd25e8cd0364141;
1743 out1[1] = 0xbaaedce6af48a03b;1743 out1[1] = 0xbaaedce6af48a03b;
...@@ -1775,7 +1775,7 @@ pub fn msat(out1: *[5]u64) void {...@@ -1775,7 +1775,7 @@ pub fn msat(out1: *[5]u64) void {
1775/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1775/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1776/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]1776/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
1777pub 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 {1777pub 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
1780 var x1: u64 = undefined;1780 var x1: u64 = undefined;
1781 var x2: u1 = undefined;1781 var x2: u1 = undefined;
...@@ -2009,7 +2009,7 @@ pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[...@@ -2009,7 +2009,7 @@ pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[
2009/// Output Bounds:2009/// Output Bounds:
2010/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]2010/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
2011pub fn divstepPrecomp(out1: *[4]u64) void {2011pub fn divstepPrecomp(out1: *[4]u64) void {
2012 @setRuntimeSafety(mode == .Debug);2012 @setRuntimeSafety(mode == .debug);
20132013
2014 out1[0] = 0xd7431a4d2b9cb4e9;2014 out1[0] = 0xd7431a4d2b9cb4e9;
2015 out1[1] = 0xab67d35a32d9c503;2015 out1[1] = 0xab67d35a32d9c503;
lib/std/crypto/tls/Client.zig+1-1
...@@ -1588,7 +1588,7 @@ const CertificatePublicKey = struct {...@@ -1588,7 +1588,7 @@ const CertificatePublicKey = struct {
1588 inline 128, 256, 384, 512 => |modulus_len| {1588 inline 128, 256, 384, 512 => |modulus_len| {
1589 const key: PublicKey = try .fromBytes(exponent, modulus);1589 const key: PublicKey = try .fromBytes(exponent, modulus);
1590 const sig = RsaSignature.fromBytes(modulus_len, encoded_sig);1590 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);
1592 },1592 },
1593 else => return error.TlsBadRsaSignatureBitCount,1593 else => return error.TlsBadRsaSignatureBitCount,
1594 }1594 }
lib/std/debug.zig+19-12
...@@ -151,6 +151,10 @@ pub fn FullPanic(comptime panicFn: fn ([]const u8, ?usize) noreturn) type {...@@ -151,6 +151,10 @@ pub fn FullPanic(comptime panicFn: fn ([]const u8, ?usize) noreturn) type {
151 @branchHint(.cold);151 @branchHint(.cold);
152 call("invalid error code", @returnAddress());152 call("invalid error code", @returnAddress());
153 }153 }
154 pub fn unexpectedErrorCode(err: anyerror) noreturn {
155 @branchHint(.cold);
156 std.debug.panicExtra(@returnAddress(), "unexpected error code, found error.{s}", .{@errorName(err)});
157 }
154 pub fn integerOutOfBounds() noreturn {158 pub fn integerOutOfBounds() noreturn {
155 @branchHint(.cold);159 @branchHint(.cold);
156 call("integer does not fit in destination type", @returnAddress());160 call("integer does not fit in destination type", @returnAddress());
...@@ -207,6 +211,10 @@ pub fn FullPanic(comptime panicFn: fn ([]const u8, ?usize) noreturn) type {...@@ -207,6 +211,10 @@ pub fn FullPanic(comptime panicFn: fn ([]const u8, ?usize) noreturn) type {
207 @branchHint(.cold);211 @branchHint(.cold);
208 call("'noreturn' function returned", @returnAddress());212 call("'noreturn' function returned", @returnAddress());
209 }213 }
214 pub fn loadUninstantiableType() noreturn {
215 @branchHint(.cold);
216 call("attempt to load uninstantiable type", @returnAddress());
217 }
210 };218 };
211}219}
212220
...@@ -237,13 +245,12 @@ pub const Symbol = struct {...@@ -237,13 +245,12 @@ pub const Symbol = struct {
237 };245 };
238};246};
239247
240/// Deprecated because it returns the optimization mode of the standard248/// Deprecated in favor of `std.lang.Optimize.runtimeSafety`, to be removed after 0.18.0
241/// library, when the caller probably wants to use the optimization mode of249///
242/// their own module.250/// Returns whether the standard library has safety checks enabled. Callsites
243pub const runtime_safety = switch (builtin.mode) {251/// likely would rather know whether their own module's optimization mode
244 .Debug, .ReleaseSafe => true,252/// (found via `@import("builtin").optimize`) has safety checks enabled.
245 .ReleaseFast, .ReleaseSmall => false,253pub const runtime_safety = builtin.mode.runtimeSafety();
246};
247254
248/// Whether we can unwind the stack on this target, allowing capturing and/or printing the current255/// Whether we can unwind the stack on this target, allowing capturing and/or printing the current
249/// stack trace. It is still legal to call `captureCurrentStackTrace`, `writeCurrentStackTrace`, and256/// 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) {...@@ -257,7 +264,7 @@ pub const sys_can_stack_trace = switch (builtin.cpu.arch) {
257 // because Emscripten's implementation is very slow.264 // because Emscripten's implementation is very slow.
258 .wasm32,265 .wasm32,
259 .wasm64,266 .wasm64,
260 => native_os == .emscripten and builtin.mode == .Debug,267 => native_os == .emscripten and builtin.mode == .debug,
261268
262 // `@returnAddress()` is unsupported in LLVM 21.269 // `@returnAddress()` is unsupported in LLVM 21.
263 .bpfel,270 .bpfel,
...@@ -419,16 +426,16 @@ pub const CpuContextPtr = if (cpu_context.Native == noreturn) noreturn else *con...@@ -419,16 +426,16 @@ pub const CpuContextPtr = if (cpu_context.Native == noreturn) noreturn else *con
419426
420/// Invokes detectable illegal behavior when `ok` is `false`.427/// Invokes detectable illegal behavior when `ok` is `false`.
421///428///
422/// In Debug and ReleaseSafe modes, calls to this function are always429/// In debug and safe modes, calls to this function are always
423/// generated, and the `unreachable` statement triggers a panic.430/// generated, and the `unreachable` statement triggers a panic.
424///431///
425/// In ReleaseFast and ReleaseSmall modes, calls to this function are optimized432/// In fast and small modes, calls to this function are optimized
426/// away, and in fact the optimizer is able to use the assertion in its433/// away, and in fact the optimizer is able to use the assertion in its
427/// heuristics.434/// heuristics.
428///435///
429/// Inside a test block, it is best to use the `testing` module rather than436/// Inside a test block, it is best to use the `testing` module rather than
430/// this function, because this function may not detect a test failure in437/// this function, because this function may not detect a test failure in
431/// ReleaseFast and ReleaseSmall mode. Outside of a test block, this assert438/// fast and small mode. Outside of a test block, this assert
432/// function is the correct function to use.439/// function is the correct function to use.
433pub fn assert(ok: bool) void {440pub fn assert(ok: bool) void {
434 @disableInstrumentation();441 @disableInstrumentation();
...@@ -1760,7 +1767,7 @@ test "manage resources correctly" {...@@ -1760,7 +1767,7 @@ test "manage resources correctly" {
1760/// In release mode, it is size 0 and all methods are no-ops.1767/// In release mode, it is size 0 and all methods are no-ops.
1761/// This is a pre-made type with default settings.1768/// This is a pre-made type with default settings.
1762/// For more advanced usage, see `ConfigurableTrace`.1769/// 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
1765pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize, comptime is_enabled: bool) type {1772pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize, comptime is_enabled: bool) type {
1766 return struct {1773 return struct {
lib/std/debug/Dwarf.zig+16-5
...@@ -450,6 +450,7 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void {...@@ -450,6 +450,7 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void {
450 unit_header.format,450 unit_header.format,
451 endian,451 endian,
452 address_size,452 address_size,
453 version,
453 )) orelse continue;454 )) orelse continue;
454455
455 switch (die_obj.tag_id) {456 switch (die_obj.tag_id) {
...@@ -485,6 +486,7 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void {...@@ -485,6 +486,7 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void {
485 unit_header.format,486 unit_header.format,
486 endian,487 endian,
487 address_size,488 address_size,
489 version,
488 )) orelse return bad();490 )) orelse return bad();
489 } else if (this_die_obj.getAttr(AT.specification)) |_| {491 } else if (this_die_obj.getAttr(AT.specification)) |_| {
490 const after_die_offset = fr.seek;492 const after_die_offset = fr.seek;
...@@ -500,6 +502,7 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void {...@@ -500,6 +502,7 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void {
500 unit_header.format,502 unit_header.format,
501 endian,503 endian,
502 address_size,504 address_size,
505 version,
503 )) orelse return bad();506 )) orelse return bad();
504 } else {507 } else {
505 break :x null;508 break :x null;
...@@ -611,6 +614,7 @@ fn scanAllCompileUnits(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!voi...@@ -611,6 +614,7 @@ fn scanAllCompileUnits(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!voi
611 unit_header.format,614 unit_header.format,
612 endian,615 endian,
613 address_size,616 address_size,
617 version,
614 )) orelse return bad();618 )) orelse return bad();
615619
616 if (compile_unit_die.tag_id != DW.TAG.compile_unit) return bad();620 if (compile_unit_die.tag_id != DW.TAG.compile_unit) return bad();
...@@ -931,6 +935,7 @@ fn parseDie(...@@ -931,6 +935,7 @@ fn parseDie(
931 format: Format,935 format: Format,
932 endian: Endian,936 endian: Endian,
933 addr_size_bytes: u8,937 addr_size_bytes: u8,
938 version: u16,
934) ScanError!?Die {939) ScanError!?Die {
935 const abbrev_code = try fr.takeLeb128(u64);940 const abbrev_code = try fr.takeLeb128(u64);
936 if (abbrev_code == 0) return null;941 if (abbrev_code == 0) return null;
...@@ -939,7 +944,7 @@ fn parseDie(...@@ -939,7 +944,7 @@ fn parseDie(
939 const attrs = attrs_buf[0..table_entry.attrs.len];944 const attrs = attrs_buf[0..table_entry.attrs.len];
940 for (attrs, table_entry.attrs) |*result_attr, attr| result_attr.* = .{945 for (attrs, table_entry.attrs) |*result_attr, attr| result_attr.* = .{
941 .id = attr.id,946 .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),
943 };948 };
944 return .{949 return .{
945 .tag_id = table_entry.tag_id,950 .tag_id = table_entry.tag_id,
...@@ -1042,7 +1047,7 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, endian: Endian, compile_unit:...@@ -1042,7 +1047,7 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, endian: Endian, compile_unit:
1042 for (try directories.addManyAsSlice(gpa, directories_count)) |*e| {1047 for (try directories.addManyAsSlice(gpa, directories_count)) |*e| {
1043 e.* = .{ .path = &.{} };1048 e.* = .{ .path = &.{} };
1044 for (dir_ent_fmt_buf[0..directory_entry_format_count]) |ent_fmt| {1049 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);
1046 switch (ent_fmt.content_type_code) {1051 switch (ent_fmt.content_type_code) {
1047 DW.LNCT.path => e.path = try form_value.getString(d.*),1052 DW.LNCT.path => e.path = try form_value.getString(d.*),
1048 DW.LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),1053 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:...@@ -1074,7 +1079,7 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, endian: Endian, compile_unit:
1074 for (try file_entries.addManyAsSlice(gpa, file_names_count)) |*e| {1079 for (try file_entries.addManyAsSlice(gpa, file_names_count)) |*e| {
1075 e.* = .{ .path = &.{} };1080 e.* = .{ .path = &.{} };
1076 for (file_ent_fmt_buf[0..file_name_entry_format_count]) |ent_fmt| {1081 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);
1078 switch (ent_fmt.content_type_code) {1083 switch (ent_fmt.content_type_code) {
1079 DW.LNCT.path => e.path = try form_value.getString(d.*),1084 DW.LNCT.path => e.path = try form_value.getString(d.*),
1080 DW.LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),1085 DW.LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),
...@@ -1285,6 +1290,7 @@ fn parseFormValue(...@@ -1285,6 +1290,7 @@ fn parseFormValue(
1285 endian: Endian,1290 endian: Endian,
1286 addr_size_bytes: u8,1291 addr_size_bytes: u8,
1287 implicit_const: ?i64,1292 implicit_const: ?i64,
1293 version: u16,
1288) ScanError!FormValue {1294) ScanError!FormValue {
1289 return switch (form_id) {1295 return switch (form_id) {
1290 // DWARF5.pdf page 213: the size of this value is encoded in the1296 // DWARF5.pdf page 213: the size of this value is encoded in the
...@@ -1319,7 +1325,12 @@ fn parseFormValue(...@@ -1319,7 +1325,12 @@ fn parseFormValue(
1319 FORM.ref8 => .{ .ref = try r.takeInt(u64, endian) },1325 FORM.ref8 => .{ .ref = try r.takeInt(u64, endian) },
1320 FORM.ref_udata => .{ .ref = try r.takeLeb128(u64) },1326 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 },
1323 FORM.ref_sig8 => .{ .ref = try r.takeInt(u64, endian) },1334 FORM.ref_sig8 => .{ .ref = try r.takeInt(u64, endian) },
13241335
1325 FORM.string => .{ .string = try r.takeSentinel(0) },1336 FORM.string => .{ .string = try r.takeSentinel(0) },
...@@ -1330,7 +1341,7 @@ fn parseFormValue(...@@ -1330,7 +1341,7 @@ fn parseFormValue(
1330 FORM.strx4 => .{ .strx = try r.takeInt(u32, endian) },1341 FORM.strx4 => .{ .strx = try r.takeInt(u32, endian) },
1331 FORM.strx => .{ .strx = try r.takeLeb128(usize) },1342 FORM.strx => .{ .strx = try r.takeLeb128(usize) },
1332 FORM.line_strp => .{ .line_strp = try readFormatSizedInt(r, format, endian) },1343 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),
1334 FORM.implicit_const => .{ .sdata = implicit_const orelse return bad() },1345 FORM.implicit_const => .{ .sdata = implicit_const orelse return bad() },
1335 FORM.loclistx => .{ .loclistx = try r.takeLeb128(u64) },1346 FORM.loclistx => .{ .loclistx = try r.takeLeb128(u64) },
1336 FORM.rnglistx => .{ .rnglistx = try r.takeLeb128(u64) },1347 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,...@@ -2,6 +2,8 @@ mapped_memory: []align(std.heap.page_size_min) const u8,
2symbols: []const Symbol,2symbols: []const Symbol,
3strings: []const u8,3strings: []const u8,
4text_vmaddr: u64,4text_vmaddr: u64,
5uuid: ?Uuid,
6adjacent_dsym: ?DsymFile,
57
6/// Key is index into `strings` of the file path.8/// Key is index into `strings` of the file path.
7ofiles: std.array_hash_map.Auto(u32, Error!OFile),9ofiles: std.array_hash_map.Auto(u32, Error!OFile),
...@@ -16,6 +18,7 @@ pub const Error = error{...@@ -16,6 +18,7 @@ pub const Error = error{
16};18};
1719
18pub fn deinit(mf: *MachOFile, gpa: Allocator) void {20pub fn deinit(mf: *MachOFile, gpa: Allocator) void {
21 if (mf.adjacent_dsym) |*dsym| dsym.deinit(gpa);
19 for (mf.ofiles.values()) |*maybe_of| {22 for (mf.ofiles.values()) |*maybe_of| {
20 const of = &(maybe_of.* catch continue);23 const of = &(maybe_of.* catch continue);
21 posix.munmap(of.mapped_memory);24 posix.munmap(of.mapped_memory);
...@@ -36,48 +39,7 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch)...@@ -36,48 +39,7 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch)
36 const all_mapped_memory = try mapDebugInfoFile(io, path);39 const all_mapped_memory = try mapDebugInfoFile(io, path);
37 errdefer posix.munmap(all_mapped_memory);40 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 "universal42 const mapped_macho = try selectMachOSlice(all_mapped_memory, arch);
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 };
8143
82 var r: Io.Reader = .fixed(mapped_macho);44 var r: Io.Reader = .fixed(mapped_macho);
83 const hdr = r.takeStruct(macho.mach_header_64, .little) catch |err| switch (err) {45 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)...@@ -88,21 +50,26 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch)
88 if (hdr.magic != macho.MH_MAGIC_64)50 if (hdr.magic != macho.MH_MAGIC_64)
89 return error.InvalidMachO;51 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: {
92 var it: macho.LoadCommandIterator = try .init(&hdr, mapped_macho[@sizeOf(macho.mach_header_64)..]);54 var it: macho.LoadCommandIterator = try .init(&hdr, mapped_macho[@sizeOf(macho.mach_header_64)..]);
93 var symtab: ?macho.symtab_command = null;55 var symtab: ?macho.symtab_command = null;
94 var text_vmaddr: ?u64 = null;56 var text_vmaddr: ?u64 = null;
57 var uuid: ?Uuid = null;
95 while (try it.next()) |cmd| switch (cmd.hdr.cmd) {58 while (try it.next()) |cmd| switch (cmd.hdr.cmd) {
96 .SYMTAB => symtab = cmd.cast(macho.symtab_command) orelse return error.InvalidMachO,59 .SYMTAB => symtab = cmd.cast(macho.symtab_command) orelse return error.InvalidMachO,
97 .SEGMENT_64 => if (cmd.cast(macho.segment_command_64)) |seg_cmd| {60 .SEGMENT_64 => if (cmd.cast(macho.segment_command_64)) |seg_cmd| {
98 if (!mem.eql(u8, seg_cmd.segName(), "__TEXT")) continue;61 if (!mem.eql(u8, seg_cmd.segName(), "__TEXT")) continue;
99 text_vmaddr = seg_cmd.vmaddr;62 text_vmaddr = seg_cmd.vmaddr;
100 },63 },
64 .UUID => if (cmd.cast(macho.uuid_command)) |uuid_cmd| {
65 uuid = uuid_cmd.uuid;
66 },
101 else => {},67 else => {},
102 };68 };
103 break :lcs .{69 break :lcs .{
104 symtab orelse return error.MissingDebugInfo,70 symtab orelse return error.MissingDebugInfo,
105 text_vmaddr orelse return error.MissingDebugInfo,71 text_vmaddr orelse return error.MissingDebugInfo,
72 uuid,
106 };73 };
107 };74 };
10875
...@@ -253,15 +220,27 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch)...@@ -253,15 +220,27 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch)
253 // This sort is so that we can binary search later.220 // This sort is so that we can binary search later.
254 mem.sort(Symbol, symbols_slice, {}, Symbol.addressLessThan);221 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
256 return .{228 return .{
257 .mapped_memory = all_mapped_memory,229 .mapped_memory = all_mapped_memory,
258 .symbols = symbols_slice,230 .symbols = symbols_slice,
259 .strings = strings,231 .strings = strings,
260 .ofiles = .empty,232 .ofiles = .empty,
261 .text_vmaddr = text_vmaddr,233 .text_vmaddr = text_vmaddr,
234 .uuid = uuid,
235 .adjacent_dsym = adjacent_dsym,
262 };236 };
263}237}
238
264pub fn getDwarfForAddress(mf: *MachOFile, gpa: Allocator, io: Io, vaddr: u64) !struct { *Dwarf, u64 } {239pub 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
265 const symbol = Symbol.find(mf.symbols, vaddr) orelse return error.MissingDebugInfo;244 const symbol = Symbol.find(mf.symbols, vaddr) orelse return error.MissingDebugInfo;
266245
267 if (symbol.ofile == Symbol.unknown_ofile) return error.MissingDebugInfo;246 if (symbol.ofile == Symbol.unknown_ofile) return error.MissingDebugInfo;
...@@ -324,6 +303,16 @@ const OFile = struct {...@@ -324,6 +303,16 @@ const OFile = struct {
324 };303 };
325};304};
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
327const Symbol = struct {316const Symbol = struct {
328 strx: u32,317 strx: u32,
329 addr: u64,318 addr: u64,
...@@ -394,6 +383,74 @@ fn appendStabSymbol(...@@ -394,6 +383,74 @@ fn appendStabSymbol(
394 }383 }
395}384}
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
397fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile {454fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile {
398 const all_mapped_memory, const mapped_ofile = map: {455 const all_mapped_memory, const mapped_ofile = map: {
399 const open_paren = paren: {456 const open_paren = paren: {
...@@ -497,19 +554,38 @@ fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile {...@@ -497,19 +554,38 @@ fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile {
497 gop.key_ptr.* = @intCast(sym_index);554 gop.key_ptr.* = @intCast(sym_index);
498 }555 }
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 {
500 var sections: Dwarf.SectionArray = @splat(null);573 var sections: Dwarf.SectionArray = @splat(null);
501 for (seg_cmd.getSections()) |sect_raw| {574 for (section_headers) |sect_raw| {
502 var sect = sect_raw;575 var sect = sect_raw;
503 if (builtin.cpu.arch.endian() != .little) std.mem.byteSwapAllFields(macho.section_64, &sect);576 if (builtin.cpu.arch.endian() != .little) std.mem.byteSwapAllFields(macho.section_64, &sect);
504577
505 if (!std.mem.eql(u8, "__DWARF", sect.segName())) continue;578 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| {580 const section_index: usize = inline for (@typeInfo(Dwarf.Section.Id).@"enum".field_names, 0..) |field_name, i| {
508 if (mem.eql(u8, "__" ++ section_name, sect.sectName())) break 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;
509 } else continue;585 } else continue;
510586
511 if (mapped_ofile.len < sect.offset + sect.size) return error.InvalidMachO;587 if (mapped_macho.len < sect.offset + sect.size) return error.InvalidMachO;
512 const section_bytes = mapped_ofile[sect.offset..][0..sect.size];588 const section_bytes = mapped_macho[sect.offset..][0..sect.size];
513 sections[section_index] = .{589 sections[section_index] = .{
514 .data = section_bytes,590 .data = section_bytes,
515 .owned = false,591 .owned = false,
...@@ -539,13 +615,56 @@ fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile {...@@ -539,13 +615,56 @@ fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile {
539 => |e| return e,615 => |e| return e,
540 };616 };
541617
542 return .{618 return dwarf;
543 .mapped_memory = all_mapped_memory,619}
544 .dwarf = dwarf,620
545 .strtab = strtab,621fn selectMachOSlice(
546 .symtab_raw = symtab_raw,622 all_mapped_memory: []align(std.heap.page_size_min) const u8,
547 .symbols_by_name = symbols_by_name.move(),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,
548 };666 };
667 return mapped_macho;
549}668}
550669
551/// Uses `mmap` to map the file at `path` into memory.670/// Uses `mmap` to map the file at `path` into memory.
...@@ -583,4 +702,5 @@ const testing = std.testing;...@@ -583,4 +702,5 @@ const testing = std.testing;
583702
584const builtin = @import("builtin");703const builtin = @import("builtin");
585704
705const Uuid = @FieldType(macho.uuid_command, "uuid");
586const MachOFile = @This();706const 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...@@ -428,6 +428,9 @@ fn findModule(si: *SelfInfo, gpa: Allocator, io: Io, address: usize, lock: enum
428 // Rebuild module list with the exclusive lock.428 // Rebuild module list with the exclusive lock.
429 {429 {
430 errdefer si.rwlock.unlock(io);430 errdefer si.rwlock.unlock(io);
431 if (si.unwind_cache) |cache| {
432 @memset(cache, .empty);
433 }
431 for (si.modules.items) |*mod| {434 for (si.modules.items) |*mod| {
432 unwind: {435 unwind: {
433 const u = &(mod.unwind orelse break :unwind catch break :unwind);436 const u = &(mod.unwind orelse break :unwind catch break :unwind);
...@@ -515,7 +518,7 @@ const DlIterContext = struct {...@@ -515,7 +518,7 @@ const DlIterContext = struct {
515 for (info.phdr[0..info.phnum]) |phdr| {518 for (info.phdr[0..info.phnum]) |phdr| {
516 if (phdr.type != .LOAD) continue;519 if (phdr.type != .LOAD) continue;
517 try context.si.ranges.append(gpa, .{520 try context.si.ranges.append(gpa, .{
518 // Overflowing addition handles VSDOs having p_vaddr = 0xffffffffff700000521 // Overflowing addition handles VSDOs having vaddr = 0xffffffffff700000
519 .start = info.addr +% phdr.vaddr,522 .start = info.addr +% phdr.vaddr,
520 .len = phdr.memsz,523 .len = phdr.memsz,
521 .module_index = module_index,524 .module_index = module_index,
lib/std/debug/cpu_context.zig+2
...@@ -2020,6 +2020,8 @@ const signal_ucontext_t = switch (native_os) {...@@ -2020,6 +2020,8 @@ const signal_ucontext_t = switch (native_os) {
2020 .mips64el,2020 .mips64el,
2021 .or1k,2021 .or1k,
2022 .s390x,2022 .s390x,
2023 .sh,
2024 .sheb,
2023 .x86,2025 .x86,
2024 .x86_64,2026 .x86_64,
2025 .xtensa,2027 .xtensa,
lib/std/debug/no_panic.zig+10
...@@ -65,6 +65,11 @@ pub fn invalidErrorCode() noreturn {...@@ -65,6 +65,11 @@ pub fn invalidErrorCode() noreturn {
65 @trap();65 @trap();
66}66}
6767
68pub fn unexpectedErrorCode(_: anyerror) noreturn {
69 @branchHint(.cold);
70 @trap();
71}
72
68pub fn integerOutOfBounds() noreturn {73pub fn integerOutOfBounds() noreturn {
69 @branchHint(.cold);74 @branchHint(.cold);
70 @trap();75 @trap();
...@@ -134,3 +139,8 @@ pub fn noreturnReturned() noreturn {...@@ -134,3 +139,8 @@ pub fn noreturnReturned() noreturn {
134 @branchHint(.cold);139 @branchHint(.cold);
135 @trap();140 @trap();
136}141}
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 {...@@ -20,109 +20,144 @@ pub fn call(msg: []const u8, ra: ?usize) noreturn {
20}20}
2121
22pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn {22pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn {
23 @branchHint(.cold);
23 _ = found;24 _ = found;
24 call("sentinel mismatch", null);25 call("sentinel mismatch", null);
25}26}
2627
27pub fn unwrapError(err: anyerror) noreturn {28pub fn unwrapError(err: anyerror) noreturn {
29 @branchHint(.cold);
28 _ = &err;30 _ = &err;
29 call("attempt to unwrap error", null);31 call("attempt to unwrap error", null);
30}32}
3133
32pub fn outOfBounds(index: usize, len: usize) noreturn {34pub fn outOfBounds(index: usize, len: usize) noreturn {
35 @branchHint(.cold);
33 _ = index;36 _ = index;
34 _ = len;37 _ = len;
35 call("index out of bounds", null);38 call("index out of bounds", null);
36}39}
3740
38pub fn startGreaterThanEnd(start: usize, end: usize) noreturn {41pub fn startGreaterThanEnd(start: usize, end: usize) noreturn {
42 @branchHint(.cold);
39 _ = start;43 _ = start;
40 _ = end;44 _ = end;
41 call("start index is larger than end index", null);45 call("start index is larger than end index", null);
42}46}
4347
44pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn {48pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn {
49 @branchHint(.cold);
45 _ = accessed;50 _ = accessed;
46 call("access of inactive union field", null);51 call("access of inactive union field", null);
47}52}
4853
49pub fn sliceCastLenRemainder(src_len: usize) noreturn {54pub fn sliceCastLenRemainder(src_len: usize) noreturn {
55 @branchHint(.cold);
50 _ = src_len;56 _ = src_len;
51 call("slice length does not divide exactly into destination elements", null);57 call("slice length does not divide exactly into destination elements", null);
52}58}
5359
54pub fn reachedUnreachable() noreturn {60pub fn reachedUnreachable() noreturn {
61 @branchHint(.cold);
55 call("reached unreachable code", null);62 call("reached unreachable code", null);
56}63}
5764
58pub fn unwrapNull() noreturn {65pub fn unwrapNull() noreturn {
66 @branchHint(.cold);
59 call("attempt to use null value", null);67 call("attempt to use null value", null);
60}68}
6169
62pub fn castToNull() noreturn {70pub fn castToNull() noreturn {
71 @branchHint(.cold);
63 call("cast causes pointer to be null", null);72 call("cast causes pointer to be null", null);
64}73}
6574
66pub fn incorrectAlignment() noreturn {75pub fn incorrectAlignment() noreturn {
76 @branchHint(.cold);
67 call("incorrect alignment", null);77 call("incorrect alignment", null);
68}78}
6979
70pub fn invalidErrorCode() noreturn {80pub fn invalidErrorCode() noreturn {
81 @branchHint(.cold);
71 call("invalid error code", null);82 call("invalid error code", null);
72}83}
7384
85pub fn unexpectedErrorCode(err: anyerror) noreturn {
86 @branchHint(.cold);
87 _ = err;
88 call("unexpected error code", null);
89}
90
74pub fn integerOutOfBounds() noreturn {91pub fn integerOutOfBounds() noreturn {
92 @branchHint(.cold);
75 call("integer does not fit in destination type", null);93 call("integer does not fit in destination type", null);
76}94}
7795
78pub fn integerOverflow() noreturn {96pub fn integerOverflow() noreturn {
97 @branchHint(.cold);
79 call("integer overflow", null);98 call("integer overflow", null);
80}99}
81100
82pub fn shlOverflow() noreturn {101pub fn shlOverflow() noreturn {
102 @branchHint(.cold);
83 call("left shift overflowed bits", null);103 call("left shift overflowed bits", null);
84}104}
85105
86pub fn shrOverflow() noreturn {106pub fn shrOverflow() noreturn {
107 @branchHint(.cold);
87 call("right shift overflowed bits", null);108 call("right shift overflowed bits", null);
88}109}
89110
90pub fn divideByZero() noreturn {111pub fn divideByZero() noreturn {
112 @branchHint(.cold);
91 call("division by zero", null);113 call("division by zero", null);
92}114}
93115
94pub fn exactDivisionRemainder() noreturn {116pub fn exactDivisionRemainder() noreturn {
117 @branchHint(.cold);
95 call("exact division produced remainder", null);118 call("exact division produced remainder", null);
96}119}
97120
98pub fn integerPartOutOfBounds() noreturn {121pub fn integerPartOutOfBounds() noreturn {
122 @branchHint(.cold);
99 call("integer part of floating point value out of bounds", null);123 call("integer part of floating point value out of bounds", null);
100}124}
101125
102pub fn corruptSwitch() noreturn {126pub fn corruptSwitch() noreturn {
127 @branchHint(.cold);
103 call("switch on corrupt value", null);128 call("switch on corrupt value", null);
104}129}
105130
106pub fn shiftRhsTooBig() noreturn {131pub fn shiftRhsTooBig() noreturn {
132 @branchHint(.cold);
107 call("shift amount is greater than the type size", null);133 call("shift amount is greater than the type size", null);
108}134}
109135
110pub fn invalidEnumValue() noreturn {136pub fn invalidEnumValue() noreturn {
137 @branchHint(.cold);
111 call("invalid enum value", null);138 call("invalid enum value", null);
112}139}
113140
114pub fn forLenMismatch() noreturn {141pub fn forLenMismatch() noreturn {
142 @branchHint(.cold);
115 call("for loop over objects with non-equal lengths", null);143 call("for loop over objects with non-equal lengths", null);
116}144}
117145
118pub fn copyLenMismatch() noreturn {146pub fn copyLenMismatch() noreturn {
147 @branchHint(.cold);
119 call("source and destination have non-equal lengths", null);148 call("source and destination have non-equal lengths", null);
120}149}
121150
122pub fn memcpyAlias() noreturn {151pub fn memcpyAlias() noreturn {
152 @branchHint(.cold);
123 call("@memcpy arguments alias", null);153 call("@memcpy arguments alias", null);
124}154}
125155
126pub fn noreturnReturned() noreturn {156pub fn noreturnReturned() noreturn {
157 @branchHint(.cold);
127 call("'noreturn' function returned", null);158 call("'noreturn' function returned", null);
128}159}
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 {...@@ -696,7 +696,7 @@ fn fuzzAgainstArrayList(_: void, smith: *std.testing.Smith) anyerror!void {
696 try q.ensureTotalCapacityPrecise(q_gpa, q.len + growth);696 try q.ensureTotalCapacityPrecise(q_gpa, q.len + growth);
697 },697 },
698 }698 }
699 try testing.expectEqual(l.getLast(), q.back());699 try testing.expectEqual(l.last(), q.back());
700 try testing.expectEqual(700 try testing.expectEqual(
701 if (l.items.len > 0) l.items[0] else null,701 if (l.items.len > 0) l.items[0] else null,
702 q.front(),702 q.front(),
lib/std/dynamic_library.zig+17-17
...@@ -103,7 +103,7 @@ pub fn get_DYNAMIC() ?[*]const elf.Dyn {...@@ -103,7 +103,7 @@ pub fn get_DYNAMIC() ?[*]const elf.Dyn {
103103
104pub fn linkmap_iterator() error{InvalidExe}!LinkMap.Iterator {104pub fn linkmap_iterator() error{InvalidExe}!LinkMap.Iterator {
105 const _DYNAMIC = get_DYNAMIC() orelse {105 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.
107 return .{ .current = null };107 return .{ .current = null };
108 };108 };
109109
...@@ -261,10 +261,10 @@ pub const ElfDynLib = struct {...@@ -261,10 +261,10 @@ pub const ElfDynLib = struct {
261 i += 1;261 i += 1;
262 ph_addr += eh.e_phentsize;262 ph_addr += eh.e_phentsize;
263 }) {263 }) {
264 const ph = @as(*elf.Phdr, @ptrFromInt(ph_addr));264 const ph = @as(*elf.ElfN.Phdr, @ptrFromInt(ph_addr));
265 switch (ph.p_type) {265 switch (ph.type) {
266 elf.PT_LOAD => virt_addr_end = @max(virt_addr_end, ph.p_vaddr + ph.p_memsz),266 .LOAD => virt_addr_end = @max(virt_addr_end, ph.vaddr + ph.memsz),
267 elf.PT_DYNAMIC => maybe_dynv = @as([*]usize, @ptrFromInt(elf_addr + ph.p_offset)),267 .DYNAMIC => maybe_dynv = @as([*]usize, @ptrFromInt(elf_addr + ph.offset)),
268 else => {},268 else => {},
269 }269 }
270 }270 }
...@@ -292,23 +292,23 @@ pub const ElfDynLib = struct {...@@ -292,23 +292,23 @@ pub const ElfDynLib = struct {
292 i += 1;292 i += 1;
293 ph_addr += eh.e_phentsize;293 ph_addr += eh.e_phentsize;
294 }) {294 }) {
295 const ph = @as(*elf.Phdr, @ptrFromInt(ph_addr));295 const ph = @as(*elf.ElfN.Phdr, @ptrFromInt(ph_addr));
296 switch (ph.p_type) {296 switch (ph.type) {
297 elf.PT_LOAD => {297 .LOAD => {
298 // The VirtAddr may not be page-aligned; in such case there will be298 // The VirtAddr may not be page-aligned; in such case there will be
299 // extra nonsense mapped before/after the VirtAddr,MemSiz299 // extra nonsense mapped before/after the VirtAddr,MemSiz
300 const aligned_addr = (base + ph.p_vaddr) & ~(@as(usize, page_size) - 1);300 const aligned_addr = (base + ph.vaddr) & ~(@as(usize, page_size) - 1);
301 const extra_bytes = (base + ph.p_vaddr) - aligned_addr;301 const extra_bytes = (base + ph.vaddr) - aligned_addr;
302 const extended_memsz = mem.alignForward(usize, ph.p_memsz + extra_bytes, page_size);302 const extended_memsz = mem.alignForward(usize, ph.memsz + extra_bytes, page_size);
303 const ptr = @as([*]align(std.heap.page_size_min) u8, @ptrFromInt(aligned_addr));303 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);
305 _ = try posix.mmap(305 _ = try posix.mmap(
306 ptr,306 ptr,
307 extended_memsz,307 extended_memsz,
308 prot,308 prot,
309 .{ .TYPE = .PRIVATE, .FIXED = true },309 .{ .TYPE = .PRIVATE, .FIXED = true },
310 file.handle,310 file.handle,
311 ph.p_offset - extra_bytes,311 ph.offset - extra_bytes,
312 );312 );
313 },313 },
314 else => {},314 else => {},
...@@ -517,11 +517,11 @@ pub const ElfDynLib = struct {...@@ -517,11 +517,11 @@ pub const ElfDynLib = struct {
517 return null;517 return null;
518 }518 }
519519
520 fn elfToProt(elf_prot: u64) posix.PROT {520 fn elfToProt(elf_prot: elf.PF) posix.PROT {
521 return .{521 return .{
522 .READ = (elf_prot & elf.PF_R) != 0,522 .READ = elf_prot.R,
523 .WRITE = (elf_prot & elf.PF_W) != 0,523 .WRITE = elf_prot.W,
524 .EXEC = (elf_prot & elf.PF_X) != 0,524 .EXEC = elf_prot.X,
525 };525 };
526 }526 }
527};527};
lib/std/elf.zig+19-88
...@@ -290,47 +290,6 @@ pub const VER_FLG_BASE = 1;...@@ -290,47 +290,6 @@ pub const VER_FLG_BASE = 1;
290/// Weak version identifier290/// Weak version identifier
291pub const VER_FLG_WEAK = 2;291pub 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
334pub const PN_XNUM = 0xffff;293pub const PN_XNUM = 0xffff;
335294
336/// Deprecated, use `@intFromEnum(std.elf.SHT.NULL)`295/// Deprecated, use `@intFromEnum(std.elf.SHT.NULL)`
...@@ -848,11 +807,11 @@ pub const ProgramHeaderIterator = struct {...@@ -848,11 +807,11 @@ pub const ProgramHeaderIterator = struct {
848 file_reader: *Io.File.Reader,807 file_reader: *Io.File.Reader,
849 index: usize = 0,808 index: usize = 0,
850809
851 pub fn next(it: *ProgramHeaderIterator) !?Elf64_Phdr {810 pub fn next(it: *ProgramHeaderIterator) !?Elf64.Phdr {
852 if (it.index >= it.phnum) return null;811 if (it.index >= it.phnum) return null;
853 defer it.index += 1;812 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);
856 const offset = it.phoff + size * it.index;815 const offset = it.phoff + size * it.index;
857 try it.file_reader.seekTo(offset);816 try it.file_reader.seekTo(offset);
858817
...@@ -869,11 +828,11 @@ pub const ProgramHeaderBufferIterator = struct {...@@ -869,11 +828,11 @@ pub const ProgramHeaderBufferIterator = struct {
869 buf: []const u8,828 buf: []const u8,
870 index: usize = 0,829 index: usize = 0,
871830
872 pub fn next(it: *ProgramHeaderBufferIterator) !?Elf64_Phdr {831 pub fn next(it: *ProgramHeaderBufferIterator) !?Elf64.Phdr {
873 if (it.index >= it.phnum) return null;832 if (it.index >= it.phnum) return null;
874 defer it.index += 1;833 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);
877 const offset = @as(usize, @intCast(it.phoff)) + size * it.index;836 const offset = @as(usize, @intCast(it.phoff)) + size * it.index;
878 var reader = Io.Reader.fixed(it.buf[offset..]);837 var reader = Io.Reader.fixed(it.buf[offset..]);
879838
...@@ -881,22 +840,22 @@ pub const ProgramHeaderBufferIterator = struct {...@@ -881,22 +840,22 @@ pub const ProgramHeaderBufferIterator = struct {
881 }840 }
882};841};
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 {
885 if (is_64) {844 if (is_64) {
886 const phdr = try reader.takeStruct(Elf64_Phdr, endian);845 const phdr = try reader.takeStruct(Elf64.Phdr, endian);
887 return phdr;846 return phdr;
888 }847 }
889848
890 const phdr = try reader.takeStruct(Elf32_Phdr, endian);849 const phdr = try reader.takeStruct(Elf32.Phdr, endian);
891 return .{850 return .{
892 .p_type = phdr.p_type,851 .type = phdr.type,
893 .p_offset = phdr.p_offset,852 .offset = phdr.offset,
894 .p_vaddr = phdr.p_vaddr,853 .vaddr = phdr.vaddr,
895 .p_paddr = phdr.p_paddr,854 .paddr = phdr.paddr,
896 .p_filesz = phdr.p_filesz,855 .filesz = phdr.filesz,
897 .p_memsz = phdr.p_memsz,856 .memsz = phdr.memsz,
898 .p_flags = phdr.p_flags,857 .flags = phdr.flags,
899 .p_align = phdr.p_align,858 .@"align" = phdr.@"align",
900 };859 };
901}860}
902861
...@@ -1276,28 +1235,6 @@ pub const Elf64_Ehdr = extern struct {...@@ -1276,28 +1235,6 @@ pub const Elf64_Ehdr = extern struct {
1276 e_shnum: Half,1235 e_shnum: Half,
1277 e_shstrndx: Half,1236 e_shstrndx: Half,
1278};1237};
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};
1301/// Deprecated, use `std.elf.Elf32.Shdr`1238/// Deprecated, use `std.elf.Elf32.Shdr`
1302pub const Elf32_Shdr = extern struct {1239pub const Elf32_Shdr = extern struct {
1303 sh_name: Word,1240 sh_name: Word,
...@@ -1568,12 +1505,6 @@ pub const Ehdr = switch (@sizeOf(usize)) {...@@ -1568,12 +1505,6 @@ pub const Ehdr = switch (@sizeOf(usize)) {
1568 8 => Elf64_Ehdr,1505 8 => Elf64_Ehdr,
1569 else => @compileError("expected pointer size of 32 or 64"),1506 else => @compileError("expected pointer size of 32 or 64"),
1570};1507};
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};
1577pub const Dyn = switch (@sizeOf(usize)) {1508pub const Dyn = switch (@sizeOf(usize)) {
1578 4 => Elf32_Dyn,1509 4 => Elf32_Dyn,
1579 8 => Elf64_Dyn,1510 8 => Elf64_Dyn,
...@@ -3272,12 +3203,12 @@ pub const ar_hdr = extern struct {...@@ -3272,12 +3203,12 @@ pub const ar_hdr = extern struct {
3272 ar_fmag: [2]u8,3203 ar_fmag: [2]u8,
32733204
3274 pub fn date(self: ar_hdr) std.fmt.ParseIntError!u64 {3205 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, " ");
3276 return std.fmt.parseInt(u64, value, 10);3207 return std.fmt.parseInt(u64, value, 10);
3277 }3208 }
32783209
3279 pub fn size(self: ar_hdr) std.fmt.ParseIntError!u32 {3210 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, " ");
3281 return std.fmt.parseInt(u32, value, 10);3212 return std.fmt.parseInt(u32, value, 10);
3282 }3213 }
32833214
...@@ -3311,7 +3242,7 @@ pub const ar_hdr = extern struct {...@@ -3311,7 +3242,7 @@ pub const ar_hdr = extern struct {
3311 pub fn nameOffset(self: ar_hdr) std.fmt.ParseIntError!?u32 {3242 pub fn nameOffset(self: ar_hdr) std.fmt.ParseIntError!?u32 {
3312 const value = &self.ar_name;3243 const value = &self.ar_name;
3313 if (value[0] != '/') return null;3244 if (value[0] != '/') return null;
3314 const trimmed = mem.trimEnd(u8, value, &[_]u8{0x20});3245 const trimmed = mem.trimEnd(u8, value, " ");
3315 return try std.fmt.parseInt(u32, trimmed[1..], 10);3246 return try std.fmt.parseInt(u32, trimmed[1..], 10);
3316 }3247 }
3317};3248};
...@@ -3319,7 +3250,7 @@ pub const ar_hdr = extern struct {...@@ -3319,7 +3250,7 @@ pub const ar_hdr = extern struct {
3319fn genSpecialMemberName(comptime name: []const u8) *const [16]u8 {3250fn genSpecialMemberName(comptime name: []const u8) *const [16]u8 {
3320 assert(name.len <= 16);3251 assert(name.len <= 16);
3321 const padding = 16 - name.len;3252 const padding = 16 - name.len;
3322 return name ++ @as([padding]u8, @splat(0x20));3253 return name ++ @as([padding]u8, @splat(' '));
3323}3254}
33243255
3325// Archive files start with the ARMAG identifying string. Then follows a3256// 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 {...@@ -33,7 +33,8 @@ pub fn fromInt(comptime E: type, integer: anytype) ?E {
33pub fn EnumFieldStruct(comptime E: type, comptime Data: type, comptime field_default: ?Data) type {33pub fn EnumFieldStruct(comptime E: type, comptime Data: type, comptime field_default: ?Data) type {
34 @setEvalBranchQuota(@typeInfo(E).@"enum".field_names.len + eval_branch_quota_cushion);34 @setEvalBranchQuota(@typeInfo(E).@"enum".field_names.len + eval_branch_quota_cushion);
35 const default_ptr: ?*const anyopaque = if (field_default) |d| @ptrCast(&d) else null;35 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 }));
37}38}
3839
39/// Looks up the supplied field values in the given enum type.40/// 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 {...@@ -454,7 +455,7 @@ pub fn EnumMap(comptime E: type, comptime V: type) type {
454 }455 }
455 }456 }
456 } else {457 } else {
457 inline for (std.meta.fieldNames(E)) |field_name| {458 inline for (@typeInfo(E).@"enum".field_names) |field_name| {
458 const key = @field(E, field_name);459 const key = @field(E, field_name);
459 if (@field(init_values, field_name)) |*v| {460 if (@field(init_values, field_name)) |*v| {
460 const i = comptime Indexer.indexOf(key);461 const i = comptime Indexer.indexOf(key);
lib/std/fmt.zig+2-4
...@@ -261,7 +261,7 @@ test printInt {...@@ -261,7 +261,7 @@ test printInt {
261261
262/// Converts values in the range [0, 100) to a base 10 string.262/// Converts values in the range [0, 100) to a base 10 string.
263pub fn digits2(value: u8) [2]u8 {263pub fn digits2(value: u8) [2]u8 {
264 if (builtin.mode == .ReleaseSmall) {264 if (builtin.mode == .small) {
265 return .{ @intCast('0' + value / 10), @intCast('0' + value % 10) };265 return .{ @intCast('0' + value / 10), @intCast('0' + value % 10) };
266 } else {266 } else {
267 return "00010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899"[value * 2 ..][0..2].*;267 return "00010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899"[value * 2 ..][0..2].*;
...@@ -924,7 +924,7 @@ test "enum" {...@@ -924,7 +924,7 @@ test "enum" {
924924
925 // test very large enum to verify ct branch quota is large enough925 // test very large enum to verify ct branch quota is large enough
926 // TODO: https://github.com/ziglang/zig/issues/15609926 // 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)) {
928 try expectFmt("enum: .INVALID_FUNCTION\n", "enum: {}\n", .{std.os.windows.Win32Error.INVALID_FUNCTION});928 try expectFmt("enum: .INVALID_FUNCTION\n", "enum: {}\n", .{std.os.windows.Win32Error.INVALID_FUNCTION});
929 }929 }
930930
...@@ -1082,8 +1082,6 @@ test "float.libc.sanity" {...@@ -1082,8 +1082,6 @@ test "float.libc.sanity" {
1082}1082}
10831083
1084test "union" {1084test "union" {
1085 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1086
1087 const TU = union(enum) {1085 const TU = union(enum) {
1088 float: f32,1086 float: f32,
1089 int: u32,1087 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 {...@@ -65,7 +65,7 @@ pub fn render(buf: []u8, value: anytype, options: Options) Error![]const u8 {
6565
66 const DT = if (@bitSizeOf(T) <= 64) u64 else u128;66 const DT = if (@bitSizeOf(T) <= 64) u64 else u128;
67 const tables = switch (DT) {67 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,
69 u128 => &Backend128_Tables,69 u128 => &Backend128_Tables,
70 else => unreachable,70 else => unreachable,
71 };71 };
lib/std/fs/path.zig+9-3
...@@ -1830,7 +1830,7 @@ fn testRelativeWindows(from: []const u8, to: []const u8, expected_output: []cons...@@ -1830,7 +1830,7 @@ fn testRelativeWindows(from: []const u8, to: []const u8, expected_output: []cons
1830/// pointer address range of `path`, even if it is length zero.1830/// pointer address range of `path`, even if it is length zero.
1831pub fn extension(path: []const u8) []const u8 {1831pub fn extension(path: []const u8) []const u8 {
1832 const filename = basename(path);1832 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..];
1834 if (index == 0) return path[path.len..];1834 if (index == 0) return path[path.len..];
1835 return filename[index..];1835 return filename[index..];
1836}1836}
...@@ -1887,8 +1887,8 @@ test extension {...@@ -1887,8 +1887,8 @@ test extension {
1887/// - "hello/world/lib" ⇒ "lib"1887/// - "hello/world/lib" ⇒ "lib"
1888pub fn stem(path: []const u8) []const u8 {1888pub fn stem(path: []const u8) []const u8 {
1889 const filename = basename(path);1889 const filename = basename(path);
1890 const index = mem.lastIndexOfScalar(u8, filename, '.') orelse return filename[0..];1890 const index = mem.findScalarLast(u8, filename, '.') orelse return filename;
1891 if (index == 0) return path;1891 if (index == 0) return filename;
1892 return filename[0..index];1892 return filename[0..index];
1893}1893}
18941894
...@@ -1904,8 +1904,14 @@ test stem {...@@ -1904,8 +1904,14 @@ test stem {
1904 try testStem("hello...", "hello..");1904 try testStem("hello...", "hello..");
1905 try testStem("hello.", "hello");1905 try testStem("hello.", "hello");
1906 try testStem("/hello.", "hello");1906 try testStem("/hello.", "hello");
1907 try testStem("hello/world/.gitignore", ".gitignore");
1908 try testStem("/.gitignore", ".gitignore");
1907 try testStem(".gitignore", ".gitignore");1909 try testStem(".gitignore", ".gitignore");
1910 try testStem(".gitignore/", ".gitignore");
1911 try testStem("hello/world/.image.png", ".image");
1912 try testStem("/.image.png", ".image");
1908 try testStem(".image.png", ".image");1913 try testStem(".image.png", ".image");
1914 try testStem(".image.png/", ".image");
1909 try testStem("file.ext", "file");1915 try testStem("file.ext", "file");
1910 try testStem("file.ext.", "file.ext");1916 try testStem("file.ext.", "file.ext");
1911 try testStem("a.b.c", "a.b");1917 try testStem("a.b.c", "a.b");
lib/std/fs/test.zig+41-3
...@@ -758,6 +758,43 @@ test "readFileAlloc" {...@@ -758,6 +758,43 @@ test "readFileAlloc" {
758 );758 );
759}759}
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
761test "Dir.statFile" {798test "Dir.statFile" {
762 try testWithAllSupportedPathTypes(struct {799 try testWithAllSupportedPathTypes(struct {
763 fn impl(ctx: *TestContext) !void {800 fn impl(ctx: *TestContext) !void {
...@@ -902,6 +939,8 @@ test "createDirPathOpen parent dirs do not exist" {...@@ -902,6 +939,8 @@ test "createDirPathOpen parent dirs do not exist" {
902}939}
903940
904test "deleteDir" {941test "deleteDir" {
942 if (builtin.target.os.tag == .windows) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35686
943
905 try testWithAllSupportedPathTypes(struct {944 try testWithAllSupportedPathTypes(struct {
906 fn impl(ctx: *TestContext) !void {945 fn impl(ctx: *TestContext) !void {
907 const io = ctx.io;946 const io = ctx.io;
...@@ -2168,7 +2207,7 @@ test "'.' and '..' in absolute functions" {...@@ -2168,7 +2207,7 @@ test "'.' and '..' in absolute functions" {
2168}2207}
21692208
2170test "chmod" {2209test "chmod" {
2171 if (native_os == .windows or native_os == .wasi) return;2210 if (native_os == .windows or native_os == .wasi) return error.SkipZigTest;
21722211
2173 const io = testing.io;2212 const io = testing.io;
21742213
...@@ -2191,8 +2230,7 @@ test "chmod" {...@@ -2191,8 +2230,7 @@ test "chmod" {
2191}2230}
21922231
2193test "change ownership" {2232test "change ownership" {
2194 if (native_os == .windows or native_os == .wasi)2233 if (native_os == .windows or native_os == .wasi) return error.SkipZigTest;
2195 return error.SkipZigTest;
21962234
2197 const io = testing.io;2235 const io = testing.io;
21982236
lib/std/hash/auto_hash.zig+1-1
...@@ -225,7 +225,7 @@ fn testHashDeepRecursive(key: anytype) u64 {...@@ -225,7 +225,7 @@ fn testHashDeepRecursive(key: anytype) u64 {
225225
226test "typeContainsSlice" {226test "typeContainsSlice" {
227 comptime {227 comptime {
228 try testing.expect(!typeContainsSlice(std.meta.Tag(std.builtin.Type)));228 try testing.expect(!typeContainsSlice(std.meta.Tag(std.lang.Type)));
229229
230 try testing.expect(typeContainsSlice([]const u8));230 try testing.expect(typeContainsSlice([]const u8));
231 try testing.expect(!typeContainsSlice(u8));231 try testing.expect(!typeContainsSlice(u8));
lib/std/hash/benchmark.zig+1-1
...@@ -355,7 +355,7 @@ fn usage() void {...@@ -355,7 +355,7 @@ fn usage() void {
355}355}
356356
357fn mode(comptime x: comptime_int) comptime_int {357fn 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;
359}359}
360360
361pub fn main(init: std.process.Init) !void {361pub 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 {...@@ -16,7 +16,7 @@ fn fetch64(ptr: [*]const u8, offset: usize) u64 {
16pub const CityHash32 = struct {16pub const CityHash32 = struct {
17 const Self = @This();17 const Self = @This();
1818
19 // Magic numbers for 32-bit hashing. Copied from Murmur3.19 // Magic numbers for 32-bit hashing. Copied from Murmur3.
20 const c1: u32 = 0xcc9e2d51;20 const c1: u32 = 0xcc9e2d51;
21 const c2: u32 = 0x1b873593;21 const c2: u32 = 0x1b873593;
2222
lib/std/hash/xxhash.zig+1-5
...@@ -1,5 +1,4 @@...@@ -1,5 +1,4 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
3const mem = std.mem;2const mem = std.mem;
4const expectEqual = std.testing.expectEqual;3const expectEqual = std.testing.expectEqual;
54
...@@ -761,7 +760,7 @@ pub const XxHash3 = struct {...@@ -761,7 +760,7 @@ pub const XxHash3 = struct {
761 var accumulator_copy = self.accumulator;760 var accumulator_copy = self.accumulator;
762 var last_block_copy: [block_bytes]u8 = undefined;761 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.
765 return accumulator_copy.digest(self.total_len, last_block: {764 return accumulator_copy.digest(self.total_len, last_block: {
766 if (self.buffered >= block_bytes) {765 if (self.buffered >= block_bytes) {
767 const block_count = ((self.buffered - 1) / block_bytes) * block_bytes;766 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)...@@ -788,7 +787,6 @@ fn testExpect(comptime H: type, seed: anytype, input: []const u8, expected: u64)
788}787}
789788
790test "xxhash3" {789test "xxhash3" {
791 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
792 const H = XxHash3;790 const H = XxHash3;
793 // Non-Seeded Tests791 // Non-Seeded Tests
794 try testExpect(H, 0, "", 0x2d06800538d394c2);792 try testExpect(H, 0, "", 0x2d06800538d394c2);
...@@ -820,7 +818,6 @@ test "xxhash3" {...@@ -820,7 +818,6 @@ test "xxhash3" {
820}818}
821819
822test "xxhash3 smhasher" {820test "xxhash3 smhasher" {
823 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
824 const Test = struct {821 const Test = struct {
825 fn do() !void {822 fn do() !void {
826 try expectEqual(verify.smhasher(XxHash3.hash), 0x9a636405);823 try expectEqual(verify.smhasher(XxHash3.hash), 0x9a636405);
...@@ -832,7 +829,6 @@ test "xxhash3 smhasher" {...@@ -832,7 +829,6 @@ test "xxhash3 smhasher" {
832}829}
833830
834test "xxhash3 iterative api" {831test "xxhash3 iterative api" {
835 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
836 const Test = struct {832 const Test = struct {
837 fn do() !void {833 fn do() !void {
838 try verify.iterativeApi(XxHash3);834 try verify.iterativeApi(XxHash3);
lib/std/hash_map.zig+1-1
...@@ -1518,7 +1518,7 @@ fn Custom(...@@ -1518,7 +1518,7 @@ fn Custom(
1518 self.available = 0;1518 self.available = 0;
1519 }1519 }
15201520
1521 /// This function is used in the debugger pretty formatters in tools/ to fetch the1521 /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the
1522 /// header type to facilitate fancy debug printing for this type.1522 /// header type to facilitate fancy debug printing for this type.
1523 fn dbHelper(self: *Self, hdr: *Header, entry: *Entry) void {1523 fn dbHelper(self: *Self, hdr: *Header, entry: *Entry) void {
1524 _ = self;1524 _ = self;
lib/std/heap/PageAllocator.zig+1
...@@ -24,6 +24,7 @@ pub const vtable: Allocator.VTable = .{...@@ -24,6 +24,7 @@ pub const vtable: Allocator.VTable = .{
24/// that don't provide a hint (for security reasons, but it serves our needs24/// that don't provide a hint (for security reasons, but it serves our needs
25/// too).25/// too).
26const enable_hints = switch (builtin.target.os.tag) {26const enable_hints = switch (builtin.target.os.tag) {
27 .linux => !builtin.target.cpu.arch.isSPARC(), // https://bugzilla.kernel.org/show_bug.cgi?id=221820
27 .openbsd => false,28 .openbsd => false,
28 else => true,29 else => true,
29};30};
lib/std/heap/SafeAllocator.zig+2-2
...@@ -39,7 +39,7 @@ const SafeAllocator = @This();...@@ -39,7 +39,7 @@ const SafeAllocator = @This();
39const scoped_log = std.log.scoped(.SafeAllocator);39const scoped_log = std.log.scoped(.SafeAllocator);
4040
41pub const Options = struct {41pub const Options = struct {
42 const is_debug = @import("builtin").mode == .Debug;42 const is_debug = @import("builtin").mode == .debug;
43 const page_size_log2 = @max(math.log2_int(usize, std.heap.page_size_max), 8);43 const page_size_log2 = @max(math.log2_int(usize, std.heap.page_size_max), 8);
4444
45 stack_trace_frames: usize = if (is_debug and std.debug.sys_can_stack_trace) 7 else 0,45 stack_trace_frames: usize = if (is_debug and std.debug.sys_can_stack_trace) 7 else 0,
...@@ -1519,7 +1519,7 @@ const FuzzSingleThreadedAllocator = struct {...@@ -1519,7 +1519,7 @@ const FuzzSingleThreadedAllocator = struct {
1519 @disableInstrumentation();1519 @disableInstrumentation();
15201520
1521 const allocs_slice = f.allocs.slice();1521 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(
1523 "invalid SafeAllocator free of {f}",1523 "invalid SafeAllocator free of {f}",
1524 .{FormatMemory{ .memory = memory, .alignment = alignment }},1524 .{FormatMemory{ .memory = memory, .alignment = alignment }},
1525 );1525 );
lib/std/http.zig+8-5
...@@ -20,6 +20,8 @@ pub const Version = enum {...@@ -20,6 +20,8 @@ pub const Version = enum {
20/// https://datatracker.ietf.org/doc/html/rfc7231#section-4 Initial definition20/// https://datatracker.ietf.org/doc/html/rfc7231#section-4 Initial definition
21///21///
22/// https://datatracker.ietf.org/doc/html/rfc5789#section-2 PATCH22/// https://datatracker.ietf.org/doc/html/rfc5789#section-2 PATCH
23///
24/// https://datatracker.ietf.org/doc/html/rfc10008#name-query-method QUERY
23pub const Method = enum {25pub const Method = enum {
24 GET,26 GET,
25 HEAD,27 HEAD,
...@@ -30,12 +32,13 @@ pub const Method = enum {...@@ -30,12 +32,13 @@ pub const Method = enum {
30 OPTIONS,32 OPTIONS,
31 TRACE,33 TRACE,
32 PATCH,34 PATCH,
35 QUERY,
3336
34 /// Returns true if a request of this method is allowed to have a body37 /// Returns true if a request of this method is allowed to have a body
35 /// Actual behavior from servers may vary and should still be checked38 /// Actual behavior from servers may vary and should still be checked
36 pub fn requestHasBody(m: Method) bool {39 pub fn requestHasBody(m: Method) bool {
37 return switch (m) {40 return switch (m) {
38 .POST, .PUT, .PATCH => true,41 .POST, .PUT, .PATCH, .QUERY => true,
39 .GET, .HEAD, .DELETE, .CONNECT, .OPTIONS, .TRACE => false,42 .GET, .HEAD, .DELETE, .CONNECT, .OPTIONS, .TRACE => false,
40 };43 };
41 }44 }
...@@ -44,7 +47,7 @@ pub const Method = enum {...@@ -44,7 +47,7 @@ pub const Method = enum {
44 /// Actual behavior from clients may vary and should still be checked47 /// Actual behavior from clients may vary and should still be checked
45 pub fn responseHasBody(m: Method) bool {48 pub fn responseHasBody(m: Method) bool {
46 return switch (m) {49 return switch (m) {
47 .GET, .POST, .PUT, .DELETE, .CONNECT, .OPTIONS, .PATCH => true,50 .GET, .POST, .PUT, .DELETE, .CONNECT, .OPTIONS, .PATCH, .QUERY => true,
48 .HEAD, .TRACE => false,51 .HEAD, .TRACE => false,
49 };52 };
50 }53 }
...@@ -56,7 +59,7 @@ pub const Method = enum {...@@ -56,7 +59,7 @@ pub const Method = enum {
56 /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.159 /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.1
57 pub fn safe(m: Method) bool {60 pub fn safe(m: Method) bool {
58 return switch (m) {61 return switch (m) {
59 .GET, .HEAD, .OPTIONS, .TRACE => true,62 .GET, .HEAD, .OPTIONS, .TRACE, .QUERY => true,
60 .POST, .PUT, .DELETE, .CONNECT, .PATCH => false,63 .POST, .PUT, .DELETE, .CONNECT, .PATCH => false,
61 };64 };
62 }65 }
...@@ -70,7 +73,7 @@ pub const Method = enum {...@@ -70,7 +73,7 @@ pub const Method = enum {
70 /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.273 /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.2
71 pub fn idempotent(m: Method) bool {74 pub fn idempotent(m: Method) bool {
72 return switch (m) {75 return switch (m) {
73 .GET, .HEAD, .PUT, .DELETE, .OPTIONS, .TRACE => true,76 .GET, .HEAD, .PUT, .DELETE, .OPTIONS, .TRACE, .QUERY => true,
74 .CONNECT, .POST, .PATCH => false,77 .CONNECT, .POST, .PATCH => false,
75 };78 };
76 }79 }
...@@ -83,7 +86,7 @@ pub const Method = enum {...@@ -83,7 +86,7 @@ pub const Method = enum {
83 /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.386 /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.3
84 pub fn cacheable(m: Method) bool {87 pub fn cacheable(m: Method) bool {
85 return switch (m) {88 return switch (m) {
86 .GET, .HEAD => true,89 .GET, .HEAD, .QUERY => true,
87 .POST, .PUT, .DELETE, .CONNECT, .OPTIONS, .TRACE, .PATCH => false,90 .POST, .PUT, .DELETE, .CONNECT, .OPTIONS, .TRACE, .PATCH => false,
88 };91 };
89 }92 }
lib/std/http/Server.zig+1-1
...@@ -102,7 +102,7 @@ pub const Request = struct {...@@ -102,7 +102,7 @@ pub const Request = struct {
102 const method = std.meta.stringToEnum(http.Method, first_line[0..method_end]) orelse102 const method = std.meta.stringToEnum(http.Method, first_line[0..method_end]) orelse
103 return error.UnknownHttpMethod;103 return error.UnknownHttpMethod;
104104
105 const version_start = mem.lastIndexOfScalar(u8, first_line, ' ') orelse105 const version_start = mem.findScalarLast(u8, first_line, ' ') orelse
106 return error.HttpHeadersInvalid;106 return error.HttpHeadersInvalid;
107 if (version_start == method_end) return error.HttpHeadersInvalid;107 if (version_start == method_end) return error.HttpHeadersInvalid;
108108
lib/std/http/test.zig+1-20
...@@ -1,5 +1,4 @@...@@ -1,5 +1,4 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
2const native_endian = builtin.cpu.arch.endian();
32
4const std = @import("std");3const std = @import("std");
5const http = std.http;4const http = std.http;
...@@ -34,7 +33,6 @@ test "content length reader state update" {...@@ -34,7 +33,6 @@ test "content length reader state update" {
34}33}
3534
36test "trailers" {35test "trailers" {
37 if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257
38 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/3080636 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
3937
40 const io = std.testing.io;38 const io = std.testing.io;
...@@ -121,7 +119,6 @@ test "trailers" {...@@ -121,7 +119,6 @@ test "trailers" {
121}119}
122120
123test "HTTP server handles a chunked transfer coding request" {121test "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
125 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806122 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
126123
127 const io = std.testing.io;124 const io = std.testing.io;
...@@ -190,7 +187,6 @@ test "HTTP server handles a chunked transfer coding request" {...@@ -190,7 +187,6 @@ test "HTTP server handles a chunked transfer coding request" {
190}187}
191188
192test "echo content server" {189test "echo content server" {
193 if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257
194 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806190 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
195191
196 const io = std.testing.io;192 const io = std.testing.io;
...@@ -281,12 +277,11 @@ test "echo content server" {...@@ -281,12 +277,11 @@ test "echo content server" {
281}277}
282278
283test "Server.Request.respondStreaming non-chunked, unknown content-length" {279test "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
285 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806280 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
286281
287 const io = std.testing.io;282 const io = std.testing.io;
288283
289 if (builtin.os.tag == .windows) {284 if (builtin.cpu.arch == .aarch64 and builtin.os.tag == .windows) {
290 // https://github.com/ziglang/zig/issues/21457285 // https://github.com/ziglang/zig/issues/21457
291 return error.SkipZigTest;286 return error.SkipZigTest;
292 }287 }
...@@ -360,7 +355,6 @@ test "Server.Request.respondStreaming non-chunked, unknown content-length" {...@@ -360,7 +355,6 @@ test "Server.Request.respondStreaming non-chunked, unknown content-length" {
360}355}
361356
362test "receiving arbitrary http headers from the client" {357test "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
364 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806358 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
365359
366 const io = std.testing.io;360 const io = std.testing.io;
...@@ -426,16 +420,10 @@ test "receiving arbitrary http headers from the client" {...@@ -426,16 +420,10 @@ test "receiving arbitrary http headers from the client" {
426}420}
427421
428test "general client/server API coverage" {422test "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
430 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806423 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
431424
432 const io = std.testing.io;425 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
439 const test_server = try createTestServer(io, struct {427 const test_server = try createTestServer(io, struct {
440 fn run(test_server: *TestServer) anyerror!void {428 fn run(test_server: *TestServer) anyerror!void {
441 const net_server = &test_server.net_server;429 const net_server = &test_server.net_server;
...@@ -922,7 +910,6 @@ test "general client/server API coverage" {...@@ -922,7 +910,6 @@ test "general client/server API coverage" {
922}910}
923911
924test "Server streams both reading and writing" {912test "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
926 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806913 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
927914
928 const io = std.testing.io;915 const io = std.testing.io;
...@@ -1162,10 +1149,6 @@ const TestServer = struct {...@@ -1162,10 +1149,6 @@ const TestServer = struct {
11621149
1163fn createTestServer(io: Io, S: type) !*TestServer {1150fn createTestServer(io: Io, S: type) !*TestServer {
1164 if (builtin.single_threaded) return error.SkipZigTest;1151 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
1170 const address = try net.IpAddress.parse("127.0.0.1", 0);1153 const address = try net.IpAddress.parse("127.0.0.1", 0);
11711154
...@@ -1192,7 +1175,6 @@ fn createTestServer(io: Io, S: type) !*TestServer {...@@ -1192,7 +1175,6 @@ fn createTestServer(io: Io, S: type) !*TestServer {
1192}1175}
11931176
1194test "redirect to different connection" {1177test "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
1196 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/308061178 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
11971179
1198 const io = std.testing.io;1180 const io = std.testing.io;
...@@ -1280,7 +1262,6 @@ test "redirect to different connection" {...@@ -1280,7 +1262,6 @@ test "redirect to different connection" {
1280}1262}
12811263
1282test "boot failed connections from the pool" {1264test "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
1284 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/308061265 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
12851266
1286 const io = std.testing.io;1267 const io = std.testing.io;
lib/std/json/Stringify.zig+3-3
...@@ -54,8 +54,8 @@ else...@@ -54,8 +54,8 @@ else
54 void = if (build_mode_has_safety) .none else {},54 void = if (build_mode_has_safety) .none else {},
5555
56const build_mode_has_safety = switch (@import("builtin").mode) {56const build_mode_has_safety = switch (@import("builtin").mode) {
57 .Debug, .ReleaseSafe => true,57 .debug, .safe => true,
58 .ReleaseFast, .ReleaseSmall => false,58 .fast, .small => false,
59};59};
6060
61/// The `safety_checks_hint` parameter determines how much memory is used to enable assertions that the above grammar is being followed,61/// 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) {...@@ -66,7 +66,7 @@ const build_mode_has_safety = switch (@import("builtin").mode) {
66/// If `.checked_to_fixed_depth` is used, there is additionally an assertion that the nesting depth never exceeds the given limit.66/// If `.checked_to_fixed_depth` is used, there is additionally an assertion that the nesting depth never exceeds the given limit.
67/// `.checked_to_fixed_depth` embeds the storage required in the `Stringify` struct.67/// `.checked_to_fixed_depth` embeds the storage required in the `Stringify` struct.
68/// `.assumed_correct` requires no space and performs none of these assertions.68/// `.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`.
70const safety_checks_hint: union(enum) {70const safety_checks_hint: union(enum) {
71 /// Rounded up to the nearest multiple of 8.71 /// Rounded up to the nearest multiple of 8.
72 checked_to_fixed_depth: usize,72 checked_to_fixed_depth: usize,
lib/std/lang.zig+47-5
...@@ -107,13 +107,52 @@ pub const CodeModel = enum(u4) {...@@ -107,13 +107,52 @@ pub const CodeModel = enum(u4) {
107 tiny,107 tiny,
108};108};
109109
110/// Deprecated, to be removed after 0.18.0
111pub const OptimizeMode = Optimize;
112
110/// This data structure is used by the Zig language code generation and113/// This data structure is used by the Zig language code generation and
111/// therefore must be kept in sync with the compiler implementation.114/// therefore must be kept in sync with the compiler implementation.
112pub const OptimizeMode = enum {115pub const Optimize = enum {
113 Debug,116 /// Safety checks enabled. Optimize for bug detection, accurate debug info,
114 ReleaseSafe,117 /// and compilation speed (in that order).
115 ReleaseFast,118 debug,
116 ReleaseSmall,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 }
117};156};
118157
119/// The calling convention of a function defines how arguments and return values are passed, as well158/// 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)) {...@@ -171,10 +210,12 @@ pub const CallingConvention = union(enum(u8)) {
171 x86_64_regcall_v4_win: CommonOptions,210 x86_64_regcall_v4_win: CommonOptions,
172 x86_64_vectorcall: CommonOptions,211 x86_64_vectorcall: CommonOptions,
173 x86_64_interrupt: CommonOptions,212 x86_64_interrupt: CommonOptions,
213 x86_64_preserve_none: CommonOptions,
174214
175 // Calling conventions for the `x86` architecture.215 // Calling conventions for the `x86` architecture.
176 x86_sysv: X86RegparmOptions,216 x86_sysv: X86RegparmOptions,
177 x86_win: X86RegparmOptions,217 x86_win: X86RegparmOptions,
218 x86_mingw: X86RegparmOptions,
178 x86_stdcall: X86RegparmOptions,219 x86_stdcall: X86RegparmOptions,
179 x86_fastcall: CommonOptions,220 x86_fastcall: CommonOptions,
180 x86_thiscall: CommonOptions,221 x86_thiscall: CommonOptions,
...@@ -197,6 +238,7 @@ pub const CallingConvention = union(enum(u8)) {...@@ -197,6 +238,7 @@ pub const CallingConvention = union(enum(u8)) {
197 aarch64_aapcs_win: CommonOptions,238 aarch64_aapcs_win: CommonOptions,
198 aarch64_vfabi: CommonOptions,239 aarch64_vfabi: CommonOptions,
199 aarch64_vfabi_sve: CommonOptions,240 aarch64_vfabi_sve: CommonOptions,
241 aarch64_preserve_none: CommonOptions,
200242
201 /// The standard `alpha` calling convention.243 /// The standard `alpha` calling convention.
202 alpha_osf: CommonOptions,244 alpha_osf: CommonOptions,
lib/std/log.zig+1-1
...@@ -53,7 +53,7 @@ pub const Level = enum {...@@ -53,7 +53,7 @@ pub const Level = enum {
53/// The default log level is based on build mode.53/// The default log level is based on build mode.
54pub const default_level: Level = switch (builtin.mode) {54pub const default_level: Level = switch (builtin.mode) {
55 .Debug => .debug,55 .Debug => .debug,
56 .ReleaseSafe, .ReleaseFast, .ReleaseSmall => .info,56 .safe, .fast, .small => .info,
57};57};
5858
59pub const ScopeLevel = struct {59pub const ScopeLevel = struct {
lib/std/macho.zig+19
...@@ -588,6 +588,25 @@ pub const rpath_command = extern struct {...@@ -588,6 +588,25 @@ pub const rpath_command = extern struct {
588 path: u32,588 path: u32,
589};589};
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
591/// The segment load command indicates that a part of this file is to be610/// The segment load command indicates that a part of this file is to be
592/// mapped into the task's address space. The size of this segment in memory,611/// mapped into the task's address space. The size of this segment in memory,
593/// vmsize, maybe equal to or larger than the amount to map from this file,612/// 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;...@@ -75,7 +75,7 @@ pub const snan = float.snan;
75///75///
76/// NaN values are never considered equal to any value.76/// NaN values are never considered equal to any value.
77pub fn approxEqAbs(comptime T: type, x: T, y: T, tolerance: T) bool {77pub 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);
79 assert(tolerance >= 0);79 assert(tolerance >= 0);
8080
81 // Fast path for equal values (and signed zeros and infinites).81 // 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 {...@@ -103,7 +103,7 @@ pub fn approxEqAbs(comptime T: type, x: T, y: T, tolerance: T) bool {
103///103///
104/// NaN values are never considered equal to any value.104/// NaN values are never considered equal to any value.
105pub fn approxEqRel(comptime T: type, x: T, y: T, tolerance: T) bool {105pub 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);
107 assert(tolerance > 0);107 assert(tolerance > 0);
108108
109 // Fast path for equal values (and signed zeros and infinites).109 // Fast path for equal values (and signed zeros and infinites).
...@@ -461,7 +461,7 @@ pub fn wrap(x: anytype, r: anytype) @TypeOf(x) {...@@ -461,7 +461,7 @@ pub fn wrap(x: anytype, r: anytype) @TypeOf(x) {
461 }461 }
462}462}
463test wrap {463test 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) {
465 // https://codeberg.org/ziglang/zig/issues/35520465 // https://codeberg.org/ziglang/zig/issues/35520
466 return error.SkipZigTest;466 return error.SkipZigTest;
467 }467 }
...@@ -1385,7 +1385,8 @@ pub fn lerp(a: anytype, b: anytype, t: anytype) @TypeOf(a, b, t) {...@@ -1385,7 +1385,8 @@ pub fn lerp(a: anytype, b: anytype, t: anytype) @TypeOf(a, b, t) {
1385}1385}
13861386
1387test lerp {1387test lerp {
1388 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/178841388 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;
1389 if (builtin.zig_backend == .stage2_x86_64 and !comptime builtin.cpu.has(.x86, .fma)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/178841390 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
1391 try testing.expectEqual(@as(f64, 75), lerp(50, 100, 0.5));1392 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 {...@@ -337,8 +337,6 @@ fn acosBinary128(x: f128) f128 {
337}337}
338338
339test "acosBinary16.special" {339test "acosBinary16.special" {
340 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
341
342 try testing.expectApproxEqAbs(0x1.92p0, acosBinary16(0x0p+0), math.floatEpsAt(f16, 0x1.92p0));340 try testing.expectApproxEqAbs(0x1.92p0, acosBinary16(0x0p+0), math.floatEpsAt(f16, 0x1.92p0));
343 try testing.expectApproxEqAbs(0x1.92p1, acosBinary16(-0x1p+0), math.floatEpsAt(f16, 0x1.92p1));341 try testing.expectApproxEqAbs(0x1.92p1, acosBinary16(-0x1p+0), math.floatEpsAt(f16, 0x1.92p1));
344 try testing.expectEqual(0x0p+0, acosBinary16(0x1p+0));342 try testing.expectEqual(0x0p+0, acosBinary16(0x1p+0));
...@@ -350,8 +348,6 @@ test "acosBinary16.special" {...@@ -350,8 +348,6 @@ test "acosBinary16.special" {
350}348}
351349
352test "acosBinary16" {350test "acosBinary16" {
353 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
354
355 try testing.expectApproxEqAbs(0x1.834p0, acosBinary16(0x1.db4p-5), math.floatEpsAt(f16, 0x1.834p0));351 try testing.expectApproxEqAbs(0x1.834p0, acosBinary16(0x1.db4p-5), math.floatEpsAt(f16, 0x1.834p0));
356 try testing.expectApproxEqAbs(0x1.d48p0, acosBinary16(-0x1.068p-2), math.floatEpsAt(f16, 0x1.d48p0));352 try testing.expectApproxEqAbs(0x1.d48p0, acosBinary16(-0x1.068p-2), math.floatEpsAt(f16, 0x1.d48p0));
357 try testing.expectApproxEqAbs(0x1.b7cp0, acosBinary16(-0x1.2c4p-3), math.floatEpsAt(f16, 0x1.b7cp0));353 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 {...@@ -326,8 +326,6 @@ fn asinBinary128(x: f128) f128 {
326}326}
327327
328test "asinBinary16.special" {328test "asinBinary16.special" {
329 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
330
331 try testing.expectApproxEqAbs(0x1.92p0, asinBinary16(0x1p+0), math.floatEpsAt(f16, 0x1.92p0));329 try testing.expectApproxEqAbs(0x1.92p0, asinBinary16(0x1p+0), math.floatEpsAt(f16, 0x1.92p0));
332 try testing.expectApproxEqAbs(-0x1.92p0, asinBinary16(-0x1p+0), math.floatEpsAt(f16, -0x1.92p0));330 try testing.expectApproxEqAbs(-0x1.92p0, asinBinary16(-0x1p+0), math.floatEpsAt(f16, -0x1.92p0));
333 try testing.expectEqual(0x0p+0, asinBinary16(0x0p+0));331 try testing.expectEqual(0x0p+0, asinBinary16(0x0p+0));
...@@ -340,8 +338,6 @@ test "asinBinary16.special" {...@@ -340,8 +338,6 @@ test "asinBinary16.special" {
340}338}
341339
342test "asinBinary16" {340test "asinBinary16" {
343 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
344
345 try testing.expectApproxEqAbs(-0x1.e4cp-6, asinBinary16(-0x1.e4cp-6), math.floatEpsAt(f16, -0x1.e4cp-6));341 try testing.expectApproxEqAbs(-0x1.e4cp-6, asinBinary16(-0x1.e4cp-6), math.floatEpsAt(f16, -0x1.e4cp-6));
346 try testing.expectApproxEqAbs(0x1.2a8p0, asinBinary16(0x1.d68p-1), math.floatEpsAt(f16, 0x1.2a8p0));342 try testing.expectApproxEqAbs(0x1.2a8p0, asinBinary16(0x1.d68p-1), math.floatEpsAt(f16, 0x1.2a8p0));
347 try testing.expectApproxEqAbs(-0x1.eep-1, asinBinary16(-0x1.a4cp-1), math.floatEpsAt(f16, -0x1.eep-1));343 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 {...@@ -481,8 +481,6 @@ fn atanBinary128(x: f128) f128 {
481}481}
482482
483test "atanBinary16.special" {483test "atanBinary16.special" {
484 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
485
486 try testing.expectEqual(0x0p+0, atanBinary16(0x0p+0));484 try testing.expectEqual(0x0p+0, atanBinary16(0x0p+0));
487 try testing.expectEqual(-0x0p+0, atanBinary16(-0x0p+0));485 try testing.expectEqual(-0x0p+0, atanBinary16(-0x0p+0));
488 try testing.expectApproxEqAbs(0x1.92p-1, atanBinary16(0x1p+0), math.floatEpsAt(f16, 0x1.92p-1));486 try testing.expectApproxEqAbs(0x1.92p-1, atanBinary16(0x1p+0), math.floatEpsAt(f16, 0x1.92p-1));
...@@ -493,8 +491,6 @@ test "atanBinary16.special" {...@@ -493,8 +491,6 @@ test "atanBinary16.special" {
493}491}
494492
495test "atanBinary16" {493test "atanBinary16" {
496 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
497
498 try testing.expectApproxEqAbs(-0x1.74cp-2, atanBinary16(-0x1.864p-2), math.floatEpsAt(f16, -0x1.74cp-2));494 try testing.expectApproxEqAbs(-0x1.74cp-2, atanBinary16(-0x1.864p-2), math.floatEpsAt(f16, -0x1.74cp-2));
499 try testing.expectApproxEqAbs(-0x1.374p0, atanBinary16(-0x1.59cp1), math.floatEpsAt(f16, -0x1.374p0));495 try testing.expectApproxEqAbs(-0x1.374p0, atanBinary16(-0x1.59cp1), math.floatEpsAt(f16, -0x1.374p0));
500 try testing.expectApproxEqAbs(-0x1.11cp0, atanBinary16(-0x1.d2cp0), math.floatEpsAt(f16, -0x1.11cp0));496 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" {...@@ -252,8 +252,8 @@ test "atan2_32.special" {
252252
253 try expect(math.isNan(atan2_32(1.0, math.nan(f32))));253 try expect(math.isNan(atan2_32(1.0, math.nan(f32))));
254 try expect(math.isNan(atan2_32(math.nan(f32), 1.0)));254 try expect(math.isNan(atan2_32(math.nan(f32), 1.0)));
255 try expect(atan2_32(0.0, 5.0) == 0.0);255 try expect(math.isPositiveZero(atan2_32(0.0, 5.0)));
256 try expect(atan2_32(-0.0, 5.0) == -0.0);256 try expect(math.isNegativeZero(atan2_32(-0.0, 5.0)));
257 try expect(math.approxEqAbs(f32, atan2_32(0.0, -5.0), math.pi, epsilon));257 try expect(math.approxEqAbs(f32, atan2_32(0.0, -5.0), math.pi, epsilon));
258 //expect(math.approxEqAbs(f32, atan2_32(-0.0, -5.0), -math.pi, .{.rel=0,.abs=epsilon})); TODO support negative zero?258 //expect(math.approxEqAbs(f32, atan2_32(-0.0, -5.0), -math.pi, .{.rel=0,.abs=epsilon})); TODO support negative zero?
259 try expect(math.approxEqAbs(f32, atan2_32(1.0, 0.0), math.pi / 2.0, epsilon));259 try expect(math.approxEqAbs(f32, atan2_32(1.0, 0.0), math.pi / 2.0, epsilon));
...@@ -276,8 +276,8 @@ test "atan2_64.special" {...@@ -276,8 +276,8 @@ test "atan2_64.special" {
276276
277 try expect(math.isNan(atan2_64(1.0, math.nan(f64))));277 try expect(math.isNan(atan2_64(1.0, math.nan(f64))));
278 try expect(math.isNan(atan2_64(math.nan(f64), 1.0)));278 try expect(math.isNan(atan2_64(math.nan(f64), 1.0)));
279 try expect(atan2_64(0.0, 5.0) == 0.0);279 try expect(math.isPositiveZero(atan2_64(0.0, 5.0)));
280 try expect(atan2_64(-0.0, 5.0) == -0.0);280 try expect(math.isNegativeZero(atan2_64(-0.0, 5.0)));
281 try expect(math.approxEqAbs(f64, atan2_64(0.0, -5.0), math.pi, epsilon));281 try expect(math.approxEqAbs(f64, atan2_64(0.0, -5.0), math.pi, epsilon));
282 //expect(math.approxEqAbs(f64, atan2_64(-0.0, -5.0), -math.pi, .{.rel=0,.abs=epsilon})); TODO support negative zero?282 //expect(math.approxEqAbs(f64, atan2_64(-0.0, -5.0), -math.pi, .{.rel=0,.abs=epsilon})); TODO support negative zero?
283 try expect(math.approxEqAbs(f64, atan2_64(1.0, 0.0), math.pi / 2.0, epsilon));283 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 @@...@@ -1,5 +1,4 @@
1const std = @import("../../std.zig");1const std = @import("../../std.zig");
2const builtin = @import("builtin");
3const mem = std.mem;2const mem = std.mem;
4const testing = std.testing;3const testing = std.testing;
5const Managed = std.math.big.int.Managed;4const Managed = std.math.big.int.Managed;
...@@ -276,8 +275,6 @@ fn setFloat(comptime Float: type) !void {...@@ -276,8 +275,6 @@ fn setFloat(comptime Float: type) !void {
276 try expectNormalized(1 << 10, res.toConst());275 try expectNormalized(1 << 10, res.toConst());
277}276}
278test setFloat {277test setFloat {
279 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
280
281 try setFloat(f16);278 try setFloat(f16);
282 try setFloat(f32);279 try setFloat(f32);
283 try setFloat(f64);280 try setFloat(f64);
...@@ -484,7 +481,6 @@ fn toFloat(comptime Float: type) !void {...@@ -484,7 +481,6 @@ fn toFloat(comptime Float: type) !void {
484 );481 );
485}482}
486test toFloat {483test toFloat {
487 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
488 try toFloat(f16);484 try toFloat(f16);
489 try toFloat(f32);485 try toFloat(f32);
490 try toFloat(f64);486 try toFloat(f64);
...@@ -1391,8 +1387,6 @@ test "mul multi-single" {...@@ -1391,8 +1387,6 @@ test "mul multi-single" {
1391}1387}
13921388
1393test "mul multi-multi" {1389test "mul multi-multi" {
1394 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1395
1396 var op1: u256 = 0x998888efefefefefefefef;1390 var op1: u256 = 0x998888efefefefefefefef;
1397 var op2: u256 = 0x333000abababababababab;1391 var op2: u256 = 0x333000abababababababab;
1398 _ = .{ &op1, &op2 };1392 _ = .{ &op1, &op2 };
...@@ -1514,8 +1508,6 @@ test "mulWrap single-single signed" {...@@ -1514,8 +1508,6 @@ test "mulWrap single-single signed" {
1514}1508}
15151509
1516test "mulWrap multi-multi unsigned" {1510test "mulWrap multi-multi unsigned" {
1517 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1518
1519 var op1: u256 = 0x998888efefefefefefefef;1511 var op1: u256 = 0x998888efefefefefefefef;
1520 var op2: u256 = 0x333000abababababababab;1512 var op2: u256 = 0x333000abababababababab;
1521 _ = .{ &op1, &op2 };1513 _ = .{ &op1, &op2 };
...@@ -1533,11 +1525,6 @@ test "mulWrap multi-multi unsigned" {...@@ -1533,11 +1525,6 @@ test "mulWrap multi-multi unsigned" {
1533}1525}
15341526
1535test "mulWrap multi-multi signed" {1527test "mulWrap multi-multi signed" {
1536 switch (builtin.zig_backend) {
1537 .stage2_c => return error.SkipZigTest,
1538 else => {},
1539 }
1540
1541 var a = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb) - 1);1528 var a = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb) - 1);
1542 defer a.deinit();1529 defer a.deinit();
1543 var b = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb));1530 var b = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb));
...@@ -1744,8 +1731,6 @@ test "div q=0 alias" {...@@ -1744,8 +1731,6 @@ test "div q=0 alias" {
1744}1731}
17451732
1746test "div multi-multi q < r" {1733test "div multi-multi q < r" {
1747 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1748
1749 const op1 = 0x1ffffffff0078f432;1734 const op1 = 0x1ffffffff0078f432;
1750 const op2 = 0x1ffffffff01000000;1735 const op2 = 0x1ffffffff01000000;
1751 var a = try Managed.initSet(testing.allocator, op1);1736 var a = try Managed.initSet(testing.allocator, op1);
...@@ -2166,8 +2151,6 @@ test "div ceil multi-limb" {...@@ -2166,8 +2151,6 @@ test "div ceil multi-limb" {
2166}2151}
21672152
2168test "div multi-multi with rem" {2153test "div multi-multi with rem" {
2169 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2170
2171 var a = try Managed.initSet(testing.allocator, 0x8888999911110000ffffeeeeddddccccbbbbaaaa9999);2154 var a = try Managed.initSet(testing.allocator, 0x8888999911110000ffffeeeeddddccccbbbbaaaa9999);
2172 defer a.deinit();2155 defer a.deinit();
2173 var b = try Managed.initSet(testing.allocator, 0x99990000111122223333);2156 var b = try Managed.initSet(testing.allocator, 0x99990000111122223333);
...@@ -2184,8 +2167,6 @@ test "div multi-multi with rem" {...@@ -2184,8 +2167,6 @@ test "div multi-multi with rem" {
2184}2167}
21852168
2186test "div multi-multi no rem" {2169test "div multi-multi no rem" {
2187 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2188
2189 var a = try Managed.initSet(testing.allocator, 0x8888999911110000ffffeeeedb4fec200ee3a4286361);2170 var a = try Managed.initSet(testing.allocator, 0x8888999911110000ffffeeeedb4fec200ee3a4286361);
2190 defer a.deinit();2171 defer a.deinit();
2191 var b = try Managed.initSet(testing.allocator, 0x99990000111122223333);2172 var b = try Managed.initSet(testing.allocator, 0x99990000111122223333);
...@@ -2202,8 +2183,6 @@ test "div multi-multi no rem" {...@@ -2202,8 +2183,6 @@ test "div multi-multi no rem" {
2202}2183}
22032184
2204test "div multi-multi (2 branch)" {2185test "div multi-multi (2 branch)" {
2205 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2206
2207 var a = try Managed.initSet(testing.allocator, 0x866666665555555588888887777777761111111111111111);2186 var a = try Managed.initSet(testing.allocator, 0x866666665555555588888887777777761111111111111111);
2208 defer a.deinit();2187 defer a.deinit();
2209 var b = try Managed.initSet(testing.allocator, 0x86666666555555554444444433333333);2188 var b = try Managed.initSet(testing.allocator, 0x86666666555555554444444433333333);
...@@ -2220,8 +2199,6 @@ test "div multi-multi (2 branch)" {...@@ -2220,8 +2199,6 @@ test "div multi-multi (2 branch)" {
2220}2199}
22212200
2222test "div multi-multi (3.1/3.3 branch)" {2201test "div multi-multi (3.1/3.3 branch)" {
2223 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2224
2225 var a = try Managed.initSet(testing.allocator, 0x11111111111111111111111111111111111111111111111111111111111111);2202 var a = try Managed.initSet(testing.allocator, 0x11111111111111111111111111111111111111111111111111111111111111);
2226 defer a.deinit();2203 defer a.deinit();
2227 var b = try Managed.initSet(testing.allocator, 0x1111111111111111111111111111111111111111171);2204 var b = try Managed.initSet(testing.allocator, 0x1111111111111111111111111111111111111111171);
...@@ -2238,8 +2215,6 @@ test "div multi-multi (3.1/3.3 branch)" {...@@ -2238,8 +2215,6 @@ test "div multi-multi (3.1/3.3 branch)" {
2238}2215}
22392216
2240test "div multi-single zero-limb trailing" {2217test "div multi-single zero-limb trailing" {
2241 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2242
2243 var a = try Managed.initSet(testing.allocator, 0x60000000000000000000000000000000000000000000000000000000000000000);2218 var a = try Managed.initSet(testing.allocator, 0x60000000000000000000000000000000000000000000000000000000000000000);
2244 defer a.deinit();2219 defer a.deinit();
2245 var b = try Managed.initSet(testing.allocator, 0x10000000000000000);2220 var b = try Managed.initSet(testing.allocator, 0x10000000000000000);
...@@ -2258,8 +2233,6 @@ test "div multi-single zero-limb trailing" {...@@ -2258,8 +2233,6 @@ test "div multi-single zero-limb trailing" {
2258}2233}
22592234
2260test "div multi-multi zero-limb trailing (with rem)" {2235test "div multi-multi zero-limb trailing (with rem)" {
2261 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2262
2263 var a = try Managed.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000);2236 var a = try Managed.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000);
2264 defer a.deinit();2237 defer a.deinit();
2265 var b = try Managed.initSet(testing.allocator, 0x8666666655555555444444443333333300000000000000000000000000000000);2238 var b = try Managed.initSet(testing.allocator, 0x8666666655555555444444443333333300000000000000000000000000000000);
...@@ -2279,8 +2252,6 @@ test "div multi-multi zero-limb trailing (with rem)" {...@@ -2279,8 +2252,6 @@ test "div multi-multi zero-limb trailing (with rem)" {
2279}2252}
22802253
2281test "div multi-multi zero-limb trailing (with rem) and dividend zero-limb count > divisor zero-limb count" {2254test "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
2284 var a = try Managed.initSet(testing.allocator, 0x8666666655555555888888877777777611111111111111110000000000000000);2255 var a = try Managed.initSet(testing.allocator, 0x8666666655555555888888877777777611111111111111110000000000000000);
2285 defer a.deinit();2256 defer a.deinit();
2286 var b = try Managed.initSet(testing.allocator, 0x8666666655555555444444443333333300000000000000000000000000000000);2257 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...@@ -2300,8 +2271,6 @@ test "div multi-multi zero-limb trailing (with rem) and dividend zero-limb count
2300}2271}
23012272
2302test "div multi-multi zero-limb trailing (with rem) and dividend zero-limb count < divisor zero-limb count" {2273test "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
2305 var a = try Managed.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000);2274 var a = try Managed.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000);
2306 defer a.deinit();2275 defer a.deinit();
2307 var b = try Managed.initSet(testing.allocator, 0x866666665555555544444444333333330000000000000000);2276 var b = try Managed.initSet(testing.allocator, 0x866666665555555544444444333333330000000000000000);
...@@ -2832,10 +2801,6 @@ test "bitNotWrap signed multi" {...@@ -2832,10 +2801,6 @@ test "bitNotWrap signed multi" {
2832}2801}
28332802
2834test "bitNotWrap more than two limbs" {2803test "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
2839 var a = try Managed.initSet(testing.allocator, maxInt(Limb));2804 var a = try Managed.initSet(testing.allocator, maxInt(Limb));
2840 defer a.deinit();2805 defer a.deinit();
28412806
...@@ -3179,8 +3144,6 @@ test "gcd non-one large" {...@@ -3179,8 +3144,6 @@ test "gcd non-one large" {
3179}3144}
31803145
3181test "gcd large multi-limb result" {3146test "gcd large multi-limb result" {
3182 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
3183
3184 var a = try Managed.initSet(testing.allocator, 0x12345678123456781234567812345678123456781234567812345678);3147 var a = try Managed.initSet(testing.allocator, 0x12345678123456781234567812345678123456781234567812345678);
3185 defer a.deinit();3148 defer a.deinit();
3186 var b = try Managed.initSet(testing.allocator, 0x12345671234567123456712345671234567123456712345671234567);3149 var b = try Managed.initSet(testing.allocator, 0x12345671234567123456712345671234567123456712345671234567);
...@@ -3431,7 +3394,7 @@ test "big int conversion read/write twos complement" {...@@ -3431,7 +3394,7 @@ test "big int conversion read/write twos complement" {
3431 var buffer1 = try testing.allocator.alloc(u8, 64);3394 var buffer1 = try testing.allocator.alloc(u8, 64);
3432 defer testing.allocator.free(buffer1);3395 defer testing.allocator.free(buffer1);
34333396
3434 const endians = [_]std.builtin.Endian{ .little, .big };3397 const endians = [_]std.lang.Endian{ .little, .big };
3435 const abi_size = 64;3398 const abi_size = 64;
34363399
3437 for (endians) |endian| {3400 for (endians) |endian| {
lib/std/math/float.zig+3-3
...@@ -112,17 +112,17 @@ pub fn FloatRepr(comptime Float: type) type {...@@ -112,17 +112,17 @@ pub fn FloatRepr(comptime Float: type) type {
112 /// This currently truncates denormal values, which needs to be fixed before this can be used to112 /// This currently truncates denormal values, which needs to be fixed before this can be used to
113 /// produce a rounded value.113 /// produce a rounded value.
114 pub fn reconstruct(normalized: Normalized, sign: std.math.Sign) Float {114 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{
116 .mantissa = 0,116 .mantissa = 0,
117 .exponent = .infinite,117 .exponent = .infinite,
118 .sign = sign,118 .sign = sign,
119 });119 });
120 const mantissa = @as(Mantissa, 1 << fractional_bits) | normalized.fraction;120 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{
122 .mantissa = @truncate(std.math.shr(122 .mantissa = @truncate(std.math.shr(
123 Mantissa,123 Mantissa,
124 mantissa,124 mantissa,
125 BiasedExponent.min_normal.unbias() - normalized.exponent,125 (comptime BiasedExponent.min_normal.unbias()) - normalized.exponent,
126 )),126 )),
127 .exponent = .denormal,127 .exponent = .denormal,
128 .sign = sign,128 .sign = sign,
lib/std/math/gamma.zig-2
...@@ -263,8 +263,6 @@ test gamma {...@@ -263,8 +263,6 @@ test gamma {
263}263}
264264
265test "gamma.special" {265test "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
268 inline for (&.{ f32, f64 }) |T| {266 inline for (&.{ f32, f64 }) |T| {
269 try expect(std.math.isNan(gamma(T, -std.math.nan(T))));267 try expect(std.math.isNan(gamma(T, -std.math.nan(T))));
270 try expect(std.math.isNan(gamma(T, std.math.nan(T))));268 try expect(std.math.isNan(gamma(T, std.math.nan(T))));
lib/std/math/hypot.zig-9
...@@ -1,4 +1,3 @@...@@ -1,4 +1,3 @@
1const builtin = @import("builtin");
2const std = @import("../std.zig");1const std = @import("../std.zig");
3const math = std.math;2const math = std.math;
4const expect = std.testing.expect;3const expect = std.testing.expect;
...@@ -93,14 +92,10 @@ const hypot_test_cases = .{...@@ -93,14 +92,10 @@ const hypot_test_cases = .{
93};92};
9493
95test hypot {94test hypot {
96 if (builtin.cpu.arch.isPowerPC() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869
97 try expect(hypot(0.3, 0.4) == 0.5);95 try expect(hypot(0.3, 0.4) == 0.5);
98}96}
9997
100test "hypot.correct" {98test "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
104 inline for (.{ f16, f32, f64, f128 }) |T| {99 inline for (.{ f16, f32, f64, f128 }) |T| {
105 inline for (hypot_test_cases) |v| {100 inline for (hypot_test_cases) |v| {
106 const a: T, const b: T, const c: T = v;101 const a: T, const b: T, const c: T = v;
...@@ -110,9 +105,6 @@ test "hypot.correct" {...@@ -110,9 +105,6 @@ test "hypot.correct" {
110}105}
111106
112test "hypot.precise" {107test "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
116 inline for (.{ f16, f32, f64 }) |T| { // f128 seems to be 5 ulp108 inline for (.{ f16, f32, f64 }) |T| { // f128 seems to be 5 ulp
117 inline for (hypot_test_cases) |v| {109 inline for (hypot_test_cases) |v| {
118 const a: T, const b: T, const c: T = v;110 const a: T, const b: T, const c: T = v;
...@@ -122,7 +114,6 @@ test "hypot.precise" {...@@ -122,7 +114,6 @@ test "hypot.precise" {
122}114}
123115
124test "hypot.special" {116test "hypot.special" {
125 if (builtin.cpu.arch.isPowerPC() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869
126 @setEvalBranchQuota(2000);117 @setEvalBranchQuota(2000);
127 inline for (.{ f16, f32, f64, f128 }) |T| {118 inline for (.{ f16, f32, f64, f128 }) |T| {
128 try expect(math.isNan(hypot(nan(T), 0.0)));119 try expect(math.isNan(hypot(nan(T), 0.0)));
lib/std/math/isnan.zig+1-7
...@@ -27,13 +27,6 @@ test isNan {...@@ -27,13 +27,6 @@ test isNan {
27}27}
2828
29test isSignalNan {29test 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
37 inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| {30 inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| {
38 // TODO: Signalling NaN values get converted to quiet NaN values in31 // TODO: Signalling NaN values get converted to quiet NaN values in
39 // some cases where they shouldn't such that this can fail.32 // some cases where they shouldn't such that this can fail.
...@@ -43,6 +36,7 @@ test isSignalNan {...@@ -43,6 +36,7 @@ test isSignalNan {
43 builtin.cpu.arch != .hexagon and36 builtin.cpu.arch != .hexagon and
44 !builtin.cpu.arch.isMIPS32() and37 !builtin.cpu.arch.isMIPS32() and
45 !builtin.cpu.arch.isPowerPC() and38 !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
46 builtin.zig_backend != .stage2_c)40 builtin.zig_backend != .stage2_c)
47 {41 {
48 try expect(isSignalNan(math.snan(T)));42 try expect(isSignalNan(math.snan(T)));
lib/std/math/log10.zig-5
...@@ -1,5 +1,4 @@...@@ -1,5 +1,4 @@
1const std = @import("../std.zig");1const std = @import("../std.zig");
2const builtin = @import("builtin");
3const testing = std.testing;2const testing = std.testing;
43
5/// Returns the base-10 logarithm of x.4/// Returns the base-10 logarithm of x.
...@@ -135,10 +134,6 @@ inline fn less_than_5(x: u32) u32 {...@@ -135,10 +134,6 @@ inline fn less_than_5(x: u32) u32 {
135}134}
136135
137test log10_int {136test 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
142 inline for (137 inline for (
143 .{ u8, u16, u32, u64, u128, u256, u512 },138 .{ u8, u16, u32, u64, u128, u256, u512 },
144 .{ 2, 4, 9, 19, 38, 77, 154 },139 .{ 2, 4, 9, 19, 38, 77, 154 },
lib/std/math/modf.zig-4
...@@ -1,5 +1,4 @@...@@ -1,5 +1,4 @@
1const std = @import("../std.zig");1const std = @import("../std.zig");
2const builtin = @import("builtin");
3const math = std.math;2const math = std.math;
4const expect = std.testing.expect;3const expect = std.testing.expect;
5const expectEqual = std.testing.expectEqual;4const expectEqual = std.testing.expectEqual;
...@@ -85,9 +84,6 @@ fn ModfTests(comptime T: type) type {...@@ -85,9 +84,6 @@ fn ModfTests(comptime T: type) type {
85 try expectApproxEqAbs(expected_c, r.fpart, epsilon);84 try expectApproxEqAbs(expected_c, r.fpart, epsilon);
86 }85 }
87 test "vector" {86 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
91 const widths = [_]comptime_int{ 1, 2, 3, 4, 8, 16 };87 const widths = [_]comptime_int{ 1, 2, 3, 4, 8, 16 };
9288
93 inline for (widths) |len| {89 inline for (widths) |len| {
lib/std/math/signbit.zig+1
...@@ -1,3 +1,4 @@...@@ -1,3 +1,4 @@
1const builtin = @import("builtin");
1const std = @import("../std.zig");2const std = @import("../std.zig");
2const math = std.math;3const math = std.math;
3const expect = std.testing.expect;4const expect = std.testing.expect;
lib/std/mem.zig+166-127
...@@ -9,6 +9,7 @@ const assert = debug.assert;...@@ -9,6 +9,7 @@ const assert = debug.assert;
9const math = std.math;9const math = std.math;
10const testing = std.testing;10const testing = std.testing;
11const Endian = std.lang.Endian;11const Endian = std.lang.Endian;
12const AbsorbSentinel = std.meta.AbsorbSentinel;
1213
13/// The standard library currently thoroughly depends on byte size14/// The standard library currently thoroughly depends on byte size
14/// being 8 bits. (see the use of u8 throughout allocation code as15/// 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 {...@@ -756,7 +757,8 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
756 }757 }
757758
758 if (a.len != b.len) return false;759 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
761 for (a, b) |a_elem, b_elem| {763 for (a, b) |a_elem, b_elem| {
762 if (a_elem != b_elem) return false;764 if (a_elem != b_elem) return false;
...@@ -781,6 +783,9 @@ test eql {...@@ -781,6 +783,9 @@ test eql {
781783
782 try testing.expect(eql(void, &.{ {}, {} }, &.{ {}, {} }));784 try testing.expect(eql(void, &.{ {}, {} }, &.{ {}, {} }));
783 try testing.expect(!eql(void, &.{{}}, &.{ {}, {} }));785 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));
784}789}
785790
786/// std.mem.eql heavily optimized for slices of bytes.791/// std.mem.eql heavily optimized for slices of bytes.
...@@ -850,20 +855,25 @@ pub const indexOfDiff = findDiff;...@@ -850,20 +855,25 @@ pub const indexOfDiff = findDiff;
850/// Compares two slices and returns the index of the first inequality.855/// Compares two slices and returns the index of the first inequality.
851/// Returns null if the slices are equal.856/// Returns null if the slices are equal.
852pub fn findDiff(comptime T: type, a: []const T, b: []const T) ?usize {857pub fn findDiff(comptime T: type, a: []const T, b: []const T) ?usize {
853 const shortest = @min(a.len, b.len);858 const shorter = @min(a.len, b.len);
854 if (a.ptr == b.ptr)859 if (@typeInfo(T) != .float and a.ptr == b.ptr) {
855 return if (a.len == b.len) null else shortest;860 return if (a.len == b.len) null else shorter;
856 var index: usize = 0;861 }
857 while (index < shortest) : (index += 1) if (a[index] != b[index]) return index;862 for (a[0..shorter], b[0..shorter], 0..) |a_elem, b_elem, i| {
858 return if (a.len == b.len) null else shortest;863 if (a_elem != b_elem) return i;
864 }
865 return if (a.len == b.len) null else shorter;
859}866}
860867
861test findDiff {868test findDiff {
862 try testing.expectEqual(findDiff(u8, "one", "one"), null);869 try testing.expectEqual(null, findDiff(u8, "one", "one"));
863 try testing.expectEqual(findDiff(u8, "one two", "one"), 3);870 try testing.expectEqual(3, findDiff(u8, "one two", "one"));
864 try testing.expectEqual(findDiff(u8, "one", "one two"), 3);871 try testing.expectEqual(3, findDiff(u8, "one", "one two"));
865 try testing.expectEqual(findDiff(u8, "one twx", "one two"), 6);872 try testing.expectEqual(6, findDiff(u8, "one twx", "one two"));
866 try testing.expectEqual(findDiff(u8, "xne", "one"), 0);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));
867}877}
868878
869/// Takes a sentinel-terminated pointer and returns a slice preserving pointer attributes.879/// 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...@@ -1519,7 +1529,7 @@ pub fn findLast(comptime T: type, haystack: []const T, needle: []const T) ?usize
1519 if (needle.len == 0) return haystack.len;1529 if (needle.len == 0) return haystack.len;
15201530
1521 if (!std.meta.hasUniqueRepresentation(T) or haystack.len < 52 or needle.len <= 4)1531 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
1524 const haystack_bytes = sliceAsBytes(haystack);1534 const haystack_bytes = sliceAsBytes(haystack);
1525 const needle_bytes = sliceAsBytes(needle);1535 const needle_bytes = sliceAsBytes(needle);
...@@ -1574,26 +1584,26 @@ pub fn findPos(comptime T: type, haystack: []const T, start_index: usize, needle...@@ -1574,26 +1584,26 @@ pub fn findPos(comptime T: type, haystack: []const T, start_index: usize, needle
15741584
1575test find {1585test find {
1576 try testing.expect(find(u8, "one two three four five six seven eight nine ten eleven", "three four").? == 8);1586 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);
1578 try testing.expect(find(u8, "one two three four five six seven eight nine ten eleven", "two two") == null);1588 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
1581 try testing.expect(find(u8, "one two three four five six seven eight nine ten", "").? == 0);1591 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
1584 try testing.expect(find(u8, "one two three four", "four").? == 14);1594 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);
1586 try testing.expect(find(u8, "one two three four", "gour") == null);1596 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);
1588 try testing.expect(find(u8, "foo", "foo").? == 0);1598 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);
1590 try testing.expect(find(u8, "foo", "fool") == null);1600 try testing.expect(find(u8, "foo", "fool") == null);
1591 try testing.expect(lastIndexOf(u8, "foo", "lfoo") == null);1601 try testing.expect(findLast(u8, "foo", "lfoo") == null);
1592 try testing.expect(lastIndexOf(u8, "foo", "fool") == null);1602 try testing.expect(findLast(u8, "foo", "fool") == null);
15931603
1594 try testing.expect(find(u8, "foo foo", "foo").? == 0);1604 try testing.expect(find(u8, "foo foo", "foo").? == 0);
1595 try testing.expect(lastIndexOf(u8, "foo foo", "foo").? == 4);1605 try testing.expect(findLast(u8, "foo foo", "foo").? == 4);
1596 try testing.expect(lastIndexOfAny(u8, "boo, cat", "abo").? == 6);1606 try testing.expect(findLastAny(u8, "boo, cat", "abo").? == 6);
1597 try testing.expect(findScalarLast(u8, "boo", 'o').? == 2);1607 try testing.expect(findScalarLast(u8, "boo", 'o').? == 2);
1598}1608}
15991609
...@@ -1615,13 +1625,13 @@ test "find multibyte" {...@@ -1615,13 +1625,13 @@ test "find multibyte" {
1615 // make haystack and needle long enough to trigger Boyer-Moore-Horspool algorithm1625 // make haystack and needle long enough to trigger Boyer-Moore-Horspool algorithm
1616 const haystack = [_]u16{ 0xbbaa, 0xccbb, 0xddcc, 0xeedd, 0xffee, 0x00ff } ++ @as([100]u16, @splat(0));1626 const haystack = [_]u16{ 0xbbaa, 0xccbb, 0xddcc, 0xeedd, 0xffee, 0x00ff } ++ @as([100]u16, @splat(0));
1617 const needle = [_]u16{ 0xbbaa, 0xccbb, 0xddcc, 0xeedd, 0xffee };1627 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
1620 // check for misaligned false positives (little and big endian)1630 // check for misaligned false positives (little and big endian)
1621 const needleLE = [_]u16{ 0xbbbb, 0xcccc, 0xdddd, 0xeeee, 0xffff };1631 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);
1623 const needleBE = [_]u16{ 0xaacc, 0xbbdd, 0xccee, 0xddff, 0xee00 };1633 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);
1625 }1635 }
1626}1636}
16271637
...@@ -2215,33 +2225,54 @@ test writeVarPackedInt {...@@ -2215,33 +2225,54 @@ test writeVarPackedInt {
2215 try testing.expectEqual(T{ .a = 1, .b = value, .c = 4 }, st);2225 try testing.expectEqual(T{ .a = 1, .b = value, .c = 4 }, st);
2216}2226}
22172227
2218/// Swap the byte order of all the members of the fields of a struct2228/// Deprecated: use `byteSwap` instead.
2219/// (Changing their endianness)2229pub const byteSwapAllFields = byteSwap;
2220pub fn byteSwapAllFields(comptime S: type, ptr: *S) void {2230
2221 byteSwapAllFieldsAligned(S, .of(S), ptr);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);
2222}2241}
22232242
2224/// Swap the byte order of all the members of the fields of a struct2243/// Reverses the byte order.
2225/// (Changing their endianness)2244/// Handles structs, unions, arrays, enums, floats, and integers recursively.
2226pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *align(a.toByteUnits()) S) void {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 {
2227 switch (@typeInfo(S)) {2253 switch (@typeInfo(S)) {
2228 .@"struct" => |@"struct"| {2254 .@"struct" => |@"struct"| {
2229 if (@"struct".backing_integer) |Int| {2255 if (@"struct".backing_integer) |Int| {
2230 ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*))));2256 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| {2257 } else {
2232 switch (@typeInfo(f_type)) {2258 if (@"struct".layout != .@"extern") {
2233 .@"struct" => byteSwapAllFieldsAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)),2259 @compileError("byteSwapAligned expects a packed or extern struct");
2234 .@"union", .array => byteSwapAllFieldsAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)),2260 }
2235 .@"enum" => {2261 inline for (@"struct".field_types, @"struct".field_names, @"struct".field_attrs) |f_type, f_name, f_attr| {
2236 @field(ptr, f_name) = @fromBackingInt(@intCast(@byteSwap(@backingInt(@field(ptr, f_name)))));2262 switch (@typeInfo(f_type)) {
2237 },2263 .@"struct" => byteSwapAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)),
2238 .bool => {},2264 .@"union", .array => byteSwapAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)),
2239 .float => |float| {2265 .@"enum" => {
2240 @field(ptr, f_name) = @bitCast(@byteSwap(@as(@Int(.unsigned, float.bits), @bitCast(@field(ptr, f_name)))));2266 @field(ptr, f_name) = @fromBackingInt(@byteSwap(@backingInt(@field(ptr, f_name))));
2241 },2267 },
2242 else => {2268 .bool => {},
2243 @field(ptr, f_name) = @byteSwap(@field(ptr, f_name));2269 .float => |float| {
2244 },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 }
2245 }2276 }
2246 }2277 }
2247 },2278 },
...@@ -2249,7 +2280,7 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a...@@ -2249,7 +2280,7 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a
2249 ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*))));2280 ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*))));
2250 } else {2281 } else {
2251 if (@"union".layout != .@"extern") {2282 if (@"union".layout != .@"extern") {
2252 @compileError("byteSwapAllFields expects a packed or extern union");2283 @compileError("byteSwapAligned expects a packed or extern union");
2253 }2284 }
22542285
2255 const first_size = @bitSizeOf(@"union".field_types[0]);2286 const first_size = @bitSizeOf(@"union".field_types[0]);
...@@ -2266,13 +2297,21 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a...@@ -2266,13 +2297,21 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a
2266 .array => |array| {2297 .array => |array| {
2267 byteSwapAllElements(array.child, ptr);2298 byteSwapAllElements(array.child, ptr);
2268 },2299 },
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 },
2269 else => {2308 else => {
2270 ptr.* = @byteSwap(ptr.*);2309 ptr.* = @byteSwap(ptr.*);
2271 },2310 },
2272 }2311 }
2273}2312}
22742313
2275test byteSwapAllFields {2314test byteSwap {
2276 const T = extern struct {2315 const T = extern struct {
2277 f0: u8,2316 f0: u8,
2278 f1: u16,2317 f1: u16,
...@@ -2304,6 +2343,9 @@ test byteSwapAllFields {...@@ -2304,6 +2343,9 @@ test byteSwapAllFields {
2304 } align(4),2343 } align(4),
2305 f2: u32,2344 f2: u32,
2306 };2345 };
2346 const E = enum(u32) {
2347 _,
2348 };
2307 var s = T{2349 var s = T{
2308 .f0 = 0x12,2350 .f0 = 0x12,
2309 .f1 = 0x1234,2351 .f1 = 0x1234,
...@@ -2327,10 +2369,14 @@ test byteSwapAllFields {...@@ -2327,10 +2369,14 @@ test byteSwapAllFields {
2327 .f1 = .{ .f0 = 0x123456789ABCDEF0 },2369 .f1 = .{ .f0 = 0x123456789ABCDEF0 },
2328 .f2 = 0x87654321,2370 .f2 = 0x87654321,
2329 };2371 };
2330 byteSwapAllFields(T, &s);2372 var e: E = @fromBackingInt(0x12345678);
2331 byteSwapAllFields(K, &k);2373 var f: f32 = @bitCast(@as(u32, 0x4640e400));
2332 byteSwapAllFields(P, &p);2374 byteSwap(T, &s);
2333 byteSwapAllFields(A, &a);2375 byteSwap(K, &k);
2376 byteSwap(P, &p);
2377 byteSwap(A, &a);
2378 byteSwap(E, &e);
2379 byteSwap(f32, &f);
2334 try std.testing.expectEqual(T{2380 try std.testing.expectEqual(T{
2335 .f0 = 0x12,2381 .f0 = 0x12,
2336 .f1 = 0x3412,2382 .f1 = 0x3412,
...@@ -2354,28 +2400,15 @@ test byteSwapAllFields {...@@ -2354,28 +2400,15 @@ test byteSwapAllFields {
2354 .f1 = .{ .f0 = 0xF0DEBC9A78563412 },2400 .f1 = .{ .f0 = 0xF0DEBC9A78563412 },
2355 .f2 = 0x21436587,2401 .f2 = 0x21436587,
2356 }, a);2402 }, a);
2403 try std.testing.expectEqual(@as(E, @fromBackingInt(0x78563412)), e);
2404 try std.testing.expectEqual(@as(f32, @bitCast(@as(u32, 0x00e44046))), f);
2357}2405}
23582406
2359/// Reverses the byte order of all elements in a slice.2407/// Reverses the byte order of all elements in a slice.
2360/// Handles structs, unions, arrays, enums, floats, and integers recursively.2408/// Handles structs, unions, arrays, enums, floats, and integers recursively.
2361/// Useful for converting between little-endian and big-endian representations.2409/// Useful for converting between little-endian and big-endian representations.
2362pub fn byteSwapAllElements(comptime Elem: type, slice: []Elem) void {2410pub fn byteSwapAllElements(comptime Elem: type, slice: []Elem) void {
2363 for (slice) |*elem| {2411 for (slice) |*elem| byteSwap(Elem, 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 }
2379}2412}
23802413
2381/// Returns an iterator that iterates over the slices of `buffer` that are not2414/// 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...@@ -3453,8 +3486,8 @@ pub fn SplitBackwardsIterator(comptime T: type, comptime delimiter_type: Delimit
3453 pub fn next(self: *Self) ?[]const T {3486 pub fn next(self: *Self) ?[]const T {
3454 const end = self.index orelse return null;3487 const end = self.index orelse return null;
3455 const start = if (switch (delimiter_type) {3488 const start = if (switch (delimiter_type) {
3456 .sequence => lastIndexOf(T, self.buffer[0..end], self.delimiter),3489 .sequence => findLast(T, self.buffer[0..end], self.delimiter),
3457 .any => lastIndexOfAny(T, self.buffer[0..end], self.delimiter),3490 .any => findLastAny(T, self.buffer[0..end], self.delimiter),
3458 .scalar => findScalarLast(T, self.buffer[0..end], self.delimiter),3491 .scalar => findScalarLast(T, self.buffer[0..end], self.delimiter),
3459 }) |delim_start| blk: {3492 }) |delim_start| blk: {
3460 self.index = delim_start;3493 self.index = delim_start;
...@@ -4706,22 +4739,28 @@ test "sliceAsBytes preserves pointer attributes" {...@@ -4706,22 +4739,28 @@ test "sliceAsBytes preserves pointer attributes" {
4706 try testing.expectEqual(in_attrs.@"align", out_attrs.@"align");4739 try testing.expectEqual(in_attrs.@"align", out_attrs.@"align");
4707}4740}
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
4715/// If the provided slice is not sentinel terminated, do nothing and return that slice.4742/// If the provided slice is not sentinel terminated, do nothing and return that slice.
4716/// If it is sentinel-terminated, return a non-sentinel-terminated slice with the4743/// If it is sentinel-terminated, return a non-sentinel-terminated slice with the
4717/// length increased by one to include the absorbed sentinel element.4744/// 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)) {
4719 const info = @typeInfo(@TypeOf(slice)).pointer;4746 const info = @typeInfo(@TypeOf(slice)).pointer;
4720 comptime assert(info.size == .slice);4747 switch (info.size) {
4721 if (info.sentinel_ptr == null) {4748 .slice => {
4722 return slice;4749 if (info.sentinel_ptr == null) {
4723 } else {4750 return slice;
4724 return slice.ptr[0 .. slice.len + 1];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,
4725 }4764 }
4726}4765}
47274766
...@@ -4730,21 +4769,28 @@ test absorbSentinel {...@@ -4730,21 +4769,28 @@ test absorbSentinel {
4730 var buffer: [3:0]u8 = .{ 1, 2, 3 };4769 var buffer: [3:0]u8 = .{ 1, 2, 3 };
4731 const foo: [:0]const u8 = &buffer;4770 const foo: [:0]const u8 = &buffer;
4732 const bar: []const u8 = &buffer;4771 const bar: []const u8 = &buffer;
4772 const baz: *const [3:0]u8 = &buffer;
4733 try testing.expectEqual([]const u8, @TypeOf(absorbSentinel(foo)));4773 try testing.expectEqual([]const u8, @TypeOf(absorbSentinel(foo)));
4734 try testing.expectEqual([]const u8, @TypeOf(absorbSentinel(bar)));4774 try testing.expectEqual([]const u8, @TypeOf(absorbSentinel(bar)));
4775 try testing.expectEqual(*const [4]u8, @TypeOf(absorbSentinel(baz)));
4735 try testing.expectEqualSlices(u8, &.{ 1, 2, 3, 0 }, absorbSentinel(foo));4776 try testing.expectEqualSlices(u8, &.{ 1, 2, 3, 0 }, absorbSentinel(foo));
4736 try testing.expectEqualSlices(u8, &.{ 1, 2, 3 }, absorbSentinel(bar));4777 try testing.expectEqualSlices(u8, &.{ 1, 2, 3 }, absorbSentinel(bar));
4778 try testing.expectEqualSlices(u8, &.{ 1, 2, 3, 0 }, absorbSentinel(baz));
4737 }4779 }
4738 {4780 {
4739 var buffer: [3:0]u8 = .{ 1, 2, 3 };4781 var buffer: [3:0]u8 = .{ 1, 2, 3 };
4740 const foo: [:0]u8 = &buffer;4782 const foo: [:0]u8 = &buffer;
4741 const bar: []u8 = &buffer;4783 const bar: []u8 = &buffer;
4784 const baz: *[3:0]u8 = &buffer;
4742 try testing.expectEqual([]u8, @TypeOf(absorbSentinel(foo)));4785 try testing.expectEqual([]u8, @TypeOf(absorbSentinel(foo)));
4743 try testing.expectEqual([]u8, @TypeOf(absorbSentinel(bar)));4786 try testing.expectEqual([]u8, @TypeOf(absorbSentinel(bar)));
4787 try testing.expectEqual(*[4]u8, @TypeOf(absorbSentinel(baz)));
4744 var expected_foo = [_]u8{ 1, 2, 3, 0 };4788 var expected_foo = [_]u8{ 1, 2, 3, 0 };
4745 try testing.expectEqualSlices(u8, &expected_foo, absorbSentinel(foo));4789 try testing.expectEqualSlices(u8, &expected_foo, absorbSentinel(foo));
4746 var expected_bar = [_]u8{ 1, 2, 3 };4790 var expected_bar = [_]u8{ 1, 2, 3 };
4747 try testing.expectEqualSlices(u8, &expected_bar, absorbSentinel(bar));4791 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));
4748 }4794 }
4749}4795}
47504796
...@@ -4780,62 +4826,58 @@ pub fn alignForwardLog2(addr: usize, log2_alignment: u8) usize {...@@ -4780,62 +4826,58 @@ pub fn alignForwardLog2(addr: usize, log2_alignment: u8) usize {
4780pub fn doNotOptimizeAway(val: anytype) void {4826pub fn doNotOptimizeAway(val: anytype) void {
4781 if (@inComptime()) return;4827 if (@inComptime()) return;
47824828
4783 const max_gp_register_bits = @bitSizeOf(c_long);4829 if (builtin.zig_backend == .stage2_c and builtin.abi == .msvc) {
4784 const t = @typeInfo(@TypeOf(val));4830 _ = @atomicRmw(*const anyopaque, @as(*volatile *const anyopaque, &struct {
4785 switch (t) {4831 var escape: *const anyopaque = undefined;
4832 }.escape), .Xchg, &val, .acq_rel); // TODO: syncscope("singlethreaded")
4833 return;
4834 }
4835
4836 switch (@typeInfo(@TypeOf(val))) {
4786 .void, .null, .comptime_int, .comptime_float => return,4837 .void, .null, .comptime_int, .comptime_float => return,
4787 .@"enum" => doNotOptimizeAway(@backingInt(val)),4838 .@"enum" => doNotOptimizeAway(@backingInt(val)),
4788 .bool => doNotOptimizeAway(@intFromBool(val)),4839 .bool => doNotOptimizeAway(@intFromBool(val)),
4789 .int => {4840 .int => |int| {
4790 const bits = t.int.bits;4841 // SPIR-V targets do not have registers per se, they have values
4791 if (bits <= max_gp_register_bits and builtin.zig_backend != .stage2_c) {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) {
4792 const val2 = @as(4850 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))),
4794 val,4852 val,
4795 );4853 );
4796 asm volatile (""4854 asm volatile (""
4797 :4855 :
4798 : [_] "r" (val2),4856 : [_] "r" (val2),
4799 );4857 );
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);
4813 } else {4858 } else {
4814 asm volatile (""4859 doNotOptimizeAway(&val);
4815 :
4816 : [_] "m" (val),
4817 : .{ .memory = true });
4818 }4860 }
4819 },4861 },
4820 .array => {4862 .float => |float| switch (float.bits) {
4821 if (t.array.len * @sizeOf(t.array.child) <= 64) {4863 else => comptime unreachable,
4822 for (val) |v| doNotOptimizeAway(v);4864 16, 80, 128 => doNotOptimizeAway(&val),
4823 } else doNotOptimizeAway(&val);4865 32, 64 => asm volatile (""
4866 :
4867 : [_] "rm" (val),
4868 ),
4824 },4869 },
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),
4825 else => doNotOptimizeAway(&val),4877 else => doNotOptimizeAway(&val),
4826 }4878 }
4827}4879}
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
4839test doNotOptimizeAway {4881test doNotOptimizeAway {
4840 comptime doNotOptimizeAway("test");4882 comptime doNotOptimizeAway("test");
48414883
...@@ -4994,12 +5036,9 @@ pub fn alignInSlice(slice: anytype, comptime new_alignment: usize) ?AlignedSlice...@@ -4994,12 +5036,9 @@ pub fn alignInSlice(slice: anytype, comptime new_alignment: usize) ?AlignedSlice
4994}5036}
49955037
4996test "read/write(Var)PackedInt" {5038test "read/write(Var)PackedInt" {
4997 switch (builtin.cpu.arch) {5039 // This test generates too much code to execute on WASI.
4998 // This test generates too much code to execute on WASI.5040 // LLVM backend fails with "too many locals: locals exceed maximum"
4999 // LLVM backend fails with "too many locals: locals exceed maximum"5041 if (builtin.cpu.arch.isWasm()) return error.SkipZigTest;
5000 .wasm32, .wasm64 => return error.SkipZigTest,
5001 else => {},
5002 }
50035042
5004 const foreign_endian: Endian = if (native_endian == .big) .little else .big;5043 const foreign_endian: Endian = if (native_endian == .big) .little else .big;
5005 const expect = std.testing.expect;5044 const expect = std.testing.expect;
lib/std/mem/Allocator.zig+56-16
...@@ -8,6 +8,8 @@ const assert = std.debug.assert;...@@ -8,6 +8,8 @@ const assert = std.debug.assert;
8const math = std.math;8const math = std.math;
9const mem = std.mem;9const mem = std.mem;
10const Alignment = std.mem.Alignment;10const Alignment = std.mem.Alignment;
11const Slice = std.meta.Slice;
12const AbsorbSentinel = std.meta.AbsorbSentinel;
1113
12pub const Error = error{OutOfMemory};14pub const Error = error{OutOfMemory};
13pub const Log2Align = math.Log2Int(usize);15pub const Log2Align = math.Log2Int(usize);
...@@ -316,8 +318,10 @@ pub fn allocBytesAligned(...@@ -316,8 +318,10 @@ pub fn allocBytesAligned(
316/// `new_len` may be zero, in which case the allocation is freed.318/// `new_len` may be zero, in which case the allocation is freed.
317pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {319pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
318 const slice_info = @typeInfo(@TypeOf(allocation)).pointer;320 const slice_info = @typeInfo(@TypeOf(allocation)).pointer;
319 comptime assert(slice_info.size == .slice);321 const T = if (slice_info.size != .slice) comptime T: {
320 const T = slice_info.child;322 assert(slice_info.size == .one);
323 break :T @typeInfo(slice_info.child).array.child;
324 } else slice_info.child;
321 if (new_len == 0) {325 if (new_len == 0) {
322 self.free(allocation);326 self.free(allocation);
323 return true;327 return true;
...@@ -326,9 +330,6 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {...@@ -326,9 +330,6 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
326 return false;330 return false;
327 }331 }
328 const old_memory: []u8 = @ptrCast(@constCast(mem.absorbSentinel(allocation)));332 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);
332 const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return false;333 const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return false;
333 return self.rawResize(334 return self.rawResize(
334 old_memory,335 old_memory,
...@@ -354,10 +355,12 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {...@@ -354,10 +355,12 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
354/// `new_len` may be zero, in which case the allocation is freed.355/// `new_len` may be zero, in which case the allocation is freed.
355///356///
356/// If the allocation's elements' type is zero bytes sized, `allocation.len` is set to `new_len`.357/// 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))) {
358 const slice_info = @typeInfo(@TypeOf(allocation)).pointer;359 const slice_info = @typeInfo(@TypeOf(allocation)).pointer;
359 comptime assert(slice_info.size == .slice);360 const T = if (slice_info.size != .slice) comptime T: {
360 const T = slice_info.child;361 assert(slice_info.size == .one);
362 break :T @typeInfo(slice_info.child).array.child;
363 } else slice_info.child;
361364
362 if (new_len == 0) {365 if (new_len == 0) {
363 self.free(allocation);366 self.free(allocation);
...@@ -372,9 +375,6 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?@TypeOf(allo...@@ -372,9 +375,6 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?@TypeOf(allo
372 return new_memory;375 return new_memory;
373 }376 }
374 const old_memory: []u8 = @ptrCast(@constCast(mem.absorbSentinel(allocation)));377 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);
378 const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return null;378 const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return null;
379 const new_ptr = self.rawRemap(379 const new_ptr = self.rawRemap(
380 old_memory,380 old_memory,
...@@ -399,7 +399,7 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?@TypeOf(allo...@@ -399,7 +399,7 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?@TypeOf(allo
399/// do the realloc more efficiently than the caller399/// do the realloc more efficiently than the caller
400/// * `resize` which returns `false` when the `Allocator` implementation cannot400/// * `resize` which returns `false` when the `Allocator` implementation cannot
401/// change the size without relocating the allocation.401/// 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))) {
403 return self.reallocAdvanced(old_mem, new_n, @returnAddress());403 return self.reallocAdvanced(old_mem, new_n, @returnAddress());
404}404}
405405
...@@ -408,10 +408,12 @@ pub fn reallocAdvanced(...@@ -408,10 +408,12 @@ pub fn reallocAdvanced(
408 old_mem: anytype,408 old_mem: anytype,
409 new_n: usize,409 new_n: usize,
410 return_address: usize,410 return_address: usize,
411) Error!@TypeOf(old_mem) {411) Error!Slice(AbsorbSentinel(@TypeOf(old_mem))) {
412 const slice_info = @typeInfo(@TypeOf(old_mem)).pointer;412 const slice_info = @typeInfo(@TypeOf(old_mem)).pointer;
413 comptime assert(slice_info.size == .slice);413 const T = if (slice_info.size != .slice) comptime T: {
414 const T = slice_info.child;414 assert(slice_info.size == .one);
415 break :T @typeInfo(slice_info.child).array.child;
416 } else slice_info.child;
415 if (old_mem.len == 0) {417 if (old_mem.len == 0) {
416 return self.allocAdvancedWithRetAddr(T, .fromByteUnitsOptional(slice_info.attrs.@"align"), new_n, return_address);418 return self.allocAdvancedWithRetAddr(T, .fromByteUnitsOptional(slice_info.attrs.@"align"), new_n, return_address);
417 }419 }
...@@ -446,7 +448,6 @@ pub fn reallocAdvanced(...@@ -446,7 +448,6 @@ pub fn reallocAdvanced(
446pub fn free(self: Allocator, memory: anytype) void {448pub fn free(self: Allocator, memory: anytype) void {
447 const slice_info = @typeInfo(@TypeOf(memory)).pointer;449 const slice_info = @typeInfo(@TypeOf(memory)).pointer;
448 if (slice_info.size != .slice) {450 if (slice_info.size != .slice) {
449 // slicing with comptime-known start and end results in *[len]T, which may be free'd
450 comptime assert(slice_info.size == .one and @typeInfo(slice_info.child) == .array);451 comptime assert(slice_info.size == .one and @typeInfo(slice_info.child) == .array);
451 }452 }
452 const bytes: []u8 = @ptrCast(@constCast(mem.absorbSentinel(memory)));453 const bytes: []u8 = @ptrCast(@constCast(mem.absorbSentinel(memory)));
...@@ -587,4 +588,43 @@ fn unreachableFree(...@@ -587,4 +588,43 @@ fn unreachableFree(
587test failing {588test failing {
588 const f: Allocator = .failing;589 const f: Allocator = .failing;
589 try std.testing.expectError(error.OutOfMemory, f.alloc(u8, 123));590 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 }
590}630}
lib/std/meta.zig+69-12
...@@ -1,10 +1,9 @@...@@ -1,10 +1,9 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
2
2const std = @import("std.zig");3const std = @import("std.zig");
3const debug = std.debug;4const assert = std.debug.assert;
4const mem = std.mem;5const mem = std.mem;
5const math = std.math;
6const testing = std.testing;6const testing = std.testing;
7const root = @import("root");
87
9pub const TrailerFlags = @import("meta/trailer_flags.zig").TrailerFlags;8pub const TrailerFlags = @import("meta/trailer_flags.zig").TrailerFlags;
109
...@@ -198,15 +197,17 @@ test containerLayout {...@@ -198,15 +197,17 @@ test containerLayout {
198 try testing.expect(containerLayout(U3) == .@"extern");197 try testing.expect(containerLayout(U3) == .@"extern");
199}198}
200199
201/// Instead of this function, prefer to use e.g. `@typeInfo(foo).@"struct".decl_names`200/// Returns the list of declaration names of namespace types.
202/// directly when you know what kind of type it is.201///
202/// This function is only useful when the callsite does not know statically
203/// which kind of container it is.
203pub fn declarations(comptime T: type) []const [:0]const u8 {204pub fn declarations(comptime T: type) []const [:0]const u8 {
204 return switch (@typeInfo(T)) {205 return switch (@typeInfo(T)) {
205 .@"struct" => |info| info.decl_names,206 .@"struct" => |info| info.decl_names,
206 .@"enum" => |info| info.decl_names,207 .@"enum" => |info| info.decl_names,
207 .@"union" => |info| info.decl_names,208 .@"union" => |info| info.decl_names,
208 .@"opaque" => |info| info.decl_names,209 .@"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
210 };211 };
211}212}
212213
...@@ -242,10 +243,13 @@ test declarations {...@@ -242,10 +243,13 @@ test declarations {
242}243}
243244
244/// To be removed after Zig 0.17.0 is tagged.245/// 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");
246/// To be removed after Zig 0.17.0 is tagged.247/// 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.
249pub fn fieldInfo(comptime T: type, comptime field: FieldEnum(T)) switch (@typeInfo(T)) {253pub fn fieldInfo(comptime T: type, comptime field: FieldEnum(T)) switch (@typeInfo(T)) {
250 .@"struct" => struct { name: [:0]const u8, type: type, attrs: Type.Struct.FieldAttributes },254 .@"struct" => struct { name: [:0]const u8, type: type, attrs: Type.Struct.FieldAttributes },
251 .@"union" => struct { name: [:0]const u8, type: type, attrs: Type.Union.FieldAttributes },255 .@"union" => struct { name: [:0]const u8, type: type, attrs: Type.Union.FieldAttributes },
...@@ -299,13 +303,16 @@ test fieldInfo {...@@ -299,13 +303,16 @@ test fieldInfo {
299 try testing.expect(comptime uf.type == u8);303 try testing.expect(comptime uf.type == u8);
300}304}
301305
306/// Deprecated in favor of `@typeInfo`.
307///
308/// To be removed after 0.17.0 is tagged.
302pub fn fieldNames(comptime T: type) []const [:0]const u8 {309pub fn fieldNames(comptime T: type) []const [:0]const u8 {
303 return switch (@typeInfo(T)) {310 return switch (@typeInfo(T)) {
304 .@"struct" => |s| s.field_names,311 .@"struct" => |s| s.field_names,
305 .@"union" => |u| u.field_names,312 .@"union" => |u| u.field_names,
306 .@"enum" => |e| e.field_names,313 .@"enum" => |e| e.field_names,
307 .error_set => |es| es.error_names.?,314 .error_set => |es| es.error_names.?,
308 else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"),315 else => comptime unreachable,
309 };316 };
310}317}
311318
...@@ -337,11 +344,14 @@ test fieldNames {...@@ -337,11 +344,14 @@ test fieldNames {
337 try testing.expectEqualSlices(u8, u1names[1], "b");344 try testing.expectEqualSlices(u8, u1names[1], "b");
338}345}
339346
347/// Deprecated in favor of `@typeInfo`.
348///
349/// To be removed after 0.17.0 is tagged.
340pub fn fieldTypes(comptime T: type) []const type {350pub fn fieldTypes(comptime T: type) []const type {
341 return switch (@typeInfo(T)) {351 return switch (@typeInfo(T)) {
342 .@"struct" => |s| s.field_types,352 .@"struct" => |s| s.field_types,
343 .@"union" => |u| u.field_types,353 .@"union" => |u| u.field_types,
344 else => @compileError("Expected struct or union type, found '" ++ @typeName(T) ++ "'"),354 else => comptime unreachable,
345 };355 };
346}356}
347357
...@@ -821,8 +831,8 @@ pub fn isError(error_union: anytype) bool {...@@ -821,8 +831,8 @@ pub fn isError(error_union: anytype) bool {
821}831}
822832
823test isError {833test isError {
824 try std.testing.expect(isError(math.divTrunc(u8, 5, 0)));834 try std.testing.expect(isError(std.math.divTrunc(u8, 5, 0)));
825 try std.testing.expect(!isError(math.divTrunc(u8, 5, 5)));835 try std.testing.expect(!isError(std.math.divTrunc(u8, 5, 5)));
826}836}
827837
828/// Returns true if a type has a namespace and the namespace contains `name`;838/// Returns true if a type has a namespace and the namespace contains `name`;
...@@ -1070,3 +1080,50 @@ test hasUniqueRepresentation {...@@ -1070,3 +1080,50 @@ test hasUniqueRepresentation {
10701080
1071 try testing.expect(hasUniqueRepresentation(StructWithComptimeFields));1081 try testing.expect(hasUniqueRepresentation(StructWithComptimeFields));
1072}1082}
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 {...@@ -39,7 +39,7 @@ pub fn TrailerFlags(comptime Fields: type) type {
39 break :blk @Struct(.auto, null, &field_names, &field_types, &field_attrs);39 break :blk @Struct(.auto, null, &field_names, &field_types, &field_attrs);
40 };40 };
4141
42 pub const Self = @This();42 const Self = @This();
4343
44 pub fn has(self: Self, comptime field: FieldEnum) bool {44 pub fn has(self: Self, comptime field: FieldEnum) bool {
45 const field_index = @backingInt(field);45 const field_index = @backingInt(field);
lib/std/multi_array_list.zig+2-2
...@@ -163,7 +163,7 @@ pub fn MultiArrayList(comptime T: type) type {...@@ -163,7 +163,7 @@ pub fn MultiArrayList(comptime T: type) type {
163 };163 };
164 }164 }
165165
166 /// This function is used in the debugger pretty formatters in tools/ to fetch the166 /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the
167 /// child field order and entry type to facilitate fancy debug printing for this type.167 /// child field order and entry type to facilitate fancy debug printing for this type.
168 fn dbHelper(self: *Slice, child: *Elem, field: *Field, entry: *Entry) void {168 fn dbHelper(self: *Slice, child: *Elem, field: *Field, entry: *Entry) void {
169 _ = self;169 _ = self;
...@@ -681,7 +681,7 @@ pub fn MultiArrayList(comptime T: type) type {...@@ -681,7 +681,7 @@ pub fn MultiArrayList(comptime T: type) type {
681 }681 }
682 break :entry @Struct(.@"extern", null, &entry_field_names, &entry_field_types, &entry_field_attrs);682 break :entry @Struct(.@"extern", null, &entry_field_names, &entry_field_types, &entry_field_attrs);
683 };683 };
684 /// This function is used in the debugger pretty formatters in tools/ to fetch the684 /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the
685 /// child field order and entry type to facilitate fancy debug printing for this type.685 /// child field order and entry type to facilitate fancy debug printing for this type.
686 fn dbHelper(self: *Self, child: *Elem, field: *Field, entry: *Entry) void {686 fn dbHelper(self: *Self, child: *Elem, field: *Field, entry: *Entry) void {
687 _ = self;687 _ = self;
lib/std/os/emscripten.zig+1-1
...@@ -730,7 +730,7 @@ pub const clock_t = i32;...@@ -730,7 +730,7 @@ pub const clock_t = i32;
730pub const dl_phdr_info = extern struct {730pub const dl_phdr_info = extern struct {
731 addr: usize,731 addr: usize,
732 name: ?[*:0]const u8,732 name: ?[*:0]const u8,
733 phdr: [*]std.elf.Phdr,733 phdr: [*]std.elf.ElfN.Phdr,
734 phnum: u16,734 phnum: u16,
735};735};
736736
lib/std/os/linux.zig+4-6
...@@ -2058,8 +2058,8 @@ pub const F = struct {...@@ -2058,8 +2058,8 @@ pub const F = struct {
2058 },2058 },
2059 };2059 };
20602060
2061 pub const SETSIG = if (is_hppa or native_arch == .alpha) 13 else 11;2061 pub const SETSIG = if (is_hppa) 13 else 10;
2062 pub const GETSIG = if (is_hppa or native_arch == .alpha) 14 else 12;2062 pub const GETSIG = if (is_hppa) 14 else 11;
20632063
2064 pub const SETOWN_EX = 15;2064 pub const SETOWN_EX = 15;
2065 pub const GETOWN_EX = 16;2065 pub const GETOWN_EX = 16;
...@@ -8181,13 +8181,11 @@ pub const rusage = extern struct {...@@ -8181,13 +8181,11 @@ pub const rusage = extern struct {
81818181
8182pub const NCC = if (is_ppc) 10 else 8;8182pub const NCC = if (is_ppc) 10 else 8;
8183pub const NCCS = if (is_mips)8183pub const NCCS = if (is_mips)
8184 328184 23
8185else if (is_ppc or native_arch == .alpha)
8186 19
8187else if (is_sparc)8185else if (is_sparc)
8188 178186 17
8189else8187else
8190 32;8188 19;
81918189
8192pub const speed_t = if (is_ppc) enum(c_uint) {8190pub const speed_t = if (is_ppc) enum(c_uint) {
8193 B0 = 0x0000000,8191 B0 = 0x0000000,
lib/std/os/linux/IoUring.zig+1-1
...@@ -267,7 +267,7 @@ pub fn cq_ready(self: *IoUring) u32 {...@@ -267,7 +267,7 @@ pub fn cq_ready(self: *IoUring) u32 {
267}267}
268268
269/// Copies as many CQEs as are ready, and that can fit into the destination `cqes` slice.269/// 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.
271/// Returns the number of CQEs copied, advancing the CQ ring.271/// Returns the number of CQEs copied, advancing the CQ ring.
272/// Provides all the wait/peek methods found in liburing, but with batching and a single method.272/// Provides all the wait/peek methods found in liburing, but with batching and a single method.
273/// The rationale for copying CQEs rather than copying pointers is that pointers are 8 bytes273/// 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" {...@@ -475,9 +475,6 @@ test "close" {
475}475}
476476
477test "accept/connect/send/recv" {477test "accept/connect/send/recv" {
478 const io = testing.io;
479 _ = io;
480
481 var ring = IoUring.init(16, 0) catch |err| switch (err) {478 var ring = IoUring.init(16, 0) catch |err| switch (err) {
482 error.SystemOutdated => return error.SkipZigTest,479 error.SystemOutdated => return error.SkipZigTest,
483 error.PermissionDenied => return error.SkipZigTest,480 error.PermissionDenied => return error.SkipZigTest,
...@@ -620,7 +617,7 @@ test "timeout (after a relative time)" {...@@ -620,7 +617,7 @@ test "timeout (after a relative time)" {
620617
621 const ms = 10;618 const ms = 10;
622 const margin = 5;619 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
625 const started = std.Io.Clock.awake.now(io);622 const started = std.Io.Clock.awake.now(io);
626 const sqe = try ring.timeout(0x55555555, &ts, 0, 0);623 const sqe = try ring.timeout(0x55555555, &ts, 0, 0);
...@@ -730,9 +727,6 @@ test "timeout_remove" {...@@ -730,9 +727,6 @@ test "timeout_remove" {
730}727}
731728
732test "accept/connect/recv/link_timeout" {729test "accept/connect/recv/link_timeout" {
733 const io = testing.io;
734 _ = io;
735
736 var ring = IoUring.init(16, 0) catch |err| switch (err) {730 var ring = IoUring.init(16, 0) catch |err| switch (err) {
737 error.SystemOutdated => return error.SkipZigTest,731 error.SystemOutdated => return error.SkipZigTest,
738 error.PermissionDenied => return error.SkipZigTest,732 error.PermissionDenied => return error.SkipZigTest,
...@@ -748,7 +742,7 @@ test "accept/connect/recv/link_timeout" {...@@ -748,7 +742,7 @@ test "accept/connect/recv/link_timeout" {
748 const sqe_recv = try ring.recv(0xffffffff, socket_test_harness.server, .{ .buffer = buffer_recv[0..] }, 0);742 const sqe_recv = try ring.recv(0xffffffff, socket_test_harness.server, .{ .buffer = buffer_recv[0..] }, 0);
749 sqe_recv.flags |= linux.IOSQE_IO_LINK;743 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 };
752 _ = try ring.link_timeout(0x22222222, &ts, 0);746 _ = try ring.link_timeout(0x22222222, &ts, 0);
753747
754 const nr_wait = try ring.submit();748 const nr_wait = try ring.submit();
...@@ -883,9 +877,6 @@ test "statx" {...@@ -883,9 +877,6 @@ test "statx" {
883}877}
884878
885test "accept/connect/recv/cancel" {879test "accept/connect/recv/cancel" {
886 const io = testing.io;
887 _ = io;
888
889 var ring = IoUring.init(16, 0) catch |err| switch (err) {880 var ring = IoUring.init(16, 0) catch |err| switch (err) {
890 error.SystemOutdated => return error.SkipZigTest,881 error.SystemOutdated => return error.SkipZigTest,
891 error.PermissionDenied => return error.SkipZigTest,882 error.PermissionDenied => return error.SkipZigTest,
...@@ -1568,9 +1559,6 @@ test "remove_buffers" {...@@ -1568,9 +1559,6 @@ test "remove_buffers" {
1568}1559}
15691560
1570test "provide_buffers: accept/connect/send/recv" {1561test "provide_buffers: accept/connect/send/recv" {
1571 const io = testing.io;
1572 _ = io;
1573
1574 var ring = IoUring.init(16, 0) catch |err| switch (err) {1562 var ring = IoUring.init(16, 0) catch |err| switch (err) {
1575 error.SystemOutdated => return error.SkipZigTest,1563 error.SystemOutdated => return error.SkipZigTest,
1576 error.PermissionDenied => return error.SkipZigTest,1564 error.PermissionDenied => return error.SkipZigTest,
...@@ -1777,11 +1765,6 @@ test "accept multishot" {...@@ -1777,11 +1765,6 @@ test "accept multishot" {
1777}1765}
17781766
1779test "accept/connect/send_zc/recv" {1767test "accept/connect/send_zc/recv" {
1780 try skipKernelLessThan(.{ .major = 6, .minor = 0, .patch = 0 });
1781
1782 const io = testing.io;
1783 _ = io;
1784
1785 var ring = IoUring.init(16, 0) catch |err| switch (err) {1768 var ring = IoUring.init(16, 0) catch |err| switch (err) {
1786 error.SystemOutdated => return error.SkipZigTest,1769 error.SystemOutdated => return error.SkipZigTest,
1787 error.PermissionDenied => return error.SkipZigTest,1770 error.PermissionDenied => return error.SkipZigTest,
...@@ -1789,6 +1772,13 @@ test "accept/connect/send_zc/recv" {...@@ -1789,6 +1772,13 @@ test "accept/connect/send_zc/recv" {
1789 };1772 };
1790 defer ring.deinit();1773 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
1792 const socket_test_harness = try createSocketTestHarness(&ring);1782 const socket_test_harness = try createSocketTestHarness(&ring);
1793 defer socket_test_harness.close();1783 defer socket_test_harness.close();
17941784
...@@ -1836,16 +1826,16 @@ test "accept/connect/send_zc/recv" {...@@ -1836,16 +1826,16 @@ test "accept/connect/send_zc/recv" {
1836}1826}
18371827
1838test "accept_direct" {1828test "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
1843 var ring = IoUring.init(1, 0) catch |err| switch (err) {1829 var ring = IoUring.init(1, 0) catch |err| switch (err) {
1844 error.SystemOutdated => return error.SkipZigTest,1830 error.SystemOutdated => return error.SkipZigTest,
1845 error.PermissionDenied => return error.SkipZigTest,1831 error.PermissionDenied => return error.SkipZigTest,
1846 else => return err,1832 else => return err,
1847 };1833 };
1848 defer ring.deinit();1834 defer ring.deinit();
1835
1836 const probe = ring.get_probe() catch return error.SkipZigTest;
1837 if (!probe.is_supported(.ACCEPT)) return error.SkipZigTest;
1838
1849 var address: linux.sockaddr.in = .{1839 var address: linux.sockaddr.in = .{
1850 .port = 0,1840 .port = 0,
1851 .addr = @as(*align(1) const u32, @ptrCast(1841 .addr = @as(*align(1) const u32, @ptrCast(
...@@ -1923,13 +1913,6 @@ test "accept_direct" {...@@ -1923,13 +1913,6 @@ test "accept_direct" {
1923}1913}
19241914
1925test "accept_multishot_direct" {1915test "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
1933 var ring = IoUring.init(1, 0) catch |err| switch (err) {1916 var ring = IoUring.init(1, 0) catch |err| switch (err) {
1934 error.SystemOutdated => return error.SkipZigTest,1917 error.SystemOutdated => return error.SkipZigTest,
1935 error.PermissionDenied => return error.SkipZigTest,1918 error.PermissionDenied => return error.SkipZigTest,
...@@ -1937,6 +1920,9 @@ test "accept_multishot_direct" {...@@ -1937,6 +1920,9 @@ test "accept_multishot_direct" {
1937 };1920 };
1938 defer ring.deinit();1921 defer ring.deinit();
19391922
1923 const probe = ring.get_probe() catch return error.SkipZigTest;
1924 if (!probe.is_supported(.ACCEPT)) return error.SkipZigTest;
1925
1940 var address: linux.sockaddr.in = .{1926 var address: linux.sockaddr.in = .{
1941 .port = 0,1927 .port = 0,
1942 .addr = @as(*align(1) const u32, @ptrCast(1928 .addr = @as(*align(1) const u32, @ptrCast(
...@@ -1991,8 +1977,6 @@ test "accept_multishot_direct" {...@@ -1991,8 +1977,6 @@ test "accept_multishot_direct" {
1991}1977}
19921978
1993test "socket" {1979test "socket" {
1994 try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 });
1995
1996 var ring = IoUring.init(1, 0) catch |err| switch (err) {1980 var ring = IoUring.init(1, 0) catch |err| switch (err) {
1997 error.SystemOutdated => return error.SkipZigTest,1981 error.SystemOutdated => return error.SkipZigTest,
1998 error.PermissionDenied => return error.SkipZigTest,1982 error.PermissionDenied => return error.SkipZigTest,
...@@ -2000,6 +1984,9 @@ test "socket" {...@@ -2000,6 +1984,9 @@ test "socket" {
2000 };1984 };
2001 defer ring.deinit();1985 defer ring.deinit();
20021986
1987 const probe = ring.get_probe() catch return error.SkipZigTest;
1988 if (!probe.is_supported(.SOCKET)) return error.SkipZigTest;
1989
2003 // prepare, submit socket operation1990 // prepare, submit socket operation
2004 _ = try ring.socket(0, linux.AF.INET, posix.SOCK.STREAM, 0, 0);1991 _ = try ring.socket(0, linux.AF.INET, posix.SOCK.STREAM, 0, 0);
2005 try testing.expectEqual(@as(u32, 1), try ring.submit());1992 try testing.expectEqual(@as(u32, 1), try ring.submit());
...@@ -2014,8 +2001,6 @@ test "socket" {...@@ -2014,8 +2001,6 @@ test "socket" {
2014}2001}
20152002
2016test "socket_direct/socket_direct_alloc/close_direct" {2003test "socket_direct/socket_direct_alloc/close_direct" {
2017 try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 });
2018
2019 var ring = IoUring.init(2, 0) catch |err| switch (err) {2004 var ring = IoUring.init(2, 0) catch |err| switch (err) {
2020 error.SystemOutdated => return error.SkipZigTest,2005 error.SystemOutdated => return error.SkipZigTest,
2021 error.PermissionDenied => return error.SkipZigTest,2006 error.PermissionDenied => return error.SkipZigTest,
...@@ -2023,6 +2008,9 @@ test "socket_direct/socket_direct_alloc/close_direct" {...@@ -2023,6 +2008,9 @@ test "socket_direct/socket_direct_alloc/close_direct" {
2023 };2008 };
2024 defer ring.deinit();2009 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
2026 var registered_fds: [3]linux.fd_t = @splat(-1);2014 var registered_fds: [3]linux.fd_t = @splat(-1);
2027 try ring.register_files(registered_fds[0..]);2015 try ring.register_files(registered_fds[0..]);
20282016
...@@ -2097,8 +2085,6 @@ test "socket_direct/socket_direct_alloc/close_direct" {...@@ -2097,8 +2085,6 @@ test "socket_direct/socket_direct_alloc/close_direct" {
2097}2085}
20982086
2099test "openat_direct/close_direct" {2087test "openat_direct/close_direct" {
2100 try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 });
2101
2102 var ring = IoUring.init(2, 0) catch |err| switch (err) {2088 var ring = IoUring.init(2, 0) catch |err| switch (err) {
2103 error.SystemOutdated => return error.SkipZigTest,2089 error.SystemOutdated => return error.SkipZigTest,
2104 error.PermissionDenied => return error.SkipZigTest,2090 error.PermissionDenied => return error.SkipZigTest,
...@@ -2106,6 +2092,9 @@ test "openat_direct/close_direct" {...@@ -2106,6 +2092,9 @@ test "openat_direct/close_direct" {
2106 };2092 };
2107 defer ring.deinit();2093 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
2109 var registered_fds: [3]linux.fd_t = @splat(-1);2098 var registered_fds: [3]linux.fd_t = @splat(-1);
2110 try ring.register_files(registered_fds[0..]);2099 try ring.register_files(registered_fds[0..]);
21112100
...@@ -2148,9 +2137,6 @@ test "openat_direct/close_direct" {...@@ -2148,9 +2137,6 @@ test "openat_direct/close_direct" {
2148}2137}
21492138
2150test "ring mapped buffers recv" {2139test "ring mapped buffers recv" {
2151 const io = testing.io;
2152 _ = io;
2153
2154 var ring = IoUring.init(16, 0) catch |err| switch (err) {2140 var ring = IoUring.init(16, 0) catch |err| switch (err) {
2155 error.SystemOutdated => return error.SkipZigTest,2141 error.SystemOutdated => return error.SkipZigTest,
2156 error.PermissionDenied => return error.SkipZigTest,2142 error.PermissionDenied => return error.SkipZigTest,
...@@ -2238,9 +2224,6 @@ test "ring mapped buffers recv" {...@@ -2238,9 +2224,6 @@ test "ring mapped buffers recv" {
2238}2224}
22392225
2240test "ring mapped buffers multishot recv" {2226test "ring mapped buffers multishot recv" {
2241 const io = testing.io;
2242 _ = io;
2243
2244 var ring = IoUring.init(16, 0) catch |err| switch (err) {2227 var ring = IoUring.init(16, 0) catch |err| switch (err) {
2245 error.SystemOutdated => return error.SkipZigTest,2228 error.SystemOutdated => return error.SkipZigTest,
2246 error.PermissionDenied => return error.SkipZigTest,2229 error.PermissionDenied => return error.SkipZigTest,
...@@ -2672,7 +2655,7 @@ pub fn createSocketTestHarness(ring: *IoUring) !SocketTestHarness {...@@ -2672,7 +2655,7 @@ pub fn createSocketTestHarness(ring: *IoUring) !SocketTestHarness {
26722655
2673 // All good2656 // All good
26742657
2675 return SocketTestHarness{2658 return .{
2676 .listener = listener_socket,2659 .listener = listener_socket,
2677 .server = cqe_accept.res,2660 .server = cqe_accept.res,
2678 .client = client,2661 .client = client,
...@@ -2695,27 +2678,6 @@ fn createListenerSocket(address: *linux.sockaddr.in) !posix.socket_t {...@@ -2695,27 +2678,6 @@ fn createListenerSocket(address: *linux.sockaddr.in) !posix.socket_t {
2695 return listener_socket;2678 return listener_socket;
2696}2679}
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
2719fn addrAny(addr: *linux.sockaddr.in) *linux.sockaddr {2681fn addrAny(addr: *linux.sockaddr.in) *linux.sockaddr {
2720 return @ptrCast(addr);2682 return @ptrCast(addr);
2721}2683}
lib/std/os/linux/aarch64.zig+1-1
...@@ -154,7 +154,7 @@ pub const restore = restore_rt;...@@ -154,7 +154,7 @@ pub const restore = restore_rt;
154pub fn restore_rt() callconv(.naked) noreturn {154pub fn restore_rt() callconv(.naked) noreturn {
155 switch (builtin.zig_backend) {155 switch (builtin.zig_backend) {
156 .stage2_c => asm volatile (156 .stage2_c => asm volatile (
157 \\ mov x8, %[number]157 \\ mov w8, %[number]
158 \\ svc #0158 \\ svc #0
159 :159 :
160 : [number] "i" (@backingInt(SYS.rt_sigreturn)),160 : [number] "i" (@backingInt(SYS.rt_sigreturn)),
lib/std/os/linux/s390x.zig+26-10
...@@ -174,19 +174,35 @@ pub fn clone() callconv(.naked) u64 {...@@ -174,19 +174,35 @@ pub fn clone() callconv(.naked) u64 {
174}174}
175175
176pub fn restore() callconv(.naked) noreturn {176pub fn restore() callconv(.naked) noreturn {
177 asm volatile (177 switch (builtin.zig_backend) {
178 \\svc 0178 .stage2_c => asm volatile (
179 :179 \\lghi %%r1, %[number]
180 : [number] "{r1}" (@backingInt(SYS.sigreturn)),180 \\svc 0
181 );181 :
182 : [number] "K" (@backingInt(SYS.sigreturn)),
183 ),
184 else => asm volatile (
185 \\svc 0
186 :
187 : [number] "{r1}" (@backingInt(SYS.sigreturn)),
188 ),
189 }
182}190}
183191
184pub fn restore_rt() callconv(.naked) noreturn {192pub fn restore_rt() callconv(.naked) noreturn {
185 asm volatile (193 switch (builtin.zig_backend) {
186 \\svc 0194 .stage2_c => asm volatile (
187 :195 \\lghi %%r1, %[number]
188 : [number] "{r1}" (@backingInt(SYS.rt_sigreturn)),196 \\svc 0
189 );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 }
190}206}
191207
192pub const time_t = i64;208pub const time_t = i64;
lib/std/os/linux/sparc.zig+8-5
...@@ -260,13 +260,16 @@ pub fn clone() callconv(.naked) u32 {...@@ -260,13 +260,16 @@ pub fn clone() callconv(.naked) u32 {
260260
261pub const restore = restore_rt;261pub const restore = restore_rt;
262262
263// Need to use C ABI here instead of naked263pub fn restore_rt() callconv(.naked) noreturn {
264// to prevent an infinite loop when calling rt_sigreturn.264 asm volatile (
265pub fn restore_rt() callconv(.c) void {265 \\ nop
266 return asm volatile ("t 0x10"266 \\ nop
267 );
268 asm volatile (
269 \\ t 0x10
267 :270 :
268 : [number] "{g1}" (@backingInt(SYS.rt_sigreturn)),271 : [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 );
270}273}
271274
272pub const VDSO = struct {275pub const VDSO = struct {
lib/std/os/linux/sparc64.zig+8-5
...@@ -259,13 +259,16 @@ pub fn clone() callconv(.naked) u64 {...@@ -259,13 +259,16 @@ pub fn clone() callconv(.naked) u64 {
259259
260pub const restore = restore_rt;260pub const restore = restore_rt;
261261
262// Need to use C ABI here instead of naked262pub fn restore_rt() callconv(.naked) noreturn {
263// to prevent an infinite loop when calling rt_sigreturn.263 asm volatile (
264pub fn restore_rt() callconv(.c) void {264 \\ nop
265 return asm volatile ("t 0x6d"265 \\ nop
266 );
267 asm volatile (
268 \\ t 0x6d
266 :269 :
267 : [number] "{g1}" (@backingInt(SYS.rt_sigreturn)),270 : [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 );
269}272}
270273
271pub const VDSO = struct {274pub const VDSO = struct {
lib/std/os/linux/tls.zig+35-14
...@@ -22,7 +22,7 @@ const page_size_min = std.heap.page_size_min;...@@ -22,7 +22,7 @@ const page_size_min = std.heap.page_size_min;
22/// Represents an ELF TLS variant.22/// Represents an ELF TLS variant.
23///23///
24/// In all variants, the TP and the TLS blocks must be aligned to the `p_align` value in the24/// 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.
26///26///
27/// The location of the DTV does not actually matter. For simplicity, we put it in the TLS area, but27/// The location of the DTV does not actually matter. For simplicity, we put it in the TLS area, but
28/// there is no actual ABI requirement that it reside there.28/// there is no actual ABI requirement that it reside there.
...@@ -480,17 +480,17 @@ pub fn getThreadPointer() usize {...@@ -480,17 +480,17 @@ pub fn getThreadPointer() usize {
480 };480 };
481}481}
482482
483fn computeAreaDesc(phdrs: []elf.Phdr) void {483fn computeAreaDesc(phdrs: []elf.ElfN.Phdr) void {
484 @setRuntimeSafety(false);484 @setRuntimeSafety(false);
485 @disableInstrumentation();485 @disableInstrumentation();
486486
487 var tls_phdr: ?*elf.Phdr = null;487 var tls_phdr: ?*elf.ElfN.Phdr = null;
488 var img_base: usize = 0;488 var img_base: usize = 0;
489489
490 for (phdrs) |*phdr| {490 for (phdrs) |*phdr| {
491 switch (phdr.p_type) {491 switch (phdr.type) {
492 elf.PT_PHDR => img_base = @intFromPtr(phdrs.ptr) - phdr.p_vaddr,492 .PHDR => img_base = @intFromPtr(phdrs.ptr) - phdr.vaddr,
493 elf.PT_TLS => tls_phdr = phdr,493 .TLS => tls_phdr = phdr,
494 else => {},494 else => {},
495 }495 }
496 }496 }
...@@ -500,12 +500,12 @@ fn computeAreaDesc(phdrs: []elf.Phdr) void {...@@ -500,12 +500,12 @@ fn computeAreaDesc(phdrs: []elf.Phdr) void {
500 var block_size: usize = undefined;500 var block_size: usize = undefined;
501501
502 if (tls_phdr) |phdr| {502 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 stored505 // The effective size in memory is represented by `memsz`; the length of the data stored
506 // in the `PT_TLS` segment is `p_filesz` and may be less than the former.506 // in the `PT.TLS` segment is `filesz` and may be less than the former.
507 block_init = @as([*]u8, @ptrFromInt(img_base + phdr.p_vaddr))[0..phdr.p_filesz];507 block_init = @as([*]u8, @ptrFromInt(img_base + phdr.vaddr))[0..phdr.filesz];
508 block_size = phdr.p_memsz;508 block_size = phdr.memsz;
509 } else {509 } else {
510 align_factor = @alignOf(usize);510 align_factor = @alignOf(usize);
511511
...@@ -651,7 +651,7 @@ var main_thread_area_buffer: [0x1000]u8 align(page_size_min) = undefined;...@@ -651,7 +651,7 @@ var main_thread_area_buffer: [0x1000]u8 align(page_size_min) = undefined;
651651
652/// Computes the layout of the static TLS area, allocates the area, initializes all of its fields,652/// Computes the layout of the static TLS area, allocates the area, initializes all of its fields,
653/// and assigns the architecture-specific value to the TP register.653/// 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 {
655 @setRuntimeSafety(false);655 @setRuntimeSafety(false);
656 @disableInstrumentation();656 @disableInstrumentation();
657657
...@@ -726,12 +726,14 @@ comptime {...@@ -726,12 +726,14 @@ comptime {
726 // function for the GD and LD models. This function is unlikely to actually be used, since726 // function for the GD and LD models. This function is unlikely to actually be used, since
727 // the linker should be able to relax every TLS access to the LE model and therefore727 // the linker should be able to relax every TLS access to the LE model and therefore
728 // eliminate all calls to this function, but that isn't guaranteed.728 // eliminate all calls to this function, but that isn't guaranteed.
729 _ = struct {729 const Fns = struct {
730 const TlsIndex = switch (native_arch) {730 const TlsIndex = switch (native_arch) {
731 .x86_64 => extern struct { module: u64, offset: u64 }, // Even for x32...731 .x86_64 => extern struct { module: u64, offset: u64 }, // Even for x32...
732 else => extern struct { module: usize, offset: usize }, // ...but not MIPS N32!732 else => extern struct { module: usize, offset: usize }, // ...but not MIPS N32!
733 };733 };
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
735 assert(ti.module == 1); // The executable's module ID is always 1737 assert(ti.module == 1); // The executable's module ID is always 1
736 const tp = getThreadPointer();738 const tp = getThreadPointer();
737 const block: [*]u8 = switch (current_variant) {739 const block: [*]u8 = switch (current_variant) {
...@@ -743,6 +745,25 @@ comptime {...@@ -743,6 +745,25 @@ comptime {
743 };745 };
744 return block[@intCast(ti.offset)..];746 return block[@intCast(ti.offset)..];
745 }747 }
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 }
746 };762 };
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" });
747 }768 }
748}769}
lib/std/os/linux/vdso.zig+5-5
...@@ -19,14 +19,14 @@ pub fn lookup(vername: []const u8, name: []const u8) usize {...@@ -19,14 +19,14 @@ pub fn lookup(vername: []const u8, name: []const u8) usize {
19 i += 1;19 i += 1;
20 ph_addr += eh.e_phentsize;20 ph_addr += eh.e_phentsize;
21 }) {21 }) {
22 const this_ph = @as(*elf.Phdr, @ptrFromInt(ph_addr));22 const this_ph = @as(*elf.ElfN.Phdr, @ptrFromInt(ph_addr));
23 switch (this_ph.p_type) {23 switch (this_ph.type) {
24 // On WSL1 as well as older kernels, the VDSO ELF image is pre-linked in the upper half24 // 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).
26 // Wrapping operations are used on this line as well as subsequent calculations relative to base26 // Wrapping operations are used on this line as well as subsequent calculations relative to base
27 // (lines 47, 78) to ensure no overflow check is tripped.27 // (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,28 .LOAD => base = vdso_addr +% this_ph.offset -% this_ph.vaddr,
29 elf.PT_DYNAMIC => maybe_dynv = @as([*]usize, @ptrFromInt(vdso_addr + this_ph.p_offset)),29 .DYNAMIC => maybe_dynv = @as([*]usize, @ptrFromInt(vdso_addr + this_ph.offset)),
30 else => {},30 else => {},
31 }31 }
32 }32 }
lib/std/pie.zig+3-3
...@@ -293,7 +293,7 @@ inline fn getDynamicSymbol() [*]const elf.Dyn {...@@ -293,7 +293,7 @@ inline fn getDynamicSymbol() [*]const elf.Dyn {
293 };293 };
294}294}
295295
296pub fn relocate(phdrs: []const elf.Phdr) void {296pub fn relocate(phdrs: []const elf.ElfN.Phdr) void {
297 @setRuntimeSafety(false);297 @setRuntimeSafety(false);
298 @disableInstrumentation();298 @disableInstrumentation();
299299
...@@ -303,8 +303,8 @@ pub fn relocate(phdrs: []const elf.Phdr) void {...@@ -303,8 +303,8 @@ pub fn relocate(phdrs: []const elf.Phdr) void {
303 // the theoretical load addresses for the `_DYNAMIC` symbol.303 // the theoretical load addresses for the `_DYNAMIC` symbol.
304 const base_addr = base: {304 const base_addr = base: {
305 for (phdrs) |*phdr| {305 for (phdrs) |*phdr| {
306 if (phdr.p_type != elf.PT_DYNAMIC) continue;306 if (phdr.type != .DYNAMIC) continue;
307 break :base @intFromPtr(dynv) - phdr.p_vaddr;307 break :base @intFromPtr(dynv) - phdr.vaddr;
308 }308 }
309 // This is not supposed to happen for well-formed binaries.309 // This is not supposed to happen for well-formed binaries.
310 @trap();310 @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 {...@@ -75,7 +75,7 @@ fn iter_fn(info: *dl_phdr_info, size: usize, counter: *usize) IterFnError!void {
75 // Count how many libraries are loaded75 // Count how many libraries are loaded
76 counter.* += @as(usize, 1);76 counter.* += @as(usize, 1);
7777
78 // The image should contain at least a PT_LOAD segment78 // The image should contain at least a PT.LOAD segment
79 if (info.phnum < 1) return error.MissingPtLoadSegment;79 if (info.phnum < 1) return error.MissingPtLoadSegment;
8080
81 // Quick & dirty validation of the phdr pointers, make sure we're not81 // 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 {...@@ -100,7 +100,7 @@ pub const UserInfo = struct {
100};100};
101101
102/// POSIX function which gets a uid from username.102/// POSIX function which gets a uid from username.
103pub fn getUserInfo(name: []const u8) !UserInfo {103pub fn getUserInfo(io: Io, name: []const u8) !UserInfo {
104 return switch (native_os) {104 return switch (native_os) {
105 .linux,105 .linux,
106 .driverkit,106 .driverkit,
...@@ -116,7 +116,7 @@ pub fn getUserInfo(name: []const u8) !UserInfo {...@@ -116,7 +116,7 @@ pub fn getUserInfo(name: []const u8) !UserInfo {
116 .haiku,116 .haiku,
117 .illumos,117 .illumos,
118 .serenity,118 .serenity,
119 => posixGetUserInfo(name),119 => posixGetUserInfo(io, name),
120 else => @compileError("Unsupported OS"),120 else => @compileError("Unsupported OS"),
121 };121 };
122}122}
...@@ -127,7 +127,7 @@ pub fn posixGetUserInfo(io: Io, name: []const u8) !UserInfo {...@@ -127,7 +127,7 @@ pub fn posixGetUserInfo(io: Io, name: []const u8) !UserInfo {
127 const file = try Io.Dir.openFileAbsolute(io, "/etc/passwd", .{});127 const file = try Io.Dir.openFileAbsolute(io, "/etc/passwd", .{});
128 defer file.close(io);128 defer file.close(io);
129 var buffer: [4096]u8 = undefined;129 var buffer: [4096]u8 = undefined;
130 var file_reader = file.reader(&buffer);130 var file_reader = file.reader(io, &buffer);
131 return posixGetUserInfoPasswdStream(name, &file_reader.interface) catch |err| switch (err) {131 return posixGetUserInfoPasswdStream(name, &file_reader.interface) catch |err| switch (err) {
132 error.ReadFailed => return file_reader.err.?,132 error.ReadFailed => return file_reader.err.?,
133 error.EndOfStream => return error.UserNotFound,133 error.EndOfStream => return error.UserNotFound,
...@@ -644,7 +644,7 @@ pub fn totalSystemMemory() TotalSystemMemoryError!u64 {...@@ -644,7 +644,7 @@ pub fn totalSystemMemory() TotalSystemMemoryError!u64 {
644/// leaks can be accurate. In release builds, this calls `exit` with code zero,644/// leaks can be accurate. In release builds, this calls `exit` with code zero,
645/// and does not return.645/// and does not return.
646pub fn cleanExit(io: Io) void {646pub fn cleanExit(io: Io) void {
647 if (builtin.mode == .Debug) return;647 if (builtin.mode == .debug) return;
648 _ = io.lockStderr(&.{}, .no_color) catch {};648 _ = io.lockStderr(&.{}, .no_color) catch {};
649 exit(0);649 exit(0);
650}650}
...@@ -809,7 +809,7 @@ pub fn abort() noreturn {...@@ -809,7 +809,7 @@ pub fn abort() noreturn {
809 // even when linking libc on Windows we use our own abort implementation.809 // even when linking libc on Windows we use our own abort implementation.
810 // See https://github.com/ziglang/zig/issues/2071 for more details.810 // See https://github.com/ziglang/zig/issues/2071 for more details.
811 if (native_os == .windows) {811 if (native_os == .windows) {
812 if (builtin.mode == .Debug and windows.peb().BeingDebugged.toBool()) {812 if (builtin.mode == .debug and windows.peb().BeingDebugged.toBool()) {
813 @breakpoint();813 @breakpoint();
814 }814 }
815 windows.ntdll.RtlExitUserProcess(3);815 windows.ntdll.RtlExitUserProcess(3);
lib/std/process/Args.zig+1-1
...@@ -752,7 +752,7 @@ pub fn IteratorGeneral(comptime options: IteratorGeneralOptions) type {...@@ -752,7 +752,7 @@ pub fn IteratorGeneral(comptime options: IteratorGeneralOptions) type {
752 start: usize = 0,752 start: usize = 0,
753 end: usize = 0,753 end: usize = 0,
754754
755 pub const Self = @This();755 const Self = @This();
756756
757 pub const InitError = error{OutOfMemory};757 pub const InitError = error{OutOfMemory};
758758
lib/std/sort/block.zig+1-1
...@@ -103,7 +103,7 @@ pub fn block(...@@ -103,7 +103,7 @@ pub fn block(
103 context: anytype,103 context: anytype,
104 comptime lessThanFn: fn (@TypeOf(context), lhs: T, rhs: T) bool,104 comptime lessThanFn: fn (@TypeOf(context), lhs: T, rhs: T) bool,
105) void {105) void {
106 const lessThan = if (builtin.mode == .Debug) struct {106 const lessThan = if (builtin.mode == .debug) struct {
107 fn lessThan(ctx: @TypeOf(context), lhs: T, rhs: T) bool {107 fn lessThan(ctx: @TypeOf(context), lhs: T, rhs: T) bool {
108 const lt = lessThanFn(ctx, lhs, rhs);108 const lt = lessThanFn(ctx, lhs, rhs);
109 const gt = lessThanFn(ctx, rhs, lhs);109 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 {...@@ -97,7 +97,7 @@ pub fn specConst(T: type, comptime default_value: T, comptime spec_id: u32) T {
97 },97 },
98 .int, .float => return asm (98 .int, .float => return asm (
99 \\%ret = OpSpecConstant %ty $default_value99 \\%ret = OpSpecConstant %ty $default_value
100 \\ OpDecorate %ret SpecId $spec_id"100 \\ OpDecorate %ret SpecId $spec_id
101 : [ret] "" (-> T),101 : [ret] "" (-> T),
102 : [ty] "t" (T),102 : [ty] "t" (T),
103 [default_value] "c" (default_value),103 [default_value] "c" (default_value),
lib/std/start.zig+11-11
...@@ -589,7 +589,7 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn {...@@ -589,7 +589,7 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn {
589 else => continue,589 else => continue,
590 }590 }
591 }591 }
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];
593 };593 };
594594
595 // Apply the initial relocations as early as possible in the startup process. We cannot595 // 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 {...@@ -621,7 +621,7 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn {
621 std.os.linux.tls.initStatic(phdrs);621 std.os.linux.tls.initStatic(phdrs);
622 }622 }
623623
624 // The way Linux executables represent stack size is via the PT_GNU_STACK624 // The way Linux executables represent stack size is via the PT.GNU_STACK
625 // program header. However the kernel does not recognize it; it always gives 8 MiB.625 // program header. However the kernel does not recognize it; it always gives 8 MiB.
626 // Here we look for the stack size in our program headers and use setrlimit626 // Here we look for the stack size in our program headers and use setrlimit
627 // to ask for more stack space.627 // to ask for more stack space.
...@@ -645,19 +645,19 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn {...@@ -645,19 +645,19 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn {
645 std.process.exit(callMainWithArgs(argc, argv, envp));645 std.process.exit(callMainWithArgs(argc, argv, envp));
646}646}
647647
648fn expandStackSize(phdrs: []elf.Phdr) void {648fn expandStackSize(phdrs: []elf.ElfN.Phdr) void {
649 @disableInstrumentation();649 @disableInstrumentation();
650 for (phdrs) |*phdr| {650 for (phdrs) |*phdr| {
651 switch (phdr.p_type) {651 switch (phdr.type) {
652 elf.PT_GNU_STACK => {652 .GNU_STACK => {
653 if (phdr.p_memsz == 0) break;653 if (phdr.memsz == 0) break;
654 assert(phdr.p_memsz % std.heap.page_size_min == 0);654 assert(phdr.memsz % std.heap.page_size_min == 0);
655655
656 // Silently fail if we are unable to get limits.656 // Silently fail if we are unable to get limits.
657 const limits = std.posix.getrlimit(.STACK) catch break;657 const limits = std.posix.getrlimit(.STACK) catch break;
658658
659 // Clamp to limits.max .659 // 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
662 if (wanted_stack_size > limits.cur) {662 if (wanted_stack_size > limits.cur) {
663 std.posix.setrlimit(.STACK, .{663 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...@@ -702,7 +702,7 @@ fn main(c_argc: c_int, c_argv: [*][*:0]c_char, c_envp: [*:null]?[*:0]c_char) cal
702 .linux => {702 .linux => {
703 const at_phdr = std.c.getauxval(elf.AT_PHDR);703 const at_phdr = std.c.getauxval(elf.AT_PHDR);
704 const at_phnum = std.c.getauxval(elf.AT_PHNUM);704 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];
706 expandStackSize(phdrs);706 expandStackSize(phdrs);
707 },707 },
708 .windows => {708 .windows => {
...@@ -742,8 +742,8 @@ fn mainWithoutEnv(c_argc: c_int, c_argv: [*][*:0]c_char) callconv(.c) c_int {...@@ -742,8 +742,8 @@ fn mainWithoutEnv(c_argc: c_int, c_argv: [*][*:0]c_char) callconv(.c) c_int {
742const bad_main_ret = "expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'";742const bad_main_ret = "expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'";
743743
744const use_safe_allocator = !is_wasm and switch (builtin.mode) {744const use_safe_allocator = !is_wasm and switch (builtin.mode) {
745 .Debug, .ReleaseSafe => true,745 .debug, .safe => true,
746 .ReleaseFast, .ReleaseSmall => !builtin.link_libc and builtin.single_threaded, // Also not ideal.746 .fast, .small => !builtin.link_libc and builtin.single_threaded, // Also not ideal.
747};747};
748var safe_allocator: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{});748var 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 {...@@ -162,7 +162,7 @@ pub const Options = struct {
162 /// This enables `std.http.Client` to log ssl secrets to the file specified by the SSLKEYLOGFILE162 /// This enables `std.http.Client` to log ssl secrets to the file specified by the SSLKEYLOGFILE
163 /// env var. Creating such a log file allows other programs with access to that file to decrypt163 /// env var. Creating such a log file allows other programs with access to that file to decrypt
164 /// all `std.http.Client` traffic made by this program.164 /// 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
167 side_channels_mitigations: crypto.SideChannelsMitigations = crypto.default_side_channels_mitigations,167 side_channels_mitigations: crypto.SideChannelsMitigations = crypto.default_side_channels_mitigations,
168168
...@@ -192,7 +192,7 @@ pub const Options = struct {...@@ -192,7 +192,7 @@ pub const Options = struct {
192 /// If this happens the fix is to add the error code to the corresponding192 /// If this happens the fix is to add the error code to the corresponding
193 /// switch expression, possibly introduce a new error in the error set, and193 /// switch expression, possibly introduce a new error in the error set, and
194 /// send a patch to Zig.194 /// 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) {
196 .stage2_llvm, .stage2_x86_64 => true,196 .stage2_llvm, .stage2_x86_64 => true,
197 else => false,197 else => false,
198 },198 },
lib/std/tar/Writer.zig+1-1
...@@ -312,7 +312,7 @@ pub const Header = extern struct {...@@ -312,7 +312,7 @@ pub const Header = extern struct {
312312
313 // add as much to prefix as you can, must split at /313 // add as much to prefix as you can, must split at /
314 const prefix_remaining = max_prefix - prefix_pos;314 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| {
316 @memcpy(w.prefix[prefix_pos..][0..sep_pos], sub_path[0..sep_pos]);316 @memcpy(w.prefix[prefix_pos..][0..sep_pos], sub_path[0..sep_pos]);
317 if ((sub_path.len - sep_pos - 1) > max_name) return error.NameTooLong;317 if ((sub_path.len - sep_pos - 1) > max_name) return error.NameTooLong;
318 @memcpy(w.name[0..][0 .. sub_path.len - sep_pos - 1], sub_path[sep_pos + 1 ..]);318 @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" {...@@ -474,14 +474,14 @@ test "should not overwrite existing file" {
474 defer root.cleanup();474 defer root.cleanup();
475 try testing.expectError(475 try testing.expectError(
476 error.PathAlreadyExists,476 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 }),
478 );478 );
479479
480 // Unpack with strip_components = 0 should pass480 // Unpack with strip_components = 0 should pass
481 r = .fixed(data);481 r = .fixed(data);
482 var root2 = std.testing.tmpDir(.{});482 var root2 = std.testing.tmpDir(.{});
483 defer root2.cleanup();483 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 });
485}485}
486486
487test "case sensitivity" {487test "case sensitivity" {
...@@ -501,7 +501,7 @@ test "case sensitivity" {...@@ -501,7 +501,7 @@ test "case sensitivity" {
501 var root = std.testing.tmpDir(.{});501 var root = std.testing.tmpDir(.{});
502 defer root.cleanup();502 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| {
505 // on case insensitive fs we fail on overwrite existing file505 // on case insensitive fs we fail on overwrite existing file
506 try testing.expectEqual(error.PathAlreadyExists, err);506 try testing.expectEqual(error.PathAlreadyExists, err);
507 return;507 return;
lib/std/testing.zig+1-1
...@@ -999,7 +999,7 @@ test "expectEqualDeep composite type" {...@@ -999,7 +999,7 @@ test "expectEqualDeep composite type" {
999}999}
10001000
1001fn printIndicatorLine(source: []const u8, indicator_index: usize) void {1001fn 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|
1003 line_begin + 11003 line_begin + 1
1004 else1004 else
1005 0;1005 0;
lib/std/testing/Smith.zig+2-2
...@@ -52,7 +52,7 @@ pub inline fn baselineWeights(T: type) []const Weight {...@@ -52,7 +52,7 @@ pub inline fn baselineWeights(T: type) []const Weight {
52 .bool, .int, .float => i: {52 .bool, .int, .float => i: {
53 // Reject types that don't have a fixed bitsize (esp. usize)53 // Reject types that don't have a fixed bitsize (esp. usize)
54 // since they are not gauraunteed to fit in a u64 across targets.54 // since they are not gauraunteed to fit in a u64 across targets.
55 if (std.mem.indexOfScalar(type, &.{55 if (std.mem.findScalar(type, &.{
56 isize, usize,56 isize, usize,
57 c_char, c_longdouble,57 c_char, c_longdouble,
58 c_short, c_ushort,58 c_short, c_ushort,
...@@ -708,7 +708,7 @@ fn constructInput(comptime values: []const union(enum) {...@@ -708,7 +708,7 @@ fn constructInput(comptime values: []const union(enum) {
708}708}
709709
710test value {710test value {
711 if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO711 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
712712
713 const S = struct {713 const S = struct {
714 v: void = {},714 v: void = {},
lib/std/unicode.zig+35
...@@ -425,6 +425,15 @@ pub const Utf8Iterator = struct {...@@ -425,6 +425,15 @@ pub const Utf8Iterator = struct {
425425
426 return it.bytes[original_i..end_ix];426 return it.bytes[original_i..end_ix];
427 }427 }
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 }
428};437};
429438
430pub fn utf16IsHighSurrogate(c: u16) bool {439pub fn utf16IsHighSurrogate(c: u16) bool {
...@@ -768,6 +777,9 @@ fn testMiscInvalidUtf8() !void {...@@ -768,6 +777,9 @@ fn testMiscInvalidUtf8() !void {
768test "utf8 iterator peeking" {777test "utf8 iterator peeking" {
769 try comptime testUtf8Peeking();778 try comptime testUtf8Peeking();
770 try testUtf8Peeking();779 try testUtf8Peeking();
780
781 comptime try testUtf8PeekCodepoint();
782 try testUtf8PeekCodepoint();
771}783}
772784
773fn testUtf8Peeking() !void {785fn testUtf8Peeking() !void {
...@@ -790,6 +802,20 @@ fn testUtf8Peeking() !void {...@@ -790,6 +802,20 @@ fn testUtf8Peeking() !void {
790 try testing.expect(mem.eql(u8, &[_]u8{}, it.peek(1)));802 try testing.expect(mem.eql(u8, &[_]u8{}, it.peek(1)));
791}803}
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
793fn testError(bytes: []const u8, expected_err: anyerror) !void {819fn testError(bytes: []const u8, expected_err: anyerror) !void {
794 try testing.expectError(expected_err, testDecode(bytes));820 try testing.expectError(expected_err, testDecode(bytes));
795}821}
...@@ -1758,6 +1784,15 @@ pub const Wtf8Iterator = struct {...@@ -1758,6 +1784,15 @@ pub const Wtf8Iterator = struct {
17581784
1759 return it.bytes[original_i..end_ix];1785 return it.bytes[original_i..end_ix];
1760 }1786 }
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 }
1761};1796};
17621797
1763pub fn wtf16LeToWtf8ArrayList(result: *std.array_list.Managed(u8), utf16le: []const u16) Allocator.Error!void {1798pub 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 {...@@ -386,23 +386,6 @@ pub const Subsystem = enum {
386 efi_boot_service_driver,386 efi_boot_service_driver,
387 efi_rom,387 efi_rom,
388 efi_runtime_driver,388 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;
406};389};
407390
408pub const CompressDebugSections = enum(u2) { none, zlib, zstd };391pub const CompressDebugSections = enum(u2) { none, zlib, zstd };
...@@ -562,8 +545,7 @@ pub fn stringEscape(bytes: []const u8, w: *Writer) Writer.Error!void {...@@ -562,8 +545,7 @@ pub fn stringEscape(bytes: []const u8, w: *Writer) Writer.Error!void {
562 '\t' => try w.writeAll("\\t"),545 '\t' => try w.writeAll("\\t"),
563 '\\' => try w.writeAll("\\\\"),546 '\\' => try w.writeAll("\\\\"),
564 '"' => try w.writeAll("\\\""),547 '"' => try w.writeAll("\\\""),
565 '\'' => try w.writeByte('\''),548 ' ', '!', '#'...'[', ']'...'~' => try w.writeByte(byte),
566 ' ', '!', '#'...'&', '('...'[', ']'...'~' => try w.writeByte(byte),
567 else => {549 else => {
568 try w.writeAll("\\x");550 try w.writeAll("\\x");
569 try w.printInt(byte, 16, .lower, .{ .width = 2, .fill = '0' });551 try w.printInt(byte, 16, .lower, .{ .width = 2, .fill = '0' });
...@@ -780,11 +762,11 @@ pub const EnvVar = enum {...@@ -780,11 +762,11 @@ pub const EnvVar = enum {
780 ZIG_LIBC,762 ZIG_LIBC,
781 ZIG_BUILD_ERROR_STYLE,763 ZIG_BUILD_ERROR_STYLE,
782 ZIG_BUILD_MULTILINE_ERRORS,764 ZIG_BUILD_MULTILINE_ERRORS,
765 ZIG_BUILD_SUMMARY,
783 ZIG_VERBOSE_LINK,766 ZIG_VERBOSE_LINK,
784 ZIG_VERBOSE_CC,767 ZIG_VERBOSE_CC,
785 ZIG_VERBOSE_CMD,768 ZIG_VERBOSE_CMD,
786 ZIG_DEBUG_CMD,769 ZIG_DEBUG_CMD,
787 ZIG_DEBUG_MAKER,
788 ZIG_IS_DETECTING_LIBC_PATHS,770 ZIG_IS_DETECTING_LIBC_PATHS,
789 ZIG_IS_AVOIDING_CALLING_ITSELF,771 ZIG_IS_AVOIDING_CALLING_ITSELF,
790772
...@@ -1577,7 +1559,7 @@ pub fn resolvePath(...@@ -1577,7 +1559,7 @@ pub fn resolvePath(
1577 // Heuristic for a fast path: if no component is absolute and ".." never appears, we just need to resolve `paths`.1559 // Heuristic for a fast path: if no component is absolute and ".." never appears, we just need to resolve `paths`.
1578 for (paths) |p| {1560 for (paths) |p| {
1579 if (Dir.path.isAbsolute(p)) break; // absolute path1561 if (Dir.path.isAbsolute(p)) break; // absolute path
1580 if (mem.indexOf(u8, p, "..") != null) break; // may contain up-dir1562 if (mem.find(u8, p, "..") != null) break; // may contain up-dir
1581 } else {1563 } else {
1582 // no absolute path, no "..".1564 // no absolute path, no "..".
1583 const res = try Dir.path.resolve(gpa, paths);1565 const res = try Dir.path.resolve(gpa, paths);
...@@ -1675,31 +1657,32 @@ pub fn buildExeSubprocess(...@@ -1675,31 +1657,32 @@ pub fn buildExeSubprocess(
1675 };1657 };
1676 defer child.kill(io);1658 defer child.kill(io);
16771659
1678 var stderr_task = io.concurrent(readStreamAlloc, .{ gpa, io, child.stderr.?, .unlimited }) catch1660 var multi_reader_buffer: Io.File.MultiReader.Buffer(2) = undefined;
1679 @panic("TODO use multireader instead");1661 var multi_reader: Io.File.MultiReader = undefined;
1680 defer if (stderr_task.cancel(io)) |slice| gpa.free(slice) else |_| {};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;1667 var stdin_buffer: [8]u8 = undefined;
1683 var stdout_reader: Io.File.Reader = .initStreaming(child.stdout.?, io, &stdout_buffer);1668 var stdin_writer = child.stdin.?.writerStreaming(io, &stdin_buffer);
1684 const stdout = &stdout_reader.interface;
16851669
1686 {1670 var client: Client = .{
1687 var w = child.stdin.?.writer(io, &.{});1671 .in = stdout,
1688 w.interface.writeStruct(Client.Message.Header{ .tag = .update, .bytes_len = 0 }, .little) catch |err| switch (err) {1672 .out = &stdin_writer.interface,
1689 error.WriteFailed => {1673 };
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 }
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
1704 var result: ?Cache.Path = null;1687 var result: ?Cache.Path = null;
1705 defer if (result) |r| gpa.free(r.sub_path);1688 defer if (result) |r| gpa.free(r.sub_path);
...@@ -1707,33 +1690,29 @@ pub fn buildExeSubprocess(...@@ -1707,33 +1690,29 @@ pub fn buildExeSubprocess(
1707 var result_error_bundle: ErrorBundle = .empty;1690 var result_error_bundle: ErrorBundle = .empty;
1708 defer result_error_bundle.deinit(gpa);1691 defer result_error_bundle.deinit(gpa);
17091692
1710 var body_buffer: std.ArrayList(u8) = .empty;
1711 defer body_buffer.deinit(gpa);
1712
1713 var received_fs_inputs = false;1693 var received_fs_inputs = false;
1714 var cache_hit = false;1694 var cache_hit = false;
17151695
1696 var eos_err: error{EndOfStream}!void = {};
1697
1716 while (true) {1698 while (true) {
1717 const header = stdout.takeStruct(Header, .little) catch |err| switch (err) {1699 const header = client.receiveMessageWithMultiReader(&multi_reader, .none) catch |err| switch (err) {
1718 error.ReadFailed => {1700 error.Timeout => unreachable,
1719 log.err("{t} reading from command: {f}", .{ stdout_reader.err.?, cmd });1701 error.EndOfStream => |e| {
1720 return error.AlreadyReported;1702 if (client.in.bufferedLen() == 0) break;
1721 },1703 // Better to report the crash with stderr below, but we set
1722 error.EndOfStream => break,1704 // this in case the child exits successfully while violating
1723 };1705 // this protocol.
1724 body_buffer.clearRetainingCapacity();1706 eos_err = e;
1725 stdout.appendExact(gpa, &body_buffer, header.bytes_len) catch |err| switch (err) {1707 break;
1726 error.ReadFailed => {
1727 log.err("{t} reading from command: {f}", .{ stdout_reader.err.?, cmd });
1728 return error.AlreadyReported;
1729 },1708 },
1730 error.OutOfMemory => |e| return e,1709 error.Canceled, error.OutOfMemory => |e| return e,
1731 error.EndOfStream => {1710 else => |e| {
1732 log.err("unexpected end of stream from command: {f}", .{cmd});1711 log.err("{t} reading from command: {f}", .{ e, cmd });
1733 return error.AlreadyReported;1712 return error.AlreadyReported;
1734 },1713 },
1735 };1714 };
1736 const body = body_buffer.items;1715 const body = stdout.take(header.bytes_len) catch unreachable;
17371716
1738 switch (header.tag) {1717 switch (header.tag) {
1739 .zig_version => {1718 .zig_version => {
...@@ -1784,16 +1763,15 @@ pub fn buildExeSubprocess(...@@ -1784,16 +1763,15 @@ pub fn buildExeSubprocess(
1784 }1763 }
1785 }1764 }
17861765
1787 const stderr_contents = stderr_task.await(io) catch |err| switch (err) {1766 const stderr_contents = stderr.buffered();
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 };
1794 if (stderr_contents.len > 0)1767 if (stderr_contents.len > 0)
1795 log.warn("unexpected stderr from {s} command:\n{s}", .{ options.argv[0], stderr_contents });1768 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
1797 // Send EOF to stdin.1775 // Send EOF to stdin.
1798 child.stdin.?.close(io);1776 child.stdin.?.close(io);
1799 child.stdin = null;1777 child.stdin = null;
...@@ -1851,14 +1829,6 @@ pub fn buildExeSubprocess(...@@ -1851,14 +1829,6 @@ pub fn buildExeSubprocess(
1851 };1829 };
1852}1830}
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
1862test {1832test {
1863 _ = Ast;1833 _ = Ast;
1864 _ = AstRlAnnotate;1834 _ = 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...@@ -941,20 +941,20 @@ fn renderExpressionFixup(r: *Render, node: Ast.Node.Index, space: Space) Error!v
941}941}
942942
943fn drainNoNewline(w: *Writer, data: []const []const u8, splat: usize) Writer.Error!usize {943fn 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) {
945 return error.WriteFailed;945 return error.WriteFailed;
946 }946 }
947947
948 var n: usize = 0;948 var n: usize = 0;
949 for (data[0 .. data.len - 1]) |v| {949 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) {
951 return error.WriteFailed;951 return error.WriteFailed;
952 }952 }
953 n += v.len;953 n += v.len;
954 }954 }
955955
956 const pattern = data[data.len - 1];956 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) {
958 return error.WriteFailed;958 return error.WriteFailed;
959 }959 }
960 n += pattern.len * splat;960 n += pattern.len * splat;
...@@ -990,7 +990,7 @@ fn rendersMultiline(r: *const Render, node: Ast.Node.Index) error{OutOfMemory}!b...@@ -990,7 +990,7 @@ fn rendersMultiline(r: *const Render, node: Ast.Node.Index) error{OutOfMemory}!b
990 error.WriteFailed => return true,990 error.WriteFailed => return true,
991 };991 };
992 if (sub_ais.disabled_offset != null) return true;992 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) {
994 return true;994 return true;
995 }995 }
996996
...@@ -2993,7 +2993,7 @@ fn hasMultilineString(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.Tok...@@ -2993,7 +2993,7 @@ fn hasMultilineString(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.Tok
2993/// Returns true if there exists a doc comment between the start2993/// Returns true if there exists a doc comment between the start
2994/// of token `start_token` and the start of token `end_token`.2994/// of token `start_token` and the start of token `end_token`.
2995fn hasDocComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {2995fn hasDocComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {
2996 return std.mem.indexOfScalar(2996 return std.mem.findScalar(
2997 Token.Tag,2997 Token.Tag,
2998 tree.tokens.items(.tag)[start_token..end_token],2998 tree.tokens.items(.tag)[start_token..end_token],
2999 .doc_comment,2999 .doc_comment,
...@@ -3459,7 +3459,7 @@ const AutoIndentingStream = struct {...@@ -3459,7 +3459,7 @@ const AutoIndentingStream = struct {
3459 /// Sets current indentation level to be the same as that of the last pushSpace.3459 /// Sets current indentation level to be the same as that of the last pushSpace.
3460 pub fn enableSpaceMode(ais: *AutoIndentingStream, space: Space) void {3460 pub fn enableSpaceMode(ais: *AutoIndentingStream, space: Space) void {
3461 if (ais.space_stack.items.len == 0) return;3461 if (ais.space_stack.items.len == 0) return;
3462 const curr = ais.space_stack.getLast().?;3462 const curr = ais.space_stack.last().?;
3463 if (curr.space != space) return;3463 if (curr.space != space) return;
3464 ais.space_mode = curr.indent_count;3464 ais.space_mode = curr.indent_count;
3465 }3465 }
...@@ -3470,7 +3470,7 @@ const AutoIndentingStream = struct {...@@ -3470,7 +3470,7 @@ const AutoIndentingStream = struct {
34703470
3471 pub fn lastSpaceModeIndent(ais: *AutoIndentingStream) usize {3471 pub fn lastSpaceModeIndent(ais: *AutoIndentingStream) usize {
3472 if (ais.space_stack.items.len == 0) return 0;3472 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;
3474 }3474 }
34753475
3476 /// Push default indentation3476 /// Push default indentation
lib/std/zig/AstGen.zig+3-2
...@@ -74,13 +74,13 @@ src_hasher: std.zig.SrcHasher,...@@ -74,13 +74,13 @@ src_hasher: std.zig.SrcHasher,
74const InnerError = error{ OutOfMemory, AnalysisFail };74const InnerError = error{ OutOfMemory, AnalysisFail };
7575
76fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 {76fn 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;
78 try astgen.extra.ensureUnusedCapacity(astgen.gpa, field_count);78 try astgen.extra.ensureUnusedCapacity(astgen.gpa, field_count);
79 return addExtraAssumeCapacity(astgen, extra);79 return addExtraAssumeCapacity(astgen, extra);
80}80}
8181
82fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 {82fn 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;
84 const extra_index: u32 = @intCast(astgen.extra.items.len);84 const extra_index: u32 = @intCast(astgen.extra.items.len);
85 astgen.extra.items.len += field_count;85 astgen.extra.items.len += field_count;
86 setExtra(astgen, extra_index, extra);86 setExtra(astgen, extra_index, extra);
...@@ -7453,6 +7453,7 @@ fn switchExpr(...@@ -7453,6 +7453,7 @@ fn switchExpr(
7453 const ident_name = try astgen.identAsString(ident_token);7453 const ident_name = try astgen.identAsString(ident_token);
7454 const ident_name_str = tree.tokenSlice(ident_token);7454 const ident_name_str = tree.tokenSlice(ident_token);
7455 if (mem.eql(u8, "_", ident_name_str)) {7455 if (mem.eql(u8, "_", ident_name_str)) {
7456 if (non_err_is_ref != .no) return astgen.failTok(payload_token, "pointer modifier invalid on discard", .{});
7456 break :scope &scratch_scope.base;7457 break :scope &scratch_scope.base;
7457 }7458 }
7458 non_err_capture = if (non_err_is_ref != .no) .by_ref else .by_val;7459 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 @@...@@ -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
1pub const Message = struct {16pub const Message = struct {
2 pub const Header = extern struct {17 pub const Header = extern struct {
3 tag: Tag,18 tag: Tag,
...@@ -46,11 +61,120 @@ pub const Message = struct {...@@ -46,11 +61,120 @@ pub const Message = struct {
46 /// The message body has the same format as in Server.61 /// The message body has the same format as in Server.
47 new_fuzz_input,62 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
49 _,69 _,
50 };70 };
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
52 comptime {86 comptime {
53 const std = @import("std");87 assert(@sizeOf(std.Build.abi.fuzz.LimitKind) == 1);
54 std.debug.assert(@sizeOf(std.Build.abi.fuzz.LimitKind) == 1);
55 }88 }
56};89};
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{...@@ -43,7 +43,7 @@ pub const FindError = error{
43pub fn parse(allocator: Allocator, io: Io, libc_file: []const u8, target: *const std.Target) !LibCInstallation {43pub fn parse(allocator: Allocator, io: Io, libc_file: []const u8, target: *const std.Target) !LibCInstallation {
44 var self: LibCInstallation = .{};44 var self: LibCInstallation = .{};
4545
46 const field_names = comptime std.meta.fieldNames(LibCInstallation);46 const field_names = @typeInfo(LibCInstallation).@"struct".field_names;
47 const FoundKey = struct {47 const FoundKey = struct {
48 found: bool,48 found: bool,
49 allocated: ?[]u8,49 allocated: ?[]u8,
lib/std/zig/Server.zig+66-19
...@@ -1,12 +1,8 @@...@@ -1,12 +1,8 @@
1const Server = @This();1const Server = @This();
22
3const builtin = @import("builtin");
4
5const std = @import("std");3const std = @import("std");
6const Allocator = std.mem.Allocator;4const Allocator = std.mem.Allocator;
7const assert = std.debug.assert;5const assert = std.debug.assert;
8const native_endian = builtin.target.cpu.arch.endian();
9const need_bswap = native_endian != .little;
10const Cache = std.Build.Cache;6const Cache = std.Build.Cache;
11const OutMessage = std.zig.Server.Message;7const OutMessage = std.zig.Server.Message;
12const InMessage = std.zig.Client.Message;8const InMessage = std.zig.Client.Message;
...@@ -16,6 +12,14 @@ const Writer = std.Io.Writer;...@@ -16,6 +12,14 @@ const Writer = std.Io.Writer;
16in: *Reader,12in: *Reader,
17out: *Writer,13out: *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
19pub const Message = struct {23pub const Message = struct {
20 pub const Header = extern struct {24 pub const Header = extern struct {
21 tag: Tag,25 tag: Tag,
...@@ -70,9 +74,62 @@ pub const Message = struct {...@@ -70,9 +74,62 @@ pub const Message = struct {
70 /// Body is a TimeReport.74 /// Body is a TimeReport.
71 time_report,75 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
73 _,98 _,
74 };99 };
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
76 pub const PathPrefix = enum(u8) {133 pub const PathPrefix = enum(u8) {
77 cwd,134 cwd,
78 zig_lib,135 zig_lib,
...@@ -140,21 +197,6 @@ pub const Message = struct {...@@ -140,21 +197,6 @@ pub const Message = struct {
140 };197 };
141};198};
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
158pub fn receiveMessage(s: *Server) !InMessage.Header {200pub fn receiveMessage(s: *Server) !InMessage.Header {
159 return s.in.takeStruct(InMessage.Header, .little);201 return s.in.takeStruct(InMessage.Header, .little);
160}202}
...@@ -183,6 +225,11 @@ pub fn serveMessageHeader(s: *const Server, header: OutMessage.Header) !void {...@@ -183,6 +225,11 @@ pub fn serveMessageHeader(s: *const Server, header: OutMessage.Header) !void {
183 try s.out.writeStruct(header, .little);225 try s.out.writeStruct(header, .little);
184}226}
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
186pub fn serveU32Message(s: *const Server, tag: OutMessage.Tag, int: u32) !void {233pub fn serveU32Message(s: *const Server, tag: OutMessage.Tag, int: u32) !void {
187 try serveMessageHeader(s, .{234 try serveMessageHeader(s, .{
188 .tag = tag,235 .tag = tag,
lib/std/zig/WindowsSdk.zig+4-4
...@@ -891,7 +891,7 @@ const MsvcLibDir = struct {...@@ -891,7 +891,7 @@ const MsvcLibDir = struct {
891891
892 lib_dir_buf.appendSliceAssumeCapacity(installation_path);892 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().?)) {
895 try lib_dir_buf.append('\\');895 try lib_dir_buf.append('\\');
896 }896 }
897 const installation_path_with_trailing_sep_len = lib_dir_buf.items.len;897 const installation_path_with_trailing_sep_len = lib_dir_buf.items.len;
...@@ -1064,7 +1064,7 @@ const MsvcLibDir = struct {...@@ -1064,7 +1064,7 @@ const MsvcLibDir = struct {
1064 errdefer msvc_dir.deinit();1064 errdefer msvc_dir.deinit();
10651065
1066 // String might contain trailing slash, so trim it here1066 // 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
1069 // Remove `\include` at the end of path1069 // Remove `\include` at the end of path
1070 if (std.mem.endsWith(u8, msvc_dir.items, "\\include")) {1070 if (std.mem.endsWith(u8, msvc_dir.items, "\\include")) {
...@@ -1108,7 +1108,7 @@ const MsvcLibDir = struct {...@@ -1108,7 +1108,7 @@ const MsvcLibDir = struct {
11081108
1109 try list.appendSlice(VS140COMNTOOLS); // C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools1109 try list.appendSlice(VS140COMNTOOLS); // C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools
1110 // String might contain trailing slash, so trim it here1110 // 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();
1112 list.shrinkRetainingCapacity(list.items.len - "\\Common7\\Tools".len); // C:\Program Files (x86)\Microsoft Visual Studio 14.01112 list.shrinkRetainingCapacity(list.items.len - "\\Common7\\Tools".len); // C:\Program Files (x86)\Microsoft Visual Studio 14.0
1113 break :base_path list;1113 break :base_path list;
1114 }1114 }
...@@ -1131,7 +1131,7 @@ const MsvcLibDir = struct {...@@ -1131,7 +1131,7 @@ const MsvcLibDir = struct {
1131 errdefer path.deinit();1131 errdefer path.deinit();
11321132
1133 // String might contain trailing slash, so trim it here1133 // 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();
1135 break :base_path path;1135 break :base_path path;
1136 }1136 }
1137 return error.PathNotFound;1137 return error.PathNotFound;
lib/std/zig/Zir.zig+2-2
...@@ -584,7 +584,7 @@ pub const Inst = struct {...@@ -584,7 +584,7 @@ pub const Inst = struct {
584 /// containing the instruction.584 /// containing the instruction.
585 /// Uses the `un_tok` union field.585 /// Uses the `un_tok` union field.
586 ref,586 ref,
587 /// Implements the dereference operand (`.*`). Checks that operand is a pointer587 /// Implements the dereference operator (`.*`). Checks that operand is a pointer
588 /// that supports being directly dereferenced.588 /// that supports being directly dereferenced.
589 /// Uses the `un_node` union field.589 /// Uses the `un_node` union field.
590 deref,590 deref,
...@@ -2522,7 +2522,7 @@ pub const Inst = struct {...@@ -2522,7 +2522,7 @@ pub const Inst = struct {
2522 // bigger than expected. Note that in Debug builds, Zig is allowed2522 // bigger than expected. Note that in Debug builds, Zig is allowed
2523 // to insert a secret field for safety checks.2523 // to insert a secret field for safety checks.
2524 comptime {2524 comptime {
2525 if (builtin.mode != .Debug and builtin.mode != .ReleaseSafe) {2525 if (builtin.mode != .debug and builtin.mode != .safe) {
2526 assert(@sizeOf(Data) == 8);2526 assert(@sizeOf(Data) == 8);
2527 }2527 }
2528 }2528 }
lib/std/zig/llvm/Builder.zig+1320-479
...@@ -17,7 +17,7 @@ gpa: Allocator,...@@ -17,7 +17,7 @@ gpa: Allocator,
17strip: bool,17strip: bool,
1818
19source_filename: String,19source_filename: String,
20data_layout: String,20data_layout: DataLayout,
21target_triple: String,21target_triple: String,
22module_asm: std.ArrayList(u8),22module_asm: std.ArrayList(u8),
2323
...@@ -87,6 +87,455 @@ pub const Options = struct {...@@ -87,6 +87,455 @@ pub const Options = struct {
87 triple: []const u8 = &.{},87 triple: []const u8 = &.{},
88};88};
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
90pub const String = enum(u32) {539pub const String = enum(u32) {
91 none = maxInt(u31),540 none = maxInt(u31),
92 empty,541 empty,
...@@ -142,8 +591,8 @@ pub const String = enum(u32) {...@@ -142,8 +591,8 @@ pub const String = enum(u32) {
142 }591 }
143592
144 fn fromIndex(index: ?usize) String {593 fn fromIndex(index: ?usize) String {
145 return @fromBackingInt(@intCast(@as(u32, @intCast((index orelse return .none) +594 return @fromBackingInt(@as(u32, @intCast((index orelse return .none) +
146 @backingInt(String.empty)))));595 @backingInt(String.empty))));
147 }596 }
148597
149 fn toIndex(self: String) ?usize {598 fn toIndex(self: String) ?usize {
...@@ -489,7 +938,10 @@ pub const Type = enum(u32) {...@@ -489,7 +938,10 @@ pub const Type = enum(u32) {
489 .double, .i64, .x86_mmx => 64,938 .double, .i64, .x86_mmx => 64,
490 .x86_fp80, .i80 => 80,939 .x86_fp80, .i80 => 80,
491 .fp128, .ppc_fp128, .i128 => 128,940 .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 ),
493 _ => {945 _ => {
494 const item = builder.type_items.items[@backingInt(self)];946 const item = builder.type_items.items[@backingInt(self)];
495 return switch (item.tag) {947 return switch (item.tag) {
...@@ -498,7 +950,9 @@ pub const Type = enum(u32) {...@@ -498,7 +950,9 @@ pub const Type = enum(u32) {
498 .vararg_function,950 .vararg_function,
499 => unreachable,951 => unreachable,
500 .integer => @intCast(item.data),952 .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 ),
502 .target => unreachable,956 .target => unreachable,
503 .vector,957 .vector,
504 .scalable_vector,958 .scalable_vector,
...@@ -931,12 +1385,74 @@ pub const Type = enum(u32) {...@@ -931,12 +1385,74 @@ pub const Type = enum(u32) {
931 },1385 },
932 };1386 };
933 }1387 }
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 }
934};1449};
9351450
936pub const Attribute = union(Kind) {1451pub const Attribute = union(Kind) {
937 // Parameter Attributes1452 // Parameter Attributes
938 zeroext,1453 zeroext,
939 signext,1454 signext,
1455 noext,
940 inreg,1456 inreg,
941 byval: Type,1457 byval: Type,
942 byref: Type,1458 byref: Type,
...@@ -947,6 +1463,7 @@ pub const Attribute = union(Kind) {...@@ -947,6 +1463,7 @@ pub const Attribute = union(Kind) {
947 @"align": Alignment.Lazy,1463 @"align": Alignment.Lazy,
948 @"noalias",1464 @"noalias",
949 nocapture,1465 nocapture,
1466 captures: Captures,
950 nofree,1467 nofree,
951 nest,1468 nest,
952 returned,1469 returned,
...@@ -965,6 +1482,11 @@ pub const Attribute = union(Kind) {...@@ -965,6 +1482,11 @@ pub const Attribute = union(Kind) {
965 readnone,1482 readnone,
966 readonly,1483 readonly,
967 writeonly,1484 writeonly,
1485 writable,
1486 initializes: []const [2]u64,
1487 dead_on_unwind,
1488 dead_on_return: ?u32,
1489 range: [2]Constant,
9681490
969 // Function Attributes1491 // Function Attributes
970 //alignstack: Alignment.Lazy,1492 //alignstack: Alignment.Lazy,
...@@ -974,7 +1496,7 @@ pub const Attribute = union(Kind) {...@@ -974,7 +1496,7 @@ pub const Attribute = union(Kind) {
974 builtin,1496 builtin,
975 cold,1497 cold,
976 convergent,1498 convergent,
977 disable_sanitizer_information,1499 disable_sanitizer_instrumentation,
978 fn_ret_thunk_extern,1500 fn_ret_thunk_extern,
979 hot,1501 hot,
980 inlinehint,1502 inlinehint,
...@@ -984,6 +1506,7 @@ pub const Attribute = union(Kind) {...@@ -984,6 +1506,7 @@ pub const Attribute = union(Kind) {
984 naked,1506 naked,
985 nobuiltin,1507 nobuiltin,
986 nocallback,1508 nocallback,
1509 nodivergencesource,
987 noduplicate,1510 noduplicate,
988 //nofree,1511 //nofree,
989 noimplicitfloat,1512 noimplicitfloat,
...@@ -1001,6 +1524,7 @@ pub const Attribute = union(Kind) {...@@ -1001,6 +1524,7 @@ pub const Attribute = union(Kind) {
1001 nosanitize_bounds,1524 nosanitize_bounds,
1002 nosanitize_coverage,1525 nosanitize_coverage,
1003 null_pointer_is_valid,1526 null_pointer_is_valid,
1527 optdebug,
1004 optforfuzzing,1528 optforfuzzing,
1005 optnone,1529 optnone,
1006 optsize,1530 optsize,
...@@ -1012,23 +1536,23 @@ pub const Attribute = union(Kind) {...@@ -1012,23 +1536,23 @@ pub const Attribute = union(Kind) {
1012 sanitize_thread,1536 sanitize_thread,
1013 sanitize_hwaddress,1537 sanitize_hwaddress,
1014 sanitize_memtag,1538 sanitize_memtag,
1539 sanitize_realtime,
1540 sanitize_realtime_blocking,
1541 sanitize_alloc_token,
1015 speculative_load_hardening,1542 speculative_load_hardening,
1016 speculatable,1543 speculatable,
1017 ssp,1544 ssp,
1018 sspstrong,1545 sspstrong,
1019 sspreq,1546 sspreq,
1020 strictfp,1547 strictfp,
1548 denormal_fpenv,
1021 uwtable: UwTable,1549 uwtable: UwTable,
1022 nocf_check,1550 nocf_check,
1023 shadowcallstack,1551 shadowcallstack,
1024 mustprogress,1552 mustprogress,
1025 vscale_range: VScaleRange,1553 vscale_range: VScaleRange,
10261554 nooutline,
1027 // Global Attributes1555 nocreateundeforpoison,
1028 no_sanitize_address,
1029 no_sanitize_hwaddress,
1030 //sanitize_memtag,
1031 sanitize_address_dyninit,
10321556
1033 string: struct { kind: String, value: String },1557 string: struct { kind: String, value: String },
1034 none: noreturn,1558 none: noreturn,
...@@ -1045,100 +1569,11 @@ pub const Attribute = union(Kind) {...@@ -1045,100 +1569,11 @@ pub const Attribute = union(Kind) {
1045 const storage = self.toStorage(builder);1569 const storage = self.toStorage(builder);
1046 if (storage.kind.toString()) |kind| return .{ .string = .{1570 if (storage.kind.toString()) |kind| return .{ .string = .{
1047 .kind = kind,1571 .kind = kind,
1048 .value = @fromBackingInt(@intCast(storage.value)),1572 .value = @fromBackingInt(storage.value),
1049 } } else return switch (storage.kind) {1573 } } else return switch (storage.kind) {
1050 inline .zeroext,1574 inline else => |kind| {
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| {
1140 const field_name, const field_type = comptime blk: {1575 const field_name, const field_type = comptime blk: {
1141 @setEvalBranchQuota(10_000);1576 @setEvalBranchQuota(12_000);
1142 const info = @typeInfo(Attribute).@"union";1577 const info = @typeInfo(Attribute).@"union";
1143 for (info.field_names, info.field_types) |field_name, field_type| {1578 for (info.field_names, info.field_types) |field_name, field_type| {
1144 if (std.mem.eql(u8, field_name, @tagName(kind))) break :blk .{ field_name, field_type };1579 if (std.mem.eql(u8, field_name, @tagName(kind))) break :blk .{ field_name, field_type };
...@@ -1149,14 +1584,17 @@ pub const Attribute = union(Kind) {...@@ -1149,14 +1584,17 @@ pub const Attribute = union(Kind) {
1149 return @unionInit(Attribute, field_name, switch (field_type) {1584 return @unionInit(Attribute, field_name, switch (field_type) {
1150 void => {},1585 void => {},
1151 u32 => storage.value,1586 u32 => storage.value,
1152 Alignment.Lazy, String, Type, UwTable => @fromBackingInt(@intCast(storage.value)),1587 Alignment.Lazy, String, Type, UwTable => @fromBackingInt(storage.value),
1153 AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(storage.value),1588 AllocKind, AllocSize, Captures, FpClass, Memory, VScaleRange => @bitCast(storage.value),
1154 else => @compileError("bad payload type: " ++ field_name ++ ": " ++1589 else => @compileError("bad payload type: " ++ field_name ++ ": " ++
1155 @typeName(field_type)),1590 @typeName(field_type)),
1156 });1591 });
1157 },1592 },
1158 .string, .none => unreachable,1593 .initializes,
1159 _ => unreachable,1594 .dead_on_return,
1595 .range,
1596 => @panic("TODO"),
1597 .string, .none, _ => unreachable,
1160 };1598 };
1161 }1599 }
11621600
...@@ -1174,6 +1612,7 @@ pub const Attribute = union(Kind) {...@@ -1174,6 +1612,7 @@ pub const Attribute = union(Kind) {
1174 switch (attribute) {1612 switch (attribute) {
1175 .zeroext,1613 .zeroext,
1176 .signext,1614 .signext,
1615 .noext,
1177 .inreg,1616 .inreg,
1178 .@"noalias",1617 .@"noalias",
1179 .nocapture,1618 .nocapture,
...@@ -1191,11 +1630,13 @@ pub const Attribute = union(Kind) {...@@ -1191,11 +1630,13 @@ pub const Attribute = union(Kind) {
1191 .readnone,1630 .readnone,
1192 .readonly,1631 .readonly,
1193 .writeonly,1632 .writeonly,
1633 .writable,
1634 .dead_on_unwind,
1194 .alwaysinline,1635 .alwaysinline,
1195 .builtin,1636 .builtin,
1196 .cold,1637 .cold,
1197 .convergent,1638 .convergent,
1198 .disable_sanitizer_information,1639 .disable_sanitizer_instrumentation,
1199 .fn_ret_thunk_extern,1640 .fn_ret_thunk_extern,
1200 .hot,1641 .hot,
1201 .inlinehint,1642 .inlinehint,
...@@ -1204,6 +1645,7 @@ pub const Attribute = union(Kind) {...@@ -1204,6 +1645,7 @@ pub const Attribute = union(Kind) {
1204 .naked,1645 .naked,
1205 .nobuiltin,1646 .nobuiltin,
1206 .nocallback,1647 .nocallback,
1648 .nodivergencesource,
1207 .noduplicate,1649 .noduplicate,
1208 .noimplicitfloat,1650 .noimplicitfloat,
1209 .@"noinline",1651 .@"noinline",
...@@ -1220,6 +1662,7 @@ pub const Attribute = union(Kind) {...@@ -1220,6 +1662,7 @@ pub const Attribute = union(Kind) {
1220 .nosanitize_bounds,1662 .nosanitize_bounds,
1221 .nosanitize_coverage,1663 .nosanitize_coverage,
1222 .null_pointer_is_valid,1664 .null_pointer_is_valid,
1665 .optdebug,
1223 .optforfuzzing,1666 .optforfuzzing,
1224 .optnone,1667 .optnone,
1225 .optsize,1668 .optsize,
...@@ -1230,18 +1673,21 @@ pub const Attribute = union(Kind) {...@@ -1230,18 +1673,21 @@ pub const Attribute = union(Kind) {
1230 .sanitize_thread,1673 .sanitize_thread,
1231 .sanitize_hwaddress,1674 .sanitize_hwaddress,
1232 .sanitize_memtag,1675 .sanitize_memtag,
1676 .sanitize_realtime,
1677 .sanitize_realtime_blocking,
1678 .sanitize_alloc_token,
1233 .speculative_load_hardening,1679 .speculative_load_hardening,
1234 .speculatable,1680 .speculatable,
1235 .ssp,1681 .ssp,
1236 .sspstrong,1682 .sspstrong,
1237 .sspreq,1683 .sspreq,
1238 .strictfp,1684 .strictfp,
1685 .denormal_fpenv,
1239 .nocf_check,1686 .nocf_check,
1240 .shadowcallstack,1687 .shadowcallstack,
1241 .mustprogress,1688 .mustprogress,
1242 .no_sanitize_address,1689 .nooutline,
1243 .no_sanitize_hwaddress,1690 .nocreateundeforpoison,
1244 .sanitize_address_dyninit,
1245 => try w.print(" {s}", .{@tagName(attribute)}),1691 => try w.print(" {s}", .{@tagName(attribute)}),
1246 .byval,1692 .byval,
1247 .byref,1693 .byref,
...@@ -1254,6 +1700,45 @@ pub const Attribute = union(Kind) {...@@ -1254,6 +1700,45 @@ pub const Attribute = union(Kind) {
1254 .dereferenceable,1700 .dereferenceable,
1255 .dereferenceable_or_null,1701 .dereferenceable_or_null,
1256 => |size| try w.print(" {s}({d})", .{ @tagName(attribute), size }),1702 => |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 },
1257 .nofpclass => |fpclass| {1742 .nofpclass => |fpclass| {
1258 const Int = @typeInfo(FpClass).@"struct".backing_integer.?;1743 const Int = @typeInfo(FpClass).@"struct".backing_integer.?;
1259 try w.print(" {s}(", .{@tagName(attribute)});1744 try w.print(" {s}(", .{@tagName(attribute)});
...@@ -1281,6 +1766,9 @@ pub const Attribute = union(Kind) {...@@ -1281,6 +1766,9 @@ pub const Attribute = union(Kind) {
1281 try w.print("({d})", .{alignment_bytes});1766 try w.print("({d})", .{alignment_bytes});
1282 }1767 }
1283 },1768 },
1769 .initializes => @panic("TODO"),
1770 .dead_on_return => @panic("TODO"),
1771 .range => @panic("TODO"),
1284 .allockind => |allockind| {1772 .allockind => |allockind| {
1285 try w.print(" {t}(\"", .{attribute});1773 try w.print(" {t}(\"", .{attribute});
1286 var any = false;1774 var any = false;
...@@ -1344,100 +1832,109 @@ pub const Attribute = union(Kind) {...@@ -1344,100 +1832,109 @@ pub const Attribute = union(Kind) {
13441832
1345 pub const Kind = enum(u32) {1833 pub const Kind = enum(u32) {
1346 // Parameter Attributes1834 // Parameter Attributes
1347 zeroext = 34,1835 zeroext = @backingInt(ATTR_KIND.Z_EXT),
1348 signext = 24,1836 signext = @backingInt(ATTR_KIND.S_EXT),
1349 inreg = 5,1837 noext = @backingInt(ATTR_KIND.NO_EXT),
1350 byval = 3,1838 inreg = @backingInt(ATTR_KIND.IN_REG),
1351 byref = 69,1839 byval = @backingInt(ATTR_KIND.BY_VAL),
1352 preallocated = 65,1840 byref = @backingInt(ATTR_KIND.BYREF),
1353 inalloca = 38,1841 preallocated = @backingInt(ATTR_KIND.PREALLOCATED),
1354 sret = 29, // TODO: ?1842 inalloca = @backingInt(ATTR_KIND.IN_ALLOCA),
1355 elementtype = 77,1843 sret = @backingInt(ATTR_KIND.STRUCT_RET),
1356 @"align" = 1,1844 elementtype = @backingInt(ATTR_KIND.ELEMENTTYPE),
1357 @"noalias" = 9,1845 @"align" = @backingInt(ATTR_KIND.ALIGNMENT),
1358 nocapture = 11,1846 @"noalias" = @backingInt(ATTR_KIND.NO_ALIAS),
1359 nofree = 62,1847 nocapture = @backingInt(ATTR_KIND.NO_CAPTURE),
1360 nest = 8,1848 captures = @backingInt(ATTR_KIND.CAPTURES),
1361 returned = 22,1849 nofree = @backingInt(ATTR_KIND.NOFREE),
1362 nonnull = 39,1850 nest = @backingInt(ATTR_KIND.NEST),
1363 dereferenceable = 41,1851 returned = @backingInt(ATTR_KIND.RETURNED),
1364 dereferenceable_or_null = 42,1852 nonnull = @backingInt(ATTR_KIND.NON_NULL),
1365 swiftself = 46,1853 dereferenceable = @backingInt(ATTR_KIND.DEREFERENCEABLE),
1366 swiftasync = 75,1854 dereferenceable_or_null = @backingInt(ATTR_KIND.DEREFERENCEABLE_OR_NULL),
1367 swifterror = 47,1855 swiftself = @backingInt(ATTR_KIND.SWIFT_SELF),
1368 immarg = 60,1856 swiftasync = @backingInt(ATTR_KIND.SWIFT_ASYNC),
1369 noundef = 68,1857 swifterror = @backingInt(ATTR_KIND.SWIFT_ERROR),
1370 nofpclass = 87,1858 immarg = @backingInt(ATTR_KIND.IMMARG),
1371 alignstack = 25,1859 noundef = @backingInt(ATTR_KIND.NOUNDEF),
1372 allocalign = 80,1860 nofpclass = @backingInt(ATTR_KIND.NOFPCLASS),
1373 allocptr = 81,1861 alignstack = @backingInt(ATTR_KIND.STACK_ALIGNMENT),
1374 readnone = 20,1862 allocalign = @backingInt(ATTR_KIND.ALLOC_ALIGN),
1375 readonly = 21,1863 allocptr = @backingInt(ATTR_KIND.ALLOCATED_POINTER),
1376 writeonly = 52,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
1378 // Function Attributes1873 // Function Attributes
1379 //alignstack,1874 //alignstack = @intFromEnum(ATTR_KIND.STACK_ALIGNMENT),
1380 allockind = 82,1875 allockind = @backingInt(ATTR_KIND.ALLOC_KIND),
1381 allocsize = 51,1876 allocsize = @backingInt(ATTR_KIND.ALLOC_SIZE),
1382 alwaysinline = 2,1877 alwaysinline = @backingInt(ATTR_KIND.ALWAYS_INLINE),
1383 builtin = 35,1878 builtin = @backingInt(ATTR_KIND.BUILTIN),
1384 cold = 36,1879 cold = @backingInt(ATTR_KIND.COLD),
1385 convergent = 43,1880 convergent = @backingInt(ATTR_KIND.CONVERGENT),
1386 disable_sanitizer_information = 78,1881 disable_sanitizer_instrumentation = @backingInt(ATTR_KIND.DISABLE_SANITIZER_INSTRUMENTATION),
1387 fn_ret_thunk_extern = 84,1882 fn_ret_thunk_extern = @backingInt(ATTR_KIND.FNRETTHUNK_EXTERN),
1388 hot = 72,1883 hot = @backingInt(ATTR_KIND.HOT),
1389 inlinehint = 4,1884 inlinehint = @backingInt(ATTR_KIND.INLINE_HINT),
1390 jumptable = 40,1885 jumptable = @backingInt(ATTR_KIND.JUMP_TABLE),
1391 memory = 86,1886 memory = @backingInt(ATTR_KIND.MEMORY),
1392 minsize = 6,1887 minsize = @backingInt(ATTR_KIND.MIN_SIZE),
1393 naked = 7,1888 naked = @backingInt(ATTR_KIND.NAKED),
1394 nobuiltin = 10,1889 nobuiltin = @backingInt(ATTR_KIND.NO_BUILTIN),
1395 nocallback = 71,1890 nocallback = @backingInt(ATTR_KIND.NO_CALLBACK),
1396 noduplicate = 12,1891 nodivergencesource = @backingInt(ATTR_KIND.NO_DIVERGENCE_SOURCE),
1397 //nofree,1892 noduplicate = @backingInt(ATTR_KIND.NO_DUPLICATE),
1398 noimplicitfloat = 13,1893 //nofree = @intFromEnum(ATTR_KIND.NOFREE),
1399 @"noinline" = 14,1894 noimplicitfloat = @backingInt(ATTR_KIND.NO_IMPLICIT_FLOAT),
1400 nomerge = 66,1895 @"noinline" = @backingInt(ATTR_KIND.NO_INLINE),
1401 nonlazybind = 15,1896 nomerge = @backingInt(ATTR_KIND.NO_MERGE),
1402 noprofile = 73,1897 nonlazybind = @backingInt(ATTR_KIND.NON_LAZY_BIND),
1403 skipprofile = 85,1898 noprofile = @backingInt(ATTR_KIND.NO_PROFILE),
1404 noredzone = 16,1899 skipprofile = @backingInt(ATTR_KIND.SKIP_PROFILE),
1405 noreturn = 17,1900 noredzone = @backingInt(ATTR_KIND.NO_RED_ZONE),
1406 norecurse = 48,1901 noreturn = @backingInt(ATTR_KIND.NO_RETURN),
1407 willreturn = 61,1902 norecurse = @backingInt(ATTR_KIND.NO_RECURSE),
1408 nosync = 63,1903 willreturn = @backingInt(ATTR_KIND.WILLRETURN),
1409 nounwind = 18,1904 nosync = @backingInt(ATTR_KIND.NOSYNC),
1410 nosanitize_bounds = 79,1905 nounwind = @backingInt(ATTR_KIND.NO_UNWIND),
1411 nosanitize_coverage = 76,1906 nosanitize_bounds = @backingInt(ATTR_KIND.NO_SANITIZE_BOUNDS),
1412 null_pointer_is_valid = 67,1907 nosanitize_coverage = @backingInt(ATTR_KIND.NO_SANITIZE_COVERAGE),
1413 optforfuzzing = 57,1908 null_pointer_is_valid = @backingInt(ATTR_KIND.NULL_POINTER_IS_VALID),
1414 optnone = 37,1909 optdebug = @backingInt(ATTR_KIND.OPTIMIZE_FOR_DEBUGGING),
1415 optsize = 19,1910 optforfuzzing = @backingInt(ATTR_KIND.OPT_FOR_FUZZING),
1416 //preallocated,1911 optnone = @backingInt(ATTR_KIND.OPTIMIZE_NONE),
1417 returns_twice = 23,1912 optsize = @backingInt(ATTR_KIND.OPTIMIZE_FOR_SIZE),
1418 safestack = 44,1913 //preallocated = @intFromEnum(ATTR_KIND.PREALLOCATED),
1419 sanitize_address = 30,1914 returns_twice = @backingInt(ATTR_KIND.RETURNS_TWICE),
1420 sanitize_memory = 32,1915 safestack = @backingInt(ATTR_KIND.SAFESTACK),
1421 sanitize_thread = 31,1916 sanitize_address = @backingInt(ATTR_KIND.SANITIZE_ADDRESS),
1422 sanitize_hwaddress = 55,1917 sanitize_memory = @backingInt(ATTR_KIND.SANITIZE_MEMORY),
1423 sanitize_memtag = 64,1918 sanitize_thread = @backingInt(ATTR_KIND.SANITIZE_THREAD),
1424 speculative_load_hardening = 59,1919 sanitize_hwaddress = @backingInt(ATTR_KIND.SANITIZE_HWADDRESS),
1425 speculatable = 53,1920 sanitize_memtag = @backingInt(ATTR_KIND.SANITIZE_MEMTAG),
1426 ssp = 26,1921 sanitize_realtime = @backingInt(ATTR_KIND.SANITIZE_REALTIME),
1427 sspstrong = 28,1922 sanitize_realtime_blocking = @backingInt(ATTR_KIND.SANITIZE_REALTIME_BLOCKING),
1428 sspreq = 27,1923 sanitize_alloc_token = @backingInt(ATTR_KIND.SANITIZE_ALLOC_TOKEN),
1429 strictfp = 54,1924 speculative_load_hardening = @backingInt(ATTR_KIND.SPECULATIVE_LOAD_HARDENING),
1430 uwtable = 33,1925 speculatable = @backingInt(ATTR_KIND.SPECULATABLE),
1431 nocf_check = 56,1926 ssp = @backingInt(ATTR_KIND.STACK_PROTECT),
1432 shadowcallstack = 58,1927 sspstrong = @backingInt(ATTR_KIND.STACK_PROTECT_STRONG),
1433 mustprogress = 70,1928 sspreq = @backingInt(ATTR_KIND.STACK_PROTECT_REQ),
1434 vscale_range = 74,1929 strictfp = @backingInt(ATTR_KIND.STRICT_FP),
14351930 denormal_fpenv = @backingInt(ATTR_KIND.DENORMAL_FPENV),
1436 // Global Attributes1931 uwtable = @backingInt(ATTR_KIND.UW_TABLE),
1437 no_sanitize_address = 100,1932 nocf_check = @backingInt(ATTR_KIND.NOCF_CHECK),
1438 no_sanitize_hwaddress = 101,1933 shadowcallstack = @backingInt(ATTR_KIND.SHADOWCALLSTACK),
1439 //sanitize_memtag,1934 mustprogress = @backingInt(ATTR_KIND.MUSTPROGRESS),
1440 sanitize_address_dyninit = 102,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
1442 string = maxInt(u31),1939 string = maxInt(u31),
1443 none = maxInt(u32),1940 none = maxInt(u32),
...@@ -1447,16 +1944,128 @@ pub const Attribute = union(Kind) {...@@ -1447,16 +1944,128 @@ pub const Attribute = union(Kind) {
14471944
1448 pub fn fromString(str: String) Kind {1945 pub fn fromString(str: String) Kind {
1449 assert(!str.isAnon());1946 assert(!str.isAnon());
1450 const kind: Kind = @fromBackingInt(@intCast(@backingInt(str)));1947 const kind: Kind = @fromBackingInt(@backingInt(str));
1451 assert(kind != .none);1948 assert(kind != .none);
1452 return kind;1949 return kind;
1453 }1950 }
14541951
1455 fn toString(self: Kind) ?String {1952 fn toString(self: Kind) ?String {
1456 assert(self != .none);1953 assert(self != .none);
1457 const str: String = @fromBackingInt(@intCast(@backingInt(self)));1954 const str: String = @fromBackingInt(@backingInt(self));
1458 return if (str.isAnon()) null else str;1955 return if (str.isAnon()) null else str;
1459 }1956 }
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 };
1460 };2069 };
14612070
1462 pub const FpClass = packed struct(u32) {2071 pub const FpClass = packed struct(u32) {
...@@ -1506,6 +2115,29 @@ pub const Attribute = union(Kind) {...@@ -1506,6 +2115,29 @@ pub const Attribute = union(Kind) {
1506 pub const pnorm = FpClass{ .positive_normal = true };2115 pub const pnorm = FpClass{ .positive_normal = true };
1507 };2116 };
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
1509 pub const AllocKind = packed struct(u32) {2141 pub const AllocKind = packed struct(u32) {
1510 alloc: bool,2142 alloc: bool,
1511 realloc: bool,2143 realloc: bool,
...@@ -1582,9 +2214,13 @@ pub const Attribute = union(Kind) {...@@ -1582,9 +2214,13 @@ pub const Attribute = union(Kind) {
1582 void => 0,2214 void => 0,
1583 u32 => value,2215 u32 => value,
1584 Alignment.Lazy, String, Type, UwTable => @backingInt(value),2216 Alignment.Lazy, String, Type, UwTable => @backingInt(value),
1585 AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(value),2217 AllocKind, AllocSize, Captures, FpClass, Memory, VScaleRange => @bitCast(value),
1586 else => @compileError("bad payload type: " ++ @tagName(tag) ++ @typeName(@TypeOf(value))),2218 else => @compileError("bad payload type: " ++ @tagName(tag) ++ ": " ++ @typeName(@TypeOf(value))),
1587 } },2219 } },
2220 .initializes,
2221 .dead_on_return,
2222 .range,
2223 => @panic("TODO"),
1588 .string => |string_attr| .{2224 .string => |string_attr| .{
1589 .kind = Kind.fromString(string_attr.kind),2225 .kind = Kind.fromString(string_attr.kind),
1590 .value = @backingInt(string_attr.value),2226 .value = @backingInt(string_attr.value),
...@@ -1907,87 +2543,87 @@ pub const AddrSpace = enum(u24) {...@@ -1907,87 +2543,87 @@ pub const AddrSpace = enum(u24) {
19072543
1908 // See llvm/lib/Target/X86/X86.h2544 // See llvm/lib/Target/X86/X86.h
1909 pub const x86 = struct {2545 pub const x86 = struct {
1910 pub const gs: AddrSpace = @fromBackingInt(@intCast(256));2546 pub const gs: AddrSpace = @fromBackingInt(256);
1911 pub const fs: AddrSpace = @fromBackingInt(@intCast(257));2547 pub const fs: AddrSpace = @fromBackingInt(257);
1912 pub const ss: AddrSpace = @fromBackingInt(@intCast(258));2548 pub const ss: AddrSpace = @fromBackingInt(258);
19132549
1914 pub const ptr32_sptr: AddrSpace = @fromBackingInt(@intCast(270));2550 pub const ptr32_sptr: AddrSpace = @fromBackingInt(270);
1915 pub const ptr32_uptr: AddrSpace = @fromBackingInt(@intCast(271));2551 pub const ptr32_uptr: AddrSpace = @fromBackingInt(271);
1916 pub const ptr64: AddrSpace = @fromBackingInt(@intCast(272));2552 pub const ptr64: AddrSpace = @fromBackingInt(272);
1917 };2553 };
1918 pub const x86_64 = x86;2554 pub const x86_64 = x86;
19192555
1920 // See llvm/lib/Target/AVR/AVR.h2556 // See llvm/lib/Target/AVR/AVR.h
1921 pub const avr = struct {2557 pub const avr = struct {
1922 pub const data: AddrSpace = @fromBackingInt(@intCast(0));2558 pub const data: AddrSpace = @fromBackingInt(0);
1923 pub const program: AddrSpace = @fromBackingInt(@intCast(1));2559 pub const program: AddrSpace = @fromBackingInt(1);
1924 pub const program1: AddrSpace = @fromBackingInt(@intCast(2));2560 pub const program1: AddrSpace = @fromBackingInt(2);
1925 pub const program2: AddrSpace = @fromBackingInt(@intCast(3));2561 pub const program2: AddrSpace = @fromBackingInt(3);
1926 pub const program3: AddrSpace = @fromBackingInt(@intCast(4));2562 pub const program3: AddrSpace = @fromBackingInt(4);
1927 pub const program4: AddrSpace = @fromBackingInt(@intCast(5));2563 pub const program4: AddrSpace = @fromBackingInt(5);
1928 pub const program5: AddrSpace = @fromBackingInt(@intCast(6));2564 pub const program5: AddrSpace = @fromBackingInt(6);
1929 };2565 };
19302566
1931 // See llvm/lib/Target/NVPTX/NVPTX.h2567 // See llvm/lib/Target/NVPTX/NVPTX.h
1932 pub const nvptx = struct {2568 pub const nvptx = struct {
1933 pub const generic: AddrSpace = @fromBackingInt(@intCast(0));2569 pub const generic: AddrSpace = @fromBackingInt(0);
1934 pub const global: AddrSpace = @fromBackingInt(@intCast(1));2570 pub const global: AddrSpace = @fromBackingInt(1);
1935 pub const constant: AddrSpace = @fromBackingInt(@intCast(2));2571 pub const constant: AddrSpace = @fromBackingInt(2);
1936 pub const shared: AddrSpace = @fromBackingInt(@intCast(3));2572 pub const shared: AddrSpace = @fromBackingInt(3);
1937 pub const param: AddrSpace = @fromBackingInt(@intCast(4));2573 pub const param: AddrSpace = @fromBackingInt(4);
1938 pub const local: AddrSpace = @fromBackingInt(@intCast(5));2574 pub const local: AddrSpace = @fromBackingInt(5);
1939 };2575 };
19402576
1941 // See llvm/lib/Target/AMDGPU/AMDGPU.h2577 // See llvm/lib/Target/AMDGPU/AMDGPU.h
1942 pub const amdgpu = struct {2578 pub const amdgpu = struct {
1943 pub const flat: AddrSpace = @fromBackingInt(@intCast(0));2579 pub const flat: AddrSpace = @fromBackingInt(0);
1944 pub const global: AddrSpace = @fromBackingInt(@intCast(1));2580 pub const global: AddrSpace = @fromBackingInt(1);
1945 pub const region: AddrSpace = @fromBackingInt(@intCast(2));2581 pub const region: AddrSpace = @fromBackingInt(2);
1946 pub const local: AddrSpace = @fromBackingInt(@intCast(3));2582 pub const local: AddrSpace = @fromBackingInt(3);
1947 pub const constant: AddrSpace = @fromBackingInt(@intCast(4));2583 pub const constant: AddrSpace = @fromBackingInt(4);
1948 pub const private: AddrSpace = @fromBackingInt(@intCast(5));2584 pub const private: AddrSpace = @fromBackingInt(5);
1949 pub const constant_32bit: AddrSpace = @fromBackingInt(@intCast(6));2585 pub const constant_32bit: AddrSpace = @fromBackingInt(6);
1950 pub const buffer_fat_pointer: AddrSpace = @fromBackingInt(@intCast(7));2586 pub const buffer_fat_pointer: AddrSpace = @fromBackingInt(7);
1951 pub const buffer_resource: AddrSpace = @fromBackingInt(@intCast(8));2587 pub const buffer_resource: AddrSpace = @fromBackingInt(8);
1952 pub const buffer_strided_pointer: AddrSpace = @fromBackingInt(@intCast(9));2588 pub const buffer_strided_pointer: AddrSpace = @fromBackingInt(9);
1953 pub const param_d: AddrSpace = @fromBackingInt(@intCast(6));2589 pub const param_d: AddrSpace = @fromBackingInt(6);
1954 pub const param_i: AddrSpace = @fromBackingInt(@intCast(7));2590 pub const param_i: AddrSpace = @fromBackingInt(7);
1955 pub const constant_buffer_0: AddrSpace = @fromBackingInt(@intCast(8));2591 pub const constant_buffer_0: AddrSpace = @fromBackingInt(8);
1956 pub const constant_buffer_1: AddrSpace = @fromBackingInt(@intCast(9));2592 pub const constant_buffer_1: AddrSpace = @fromBackingInt(9);
1957 pub const constant_buffer_2: AddrSpace = @fromBackingInt(@intCast(10));2593 pub const constant_buffer_2: AddrSpace = @fromBackingInt(10);
1958 pub const constant_buffer_3: AddrSpace = @fromBackingInt(@intCast(11));2594 pub const constant_buffer_3: AddrSpace = @fromBackingInt(11);
1959 pub const constant_buffer_4: AddrSpace = @fromBackingInt(@intCast(12));2595 pub const constant_buffer_4: AddrSpace = @fromBackingInt(12);
1960 pub const constant_buffer_5: AddrSpace = @fromBackingInt(@intCast(13));2596 pub const constant_buffer_5: AddrSpace = @fromBackingInt(13);
1961 pub const constant_buffer_6: AddrSpace = @fromBackingInt(@intCast(14));2597 pub const constant_buffer_6: AddrSpace = @fromBackingInt(14);
1962 pub const constant_buffer_7: AddrSpace = @fromBackingInt(@intCast(15));2598 pub const constant_buffer_7: AddrSpace = @fromBackingInt(15);
1963 pub const constant_buffer_8: AddrSpace = @fromBackingInt(@intCast(16));2599 pub const constant_buffer_8: AddrSpace = @fromBackingInt(16);
1964 pub const constant_buffer_9: AddrSpace = @fromBackingInt(@intCast(17));2600 pub const constant_buffer_9: AddrSpace = @fromBackingInt(17);
1965 pub const constant_buffer_10: AddrSpace = @fromBackingInt(@intCast(18));2601 pub const constant_buffer_10: AddrSpace = @fromBackingInt(18);
1966 pub const constant_buffer_11: AddrSpace = @fromBackingInt(@intCast(19));2602 pub const constant_buffer_11: AddrSpace = @fromBackingInt(19);
1967 pub const constant_buffer_12: AddrSpace = @fromBackingInt(@intCast(20));2603 pub const constant_buffer_12: AddrSpace = @fromBackingInt(20);
1968 pub const constant_buffer_13: AddrSpace = @fromBackingInt(@intCast(21));2604 pub const constant_buffer_13: AddrSpace = @fromBackingInt(21);
1969 pub const constant_buffer_14: AddrSpace = @fromBackingInt(@intCast(22));2605 pub const constant_buffer_14: AddrSpace = @fromBackingInt(22);
1970 pub const constant_buffer_15: AddrSpace = @fromBackingInt(@intCast(23));2606 pub const constant_buffer_15: AddrSpace = @fromBackingInt(23);
1971 pub const streamout_register: AddrSpace = @fromBackingInt(@intCast(128));2607 pub const streamout_register: AddrSpace = @fromBackingInt(128);
1972 };2608 };
19732609
1974 pub const spirv = struct {2610 pub const spirv = struct {
1975 pub const function: AddrSpace = @fromBackingInt(@intCast(0));2611 pub const function: AddrSpace = @fromBackingInt(0);
1976 pub const cross_workgroup: AddrSpace = @fromBackingInt(@intCast(1));2612 pub const cross_workgroup: AddrSpace = @fromBackingInt(1);
1977 pub const uniform_constant: AddrSpace = @fromBackingInt(@intCast(2));2613 pub const uniform_constant: AddrSpace = @fromBackingInt(2);
1978 pub const workgroup: AddrSpace = @fromBackingInt(@intCast(3));2614 pub const workgroup: AddrSpace = @fromBackingInt(3);
1979 pub const generic: AddrSpace = @fromBackingInt(@intCast(4));2615 pub const generic: AddrSpace = @fromBackingInt(4);
1980 pub const device_only_intel: AddrSpace = @fromBackingInt(@intCast(5));2616 pub const device_only_intel: AddrSpace = @fromBackingInt(5);
1981 pub const host_only_intel: AddrSpace = @fromBackingInt(@intCast(6));2617 pub const host_only_intel: AddrSpace = @fromBackingInt(6);
1982 pub const input: AddrSpace = @fromBackingInt(@intCast(7));2618 pub const input: AddrSpace = @fromBackingInt(7);
1983 };2619 };
19842620
1985 // See llvm/include/llvm/CodeGen/WasmAddressSpaces.h2621 // See llvm/include/llvm/CodeGen/WasmAddressSpaces.h
1986 pub const wasm = struct {2622 pub const wasm = struct {
1987 pub const default: AddrSpace = @fromBackingInt(@intCast(0));2623 pub const default: AddrSpace = @fromBackingInt(0);
1988 pub const variable: AddrSpace = @fromBackingInt(@intCast(1));2624 pub const variable: AddrSpace = @fromBackingInt(1);
1989 pub const externref: AddrSpace = @fromBackingInt(@intCast(10));2625 pub const externref: AddrSpace = @fromBackingInt(10);
1990 pub const funcref: AddrSpace = @fromBackingInt(@intCast(20));2626 pub const funcref: AddrSpace = @fromBackingInt(20);
1991 };2627 };
19922628
1993 pub fn format(addr_space: AddrSpace, w: *Writer) Writer.Error!void {2629 pub fn format(addr_space: AddrSpace, w: *Writer) Writer.Error!void {
...@@ -2030,7 +2666,7 @@ pub const Alignment = enum(u6) {...@@ -2030,7 +2666,7 @@ pub const Alignment = enum(u6) {
2030 _,2666 _,
20312667
2032 pub fn wrap(a: Alignment) Lazy {2668 pub fn wrap(a: Alignment) Lazy {
2033 return @fromBackingInt(@intCast(@backingInt(a)));2669 return @fromBackingInt(@backingInt(a));
2034 }2670 }
2035 pub fn resolve(l: Lazy, b: *const Builder) Alignment {2671 pub fn resolve(l: Lazy, b: *const Builder) Alignment {
2036 return switch (@backingInt(l)) {2672 return switch (@backingInt(l)) {
...@@ -2061,11 +2697,18 @@ pub const Alignment = enum(u6) {...@@ -2061,11 +2697,18 @@ pub const Alignment = enum(u6) {
2061 };2697 };
2062 }2698 }
20632699
2064 /// Asserts that neither `a` nor `b` is `.default`.2700 /// Asserts that neither `lhs` nor `rhs` is `.default`.
2065 pub fn max(a: Alignment, b: Alignment) Alignment {2701 pub fn max(lhs: Alignment, rhs: Alignment) Alignment {
2066 assert(a != .default);2702 assert(lhs != .default);
2067 assert(b != .default);2703 assert(rhs != .default);
2068 return @fromBackingInt(@intCast(@max(@backingInt(a), @backingInt(b))));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));
2069 }2712 }
20702713
2071 pub fn toLlvm(self: Alignment) u6 {2714 pub fn toLlvm(self: Alignment) u6 {
...@@ -2106,6 +2749,7 @@ pub const CallConv = enum(u10) {...@@ -2106,6 +2749,7 @@ pub const CallConv = enum(u10) {
2106 tailcc,2749 tailcc,
2107 cfguard_checkcc,2750 cfguard_checkcc,
2108 swifttailcc,2751 swifttailcc,
2752 preserve_nonecc,
21092753
2110 x86_stdcallcc = 64,2754 x86_stdcallcc = 64,
2111 x86_fastcallcc,2755 x86_fastcallcc,
...@@ -2174,6 +2818,7 @@ pub const CallConv = enum(u10) {...@@ -2174,6 +2818,7 @@ pub const CallConv = enum(u10) {
2174 .tailcc,2818 .tailcc,
2175 .cfguard_checkcc,2819 .cfguard_checkcc,
2176 .swifttailcc,2820 .swifttailcc,
2821 .preserve_nonecc,
2177 .x86_stdcallcc,2822 .x86_stdcallcc,
2178 .x86_fastcallcc,2823 .x86_fastcallcc,
2179 .arm_apcscc,2824 .arm_apcscc,
...@@ -2261,8 +2906,7 @@ pub const StrtabString = enum(u32) {...@@ -2261,8 +2906,7 @@ pub const StrtabString = enum(u32) {
2261 }2906 }
22622907
2263 fn fromIndex(index: ?usize) StrtabString {2908 fn fromIndex(index: ?usize) StrtabString {
2264 return @fromBackingInt(@intCast(@as(u32, @intCast((index orelse return .none) +2909 return @fromBackingInt(@intCast((index orelse return .none) + @backingInt(StrtabString.empty)));
2265 @backingInt(StrtabString.empty)))));
2266 }2910 }
22672911
2268 fn toIndex(self: StrtabString) ?usize {2912 fn toIndex(self: StrtabString) ?usize {
...@@ -2318,7 +2962,7 @@ pub fn trailingStrtabString(self: *Builder) Allocator.Error!StrtabString {...@@ -2318,7 +2962,7 @@ pub fn trailingStrtabString(self: *Builder) Allocator.Error!StrtabString {
2318}2962}
23192963
2320pub fn trailingStrtabStringAssumeCapacity(self: *Builder) StrtabString {2964pub fn trailingStrtabStringAssumeCapacity(self: *Builder) StrtabString {
2321 const start = self.strtab_string_indices.getLast().?;2965 const start = self.strtab_string_indices.last().?;
2322 const bytes: []const u8 = self.strtab_string_bytes.items[start..];2966 const bytes: []const u8 = self.strtab_string_bytes.items[start..];
2323 const gop = self.strtab_string_map.getOrPutAssumeCapacityAdapted(bytes, StrtabString.Adapter{ .builder = self });2967 const gop = self.strtab_string_map.getOrPutAssumeCapacityAdapted(bytes, StrtabString.Adapter{ .builder = self });
2324 if (gop.found_existing) {2968 if (gop.found_existing) {
...@@ -2398,7 +3042,7 @@ pub const Global = struct {...@@ -2398,7 +3042,7 @@ pub const Global = struct {
2398 }3042 }
23993043
2400 pub fn toConst(global: Index) Constant {3044 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));
2402 }3046 }
24033047
2404 pub fn toValue(global: Index) Value {3048 pub fn toValue(global: Index) Value {
...@@ -2526,7 +3170,7 @@ pub const Global = struct {...@@ -2526,7 +3170,7 @@ pub const Global = struct {
2526 _ = builder.addGlobalAssumeCapacity(new_name, builder.globals.values()[index]);3170 _ = builder.addGlobalAssumeCapacity(new_name, builder.globals.values()[index]);
2527 builder.globals.swapRemoveAt(index);3171 builder.globals.swapRemoveAt(index);
2528 if (!old_name.isAnon()) return;3172 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);
2530 if (builder.next_unnamed_global == old_name) return;3174 if (builder.next_unnamed_global == old_name) return;
2531 builder.getGlobal(builder.next_unnamed_global).?.renameAssumeCapacity(old_name, builder);3175 builder.getGlobal(builder.next_unnamed_global).?.renameAssumeCapacity(old_name, builder);
2532 }3176 }
...@@ -2539,7 +3183,7 @@ pub const Global = struct {...@@ -2539,7 +3183,7 @@ pub const Global = struct {
25393183
2540 fn replaceAssumeCapacity(self: Index, other: Index, builder: *Builder) void {3184 fn replaceAssumeCapacity(self: Index, other: Index, builder: *Builder) void {
2541 if (self.eql(other, builder)) return;3185 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);
2543 self.renameAssumeCapacity(builder.next_replaced_global, builder);3187 self.renameAssumeCapacity(builder.next_replaced_global, builder);
2544 self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) };3188 self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) };
2545 }3189 }
...@@ -2699,6 +3343,8 @@ pub const Intrinsic = enum {...@@ -2699,6 +3343,8 @@ pub const Intrinsic = enum {
2699 smin,3343 smin,
2700 umax,3344 umax,
2701 umin,3345 umin,
3346 scmp,
3347 ucmp,
2702 memcpy,3348 memcpy,
2703 @"memcpy.inline",3349 @"memcpy.inline",
2704 memmove,3350 memmove,
...@@ -2708,10 +3354,21 @@ pub const Intrinsic = enum {...@@ -2708,10 +3354,21 @@ pub const Intrinsic = enum {
2708 powi,3354 powi,
2709 sin,3355 sin,
2710 cos,3356 cos,
3357 tan,
3358 asin,
3359 acos,
3360 atan,
3361 atan2,
3362 sinh,
3363 cosh,
3364 tanh,
3365 sincos,
3366 sincospi,
3367 modf,
2711 pow,3368 pow,
2712 exp,3369 exp,
2713 exp10,
2714 exp2,3370 exp2,
3371 exp10,
2715 ldexp,3372 ldexp,
2716 frexp,3373 frexp,
2717 log,3374 log,
...@@ -2723,6 +3380,8 @@ pub const Intrinsic = enum {...@@ -2723,6 +3380,8 @@ pub const Intrinsic = enum {
2723 maxnum,3380 maxnum,
2724 minimum,3381 minimum,
2725 maximum,3382 maximum,
3383 minimumnum,
3384 maximumnum,
2726 copysign,3385 copysign,
2727 floor,3386 floor,
2728 ceil,3387 ceil,
...@@ -2744,6 +3403,7 @@ pub const Intrinsic = enum {...@@ -2744,6 +3403,7 @@ pub const Intrinsic = enum {
2744 cttz,3403 cttz,
2745 fshl,3404 fshl,
2746 fshr,3405 fshr,
3406 clmul,
27473407
2748 // Arithmetic with Overflow3408 // Arithmetic with Overflow
2749 @"sadd.with.overflow",3409 @"sadd.with.overflow",
...@@ -2904,21 +3564,21 @@ pub const Intrinsic = enum {...@@ -2904,21 +3564,21 @@ pub const Intrinsic = enum {
2904 .{ .kind = .{ .type = .ptr } },3564 .{ .kind = .{ .type = .ptr } },
2905 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },3565 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
2906 },3566 },
2907 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },3567 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
2908 },3568 },
2909 .addressofreturnaddress = .{3569 .addressofreturnaddress = .{
2910 .ret_len = 1,3570 .ret_len = 1,
2911 .params = &.{3571 .params = &.{
2912 .{ .kind = .overloaded },3572 .{ .kind = .overloaded },
2913 },3573 },
2914 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },3574 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
2915 },3575 },
2916 .sponentry = .{3576 .sponentry = .{
2917 .ret_len = 1,3577 .ret_len = 1,
2918 .params = &.{3578 .params = &.{
2919 .{ .kind = .overloaded },3579 .{ .kind = .overloaded },
2920 },3580 },
2921 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },3581 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
2922 },3582 },
2923 .frameaddress = .{3583 .frameaddress = .{
2924 .ret_len = 1,3584 .ret_len = 1,
...@@ -2926,7 +3586,7 @@ pub const Intrinsic = enum {...@@ -2926,7 +3586,7 @@ pub const Intrinsic = enum {
2926 .{ .kind = .overloaded },3586 .{ .kind = .overloaded },
2927 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },3587 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
2928 },3588 },
2929 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },3589 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
2930 },3590 },
2931 .prefetch = .{3591 .prefetch = .{
2932 .ret_len = 0,3592 .ret_len = 0,
...@@ -2936,14 +3596,14 @@ pub const Intrinsic = enum {...@@ -2936,14 +3596,14 @@ pub const Intrinsic = enum {
2936 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },3596 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
2937 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },3597 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
2938 },3598 },
2939 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.readwrite) } },3599 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.readwrite) } },
2940 },3600 },
2941 .@"thread.pointer" = .{3601 .@"thread.pointer" = .{
2942 .ret_len = 1,3602 .ret_len = 1,
2943 .params = &.{3603 .params = &.{
2944 .{ .kind = .{ .type = .ptr } },3604 .{ .kind = .{ .type = .ptr } },
2945 },3605 },
2946 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },3606 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
2947 },3607 },
29483608
2949 .abs = .{3609 .abs = .{
...@@ -2953,7 +3613,7 @@ pub const Intrinsic = enum {...@@ -2953,7 +3613,7 @@ pub const Intrinsic = enum {
2953 .{ .kind = .{ .matches = 0 } },3613 .{ .kind = .{ .matches = 0 } },
2954 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },3614 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
2955 },3615 },
2956 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },3616 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
2957 },3617 },
2958 .smax = .{3618 .smax = .{
2959 .ret_len = 1,3619 .ret_len = 1,
...@@ -2962,7 +3622,7 @@ pub const Intrinsic = enum {...@@ -2962,7 +3622,7 @@ pub const Intrinsic = enum {
2962 .{ .kind = .{ .matches = 0 } },3622 .{ .kind = .{ .matches = 0 } },
2963 .{ .kind = .{ .matches = 0 } },3623 .{ .kind = .{ .matches = 0 } },
2964 },3624 },
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) } },
2966 },3626 },
2967 .smin = .{3627 .smin = .{
2968 .ret_len = 1,3628 .ret_len = 1,
...@@ -2971,7 +3631,7 @@ pub const Intrinsic = enum {...@@ -2971,7 +3631,7 @@ pub const Intrinsic = enum {
2971 .{ .kind = .{ .matches = 0 } },3631 .{ .kind = .{ .matches = 0 } },
2972 .{ .kind = .{ .matches = 0 } },3632 .{ .kind = .{ .matches = 0 } },
2973 },3633 },
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) } },
2975 },3635 },
2976 .umax = .{3636 .umax = .{
2977 .ret_len = 1,3637 .ret_len = 1,
...@@ -2980,7 +3640,7 @@ pub const Intrinsic = enum {...@@ -2980,7 +3640,7 @@ pub const Intrinsic = enum {
2980 .{ .kind = .{ .matches = 0 } },3640 .{ .kind = .{ .matches = 0 } },
2981 .{ .kind = .{ .matches = 0 } },3641 .{ .kind = .{ .matches = 0 } },
2982 },3642 },
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) } },
2984 },3644 },
2985 .umin = .{3645 .umin = .{
2986 .ret_len = 1,3646 .ret_len = 1,
...@@ -2989,7 +3649,25 @@ pub const Intrinsic = enum {...@@ -2989,7 +3649,25 @@ pub const Intrinsic = enum {
2989 .{ .kind = .{ .matches = 0 } },3649 .{ .kind = .{ .matches = 0 } },
2990 .{ .kind = .{ .matches = 0 } },3650 .{ .kind = .{ .matches = 0 } },
2991 },3651 },
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) } },
2993 },3671 },
2994 .memcpy = .{3672 .memcpy = .{
2995 .ret_len = 0,3673 .ret_len = 0,
...@@ -3047,7 +3725,7 @@ pub const Intrinsic = enum {...@@ -3047,7 +3725,7 @@ pub const Intrinsic = enum {
3047 .{ .kind = .overloaded },3725 .{ .kind = .overloaded },
3048 .{ .kind = .{ .matches = 0 } },3726 .{ .kind = .{ .matches = 0 } },
3049 },3727 },
3050 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },3728 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3051 },3729 },
3052 .powi = .{3730 .powi = .{
3053 .ret_len = 1,3731 .ret_len = 1,
...@@ -3056,7 +3734,7 @@ pub const Intrinsic = enum {...@@ -3056,7 +3734,7 @@ pub const Intrinsic = enum {
3056 .{ .kind = .{ .matches = 0 } },3734 .{ .kind = .{ .matches = 0 } },
3057 .{ .kind = .overloaded },3735 .{ .kind = .overloaded },
3058 },3736 },
3059 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },3737 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3060 },3738 },
3061 .sin = .{3739 .sin = .{
3062 .ret_len = 1,3740 .ret_len = 1,
...@@ -3064,7 +3742,7 @@ pub const Intrinsic = enum {...@@ -3064,7 +3742,7 @@ pub const Intrinsic = enum {
3064 .{ .kind = .overloaded },3742 .{ .kind = .overloaded },
3065 .{ .kind = .{ .matches = 0 } },3743 .{ .kind = .{ .matches = 0 } },
3066 },3744 },
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) } },
3068 },3746 },
3069 .cos = .{3747 .cos = .{
3070 .ret_len = 1,3748 .ret_len = 1,
...@@ -3072,7 +3750,99 @@ pub const Intrinsic = enum {...@@ -3072,7 +3750,99 @@ pub const Intrinsic = enum {
3072 .{ .kind = .overloaded },3750 .{ .kind = .overloaded },
3073 .{ .kind = .{ .matches = 0 } },3751 .{ .kind = .{ .matches = 0 } },
3074 },3752 },
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) } },
3076 },3846 },
3077 .pow = .{3847 .pow = .{
3078 .ret_len = 1,3848 .ret_len = 1,
...@@ -3081,7 +3851,7 @@ pub const Intrinsic = enum {...@@ -3081,7 +3851,7 @@ pub const Intrinsic = enum {
3081 .{ .kind = .{ .matches = 0 } },3851 .{ .kind = .{ .matches = 0 } },
3082 .{ .kind = .{ .matches = 0 } },3852 .{ .kind = .{ .matches = 0 } },
3083 },3853 },
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) } },
3085 },3855 },
3086 .exp = .{3856 .exp = .{
3087 .ret_len = 1,3857 .ret_len = 1,
...@@ -3089,7 +3859,7 @@ pub const Intrinsic = enum {...@@ -3089,7 +3859,7 @@ pub const Intrinsic = enum {
3089 .{ .kind = .overloaded },3859 .{ .kind = .overloaded },
3090 .{ .kind = .{ .matches = 0 } },3860 .{ .kind = .{ .matches = 0 } },
3091 },3861 },
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) } },
3093 },3863 },
3094 .exp2 = .{3864 .exp2 = .{
3095 .ret_len = 1,3865 .ret_len = 1,
...@@ -3097,7 +3867,7 @@ pub const Intrinsic = enum {...@@ -3097,7 +3867,7 @@ pub const Intrinsic = enum {
3097 .{ .kind = .overloaded },3867 .{ .kind = .overloaded },
3098 .{ .kind = .{ .matches = 0 } },3868 .{ .kind = .{ .matches = 0 } },
3099 },3869 },
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) } },
3101 },3871 },
3102 .exp10 = .{3872 .exp10 = .{
3103 .ret_len = 1,3873 .ret_len = 1,
...@@ -3105,7 +3875,7 @@ pub const Intrinsic = enum {...@@ -3105,7 +3875,7 @@ pub const Intrinsic = enum {
3105 .{ .kind = .overloaded },3875 .{ .kind = .overloaded },
3106 .{ .kind = .{ .matches = 0 } },3876 .{ .kind = .{ .matches = 0 } },
3107 },3877 },
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) } },
3109 },3879 },
3110 .ldexp = .{3880 .ldexp = .{
3111 .ret_len = 1,3881 .ret_len = 1,
...@@ -3114,7 +3884,7 @@ pub const Intrinsic = enum {...@@ -3114,7 +3884,7 @@ pub const Intrinsic = enum {
3114 .{ .kind = .{ .matches = 0 } },3884 .{ .kind = .{ .matches = 0 } },
3115 .{ .kind = .overloaded },3885 .{ .kind = .overloaded },
3116 },3886 },
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) } },
3118 },3888 },
3119 .frexp = .{3889 .frexp = .{
3120 .ret_len = 2,3890 .ret_len = 2,
...@@ -3123,7 +3893,7 @@ pub const Intrinsic = enum {...@@ -3123,7 +3893,7 @@ pub const Intrinsic = enum {
3123 .{ .kind = .overloaded },3893 .{ .kind = .overloaded },
3124 .{ .kind = .{ .matches = 0 } },3894 .{ .kind = .{ .matches = 0 } },
3125 },3895 },
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) } },
3127 },3897 },
3128 .log = .{3898 .log = .{
3129 .ret_len = 1,3899 .ret_len = 1,
...@@ -3131,7 +3901,7 @@ pub const Intrinsic = enum {...@@ -3131,7 +3901,7 @@ pub const Intrinsic = enum {
3131 .{ .kind = .overloaded },3901 .{ .kind = .overloaded },
3132 .{ .kind = .{ .matches = 0 } },3902 .{ .kind = .{ .matches = 0 } },
3133 },3903 },
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) } },
3135 },3905 },
3136 .log10 = .{3906 .log10 = .{
3137 .ret_len = 1,3907 .ret_len = 1,
...@@ -3139,7 +3909,7 @@ pub const Intrinsic = enum {...@@ -3139,7 +3909,7 @@ pub const Intrinsic = enum {
3139 .{ .kind = .overloaded },3909 .{ .kind = .overloaded },
3140 .{ .kind = .{ .matches = 0 } },3910 .{ .kind = .{ .matches = 0 } },
3141 },3911 },
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) } },
3143 },3913 },
3144 .log2 = .{3914 .log2 = .{
3145 .ret_len = 1,3915 .ret_len = 1,
...@@ -3147,7 +3917,7 @@ pub const Intrinsic = enum {...@@ -3147,7 +3917,7 @@ pub const Intrinsic = enum {
3147 .{ .kind = .overloaded },3917 .{ .kind = .overloaded },
3148 .{ .kind = .{ .matches = 0 } },3918 .{ .kind = .{ .matches = 0 } },
3149 },3919 },
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) } },
3151 },3921 },
3152 .fma = .{3922 .fma = .{
3153 .ret_len = 1,3923 .ret_len = 1,
...@@ -3157,7 +3927,7 @@ pub const Intrinsic = enum {...@@ -3157,7 +3927,7 @@ pub const Intrinsic = enum {
3157 .{ .kind = .{ .matches = 0 } },3927 .{ .kind = .{ .matches = 0 } },
3158 .{ .kind = .{ .matches = 0 } },3928 .{ .kind = .{ .matches = 0 } },
3159 },3929 },
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) } },
3161 },3931 },
3162 .fabs = .{3932 .fabs = .{
3163 .ret_len = 1,3933 .ret_len = 1,
...@@ -3165,7 +3935,7 @@ pub const Intrinsic = enum {...@@ -3165,7 +3935,7 @@ pub const Intrinsic = enum {
3165 .{ .kind = .overloaded },3935 .{ .kind = .overloaded },
3166 .{ .kind = .{ .matches = 0 } },3936 .{ .kind = .{ .matches = 0 } },
3167 },3937 },
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) } },
3169 },3939 },
3170 .minnum = .{3940 .minnum = .{
3171 .ret_len = 1,3941 .ret_len = 1,
...@@ -3174,7 +3944,7 @@ pub const Intrinsic = enum {...@@ -3174,7 +3944,7 @@ pub const Intrinsic = enum {
3174 .{ .kind = .{ .matches = 0 } },3944 .{ .kind = .{ .matches = 0 } },
3175 .{ .kind = .{ .matches = 0 } },3945 .{ .kind = .{ .matches = 0 } },
3176 },3946 },
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) } },
3178 },3948 },
3179 .maxnum = .{3949 .maxnum = .{
3180 .ret_len = 1,3950 .ret_len = 1,
...@@ -3183,7 +3953,7 @@ pub const Intrinsic = enum {...@@ -3183,7 +3953,7 @@ pub const Intrinsic = enum {
3183 .{ .kind = .{ .matches = 0 } },3953 .{ .kind = .{ .matches = 0 } },
3184 .{ .kind = .{ .matches = 0 } },3954 .{ .kind = .{ .matches = 0 } },
3185 },3955 },
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) } },
3187 },3957 },
3188 .minimum = .{3958 .minimum = .{
3189 .ret_len = 1,3959 .ret_len = 1,
...@@ -3192,7 +3962,7 @@ pub const Intrinsic = enum {...@@ -3192,7 +3962,7 @@ pub const Intrinsic = enum {
3192 .{ .kind = .{ .matches = 0 } },3962 .{ .kind = .{ .matches = 0 } },
3193 .{ .kind = .{ .matches = 0 } },3963 .{ .kind = .{ .matches = 0 } },
3194 },3964 },
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) } },
3196 },3966 },
3197 .maximum = .{3967 .maximum = .{
3198 .ret_len = 1,3968 .ret_len = 1,
...@@ -3201,7 +3971,25 @@ pub const Intrinsic = enum {...@@ -3201,7 +3971,25 @@ pub const Intrinsic = enum {
3201 .{ .kind = .{ .matches = 0 } },3971 .{ .kind = .{ .matches = 0 } },
3202 .{ .kind = .{ .matches = 0 } },3972 .{ .kind = .{ .matches = 0 } },
3203 },3973 },
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) } },
3205 },3993 },
3206 .copysign = .{3994 .copysign = .{
3207 .ret_len = 1,3995 .ret_len = 1,
...@@ -3210,7 +3998,7 @@ pub const Intrinsic = enum {...@@ -3210,7 +3998,7 @@ pub const Intrinsic = enum {
3210 .{ .kind = .{ .matches = 0 } },3998 .{ .kind = .{ .matches = 0 } },
3211 .{ .kind = .{ .matches = 0 } },3999 .{ .kind = .{ .matches = 0 } },
3212 },4000 },
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) } },
3214 },4002 },
3215 .floor = .{4003 .floor = .{
3216 .ret_len = 1,4004 .ret_len = 1,
...@@ -3218,7 +4006,7 @@ pub const Intrinsic = enum {...@@ -3218,7 +4006,7 @@ pub const Intrinsic = enum {
3218 .{ .kind = .overloaded },4006 .{ .kind = .overloaded },
3219 .{ .kind = .{ .matches = 0 } },4007 .{ .kind = .{ .matches = 0 } },
3220 },4008 },
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) } },
3222 },4010 },
3223 .ceil = .{4011 .ceil = .{
3224 .ret_len = 1,4012 .ret_len = 1,
...@@ -3226,7 +4014,7 @@ pub const Intrinsic = enum {...@@ -3226,7 +4014,7 @@ pub const Intrinsic = enum {
3226 .{ .kind = .overloaded },4014 .{ .kind = .overloaded },
3227 .{ .kind = .{ .matches = 0 } },4015 .{ .kind = .{ .matches = 0 } },
3228 },4016 },
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) } },
3230 },4018 },
3231 .trunc = .{4019 .trunc = .{
3232 .ret_len = 1,4020 .ret_len = 1,
...@@ -3234,7 +4022,7 @@ pub const Intrinsic = enum {...@@ -3234,7 +4022,7 @@ pub const Intrinsic = enum {
3234 .{ .kind = .overloaded },4022 .{ .kind = .overloaded },
3235 .{ .kind = .{ .matches = 0 } },4023 .{ .kind = .{ .matches = 0 } },
3236 },4024 },
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) } },
3238 },4026 },
3239 .rint = .{4027 .rint = .{
3240 .ret_len = 1,4028 .ret_len = 1,
...@@ -3242,7 +4030,7 @@ pub const Intrinsic = enum {...@@ -3242,7 +4030,7 @@ pub const Intrinsic = enum {
3242 .{ .kind = .overloaded },4030 .{ .kind = .overloaded },
3243 .{ .kind = .{ .matches = 0 } },4031 .{ .kind = .{ .matches = 0 } },
3244 },4032 },
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) } },
3246 },4034 },
3247 .nearbyint = .{4035 .nearbyint = .{
3248 .ret_len = 1,4036 .ret_len = 1,
...@@ -3250,7 +4038,7 @@ pub const Intrinsic = enum {...@@ -3250,7 +4038,7 @@ pub const Intrinsic = enum {
3250 .{ .kind = .overloaded },4038 .{ .kind = .overloaded },
3251 .{ .kind = .{ .matches = 0 } },4039 .{ .kind = .{ .matches = 0 } },
3252 },4040 },
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) } },
3254 },4042 },
3255 .round = .{4043 .round = .{
3256 .ret_len = 1,4044 .ret_len = 1,
...@@ -3258,7 +4046,7 @@ pub const Intrinsic = enum {...@@ -3258,7 +4046,7 @@ pub const Intrinsic = enum {
3258 .{ .kind = .overloaded },4046 .{ .kind = .overloaded },
3259 .{ .kind = .{ .matches = 0 } },4047 .{ .kind = .{ .matches = 0 } },
3260 },4048 },
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) } },
3262 },4050 },
3263 .roundeven = .{4051 .roundeven = .{
3264 .ret_len = 1,4052 .ret_len = 1,
...@@ -3266,7 +4054,7 @@ pub const Intrinsic = enum {...@@ -3266,7 +4054,7 @@ pub const Intrinsic = enum {
3266 .{ .kind = .overloaded },4054 .{ .kind = .overloaded },
3267 .{ .kind = .{ .matches = 0 } },4055 .{ .kind = .{ .matches = 0 } },
3268 },4056 },
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) } },
3270 },4058 },
3271 .lround = .{4059 .lround = .{
3272 .ret_len = 1,4060 .ret_len = 1,
...@@ -3274,7 +4062,7 @@ pub const Intrinsic = enum {...@@ -3274,7 +4062,7 @@ pub const Intrinsic = enum {
3274 .{ .kind = .overloaded },4062 .{ .kind = .overloaded },
3275 .{ .kind = .overloaded },4063 .{ .kind = .overloaded },
3276 },4064 },
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) } },
3278 },4066 },
3279 .llround = .{4067 .llround = .{
3280 .ret_len = 1,4068 .ret_len = 1,
...@@ -3282,7 +4070,7 @@ pub const Intrinsic = enum {...@@ -3282,7 +4070,7 @@ pub const Intrinsic = enum {
3282 .{ .kind = .overloaded },4070 .{ .kind = .overloaded },
3283 .{ .kind = .overloaded },4071 .{ .kind = .overloaded },
3284 },4072 },
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) } },
3286 },4074 },
3287 .lrint = .{4075 .lrint = .{
3288 .ret_len = 1,4076 .ret_len = 1,
...@@ -3290,7 +4078,7 @@ pub const Intrinsic = enum {...@@ -3290,7 +4078,7 @@ pub const Intrinsic = enum {
3290 .{ .kind = .overloaded },4078 .{ .kind = .overloaded },
3291 .{ .kind = .overloaded },4079 .{ .kind = .overloaded },
3292 },4080 },
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) } },
3294 },4082 },
3295 .llrint = .{4083 .llrint = .{
3296 .ret_len = 1,4084 .ret_len = 1,
...@@ -3298,7 +4086,7 @@ pub const Intrinsic = enum {...@@ -3298,7 +4086,7 @@ pub const Intrinsic = enum {
3298 .{ .kind = .overloaded },4086 .{ .kind = .overloaded },
3299 .{ .kind = .overloaded },4087 .{ .kind = .overloaded },
3300 },4088 },
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) } },
3302 },4090 },
33034091
3304 .bitreverse = .{4092 .bitreverse = .{
...@@ -3307,7 +4095,7 @@ pub const Intrinsic = enum {...@@ -3307,7 +4095,7 @@ pub const Intrinsic = enum {
3307 .{ .kind = .overloaded },4095 .{ .kind = .overloaded },
3308 .{ .kind = .{ .matches = 0 } },4096 .{ .kind = .{ .matches = 0 } },
3309 },4097 },
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) } },
3311 },4099 },
3312 .bswap = .{4100 .bswap = .{
3313 .ret_len = 1,4101 .ret_len = 1,
...@@ -3315,7 +4103,7 @@ pub const Intrinsic = enum {...@@ -3315,7 +4103,7 @@ pub const Intrinsic = enum {
3315 .{ .kind = .overloaded },4103 .{ .kind = .overloaded },
3316 .{ .kind = .{ .matches = 0 } },4104 .{ .kind = .{ .matches = 0 } },
3317 },4105 },
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) } },
3319 },4107 },
3320 .ctpop = .{4108 .ctpop = .{
3321 .ret_len = 1,4109 .ret_len = 1,
...@@ -3323,7 +4111,7 @@ pub const Intrinsic = enum {...@@ -3323,7 +4111,7 @@ pub const Intrinsic = enum {
3323 .{ .kind = .overloaded },4111 .{ .kind = .overloaded },
3324 .{ .kind = .{ .matches = 0 } },4112 .{ .kind = .{ .matches = 0 } },
3325 },4113 },
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) } },
3327 },4115 },
3328 .ctlz = .{4116 .ctlz = .{
3329 .ret_len = 1,4117 .ret_len = 1,
...@@ -3332,7 +4120,7 @@ pub const Intrinsic = enum {...@@ -3332,7 +4120,7 @@ pub const Intrinsic = enum {
3332 .{ .kind = .{ .matches = 0 } },4120 .{ .kind = .{ .matches = 0 } },
3333 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },4121 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
3334 },4122 },
3335 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4123 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3336 },4124 },
3337 .cttz = .{4125 .cttz = .{
3338 .ret_len = 1,4126 .ret_len = 1,
...@@ -3341,7 +4129,7 @@ pub const Intrinsic = enum {...@@ -3341,7 +4129,7 @@ pub const Intrinsic = enum {
3341 .{ .kind = .{ .matches = 0 } },4129 .{ .kind = .{ .matches = 0 } },
3342 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },4130 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
3343 },4131 },
3344 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4132 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3345 },4133 },
3346 .fshl = .{4134 .fshl = .{
3347 .ret_len = 1,4135 .ret_len = 1,
...@@ -3351,7 +4139,7 @@ pub const Intrinsic = enum {...@@ -3351,7 +4139,7 @@ pub const Intrinsic = enum {
3351 .{ .kind = .{ .matches = 0 } },4139 .{ .kind = .{ .matches = 0 } },
3352 .{ .kind = .{ .matches = 0 } },4140 .{ .kind = .{ .matches = 0 } },
3353 },4141 },
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) } },
3355 },4143 },
3356 .fshr = .{4144 .fshr = .{
3357 .ret_len = 1,4145 .ret_len = 1,
...@@ -3361,7 +4149,16 @@ pub const Intrinsic = enum {...@@ -3361,7 +4149,16 @@ pub const Intrinsic = enum {
3361 .{ .kind = .{ .matches = 0 } },4149 .{ .kind = .{ .matches = 0 } },
3362 .{ .kind = .{ .matches = 0 } },4150 .{ .kind = .{ .matches = 0 } },
3363 },4151 },
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) } },
3365 },4162 },
33664163
3367 .@"sadd.with.overflow" = .{4164 .@"sadd.with.overflow" = .{
...@@ -3372,7 +4169,7 @@ pub const Intrinsic = enum {...@@ -3372,7 +4169,7 @@ pub const Intrinsic = enum {
3372 .{ .kind = .{ .matches = 0 } },4169 .{ .kind = .{ .matches = 0 } },
3373 .{ .kind = .{ .matches = 0 } },4170 .{ .kind = .{ .matches = 0 } },
3374 },4171 },
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) } },
3376 },4173 },
3377 .@"uadd.with.overflow" = .{4174 .@"uadd.with.overflow" = .{
3378 .ret_len = 2,4175 .ret_len = 2,
...@@ -3382,7 +4179,7 @@ pub const Intrinsic = enum {...@@ -3382,7 +4179,7 @@ pub const Intrinsic = enum {
3382 .{ .kind = .{ .matches = 0 } },4179 .{ .kind = .{ .matches = 0 } },
3383 .{ .kind = .{ .matches = 0 } },4180 .{ .kind = .{ .matches = 0 } },
3384 },4181 },
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) } },
3386 },4183 },
3387 .@"ssub.with.overflow" = .{4184 .@"ssub.with.overflow" = .{
3388 .ret_len = 2,4185 .ret_len = 2,
...@@ -3392,7 +4189,7 @@ pub const Intrinsic = enum {...@@ -3392,7 +4189,7 @@ pub const Intrinsic = enum {
3392 .{ .kind = .{ .matches = 0 } },4189 .{ .kind = .{ .matches = 0 } },
3393 .{ .kind = .{ .matches = 0 } },4190 .{ .kind = .{ .matches = 0 } },
3394 },4191 },
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) } },
3396 },4193 },
3397 .@"usub.with.overflow" = .{4194 .@"usub.with.overflow" = .{
3398 .ret_len = 2,4195 .ret_len = 2,
...@@ -3402,7 +4199,7 @@ pub const Intrinsic = enum {...@@ -3402,7 +4199,7 @@ pub const Intrinsic = enum {
3402 .{ .kind = .{ .matches = 0 } },4199 .{ .kind = .{ .matches = 0 } },
3403 .{ .kind = .{ .matches = 0 } },4200 .{ .kind = .{ .matches = 0 } },
3404 },4201 },
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) } },
3406 },4203 },
3407 .@"smul.with.overflow" = .{4204 .@"smul.with.overflow" = .{
3408 .ret_len = 2,4205 .ret_len = 2,
...@@ -3412,7 +4209,7 @@ pub const Intrinsic = enum {...@@ -3412,7 +4209,7 @@ pub const Intrinsic = enum {
3412 .{ .kind = .{ .matches = 0 } },4209 .{ .kind = .{ .matches = 0 } },
3413 .{ .kind = .{ .matches = 0 } },4210 .{ .kind = .{ .matches = 0 } },
3414 },4211 },
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) } },
3416 },4213 },
3417 .@"umul.with.overflow" = .{4214 .@"umul.with.overflow" = .{
3418 .ret_len = 2,4215 .ret_len = 2,
...@@ -3422,7 +4219,7 @@ pub const Intrinsic = enum {...@@ -3422,7 +4219,7 @@ pub const Intrinsic = enum {
3422 .{ .kind = .{ .matches = 0 } },4219 .{ .kind = .{ .matches = 0 } },
3423 .{ .kind = .{ .matches = 0 } },4220 .{ .kind = .{ .matches = 0 } },
3424 },4221 },
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) } },
3426 },4223 },
34274224
3428 .@"sadd.sat" = .{4225 .@"sadd.sat" = .{
...@@ -3432,7 +4229,7 @@ pub const Intrinsic = enum {...@@ -3432,7 +4229,7 @@ pub const Intrinsic = enum {
3432 .{ .kind = .{ .matches = 0 } },4229 .{ .kind = .{ .matches = 0 } },
3433 .{ .kind = .{ .matches = 0 } },4230 .{ .kind = .{ .matches = 0 } },
3434 },4231 },
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) } },
3436 },4233 },
3437 .@"uadd.sat" = .{4234 .@"uadd.sat" = .{
3438 .ret_len = 1,4235 .ret_len = 1,
...@@ -3441,7 +4238,7 @@ pub const Intrinsic = enum {...@@ -3441,7 +4238,7 @@ pub const Intrinsic = enum {
3441 .{ .kind = .{ .matches = 0 } },4238 .{ .kind = .{ .matches = 0 } },
3442 .{ .kind = .{ .matches = 0 } },4239 .{ .kind = .{ .matches = 0 } },
3443 },4240 },
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) } },
3445 },4242 },
3446 .@"ssub.sat" = .{4243 .@"ssub.sat" = .{
3447 .ret_len = 1,4244 .ret_len = 1,
...@@ -3450,7 +4247,7 @@ pub const Intrinsic = enum {...@@ -3450,7 +4247,7 @@ pub const Intrinsic = enum {
3450 .{ .kind = .{ .matches = 0 } },4247 .{ .kind = .{ .matches = 0 } },
3451 .{ .kind = .{ .matches = 0 } },4248 .{ .kind = .{ .matches = 0 } },
3452 },4249 },
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) } },
3454 },4251 },
3455 .@"usub.sat" = .{4252 .@"usub.sat" = .{
3456 .ret_len = 1,4253 .ret_len = 1,
...@@ -3459,7 +4256,7 @@ pub const Intrinsic = enum {...@@ -3459,7 +4256,7 @@ pub const Intrinsic = enum {
3459 .{ .kind = .{ .matches = 0 } },4256 .{ .kind = .{ .matches = 0 } },
3460 .{ .kind = .{ .matches = 0 } },4257 .{ .kind = .{ .matches = 0 } },
3461 },4258 },
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) } },
3463 },4260 },
3464 .@"sshl.sat" = .{4261 .@"sshl.sat" = .{
3465 .ret_len = 1,4262 .ret_len = 1,
...@@ -3468,7 +4265,7 @@ pub const Intrinsic = enum {...@@ -3468,7 +4265,7 @@ pub const Intrinsic = enum {
3468 .{ .kind = .{ .matches = 0 } },4265 .{ .kind = .{ .matches = 0 } },
3469 .{ .kind = .{ .matches = 0 } },4266 .{ .kind = .{ .matches = 0 } },
3470 },4267 },
3471 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4268 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3472 },4269 },
3473 .@"ushl.sat" = .{4270 .@"ushl.sat" = .{
3474 .ret_len = 1,4271 .ret_len = 1,
...@@ -3477,7 +4274,7 @@ pub const Intrinsic = enum {...@@ -3477,7 +4274,7 @@ pub const Intrinsic = enum {
3477 .{ .kind = .{ .matches = 0 } },4274 .{ .kind = .{ .matches = 0 } },
3478 .{ .kind = .{ .matches = 0 } },4275 .{ .kind = .{ .matches = 0 } },
3479 },4276 },
3480 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4277 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3481 },4278 },
34824279
3483 .@"smul.fix" = .{4280 .@"smul.fix" = .{
...@@ -3488,7 +4285,7 @@ pub const Intrinsic = enum {...@@ -3488,7 +4285,7 @@ pub const Intrinsic = enum {
3488 .{ .kind = .{ .matches = 0 } },4285 .{ .kind = .{ .matches = 0 } },
3489 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },4286 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
3490 },4287 },
3491 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4288 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3492 },4289 },
3493 .@"umul.fix" = .{4290 .@"umul.fix" = .{
3494 .ret_len = 1,4291 .ret_len = 1,
...@@ -3498,7 +4295,7 @@ pub const Intrinsic = enum {...@@ -3498,7 +4295,7 @@ pub const Intrinsic = enum {
3498 .{ .kind = .{ .matches = 0 } },4295 .{ .kind = .{ .matches = 0 } },
3499 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },4296 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
3500 },4297 },
3501 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4298 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3502 },4299 },
3503 .@"smul.fix.sat" = .{4300 .@"smul.fix.sat" = .{
3504 .ret_len = 1,4301 .ret_len = 1,
...@@ -3508,7 +4305,7 @@ pub const Intrinsic = enum {...@@ -3508,7 +4305,7 @@ pub const Intrinsic = enum {
3508 .{ .kind = .{ .matches = 0 } },4305 .{ .kind = .{ .matches = 0 } },
3509 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },4306 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
3510 },4307 },
3511 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4308 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3512 },4309 },
3513 .@"umul.fix.sat" = .{4310 .@"umul.fix.sat" = .{
3514 .ret_len = 1,4311 .ret_len = 1,
...@@ -3518,7 +4315,7 @@ pub const Intrinsic = enum {...@@ -3518,7 +4315,7 @@ pub const Intrinsic = enum {
3518 .{ .kind = .{ .matches = 0 } },4315 .{ .kind = .{ .matches = 0 } },
3519 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },4316 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
3520 },4317 },
3521 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4318 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3522 },4319 },
3523 .@"sdiv.fix" = .{4320 .@"sdiv.fix" = .{
3524 .ret_len = 1,4321 .ret_len = 1,
...@@ -3528,7 +4325,7 @@ pub const Intrinsic = enum {...@@ -3528,7 +4325,7 @@ pub const Intrinsic = enum {
3528 .{ .kind = .{ .matches = 0 } },4325 .{ .kind = .{ .matches = 0 } },
3529 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },4326 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
3530 },4327 },
3531 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4328 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
3532 },4329 },
3533 .@"udiv.fix" = .{4330 .@"udiv.fix" = .{
3534 .ret_len = 1,4331 .ret_len = 1,
...@@ -3538,7 +4335,7 @@ pub const Intrinsic = enum {...@@ -3538,7 +4335,7 @@ pub const Intrinsic = enum {
3538 .{ .kind = .{ .matches = 0 } },4335 .{ .kind = .{ .matches = 0 } },
3539 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },4336 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
3540 },4337 },
3541 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4338 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
3542 },4339 },
3543 .@"sdiv.fix.sat" = .{4340 .@"sdiv.fix.sat" = .{
3544 .ret_len = 1,4341 .ret_len = 1,
...@@ -3548,7 +4345,7 @@ pub const Intrinsic = enum {...@@ -3548,7 +4345,7 @@ pub const Intrinsic = enum {
3548 .{ .kind = .{ .matches = 0 } },4345 .{ .kind = .{ .matches = 0 } },
3549 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },4346 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
3550 },4347 },
3551 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4348 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
3552 },4349 },
3553 .@"udiv.fix.sat" = .{4350 .@"udiv.fix.sat" = .{
3554 .ret_len = 1,4351 .ret_len = 1,
...@@ -3558,7 +4355,7 @@ pub const Intrinsic = enum {...@@ -3558,7 +4355,7 @@ pub const Intrinsic = enum {
3558 .{ .kind = .{ .matches = 0 } },4355 .{ .kind = .{ .matches = 0 } },
3559 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },4356 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
3560 },4357 },
3561 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4358 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
3562 },4359 },
35634360
3564 .canonicalize = .{4361 .canonicalize = .{
...@@ -3567,7 +4364,7 @@ pub const Intrinsic = enum {...@@ -3567,7 +4364,7 @@ pub const Intrinsic = enum {
3567 .{ .kind = .overloaded },4364 .{ .kind = .overloaded },
3568 .{ .kind = .{ .matches = 0 } },4365 .{ .kind = .{ .matches = 0 } },
3569 },4366 },
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) } },
3571 },4368 },
3572 .fmuladd = .{4369 .fmuladd = .{
3573 .ret_len = 1,4370 .ret_len = 1,
...@@ -3577,7 +4374,7 @@ pub const Intrinsic = enum {...@@ -3577,7 +4374,7 @@ pub const Intrinsic = enum {
3577 .{ .kind = .{ .matches = 0 } },4374 .{ .kind = .{ .matches = 0 } },
3578 .{ .kind = .{ .matches = 0 } },4375 .{ .kind = .{ .matches = 0 } },
3579 },4376 },
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) } },
3581 },4378 },
35824379
3583 .@"vector.reduce.add" = .{4380 .@"vector.reduce.add" = .{
...@@ -3586,7 +4383,7 @@ pub const Intrinsic = enum {...@@ -3586,7 +4383,7 @@ pub const Intrinsic = enum {
3586 .{ .kind = .{ .matches_scalar = 1 } },4383 .{ .kind = .{ .matches_scalar = 1 } },
3587 .{ .kind = .overloaded },4384 .{ .kind = .overloaded },
3588 },4385 },
3589 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4386 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3590 },4387 },
3591 .@"vector.reduce.fadd" = .{4388 .@"vector.reduce.fadd" = .{
3592 .ret_len = 1,4389 .ret_len = 1,
...@@ -3595,7 +4392,7 @@ pub const Intrinsic = enum {...@@ -3595,7 +4392,7 @@ pub const Intrinsic = enum {
3595 .{ .kind = .{ .matches_scalar = 2 } },4392 .{ .kind = .{ .matches_scalar = 2 } },
3596 .{ .kind = .overloaded },4393 .{ .kind = .overloaded },
3597 },4394 },
3598 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4395 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3599 },4396 },
3600 .@"vector.reduce.mul" = .{4397 .@"vector.reduce.mul" = .{
3601 .ret_len = 1,4398 .ret_len = 1,
...@@ -3603,7 +4400,7 @@ pub const Intrinsic = enum {...@@ -3603,7 +4400,7 @@ pub const Intrinsic = enum {
3603 .{ .kind = .{ .matches_scalar = 1 } },4400 .{ .kind = .{ .matches_scalar = 1 } },
3604 .{ .kind = .overloaded },4401 .{ .kind = .overloaded },
3605 },4402 },
3606 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4403 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3607 },4404 },
3608 .@"vector.reduce.fmul" = .{4405 .@"vector.reduce.fmul" = .{
3609 .ret_len = 1,4406 .ret_len = 1,
...@@ -3612,7 +4409,7 @@ pub const Intrinsic = enum {...@@ -3612,7 +4409,7 @@ pub const Intrinsic = enum {
3612 .{ .kind = .{ .matches_scalar = 2 } },4409 .{ .kind = .{ .matches_scalar = 2 } },
3613 .{ .kind = .overloaded },4410 .{ .kind = .overloaded },
3614 },4411 },
3615 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4412 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3616 },4413 },
3617 .@"vector.reduce.and" = .{4414 .@"vector.reduce.and" = .{
3618 .ret_len = 1,4415 .ret_len = 1,
...@@ -3620,7 +4417,7 @@ pub const Intrinsic = enum {...@@ -3620,7 +4417,7 @@ pub const Intrinsic = enum {
3620 .{ .kind = .{ .matches_scalar = 1 } },4417 .{ .kind = .{ .matches_scalar = 1 } },
3621 .{ .kind = .overloaded },4418 .{ .kind = .overloaded },
3622 },4419 },
3623 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4420 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3624 },4421 },
3625 .@"vector.reduce.or" = .{4422 .@"vector.reduce.or" = .{
3626 .ret_len = 1,4423 .ret_len = 1,
...@@ -3628,7 +4425,7 @@ pub const Intrinsic = enum {...@@ -3628,7 +4425,7 @@ pub const Intrinsic = enum {
3628 .{ .kind = .{ .matches_scalar = 1 } },4425 .{ .kind = .{ .matches_scalar = 1 } },
3629 .{ .kind = .overloaded },4426 .{ .kind = .overloaded },
3630 },4427 },
3631 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4428 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3632 },4429 },
3633 .@"vector.reduce.xor" = .{4430 .@"vector.reduce.xor" = .{
3634 .ret_len = 1,4431 .ret_len = 1,
...@@ -3636,7 +4433,7 @@ pub const Intrinsic = enum {...@@ -3636,7 +4433,7 @@ pub const Intrinsic = enum {
3636 .{ .kind = .{ .matches_scalar = 1 } },4433 .{ .kind = .{ .matches_scalar = 1 } },
3637 .{ .kind = .overloaded },4434 .{ .kind = .overloaded },
3638 },4435 },
3639 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4436 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3640 },4437 },
3641 .@"vector.reduce.smax" = .{4438 .@"vector.reduce.smax" = .{
3642 .ret_len = 1,4439 .ret_len = 1,
...@@ -3644,7 +4441,7 @@ pub const Intrinsic = enum {...@@ -3644,7 +4441,7 @@ pub const Intrinsic = enum {
3644 .{ .kind = .{ .matches_scalar = 1 } },4441 .{ .kind = .{ .matches_scalar = 1 } },
3645 .{ .kind = .overloaded },4442 .{ .kind = .overloaded },
3646 },4443 },
3647 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4444 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3648 },4445 },
3649 .@"vector.reduce.smin" = .{4446 .@"vector.reduce.smin" = .{
3650 .ret_len = 1,4447 .ret_len = 1,
...@@ -3652,7 +4449,7 @@ pub const Intrinsic = enum {...@@ -3652,7 +4449,7 @@ pub const Intrinsic = enum {
3652 .{ .kind = .{ .matches_scalar = 1 } },4449 .{ .kind = .{ .matches_scalar = 1 } },
3653 .{ .kind = .overloaded },4450 .{ .kind = .overloaded },
3654 },4451 },
3655 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4452 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3656 },4453 },
3657 .@"vector.reduce.umax" = .{4454 .@"vector.reduce.umax" = .{
3658 .ret_len = 1,4455 .ret_len = 1,
...@@ -3660,7 +4457,7 @@ pub const Intrinsic = enum {...@@ -3660,7 +4457,7 @@ pub const Intrinsic = enum {
3660 .{ .kind = .{ .matches_scalar = 1 } },4457 .{ .kind = .{ .matches_scalar = 1 } },
3661 .{ .kind = .overloaded },4458 .{ .kind = .overloaded },
3662 },4459 },
3663 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4460 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3664 },4461 },
3665 .@"vector.reduce.umin" = .{4462 .@"vector.reduce.umin" = .{
3666 .ret_len = 1,4463 .ret_len = 1,
...@@ -3668,7 +4465,7 @@ pub const Intrinsic = enum {...@@ -3668,7 +4465,7 @@ pub const Intrinsic = enum {
3668 .{ .kind = .{ .matches_scalar = 1 } },4465 .{ .kind = .{ .matches_scalar = 1 } },
3669 .{ .kind = .overloaded },4466 .{ .kind = .overloaded },
3670 },4467 },
3671 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4468 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3672 },4469 },
3673 .@"vector.reduce.fmax" = .{4470 .@"vector.reduce.fmax" = .{
3674 .ret_len = 1,4471 .ret_len = 1,
...@@ -3676,7 +4473,7 @@ pub const Intrinsic = enum {...@@ -3676,7 +4473,7 @@ pub const Intrinsic = enum {
3676 .{ .kind = .{ .matches_scalar = 1 } },4473 .{ .kind = .{ .matches_scalar = 1 } },
3677 .{ .kind = .overloaded },4474 .{ .kind = .overloaded },
3678 },4475 },
3679 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4476 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3680 },4477 },
3681 .@"vector.reduce.fmin" = .{4478 .@"vector.reduce.fmin" = .{
3682 .ret_len = 1,4479 .ret_len = 1,
...@@ -3684,7 +4481,7 @@ pub const Intrinsic = enum {...@@ -3684,7 +4481,7 @@ pub const Intrinsic = enum {
3684 .{ .kind = .{ .matches_scalar = 1 } },4481 .{ .kind = .{ .matches_scalar = 1 } },
3685 .{ .kind = .overloaded },4482 .{ .kind = .overloaded },
3686 },4483 },
3687 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4484 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3688 },4485 },
3689 .@"vector.reduce.fmaximum" = .{4486 .@"vector.reduce.fmaximum" = .{
3690 .ret_len = 1,4487 .ret_len = 1,
...@@ -3692,7 +4489,7 @@ pub const Intrinsic = enum {...@@ -3692,7 +4489,7 @@ pub const Intrinsic = enum {
3692 .{ .kind = .{ .matches_scalar = 1 } },4489 .{ .kind = .{ .matches_scalar = 1 } },
3693 .{ .kind = .overloaded },4490 .{ .kind = .overloaded },
3694 },4491 },
3695 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4492 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3696 },4493 },
3697 .@"vector.reduce.fminimum" = .{4494 .@"vector.reduce.fminimum" = .{
3698 .ret_len = 1,4495 .ret_len = 1,
...@@ -3700,7 +4497,7 @@ pub const Intrinsic = enum {...@@ -3700,7 +4497,7 @@ pub const Intrinsic = enum {
3700 .{ .kind = .{ .matches_scalar = 1 } },4497 .{ .kind = .{ .matches_scalar = 1 } },
3701 .{ .kind = .overloaded },4498 .{ .kind = .overloaded },
3702 },4499 },
3703 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4500 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3704 },4501 },
3705 .@"vector.insert" = .{4502 .@"vector.insert" = .{
3706 .ret_len = 1,4503 .ret_len = 1,
...@@ -3710,7 +4507,7 @@ pub const Intrinsic = enum {...@@ -3710,7 +4507,7 @@ pub const Intrinsic = enum {
3710 .{ .kind = .overloaded },4507 .{ .kind = .overloaded },
3711 .{ .kind = .{ .type = .i64 } },4508 .{ .kind = .{ .type = .i64 } },
3712 },4509 },
3713 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4510 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3714 },4511 },
3715 .@"vector.extract" = .{4512 .@"vector.extract" = .{
3716 .ret_len = 1,4513 .ret_len = 1,
...@@ -3719,7 +4516,7 @@ pub const Intrinsic = enum {...@@ -3719,7 +4516,7 @@ pub const Intrinsic = enum {
3719 .{ .kind = .overloaded },4516 .{ .kind = .overloaded },
3720 .{ .kind = .{ .type = .i64 } },4517 .{ .kind = .{ .type = .i64 } },
3721 },4518 },
3722 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4519 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3723 },4520 },
37244521
3725 .@"is.fpclass" = .{4522 .@"is.fpclass" = .{
...@@ -3729,7 +4526,7 @@ pub const Intrinsic = enum {...@@ -3729,7 +4526,7 @@ pub const Intrinsic = enum {
3729 .{ .kind = .overloaded },4526 .{ .kind = .overloaded },
3730 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },4527 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
3731 },4528 },
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) } },
3733 },4530 },
37344531
3735 .@"var.annotation" = .{4532 .@"var.annotation" = .{
...@@ -3814,7 +4611,7 @@ pub const Intrinsic = enum {...@@ -3814,7 +4611,7 @@ pub const Intrinsic = enum {
3814 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },4611 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
3815 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },4612 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
3816 },4613 },
3817 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4614 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3818 },4615 },
3819 .expect = .{4616 .expect = .{
3820 .ret_len = 1,4617 .ret_len = 1,
...@@ -3823,7 +4620,7 @@ pub const Intrinsic = enum {...@@ -3823,7 +4620,7 @@ pub const Intrinsic = enum {
3823 .{ .kind = .{ .matches = 0 } },4620 .{ .kind = .{ .matches = 0 } },
3824 .{ .kind = .{ .matches = 0 } },4621 .{ .kind = .{ .matches = 0 } },
3825 },4622 },
3826 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4623 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
3827 },4624 },
3828 .@"expect.with.probability" = .{4625 .@"expect.with.probability" = .{
3829 .ret_len = 1,4626 .ret_len = 1,
...@@ -3833,7 +4630,7 @@ pub const Intrinsic = enum {...@@ -3833,7 +4630,7 @@ pub const Intrinsic = enum {
3833 .{ .kind = .{ .matches = 0 } },4630 .{ .kind = .{ .matches = 0 } },
3834 .{ .kind = .{ .type = .double }, .attrs = &.{.immarg} },4631 .{ .kind = .{ .type = .double }, .attrs = &.{.immarg} },
3835 },4632 },
3836 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4633 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
3837 },4634 },
3838 .assume = .{4635 .assume = .{
3839 .ret_len = 0,4636 .ret_len = 0,
...@@ -3848,7 +4645,7 @@ pub const Intrinsic = enum {...@@ -3848,7 +4645,7 @@ pub const Intrinsic = enum {
3848 .{ .kind = .overloaded },4645 .{ .kind = .overloaded },
3849 .{ .kind = .{ .matches = 0 }, .attrs = &.{.returned} },4646 .{ .kind = .{ .matches = 0 }, .attrs = &.{.returned} },
3850 },4647 },
3851 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4648 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
3852 },4649 },
3853 .@"type.test" = .{4650 .@"type.test" = .{
3854 .ret_len = 1,4651 .ret_len = 1,
...@@ -3857,7 +4654,7 @@ pub const Intrinsic = enum {...@@ -3857,7 +4654,7 @@ pub const Intrinsic = enum {
3857 .{ .kind = .{ .type = .ptr } },4654 .{ .kind = .{ .type = .ptr } },
3858 .{ .kind = .{ .type = .metadata } },4655 .{ .kind = .{ .type = .metadata } },
3859 },4656 },
3860 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4657 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3861 },4658 },
3862 .@"type.checked.load" = .{4659 .@"type.checked.load" = .{
3863 .ret_len = 2,4660 .ret_len = 2,
...@@ -3868,7 +4665,7 @@ pub const Intrinsic = enum {...@@ -3868,7 +4665,7 @@ pub const Intrinsic = enum {
3868 .{ .kind = .{ .type = .i32 } },4665 .{ .kind = .{ .type = .i32 } },
3869 .{ .kind = .{ .type = .metadata } },4666 .{ .kind = .{ .type = .metadata } },
3870 },4667 },
3871 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4668 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
3872 },4669 },
3873 .@"type.checked.load.relative" = .{4670 .@"type.checked.load.relative" = .{
3874 .ret_len = 2,4671 .ret_len = 2,
...@@ -3879,7 +4676,7 @@ pub const Intrinsic = enum {...@@ -3879,7 +4676,7 @@ pub const Intrinsic = enum {
3879 .{ .kind = .{ .type = .i32 } },4676 .{ .kind = .{ .type = .i32 } },
3880 .{ .kind = .{ .type = .metadata } },4677 .{ .kind = .{ .type = .metadata } },
3881 },4678 },
3882 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4679 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
3883 },4680 },
3884 .@"arithmetic.fence" = .{4681 .@"arithmetic.fence" = .{
3885 .ret_len = 1,4682 .ret_len = 1,
...@@ -3887,12 +4684,12 @@ pub const Intrinsic = enum {...@@ -3887,12 +4684,12 @@ pub const Intrinsic = enum {
3887 .{ .kind = .overloaded },4684 .{ .kind = .overloaded },
3888 .{ .kind = .{ .matches = 0 } },4685 .{ .kind = .{ .matches = 0 } },
3889 },4686 },
3890 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4687 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3891 },4688 },
3892 .donothing = .{4689 .donothing = .{
3893 .ret_len = 0,4690 .ret_len = 0,
3894 .params = &.{},4691 .params = &.{},
3895 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4692 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
3896 },4693 },
3897 .@"load.relative" = .{4694 .@"load.relative" = .{
3898 .ret_len = 1,4695 .ret_len = 1,
...@@ -3914,7 +4711,7 @@ pub const Intrinsic = enum {...@@ -3914,7 +4711,7 @@ pub const Intrinsic = enum {
3914 .{ .kind = .{ .type = .i1 } },4711 .{ .kind = .{ .type = .i1 } },
3915 .{ .kind = .overloaded },4712 .{ .kind = .overloaded },
3916 },4713 },
3917 .attrs = &.{ .convergent, .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4714 .attrs = &.{ .convergent, .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
3918 },4715 },
3919 .ptrmask = .{4716 .ptrmask = .{
3920 .ret_len = 1,4717 .ret_len = 1,
...@@ -3923,7 +4720,7 @@ pub const Intrinsic = enum {...@@ -3923,7 +4720,7 @@ pub const Intrinsic = enum {
3923 .{ .kind = .{ .matches = 0 } },4720 .{ .kind = .{ .matches = 0 } },
3924 .{ .kind = .overloaded },4721 .{ .kind = .overloaded },
3925 },4722 },
3926 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4723 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3927 },4724 },
3928 .@"threadlocal.address" = .{4725 .@"threadlocal.address" = .{
3929 .ret_len = 1,4726 .ret_len = 1,
...@@ -3931,14 +4728,14 @@ pub const Intrinsic = enum {...@@ -3931,14 +4728,14 @@ pub const Intrinsic = enum {
3931 .{ .kind = .overloaded, .attrs = &.{.nonnull} },4728 .{ .kind = .overloaded, .attrs = &.{.nonnull} },
3932 .{ .kind = .{ .matches = 0 }, .attrs = &.{.nonnull} },4729 .{ .kind = .{ .matches = 0 }, .attrs = &.{.nonnull} },
3933 },4730 },
3934 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4731 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3935 },4732 },
3936 .vscale = .{4733 .vscale = .{
3937 .ret_len = 1,4734 .ret_len = 1,
3938 .params = &.{4735 .params = &.{
3939 .{ .kind = .overloaded },4736 .{ .kind = .overloaded },
3940 },4737 },
3941 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4738 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
3942 },4739 },
39434740
3944 .@"dbg.declare" = .{4741 .@"dbg.declare" = .{
...@@ -3948,7 +4745,7 @@ pub const Intrinsic = enum {...@@ -3948,7 +4745,7 @@ pub const Intrinsic = enum {
3948 .{ .kind = .{ .type = .metadata } },4745 .{ .kind = .{ .type = .metadata } },
3949 .{ .kind = .{ .type = .metadata } },4746 .{ .kind = .{ .type = .metadata } },
3950 },4747 },
3951 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4748 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3952 },4749 },
3953 .@"dbg.value" = .{4750 .@"dbg.value" = .{
3954 .ret_len = 0,4751 .ret_len = 0,
...@@ -3957,7 +4754,7 @@ pub const Intrinsic = enum {...@@ -3957,7 +4754,7 @@ pub const Intrinsic = enum {
3957 .{ .kind = .{ .type = .metadata } },4754 .{ .kind = .{ .type = .metadata } },
3958 .{ .kind = .{ .type = .metadata } },4755 .{ .kind = .{ .type = .metadata } },
3959 },4756 },
3960 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4757 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3961 },4758 },
39624759
3963 .@"amdgcn.workitem.id.x" = .{4760 .@"amdgcn.workitem.id.x" = .{
...@@ -3965,42 +4762,42 @@ pub const Intrinsic = enum {...@@ -3965,42 +4762,42 @@ pub const Intrinsic = enum {
3965 .params = &.{4762 .params = &.{
3966 .{ .kind = .{ .type = .i32 } },4763 .{ .kind = .{ .type = .i32 } },
3967 },4764 },
3968 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4765 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3969 },4766 },
3970 .@"amdgcn.workitem.id.y" = .{4767 .@"amdgcn.workitem.id.y" = .{
3971 .ret_len = 1,4768 .ret_len = 1,
3972 .params = &.{4769 .params = &.{
3973 .{ .kind = .{ .type = .i32 } },4770 .{ .kind = .{ .type = .i32 } },
3974 },4771 },
3975 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4772 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3976 },4773 },
3977 .@"amdgcn.workitem.id.z" = .{4774 .@"amdgcn.workitem.id.z" = .{
3978 .ret_len = 1,4775 .ret_len = 1,
3979 .params = &.{4776 .params = &.{
3980 .{ .kind = .{ .type = .i32 } },4777 .{ .kind = .{ .type = .i32 } },
3981 },4778 },
3982 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4779 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3983 },4780 },
3984 .@"amdgcn.workgroup.id.x" = .{4781 .@"amdgcn.workgroup.id.x" = .{
3985 .ret_len = 1,4782 .ret_len = 1,
3986 .params = &.{4783 .params = &.{
3987 .{ .kind = .{ .type = .i32 } },4784 .{ .kind = .{ .type = .i32 } },
3988 },4785 },
3989 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4786 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3990 },4787 },
3991 .@"amdgcn.workgroup.id.y" = .{4788 .@"amdgcn.workgroup.id.y" = .{
3992 .ret_len = 1,4789 .ret_len = 1,
3993 .params = &.{4790 .params = &.{
3994 .{ .kind = .{ .type = .i32 } },4791 .{ .kind = .{ .type = .i32 } },
3995 },4792 },
3996 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4793 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3997 },4794 },
3998 .@"amdgcn.workgroup.id.z" = .{4795 .@"amdgcn.workgroup.id.z" = .{
3999 .ret_len = 1,4796 .ret_len = 1,
4000 .params = &.{4797 .params = &.{
4001 .{ .kind = .{ .type = .i32 } },4798 .{ .kind = .{ .type = .i32 } },
4002 },4799 },
4003 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4800 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
4004 },4801 },
4005 .@"amdgcn.dispatch.ptr" = .{4802 .@"amdgcn.dispatch.ptr" = .{
4006 .ret_len = 1,4803 .ret_len = 1,
...@@ -4010,7 +4807,7 @@ pub const Intrinsic = enum {...@@ -4010,7 +4807,7 @@ pub const Intrinsic = enum {
4010 .attrs = &.{.{ .@"align" = .wrap(.fromByteUnits(4)) }},4807 .attrs = &.{.{ .@"align" = .wrap(.fromByteUnits(4)) }},
4011 },4808 },
4012 },4809 },
4013 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4810 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
4014 },4811 },
40154812
4016 .@"nvvm.read.ptx.sreg.tid.x" = .{4813 .@"nvvm.read.ptx.sreg.tid.x" = .{
...@@ -4085,7 +4882,7 @@ pub const Intrinsic = enum {...@@ -4085,7 +4882,7 @@ pub const Intrinsic = enum {
4085 .{ .kind = .overloaded },4882 .{ .kind = .overloaded },
4086 .{ .kind = .{ .type = .i32 } },4883 .{ .kind = .{ .type = .i32 } },
4087 },4884 },
4088 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },4885 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
4089 },4886 },
4090 .@"wasm.memory.grow" = .{4887 .@"wasm.memory.grow" = .{
4091 .ret_len = 1,4888 .ret_len = 1,
...@@ -4166,6 +4963,10 @@ pub const Function = struct {...@@ -4166,6 +4963,10 @@ pub const Function = struct {
4166 self.ptr(builder).attributes = new_function_attributes;4963 self.ptr(builder).attributes = new_function_attributes;
4167 }4964 }
41684965
4966 pub fn getAttributes(self: Index, builder: *Builder) FunctionAttributes {
4967 return self.ptr(builder).attributes;
4968 }
4969
4169 pub fn setSection(self: Index, section: String, builder: *Builder) void {4970 pub fn setSection(self: Index, section: String, builder: *Builder) void {
4170 self.ptr(builder).section = section;4971 self.ptr(builder).section = section;
4171 }4972 }
...@@ -4487,7 +5288,7 @@ pub const Function = struct {...@@ -4487,7 +5288,7 @@ pub const Function = struct {
4487 }5288 }
44885289
4489 pub fn toValue(self: Instruction.Index) Value {5290 pub fn toValue(self: Instruction.Index) Value {
4490 return @fromBackingInt(@intCast(@backingInt(self)));5291 return @fromBackingInt(@backingInt(self));
4491 }5292 }
44925293
4493 pub fn isTerminatorWip(self: Instruction.Index, wip: *const WipFunction) bool {5294 pub fn isTerminatorWip(self: Instruction.Index, wip: *const WipFunction) bool {
...@@ -4679,7 +5480,7 @@ pub const Function = struct {...@@ -4679,7 +5480,7 @@ pub const Function = struct {
4679 .changeScalarAssumeCapacity(.i1, wip.builder),5480 .changeScalarAssumeCapacity(.i1, wip.builder),
4680 .fneg,5481 .fneg,
4681 .@"fneg fast",5482 .@"fneg fast",
4682 => @as(Value, @fromBackingInt(@intCast(instruction.data))).typeOfWip(wip),5483 => @as(Value, @fromBackingInt(instruction.data)).typeOfWip(wip),
4683 .getelementptr,5484 .getelementptr,
4684 .@"getelementptr inbounds",5485 .@"getelementptr inbounds",
4685 => {5486 => {
...@@ -4871,7 +5672,7 @@ pub const Function = struct {...@@ -4871,7 +5672,7 @@ pub const Function = struct {
4871 .changeScalarAssumeCapacity(.i1, builder),5672 .changeScalarAssumeCapacity(.i1, builder),
4872 .fneg,5673 .fneg,
4873 .@"fneg fast",5674 .@"fneg fast",
4874 => @as(Value, @fromBackingInt(@intCast(instruction.data))).typeOf(function_index, builder),5675 => @as(Value, @fromBackingInt(instruction.data)).typeOf(function_index, builder),
4875 .getelementptr,5676 .getelementptr,
4876 .@"getelementptr inbounds",5677 .@"getelementptr inbounds",
4877 => {5678 => {
...@@ -4963,7 +5764,7 @@ pub const Function = struct {...@@ -4963,7 +5764,7 @@ pub const Function = struct {
49635764
4964 pub fn fromMetadata(metadata: Metadata) Weights {5765 pub fn fromMetadata(metadata: Metadata) Weights {
4965 assert(metadata.kind == .node);5766 assert(metadata.kind == .node);
4966 return @fromBackingInt(@intCast(metadata.index));5767 return @fromBackingInt(metadata.index);
4967 }5768 }
49685769
4969 pub fn toMetadata(weights: Weights) Metadata {5770 pub fn toMetadata(weights: Weights) Metadata {
...@@ -5156,7 +5957,7 @@ pub const Function = struct {...@@ -5156,7 +5957,7 @@ pub const Function = struct {
5156 assert(argument.tag == .arg);5957 assert(argument.tag == .arg);
5157 assert(argument.data == index);5958 assert(argument.data == index);
51585959
5159 const argument_index: Instruction.Index = @fromBackingInt(@intCast(index));5960 const argument_index: Instruction.Index = @fromBackingInt(index);
5160 return argument_index.toValue();5961 return argument_index.toValue();
5161 }5962 }
51625963
...@@ -5202,7 +6003,7 @@ pub const Function = struct {...@@ -5202,7 +6003,7 @@ pub const Function = struct {
5202 Type,6003 Type,
5203 Value,6004 Value,
5204 Instruction.BrCond.Weights,6005 Instruction.BrCond.Weights,
5205 => @fromBackingInt(@intCast(value)),6006 => @fromBackingInt(value),
5206 MemoryAccessInfo,6007 MemoryAccessInfo,
5207 Instruction.Alloca.Info,6008 Instruction.Alloca.Info,
5208 Instruction.Call.Info,6009 Instruction.Call.Info,
...@@ -5327,7 +6128,7 @@ pub const WipFunction = struct {...@@ -5327,7 +6128,7 @@ pub const WipFunction = struct {
5327 assert(argument.tag == .arg);6128 assert(argument.tag == .arg);
5328 assert(argument.data == index);6129 assert(argument.data == index);
53296130
5330 const argument_index: Instruction.Index = @fromBackingInt(@intCast(index));6131 const argument_index: Instruction.Index = @fromBackingInt(index);
5331 return argument_index.toValue();6132 return argument_index.toValue();
5332 }6133 }
53336134
...@@ -5722,7 +6523,7 @@ pub const WipFunction = struct {...@@ -5722,7 +6523,7 @@ pub const WipFunction = struct {
5722 alignment: Alignment,6523 alignment: Alignment,
5723 name: []const u8,6524 name: []const u8,
5724 ) Allocator.Error!Value {6525 ) 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);
5726 }6527 }
57276528
5728 pub fn loadAtomic(6529 pub fn loadAtomic(
...@@ -5766,7 +6567,7 @@ pub const WipFunction = struct {...@@ -5766,7 +6567,7 @@ pub const WipFunction = struct {
5766 ptr: Value,6567 ptr: Value,
5767 alignment: Alignment,6568 alignment: Alignment,
5768 ) Allocator.Error!Instruction.Index {6569 ) Allocator.Error!Instruction.Index {
5769 return self.storeAtomic(kind, val, ptr, .system, .none, alignment);6570 return self.storeAtomic(kind, val, ptr, undefined, .none, alignment);
5770 }6571 }
57716572
5772 pub fn storeAtomic(6573 pub fn storeAtomic(
...@@ -6414,24 +7215,24 @@ pub const WipFunction = struct {...@@ -6414,24 +7215,24 @@ pub const WipFunction = struct {
6414 errdefer function.instructions.shrinkRetainingCapacity(0);7215 errdefer function.instructions.shrinkRetainingCapacity(0);
64157216
6416 {7217 {
6417 var final_instruction_index: Instruction.Index = @fromBackingInt(@intCast(0));7218 var final_instruction_index: Instruction.Index = @fromBackingInt(0);
6418 for (0..params_len) |param_index| {7219 for (0..params_len) |param_index| {
6419 instructions.items[param_index] = final_instruction_index;7220 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);
6421 }7222 }
6422 for (blocks, self.blocks.items) |*final_block, current_block| {7223 for (blocks, self.blocks.items) |*final_block, current_block| {
6423 assert(current_block.incoming == current_block.branches);7224 assert(current_block.incoming == current_block.branches);
6424 final_block.instruction = final_instruction_index;7225 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);
6426 for (current_block.instructions.items) |instruction| {7227 for (current_block.instructions.items) |instruction| {
6427 instructions.items[@backingInt(instruction)] = final_instruction_index;7228 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);
6429 }7230 }
6430 }7231 }
6431 }7232 }
64327233
6433 var wip_name: struct {7234 var wip_name: struct {
6434 next_name: String = @fromBackingInt(@intCast(0)),7235 next_name: String = @fromBackingInt(0),
6435 next_unique_name: std.AutoHashMap(String, String),7236 next_unique_name: std.AutoHashMap(String, String),
6436 builder: *Builder,7237 builder: *Builder,
64377238
...@@ -6440,19 +7241,19 @@ pub const WipFunction = struct {...@@ -6440,19 +7241,19 @@ pub const WipFunction = struct {
6440 .none => return .none,7241 .none => return .none,
6441 .empty => {7242 .empty => {
6442 assert(wip_name.next_name != .none);7243 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);
6444 return wip_name.next_name;7245 return wip_name.next_name;
6445 },7246 },
6446 _ => {7247 _ => {
6447 assert(!name.isAnon());7248 assert(!name.isAnon());
6448 const gop = try wip_name.next_unique_name.getOrPut(name);7249 const gop = try wip_name.next_unique_name.getOrPut(name);
6449 if (!gop.found_existing) {7250 if (!gop.found_existing) {
6450 gop.value_ptr.* = @fromBackingInt(@intCast(0));7251 gop.value_ptr.* = @fromBackingInt(0);
6451 return name;7252 return name;
6452 }7253 }
64537254
6454 while (true) {7255 while (true) {
6455 gop.value_ptr.* = @fromBackingInt(@intCast(@backingInt(gop.value_ptr.*) + 1));7256 gop.value_ptr.* = @fromBackingInt(@backingInt(gop.value_ptr.*) + 1);
6456 const unique_name = try wip_name.builder.fmt("{f}{s}{f}", .{7257 const unique_name = try wip_name.builder.fmt("{f}{s}{f}", .{
6457 name.fmtRaw(wip_name.builder),7258 name.fmtRaw(wip_name.builder),
6458 sep,7259 sep,
...@@ -6460,7 +7261,7 @@ pub const WipFunction = struct {...@@ -6460,7 +7261,7 @@ pub const WipFunction = struct {
6460 });7261 });
6461 const unique_gop = try wip_name.next_unique_name.getOrPut(unique_name);7262 const unique_gop = try wip_name.next_unique_name.getOrPut(unique_name);
6462 if (!unique_gop.found_existing) {7263 if (!unique_gop.found_existing) {
6463 unique_gop.value_ptr.* = @fromBackingInt(@intCast(0));7264 unique_gop.value_ptr.* = @fromBackingInt(0);
6464 return unique_name;7265 return unique_name;
6465 }7266 }
6466 }7267 }
...@@ -6702,7 +7503,7 @@ pub const WipFunction = struct {...@@ -6702,7 +7503,7 @@ pub const WipFunction = struct {
6702 .fneg,7503 .fneg,
6703 .@"fneg fast",7504 .@"fneg fast",
6704 .ret,7505 .ret,
6705 => instruction.data = @backingInt(instructions.map(@fromBackingInt(@intCast(instruction.data)))),7506 => instruction.data = @backingInt(instructions.map(@fromBackingInt(instruction.data))),
6706 .getelementptr,7507 .getelementptr,
6707 .@"getelementptr inbounds",7508 .@"getelementptr inbounds",
6708 => {7509 => {
...@@ -7079,7 +7880,7 @@ pub const WipFunction = struct {...@@ -7079,7 +7880,7 @@ pub const WipFunction = struct {
7079 Type,7880 Type,
7080 Value,7881 Value,
7081 Instruction.BrCond.Weights,7882 Instruction.BrCond.Weights,
7082 => @fromBackingInt(@intCast(value)),7883 => @fromBackingInt(value),
7083 MemoryAccessInfo,7884 MemoryAccessInfo,
7084 Instruction.Alloca.Info,7885 Instruction.Alloca.Info,
7085 Instruction.Call.Info,7886 Instruction.Call.Info,
...@@ -7268,7 +8069,7 @@ pub const Constant = enum(u32) {...@@ -7268,7 +8069,7 @@ pub const Constant = enum(u32) {
7268 no_init = (1 << 30) - 1,8069 no_init = (1 << 30) - 1,
7269 _,8070 _,
72708071
7271 const first_global: Constant = @fromBackingInt(@intCast(1 << 29));8072 const first_global: Constant = @fromBackingInt(1 << 29);
72728073
7273 pub const Tag = enum(u7) {8074 pub const Tag = enum(u7) {
7274 positive_integer,8075 positive_integer,
...@@ -7405,7 +8206,18 @@ pub const Constant = enum(u32) {...@@ -7405,7 +8206,18 @@ pub const Constant = enum(u32) {
7405 val: Constant,8206 val: Constant,
7406 type: Type,8207 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 };
7409 };8221 };
74108222
7411 pub const GetElementPtr = struct {8223 pub const GetElementPtr = struct {
...@@ -7444,11 +8256,11 @@ pub const Constant = enum(u32) {...@@ -7444,11 +8256,11 @@ pub const Constant = enum(u32) {
7444 return if (@backingInt(self) < @backingInt(first_global))8256 return if (@backingInt(self) < @backingInt(first_global))
7445 .{ .constant = @intCast(@backingInt(self)) }8257 .{ .constant = @intCast(@backingInt(self)) }
7446 else8258 else
7447 .{ .global = @fromBackingInt(@intCast(@backingInt(self) - @backingInt(first_global))) };8259 .{ .global = @fromBackingInt(@backingInt(self) - @backingInt(first_global)) };
7448 }8260 }
74498261
7450 pub fn toValue(self: Constant) Value {8262 pub fn toValue(self: Constant) Value {
7451 return @fromBackingInt(@intCast(Value.first_constant + @backingInt(self)));8263 return @fromBackingInt(Value.first_constant + @backingInt(self));
7452 }8264 }
74538265
7454 pub fn typeOf(self: Constant, builder: *Builder) Type {8266 pub fn typeOf(self: Constant, builder: *Builder) Type {
...@@ -7474,7 +8286,7 @@ pub const Constant = enum(u32) {...@@ -7474,7 +8286,7 @@ pub const Constant = enum(u32) {
7474 .zeroinitializer,8286 .zeroinitializer,
7475 .undef,8287 .undef,
7476 .poison,8288 .poison,
7477 => @fromBackingInt(@intCast(item.data)),8289 => @fromBackingInt(item.data),
7478 .structure,8290 .structure,
7479 .packed_structure,8291 .packed_structure,
7480 .array,8292 .array,
...@@ -7482,7 +8294,7 @@ pub const Constant = enum(u32) {...@@ -7482,7 +8294,7 @@ pub const Constant = enum(u32) {
7482 => builder.constantExtraData(Aggregate, item.data).type,8294 => builder.constantExtraData(Aggregate, item.data).type,
7483 .splat => builder.constantExtraData(Splat, item.data).type,8295 .splat => builder.constantExtraData(Splat, item.data).type,
7484 .string => builder.arrayTypeAssumeCapacity(8296 .string => builder.arrayTypeAssumeCapacity(
7485 @as(String, @fromBackingInt(@intCast(item.data))).slice(builder).?.len,8297 @as(String, @fromBackingInt(item.data)).slice(builder).?.len,
7486 .i8,8298 .i8,
7487 ),8299 ),
7488 .blockaddress => builder.ptrTypeAssumeCapacity(8300 .blockaddress => builder.ptrTypeAssumeCapacity(
...@@ -7491,7 +8303,7 @@ pub const Constant = enum(u32) {...@@ -7491,7 +8303,7 @@ pub const Constant = enum(u32) {
7491 ),8303 ),
7492 .dso_local_equivalent,8304 .dso_local_equivalent,
7493 .no_cfi,8305 .no_cfi,
7494 => builder.ptrTypeAssumeCapacity(@as(Function.Index, @fromBackingInt(@intCast(item.data)))8306 => builder.ptrTypeAssumeCapacity(@as(Function.Index, @fromBackingInt(item.data))
7495 .ptrConst(builder).global.ptrConst(builder).addr_space),8307 .ptrConst(builder).global.ptrConst(builder).addr_space),
7496 .trunc,8308 .trunc,
7497 .ptrtoint,8309 .ptrtoint,
...@@ -7802,7 +8614,7 @@ pub const Constant = enum(u32) {...@@ -7802,7 +8614,7 @@ pub const Constant = enum(u32) {
7802 try w.writeByte('>');8614 try w.writeByte('>');
7803 },8615 },
7804 .string => try w.print("c{f}", .{8616 .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),
7806 }),8618 }),
7807 .blockaddress => |tag| {8619 .blockaddress => |tag| {
7808 const extra = data.builder.constantExtraData(BlockAddress, item.data);8620 const extra = data.builder.constantExtraData(BlockAddress, item.data);
...@@ -7816,7 +8628,7 @@ pub const Constant = enum(u32) {...@@ -7816,7 +8628,7 @@ pub const Constant = enum(u32) {
7816 .dso_local_equivalent,8628 .dso_local_equivalent,
7817 .no_cfi,8629 .no_cfi,
7818 => |tag| {8630 => |tag| {
7819 const function: Function.Index = @fromBackingInt(@intCast(item.data));8631 const function: Function.Index = @fromBackingInt(item.data);
7820 try w.print("{s} {f}", .{8632 try w.print("{s} {f}", .{
7821 @tagName(tag),8633 @tagName(tag),
7822 function.ptrConst(data.builder).global.fmt(data.builder),8634 function.ptrConst(data.builder).global.fmt(data.builder),
...@@ -7920,9 +8732,9 @@ pub const Value = enum(u32) {...@@ -7920,9 +8732,9 @@ pub const Value = enum(u32) {
7920 metadata: Metadata,8732 metadata: Metadata,
7921 } {8733 } {
7922 return if (@backingInt(self) < first_constant)8734 return if (@backingInt(self) < first_constant)
7923 .{ .instruction = @fromBackingInt(@intCast(@backingInt(self))) }8735 .{ .instruction = @fromBackingInt(@backingInt(self)) }
7924 else if (@backingInt(self) < first_metadata)8736 else if (@backingInt(self) < first_metadata)
7925 .{ .constant = @fromBackingInt(@intCast(@backingInt(self) - first_constant)) }8737 .{ .constant = @fromBackingInt(@backingInt(self) - first_constant) }
7926 else8738 else
7927 .{ .metadata = @bitCast(@backingInt(self) - first_metadata) };8739 .{ .metadata = @bitCast(@backingInt(self) - first_metadata) };
7928 }8740 }
...@@ -8016,7 +8828,7 @@ pub const Metadata = packed struct(u32) {...@@ -8016,7 +8828,7 @@ pub const Metadata = packed struct(u32) {
8016 return .{ .index = metadata.index, .kind = metadata.kind, .is_none = false };8828 return .{ .index = metadata.index, .kind = metadata.kind, .is_none = false };
8017 }8829 }
8018 pub fn toValue(metadata: Metadata) Value {8830 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)));
8020 }8832 }
80218833
8022 pub const String = enum(u32) {8834 pub const String = enum(u32) {
...@@ -8032,7 +8844,7 @@ pub const Metadata = packed struct(u32) {...@@ -8032,7 +8844,7 @@ pub const Metadata = packed struct(u32) {
8032 pub fn unwrap(metadata: Metadata.String.Optional) ?Metadata.String {8844 pub fn unwrap(metadata: Metadata.String.Optional) ?Metadata.String {
8033 return switch (metadata) {8845 return switch (metadata) {
8034 .none => null,8846 .none => null,
8035 else => @fromBackingInt(@intCast(@backingInt(metadata))),8847 else => @fromBackingInt(@backingInt(metadata)),
8036 };8848 };
8037 }8849 }
8038 pub fn toMetadata(metadata: Metadata.String.Optional) Metadata.Optional {8850 pub fn toMetadata(metadata: Metadata.String.Optional) Metadata.Optional {
...@@ -8040,7 +8852,7 @@ pub const Metadata = packed struct(u32) {...@@ -8040,7 +8852,7 @@ pub const Metadata = packed struct(u32) {
8040 }8852 }
8041 };8853 };
8042 pub fn toOptional(metadata: Metadata.String) Metadata.String.Optional {8854 pub fn toOptional(metadata: Metadata.String) Metadata.String.Optional {
8043 return @fromBackingInt(@intCast(@backingInt(metadata)));8855 return @fromBackingInt(@backingInt(metadata));
8044 }8856 }
8045 pub fn toMetadata(metadata: Metadata.String) Metadata {8857 pub fn toMetadata(metadata: Metadata.String) Metadata {
8046 return .{ .index = @intCast(@backingInt(metadata)), .kind = .string };8858 return .{ .index = @intCast(@backingInt(metadata)), .kind = .string };
...@@ -8077,7 +8889,7 @@ pub const Metadata = packed struct(u32) {...@@ -8077,7 +8889,7 @@ pub const Metadata = packed struct(u32) {
8077 };8889 };
8078 pub fn toString(metadata: Metadata) Metadata.String {8890 pub fn toString(metadata: Metadata) Metadata.String {
8079 assert(metadata.kind == .string);8891 assert(metadata.kind == .string);
8080 return @fromBackingInt(@intCast(metadata.index));8892 return @fromBackingInt(metadata.index);
8081 }8893 }
80828894
8083 pub const Tag = enum(u6) {8895 pub const Tag = enum(u6) {
...@@ -8542,7 +9354,7 @@ pub const Metadata = packed struct(u32) {...@@ -8542,7 +9354,7 @@ pub const Metadata = packed struct(u32) {
8542 try w.writeByte(')');9354 try w.writeByte(')');
8543 },9355 },
8544 .constant => try Constant.format(.{9356 .constant => try Constant.format(.{
8545 .constant = @fromBackingInt(@intCast(node_item.data)),9357 .constant = @fromBackingInt(node_item.data),
8546 .builder = builder,9358 .builder = builder,
8547 .flags = data.specialized orelse .{},9359 .flags = data.specialized orelse .{},
8548 }, w),9360 }, w),
...@@ -8705,7 +9517,7 @@ pub const Metadata = packed struct(u32) {...@@ -8705,7 +9517,7 @@ pub const Metadata = packed struct(u32) {
8705 nodes: anytype,9517 nodes: anytype,
8706 w: *Writer,9518 w: *Writer,
8707 ) !void {9519 ) !void {
8708 const names = comptime std.meta.fieldNames(@TypeOf(nodes));9520 const names = @typeInfo(@TypeOf(nodes)).@"struct".field_names;
87099521
8710 comptime var fmt_str: []const u8 = "{[distinct]s}{[node]s}(";9522 comptime var fmt_str: []const u8 = "{[distinct]s}{[node]s}(";
8711 inline for (names) |name| fmt_str = fmt_str ++ "{[" ++ name ++ "]f}";9523 inline for (names) |name| fmt_str = fmt_str ++ "{[" ++ name ++ "]f}";
...@@ -8735,7 +9547,14 @@ pub fn init(options: Options) Allocator.Error!Builder {...@@ -8735,7 +9547,14 @@ pub fn init(options: Options) Allocator.Error!Builder {
8735 .strip = options.strip,9547 .strip = options.strip,
87369548
8737 .source_filename = .none,9549 .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 },
8739 .target_triple = .none,9558 .target_triple = .none,
8740 .module_asm = .empty,9559 .module_asm = .empty,
87419560
...@@ -8744,7 +9563,7 @@ pub fn init(options: Options) Allocator.Error!Builder {...@@ -8744,7 +9563,7 @@ pub fn init(options: Options) Allocator.Error!Builder {
8744 .string_bytes = .empty,9563 .string_bytes = .empty,
87459564
8746 .types = .empty,9565 .types = .empty,
8747 .next_unnamed_type = @fromBackingInt(@intCast(0)),9566 .next_unnamed_type = @fromBackingInt(0),
8748 .next_unique_type_id = .empty,9567 .next_unique_type_id = .empty,
8749 .type_map = .empty,9568 .type_map = .empty,
8750 .type_items = .empty,9569 .type_items = .empty,
...@@ -8758,7 +9577,7 @@ pub fn init(options: Options) Allocator.Error!Builder {...@@ -8758,7 +9577,7 @@ pub fn init(options: Options) Allocator.Error!Builder {
8758 .function_attributes_set = .empty,9577 .function_attributes_set = .empty,
87599578
8760 .globals = .empty,9579 .globals = .empty,
8761 .next_unnamed_global = @fromBackingInt(@intCast(0)),9580 .next_unnamed_global = @fromBackingInt(0),
8762 .next_replaced_global = .none,9581 .next_replaced_global = .none,
8763 .next_unique_global_id = .empty,9582 .next_unique_global_id = .empty,
8764 .aliases = .empty,9583 .aliases = .empty,
...@@ -8791,14 +9610,14 @@ pub fn init(options: Options) Allocator.Error!Builder {...@@ -8791,14 +9610,14 @@ pub fn init(options: Options) Allocator.Error!Builder {
8791 try self.string_indices.append(self.gpa, 0);9610 try self.string_indices.append(self.gpa, 0);
8792 assert(try self.string("") == .empty);9611 assert(try self.string("") == .empty);
87939612
9613 self.data_layout = try .parseString(try self.string(DataLayout.stringForTarget(options.target)), &self);
9614
8794 try self.strtab_string_indices.append(self.gpa, 0);9615 try self.strtab_string_indices.append(self.gpa, 0);
8795 assert(try self.strtabString("") == .empty);9616 assert(try self.strtabString("") == .empty);
87969617
8797 if (options.name.len > 0) self.source_filename = try self.string(options.name);9618 if (options.name.len > 0) self.source_filename = try self.string(options.name);
87989619
8799 if (options.triple.len > 0) {9620 if (options.triple.len > 0) self.target_triple = try self.string(options.triple);
8800 self.target_triple = try self.string(options.triple);
8801 }
88029621
8803 {9622 {
8804 const static_len = @typeInfo(Type).@"enum".field_names.len - 1;9623 const static_len = @typeInfo(Type).@"enum".field_names.len - 1;
...@@ -8815,7 +9634,7 @@ pub fn init(options: Options) Allocator.Error!Builder {...@@ -8815,7 +9634,7 @@ pub fn init(options: Options) Allocator.Error!Builder {
8815 assert(self.intTypeAssumeCapacity(bits) ==9634 assert(self.intTypeAssumeCapacity(bits) ==
8816 @field(Type, std.fmt.comptimePrint("i{d}", .{bits})));9635 @field(Type, std.fmt.comptimePrint("i{d}", .{bits})));
8817 inline for (.{ 0, 4 }) |addr_space_index| {9636 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);
8819 assert(self.ptrTypeAssumeCapacity(addr_space) ==9638 assert(self.ptrTypeAssumeCapacity(addr_space) ==
8820 @field(Type, std.fmt.comptimePrint("ptr{f}", .{addr_space.fmt(" ")})));9639 @field(Type, std.fmt.comptimePrint("ptr{f}", .{addr_space.fmt(" ")})));
8821 }9640 }
...@@ -8891,6 +9710,8 @@ pub fn clearAndFree(self: *Builder) void {...@@ -8891,6 +9710,8 @@ pub fn clearAndFree(self: *Builder) void {
8891pub fn deinit(self: *Builder) void {9710pub fn deinit(self: *Builder) void {
8892 const gpa = self.gpa;9711 const gpa = self.gpa;
88939712
9713 self.data_layout.deinit(gpa);
9714
8894 self.module_asm.deinit(gpa);9715 self.module_asm.deinit(gpa);
88959716
8896 self.string_map.deinit(gpa);9717 self.string_map.deinit(gpa);
...@@ -8944,7 +9765,7 @@ pub fn deinit(self: *Builder) void {...@@ -8944,7 +9765,7 @@ pub fn deinit(self: *Builder) void {
89449765
8945pub fn finishModuleAsm(self: *Builder, aw: *Writer.Allocating) Allocator.Error!void {9766pub fn finishModuleAsm(self: *Builder, aw: *Writer.Allocating) Allocator.Error!void {
8946 self.module_asm = aw.toArrayList();9767 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')
8948 try self.module_asm.append(self.gpa, '\n');9769 try self.module_asm.append(self.gpa, '\n');
8949}9770}
89509771
...@@ -8990,7 +9811,7 @@ pub fn trailingString(self: *Builder) Allocator.Error!String {...@@ -8990,7 +9811,7 @@ pub fn trailingString(self: *Builder) Allocator.Error!String {
8990}9811}
89919812
8992pub fn trailingStringAssumeCapacity(self: *Builder) String {9813pub fn trailingStringAssumeCapacity(self: *Builder) String {
8993 const start = self.string_indices.getLast().?;9814 const start = self.string_indices.last().?;
8994 const bytes: []const u8 = self.string_bytes.items[start..];9815 const bytes: []const u8 = self.string_bytes.items[start..];
8995 const gop = self.string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self });9816 const gop = self.string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self });
8996 if (gop.found_existing) {9817 if (gop.found_existing) {
...@@ -9092,17 +9913,17 @@ pub fn attrs(self: *Builder, attributes: []Attribute.Index) Allocator.Error!Attr...@@ -9092,17 +9913,17 @@ pub fn attrs(self: *Builder, attributes: []Attribute.Index) Allocator.Error!Attr
9092 return @backingInt(lhs_kind) < @backingInt(rhs_kind);9913 return @backingInt(lhs_kind) < @backingInt(rhs_kind);
9093 }9914 }
9094 }.lessThan);9915 }.lessThan);
9095 return @fromBackingInt(@intCast(try self.attrGeneric(@ptrCast(attributes))));9916 return @fromBackingInt(try self.attrGeneric(@ptrCast(attributes)));
9096}9917}
90979918
9098pub fn fnAttrs(self: *Builder, fn_attributes: []const Attributes) Allocator.Error!FunctionAttributes {9919pub fn fnAttrs(self: *Builder, fn_attributes: []const Attributes) Allocator.Error!FunctionAttributes {
9099 try self.function_attributes_set.ensureUnusedCapacity(self.gpa, 1);9920 try self.function_attributes_set.ensureUnusedCapacity(self.gpa, 1);
9100 const function_attributes: FunctionAttributes = @fromBackingInt(@intCast(try self.attrGeneric(@ptrCast(9921 const function_attributes: FunctionAttributes = @fromBackingInt(try self.attrGeneric(@ptrCast(
9101 fn_attributes[0..if (std.mem.lastIndexOfNone(Attributes, fn_attributes, &.{.none})) |last|9922 fn_attributes[0..if (std.mem.findLastNone(Attributes, fn_attributes, &.{.none})) |last|
9102 last + 19923 last + 1
9103 else9924 else
9104 0],9925 0],
9105 ))));9926 )));
91069927
9107 _ = self.function_attributes_set.getOrPutAssumeCapacity(function_attributes);9928 _ = self.function_attributes_set.getOrPutAssumeCapacity(function_attributes);
9108 return function_attributes;9929 return function_attributes;
...@@ -9121,7 +9942,7 @@ pub fn addGlobalAssumeCapacity(self: *Builder, name: StrtabString, global: Globa...@@ -9121,7 +9942,7 @@ pub fn addGlobalAssumeCapacity(self: *Builder, name: StrtabString, global: Globa
9121 if (name == .empty) {9942 if (name == .empty) {
9122 id = self.next_unnamed_global;9943 id = self.next_unnamed_global;
9123 assert(id != self.next_replaced_global);9944 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);
9125 }9946 }
9126 while (true) {9947 while (true) {
9127 const global_gop = self.globals.getOrPutAssumeCapacity(id);9948 const global_gop = self.globals.getOrPutAssumeCapacity(id);
...@@ -9710,17 +10531,17 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void...@@ -9710,17 +10531,17 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
9710 var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined };10531 var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined };
9711 defer metadata_formatter.map.deinit(self.gpa);10532 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) {
9714 if (need_newline) try w.writeByte('\n') else need_newline = true;10535 if (need_newline) try w.writeByte('\n') else need_newline = true;
9715 if (self.source_filename != .none) try w.print(10536 if (self.source_filename != .none) try w.print(
9716 \\; ModuleID = '{s}'10537 \\; ModuleID = '{s}'
9717 \\source_filename = {f}10538 \\source_filename = {f}
9718 \\10539 \\
9719 , .{ self.source_filename.slice(self).?, self.source_filename.fmtQ(self) });10540 , .{ 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(
9721 \\target datalayout = {f}10542 \\target datalayout = {f}
9722 \\10543 \\
9723 , .{self.data_layout.fmtQ(self)});10544 , .{self.data_layout.string_repr.fmtQ(self)});
9724 if (self.target_triple != .none) try w.print(10545 if (self.target_triple != .none) try w.print(
9725 \\target triple = {f}10546 \\target triple = {f}
9726 \\10547 \\
...@@ -10058,7 +10879,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void...@@ -10058,7 +10879,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
10058 continue;10879 continue;
10059 },10880 },
10060 .br => |tag| {10881 .br => |tag| {
10061 const target: Function.Block.Index = @fromBackingInt(@intCast(instruction.data));10882 const target: Function.Block.Index = @fromBackingInt(instruction.data);
10062 try w.print(" {s} {f}", .{10883 try w.print(" {s} {f}", .{
10063 @tagName(tag), target.toInst(&function).fmt(function_index, self, .{ .percent = true }),10884 @tagName(tag), target.toInst(&function).fmt(function_index, self, .{ .percent = true }),
10064 });10885 });
...@@ -10187,7 +11008,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void...@@ -10187,7 +11008,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
10187 .fneg,11008 .fneg,
10188 .@"fneg fast",11009 .@"fneg fast",
10189 => |tag| {11010 => |tag| {
10190 const val: Value = @fromBackingInt(@intCast(instruction.data));11011 const val: Value = @fromBackingInt(instruction.data);
10191 try w.print(" %{f} = {s} {f}", .{11012 try w.print(" %{f} = {s} {f}", .{
10192 instruction_index.name(&function).fmt(self),11013 instruction_index.name(&function).fmt(self),
10193 @tagName(tag),11014 @tagName(tag),
...@@ -10288,7 +11109,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void...@@ -10288,7 +11109,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
10288 }11109 }
10289 },11110 },
10290 .ret => |tag| {11111 .ret => |tag| {
10291 const val: Value = @fromBackingInt(@intCast(instruction.data));11112 const val: Value = @fromBackingInt(instruction.data);
10292 try w.print(" {s} {f}", .{11113 try w.print(" {s} {f}", .{
10293 @tagName(tag),11114 @tagName(tag),
10294 val.fmt(function_index, self, .{ .percent = true }),11115 val.fmt(function_index, self, .{ .percent = true }),
...@@ -11020,7 +11841,7 @@ fn opaqueTypeAssumeCapacity(self: *Builder, name: String) Type {...@@ -11020,7 +11841,7 @@ fn opaqueTypeAssumeCapacity(self: *Builder, name: String) Type {
11020 if (name == .empty) {11841 if (name == .empty) {
11021 id = self.next_unnamed_type;11842 id = self.next_unnamed_type;
11022 assert(id != .none);11843 assert(id != .none);
11023 self.next_unnamed_type = @fromBackingInt(@intCast(@backingInt(id) + 1));11844 self.next_unnamed_type = @fromBackingInt(@backingInt(id) + 1);
11024 } else assert(!name.isAnon());11845 } else assert(!name.isAnon());
11025 while (true) {11846 while (true) {
11026 const type_gop = self.types.getOrPutAssumeCapacity(id);11847 const type_gop = self.types.getOrPutAssumeCapacity(id);
...@@ -11135,7 +11956,7 @@ fn typeExtraDataTrail(...@@ -11135,7 +11956,7 @@ fn typeExtraDataTrail(
11135 ) |field_name, field_type, value|11956 ) |field_name, field_type, value|
11136 @field(result, field_name) = switch (field_type) {11957 @field(result, field_name) = switch (field_type) {
11137 u32 => value,11958 u32 => value,
11138 String, Type => @fromBackingInt(@intCast(value)),11959 String, Type => @fromBackingInt(value),
11139 else => @compileError("bad field type: " ++ @typeName(field_type)),11960 else => @compileError("bad field type: " ++ @typeName(field_type)),
11140 };11961 };
11141 return .{11962 return .{
...@@ -11746,7 +12567,7 @@ fn castConstAssumeCapacity(self: *Builder, tag: Constant.Tag, val: Constant, ty:...@@ -11746,7 +12567,7 @@ fn castConstAssumeCapacity(self: *Builder, tag: Constant.Tag, val: Constant, ty:
11746 return std.meta.eql(lhs_key.cast, rhs_extra);12567 return std.meta.eql(lhs_key.cast, rhs_extra);
11747 }12568 }
11748 };12569 };
11749 const data = Key{ .tag = tag, .cast = .{ .val = val, .type = ty } };12570 const data: Key = .{ .tag = tag, .cast = .{ .val = val, .type = ty } };
11750 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });12571 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
11751 if (!gop.found_existing) {12572 if (!gop.found_existing) {
11752 gop.key_ptr.* = {};12573 gop.key_ptr.* = {};
...@@ -11828,10 +12649,10 @@ fn gepConstAssumeCapacity(...@@ -11828,10 +12649,10 @@ fn gepConstAssumeCapacity(
11828 std.mem.eql(Constant, lhs_key.indices, rhs_indices);12649 std.mem.eql(Constant, lhs_key.indices, rhs_indices);
11829 }12650 }
11830 };12651 };
11831 const data = Key{12652 const data: Key = .{
11832 .type = ty,12653 .type = ty,
11833 .base = base,12654 .base = base,
11834 .inrange = if (inrange) |index| @fromBackingInt(@intCast(index)) else .none,12655 .inrange = if (inrange) |index| @fromBackingInt(index) else .none,
11835 .indices = indices,12656 .indices = indices,
11836 };12657 };
11837 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });12658 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
...@@ -11885,7 +12706,7 @@ fn binConstAssumeCapacity(...@@ -11885,7 +12706,7 @@ fn binConstAssumeCapacity(
11885 return std.meta.eql(lhs_key.extra, rhs_extra);12706 return std.meta.eql(lhs_key.extra, rhs_extra);
11886 }12707 }
11887 };12708 };
11888 const data = Key{ .tag = tag, .extra = .{ .lhs = lhs, .rhs = rhs } };12709 const data: Key = .{ .tag = tag, .extra = .{ .lhs = lhs, .rhs = rhs } };
11889 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });12710 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
11890 if (!gop.found_existing) {12711 if (!gop.found_existing) {
11891 gop.key_ptr.* = {};12712 gop.key_ptr.* = {};
...@@ -11924,8 +12745,8 @@ fn asmConstAssumeCapacity(...@@ -11924,8 +12745,8 @@ fn asmConstAssumeCapacity(
11924 }12745 }
11925 };12746 };
1192612747
11927 const data = Key{12748 const data: Key = .{
11928 .tag = @fromBackingInt(@intCast(@backingInt(Constant.Tag.@"asm") + @as(u4, @bitCast(info)))),12749 .tag = @fromBackingInt(@backingInt(Constant.Tag.@"asm") + @as(u4, @bitCast(info))),
11929 .extra = .{ .type = ty, .assembly = assembly, .constraints = constraints },12750 .extra = .{ .type = ty, .assembly = assembly, .constraints = constraints },
11930 };12751 };
11931 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });12752 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
...@@ -12073,7 +12894,7 @@ fn constantExtraDataTrail(...@@ -12073,7 +12894,7 @@ fn constantExtraDataTrail(
12073 ) |field_name, field_type, value|12894 ) |field_name, field_type, value|
12074 @field(result, field_name) = switch (field_type) {12895 @field(result, field_name) = switch (field_type) {
12075 u32 => value,12896 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),
12077 Constant.GetElementPtr.Info => @bitCast(value),12898 Constant.GetElementPtr.Info => @bitCast(value),
12078 else => @compileError("bad field type: " ++ @typeName(field_type)),12899 else => @compileError("bad field type: " ++ @typeName(field_type)),
12079 };12900 };
...@@ -12151,7 +12972,7 @@ fn metadataExtraDataTrail(...@@ -12151,7 +12972,7 @@ fn metadataExtraDataTrail(
12151 ) |field_name, field_type, value|12972 ) |field_name, field_type, value|
12152 @field(result, field_name) = switch (field_type) {12973 @field(result, field_name) = switch (field_type) {
12153 u32 => value,12974 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),
12155 Metadata, Metadata.Optional, Metadata.DIFlags => @bitCast(value),12976 Metadata, Metadata.Optional, Metadata.DIFlags => @bitCast(value),
12156 else => @compileError("bad field type: " ++ @typeName(field_type)),12977 else => @compileError("bad field type: " ++ @typeName(field_type)),
12157 };12978 };
...@@ -12221,7 +13042,7 @@ pub fn trailingMetadataString(self: *Builder) Allocator.Error!Metadata.String {...@@ -12221,7 +13042,7 @@ pub fn trailingMetadataString(self: *Builder) Allocator.Error!Metadata.String {
12221}13042}
1222213043
12223pub fn trailingMetadataStringAssumeCapacity(self: *Builder) Metadata.String {13044pub fn trailingMetadataStringAssumeCapacity(self: *Builder) Metadata.String {
12224 const start = self.metadata_string_indices.getLast().?;13045 const start = self.metadata_string_indices.last().?;
12225 const bytes: []const u8 = self.metadata_string_bytes.items[start..];13046 const bytes: []const u8 = self.metadata_string_bytes.items[start..];
12226 assert(bytes.len > 0);13047 assert(bytes.len > 0);
12227 const gop = self.metadata_string_map.getOrPutAssumeCapacityAdapted(bytes, Metadata.String.Adapter{ .builder = self });13048 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...@@ -12663,7 +13484,7 @@ fn metadataSimpleAssumeCapacity(self: *Builder, tag: Metadata.Tag, value: anytyp
12663 builder: *const Builder,13484 builder: *const Builder,
12664 pub fn hash(_: @This(), key: Key) u32 {13485 pub fn hash(_: @This(), key: Key) u32 {
12665 var hasher = std.hash.Wyhash.init(std.hash.int(@backingInt(key.tag)));13486 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| {
12667 hasher.update(std.mem.asBytes(&@field(key.value, field_name)));13488 hasher.update(std.mem.asBytes(&@field(key.value, field_name)));
12668 }13489 }
12669 return @truncate(hasher.final());13490 return @truncate(hasher.final());
...@@ -12759,8 +13580,8 @@ fn debugSubprogramAssumeCapacity(...@@ -12759,8 +13580,8 @@ fn debugSubprogramAssumeCapacity(
12759 compile_unit: ?Metadata,13580 compile_unit: ?Metadata,
12760) Metadata {13581) Metadata {
12761 assert(!self.strip);13582 assert(!self.strip);
12762 const tag: Metadata.Tag = @fromBackingInt(@intCast(@backingInt(Metadata.Tag.subprogram) +13583 const tag: Metadata.Tag = @fromBackingInt(@backingInt(Metadata.Tag.subprogram) +
12763 @as(u3, @truncate(@as(u32, @bitCast(options.sp_flags)) >> 2))));13584 @as(u3, @truncate(@as(u32, @bitCast(options.sp_flags)) >> 2)));
12764 return self.metadataDistinctAssumeCapacity(tag, Metadata.Subprogram{13585 return self.metadataDistinctAssumeCapacity(tag, Metadata.Subprogram{
12765 .file = .wrap(file),13586 .file = .wrap(file),
12766 .name = .wrap(name),13587 .name = .wrap(name),
...@@ -13345,7 +14166,7 @@ fn metadataConstantAssumeCapacity(self: *Builder, constant: Constant) Metadata {...@@ -13345,7 +14166,7 @@ fn metadataConstantAssumeCapacity(self: *Builder, constant: Constant) Metadata {
1334514166
13346 pub fn eql(ctx: @This(), lhs_key: Constant, _: void, rhs_index: usize) bool {14167 pub fn eql(ctx: @This(), lhs_key: Constant, _: void, rhs_index: usize) bool {
13347 if (Metadata.Tag.constant != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false;14168 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]);
13349 return rhs_data == lhs_key;14170 return rhs_data == lhs_key;
13350 }14171 }
13351 };14172 };
...@@ -13418,7 +14239,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco...@@ -13418,7 +14239,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
13418 });14239 });
13419 }14240 }
1342014241
13421 if (self.data_layout.slice(self)) |data_layout| {14242 if (self.data_layout.string_repr.slice(self)) |data_layout| {
13422 try module_block.writeAbbrev(ModuleBlock.String{14243 try module_block.writeAbbrev(ModuleBlock.String{
13423 .code = 3,14244 .code = 3,
13424 .string = data_layout,14245 .string = data_layout,
...@@ -13577,6 +14398,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco...@@ -13577,6 +14398,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
13577 switch (attr_index.toAttribute(self)) {14398 switch (attr_index.toAttribute(self)) {
13578 .zeroext,14399 .zeroext,
13579 .signext,14400 .signext,
14401 .noext,
13580 .inreg,14402 .inreg,
13581 .@"noalias",14403 .@"noalias",
13582 .nocapture,14404 .nocapture,
...@@ -13594,11 +14416,13 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco...@@ -13594,11 +14416,13 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
13594 .readnone,14416 .readnone,
13595 .readonly,14417 .readonly,
13596 .writeonly,14418 .writeonly,
14419 .writable,
14420 .dead_on_unwind,
13597 .alwaysinline,14421 .alwaysinline,
13598 .builtin,14422 .builtin,
13599 .cold,14423 .cold,
13600 .convergent,14424 .convergent,
13601 .disable_sanitizer_information,14425 .disable_sanitizer_instrumentation,
13602 .fn_ret_thunk_extern,14426 .fn_ret_thunk_extern,
13603 .hot,14427 .hot,
13604 .inlinehint,14428 .inlinehint,
...@@ -13607,6 +14431,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco...@@ -13607,6 +14431,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
13607 .naked,14431 .naked,
13608 .nobuiltin,14432 .nobuiltin,
13609 .nocallback,14433 .nocallback,
14434 .nodivergencesource,
13610 .noduplicate,14435 .noduplicate,
13611 .noimplicitfloat,14436 .noimplicitfloat,
13612 .@"noinline",14437 .@"noinline",
...@@ -13623,6 +14448,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco...@@ -13623,6 +14448,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
13623 .nosanitize_bounds,14448 .nosanitize_bounds,
13624 .nosanitize_coverage,14449 .nosanitize_coverage,
13625 .null_pointer_is_valid,14450 .null_pointer_is_valid,
14451 .optdebug,
13626 .optforfuzzing,14452 .optforfuzzing,
13627 .optnone,14453 .optnone,
13628 .optsize,14454 .optsize,
...@@ -13633,18 +14459,21 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco...@@ -13633,18 +14459,21 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
13633 .sanitize_thread,14459 .sanitize_thread,
13634 .sanitize_hwaddress,14460 .sanitize_hwaddress,
13635 .sanitize_memtag,14461 .sanitize_memtag,
14462 .sanitize_realtime,
14463 .sanitize_realtime_blocking,
14464 .sanitize_alloc_token,
13636 .speculative_load_hardening,14465 .speculative_load_hardening,
13637 .speculatable,14466 .speculatable,
13638 .ssp,14467 .ssp,
13639 .sspstrong,14468 .sspstrong,
13640 .sspreq,14469 .sspreq,
13641 .strictfp,14470 .strictfp,
14471 .denormal_fpenv,
13642 .nocf_check,14472 .nocf_check,
13643 .shadowcallstack,14473 .shadowcallstack,
13644 .mustprogress,14474 .mustprogress,
13645 .no_sanitize_address,14475 .nooutline,
13646 .no_sanitize_hwaddress,14476 .nocreateundeforpoison,
13647 .sanitize_address_dyninit,
13648 => {14477 => {
13649 try record.ensureUnusedCapacity(self.gpa, 2);14478 try record.ensureUnusedCapacity(self.gpa, 2);
13650 record.appendAssumeCapacity(0);14479 record.appendAssumeCapacity(0);
...@@ -13670,6 +14499,12 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco...@@ -13670,6 +14499,12 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
13670 record.appendAssumeCapacity(@backingInt(kind));14499 record.appendAssumeCapacity(@backingInt(kind));
13671 record.appendAssumeCapacity(alignment.resolve(self).toByteUnits() orelse 0);14500 record.appendAssumeCapacity(alignment.resolve(self).toByteUnits() orelse 0);
13672 },14501 },
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 },
13673 .dereferenceable,14508 .dereferenceable,
13674 .dereferenceable_or_null,14509 .dereferenceable_or_null,
13675 => |size| {14510 => |size| {
...@@ -13684,6 +14519,9 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco...@@ -13684,6 +14519,9 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
13684 record.appendAssumeCapacity(@backingInt(kind));14519 record.appendAssumeCapacity(@backingInt(kind));
13685 record.appendAssumeCapacity(@as(u32, @bitCast(fpclass)));14520 record.appendAssumeCapacity(@as(u32, @bitCast(fpclass)));
13686 },14521 },
14522 .initializes => @panic("TODO"),
14523 .dead_on_return => @panic("TODO"),
14524 .range => @panic("TODO"),
13687 .allockind => |allockind| {14525 .allockind => |allockind| {
13688 try record.ensureUnusedCapacity(self.gpa, 3);14526 try record.ensureUnusedCapacity(self.gpa, 3);
13689 record.appendAssumeCapacity(1);14527 record.appendAssumeCapacity(1);
...@@ -13955,8 +14793,11 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco...@@ -13955,8 +14793,11 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
13955 }14793 }
1395614794
13957 const strtab = alias.global.strtab(self);14795 const strtab = alias.global.strtab(self);
13958
13959 const global = alias.global.ptrConst(self);14796 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
13960 try module_block.writeAbbrev(ModuleBlock.Alias{14801 try module_block.writeAbbrev(ModuleBlock.Alias{
13961 .strtab_offset = strtab.offset,14802 .strtab_offset = strtab.offset,
13962 .strtab_size = strtab.size,14803 .strtab_size = strtab.size,
...@@ -14096,7 +14937,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco...@@ -14096,7 +14937,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
14096 }14937 }
14097 },14938 },
14098 .string => {14939 .string => {
14099 const str: String = @fromBackingInt(@intCast(data));14940 const str: String = @fromBackingInt(data);
14100 if (str == .none) {14941 if (str == .none) {
14101 try constants_block.writeAbbrev(ConstantsBlock.Null{});14942 try constants_block.writeAbbrev(ConstantsBlock.Null{});
14102 } else {14943 } else {
...@@ -14223,7 +15064,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco...@@ -14223,7 +15064,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
14223 .dso_local_equivalent,15064 .dso_local_equivalent,
14224 .no_cfi,15065 .no_cfi,
14225 => |tag| {15066 => |tag| {
14226 const function: Function.Index = @fromBackingInt(@intCast(data));15067 const function: Function.Index = @fromBackingInt(data);
14227 try constants_block.writeAbbrev(ConstantsBlock.DsoLocalEquivalentOrNoCfi{15068 try constants_block.writeAbbrev(ConstantsBlock.DsoLocalEquivalentOrNoCfi{
14228 .code = switch (tag) {15069 .code = switch (tag) {
14229 .dso_local_equivalent => .DSO_LOCAL_EQUIVALENT,15070 .dso_local_equivalent => .DSO_LOCAL_EQUIVALENT,
...@@ -14606,7 +15447,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco...@@ -14606,7 +15447,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
14606 }, metadata_adapter);15447 }, metadata_adapter);
14607 },15448 },
14608 .constant => {15449 .constant => {
14609 const constant: Constant = @fromBackingInt(@intCast(data));15450 const constant: Constant = @fromBackingInt(data);
14610 try metadata_block.writeAbbrevAdapted(MetadataBlock.Constant{15451 try metadata_block.writeAbbrevAdapted(MetadataBlock.Constant{
14611 .ty = constant.typeOf(self),15452 .ty = constant.typeOf(self),
14612 .constant = constant,15453 .constant = constant,
...@@ -14775,7 +15616,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco...@@ -14775,7 +15616,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
14775 var adapter: FunctionAdapter = .{15616 var adapter: FunctionAdapter = .{
14776 .metadata_adapter = metadata_adapter,15617 .metadata_adapter = metadata_adapter,
14777 .func = &func,15618 .func = &func,
14778 .instruction_index = @fromBackingInt(@intCast(0)),15619 .instruction_index = @fromBackingInt(0),
14779 };15620 };
1478015621
14781 // Emit function level metadata block15622 // Emit function level metadata block
...@@ -14786,7 +15627,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco...@@ -14786,7 +15627,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
14786 for (func.debug_values) |value| {15627 for (func.debug_values) |value| {
14787 try metadata_block.writeAbbrev(MetadataBlock.Value{15628 try metadata_block.writeAbbrev(MetadataBlock.Value{
14788 .ty = value.typeOf(@fromBackingInt(@intCast(func_index)), self),15629 .ty = value.typeOf(@fromBackingInt(@intCast(func_index)), self),
14789 .value = @fromBackingInt(@intCast(adapter.getValueIndex(value.toValue()))),15630 .value = @fromBackingInt(adapter.getValueIndex(value.toValue())),
14790 });15631 });
14791 }15632 }
1479215633
...@@ -15068,10 +15909,10 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco...@@ -15068,10 +15909,10 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
15068 });15909 });
15069 },15910 },
15070 .fneg => try function_block.writeAbbrev(FunctionBlock.FNeg{15911 .fneg => try function_block.writeAbbrev(FunctionBlock.FNeg{
15071 .val = adapter.getOffsetValueIndex(@fromBackingInt(@intCast(data))),15912 .val = adapter.getOffsetValueIndex(@fromBackingInt(data)),
15072 }),15913 }),
15073 .@"fneg fast" => try function_block.writeAbbrev(FunctionBlock.FNegFast{15914 .@"fneg fast" => try function_block.writeAbbrev(FunctionBlock.FNegFast{
15074 .val = adapter.getOffsetValueIndex(@fromBackingInt(@intCast(data))),15915 .val = adapter.getOffsetValueIndex(@fromBackingInt(data)),
15075 .fast_math = FastMath.fast,15916 .fast_math = FastMath.fast,
15076 }),15917 }),
15077 .extractvalue => {15918 .extractvalue => {
...@@ -15271,7 +16112,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco...@@ -15271,7 +16112,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
15271 try function_block.writeUnabbrev(16, record.items);16112 try function_block.writeUnabbrev(16, record.items);
15272 },16113 },
15273 .ret => try function_block.writeAbbrev(FunctionBlock.Ret{16114 .ret => try function_block.writeAbbrev(FunctionBlock.Ret{
15274 .val = adapter.getOffsetValueIndex(@fromBackingInt(@intCast(data))),16115 .val = adapter.getOffsetValueIndex(@fromBackingInt(data)),
15275 }),16116 }),
15276 .@"ret void" => try function_block.writeAbbrev(FunctionBlock.RetVoid{}),16117 .@"ret void" => try function_block.writeAbbrev(FunctionBlock.RetVoid{}),
15277 .atomicrmw => {16118 .atomicrmw => {
lib/std/zig/llvm/bitcode_writer.zig+1-1
...@@ -246,7 +246,7 @@ pub fn BitcodeWriter(comptime types: []const type) type {...@@ -246,7 +246,7 @@ pub fn BitcodeWriter(comptime types: []const type) type {
246246
247 try self.bitcode.writeBits(comptime abbrevId(Abbrev), abbrev_len);247 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
251 // This abbreviation might only contain literals251 // This abbreviation might only contain literals
252 if (field_names.len == 0) return;252 if (field_names.len == 0) return;
lib/std/zig/system.zig+9-9
...@@ -597,23 +597,23 @@ fn abiAndDynamicLinkerFromFile(...@@ -597,23 +597,23 @@ fn abiAndDynamicLinkerFromFile(
597 .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch),597 .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch),
598 .dynamic_linker = query.dynamic_linker orelse .none,598 .dynamic_linker = query.dynamic_linker orelse .none,
599 };599 };
600 var rpath_offset: ?u64 = null; // Found inside PT_DYNAMIC600 var rpath_offset: ?u64 = null; // Found inside PT.DYNAMIC
601 const look_for_ld = query.dynamic_linker == null;601 const look_for_ld = query.dynamic_linker == null;
602602
603 var got_dyn_section: bool = false;603 var got_dyn_section: bool = false;
604 {604 {
605 var it = header.iterateProgramHeaders(file_reader);605 var it = header.iterateProgramHeaders(file_reader);
606 while (try it.next()) |phdr| switch (phdr.p_type) {606 while (try it.next()) |phdr| switch (phdr.type) {
607 elf.PT_INTERP => {607 .INTERP => {
608 got_dyn_section = true;608 got_dyn_section = true;
609609
610 if (look_for_ld) {610 if (look_for_ld) {
611 const p_filesz = phdr.p_filesz;611 const p_filesz = phdr.filesz;
612 if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong;612 if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong;
613 const filesz: usize = @intCast(p_filesz);613 const filesz: usize = @intCast(p_filesz);
614 try file_reader.seekTo(phdr.p_offset);614 try file_reader.seekTo(phdr.offset);
615 try file_reader.interface.readSliceAll(result.dynamic_linker.buffer[0..filesz]);615 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.
617 const len = filesz - 1;617 const len = filesz - 1;
618 // dynamic_linker.max_byte is "max", not "len".618 // dynamic_linker.max_byte is "max", not "len".
619 // We know it will fit in u8 because we check against dynamic_linker.buffer.len above.619 // We know it will fit in u8 because we check against dynamic_linker.buffer.len above.
...@@ -631,11 +631,11 @@ fn abiAndDynamicLinkerFromFile(...@@ -631,11 +631,11 @@ fn abiAndDynamicLinkerFromFile(
631 }631 }
632 },632 },
633 // We only need this for detecting glibc version.633 // We only need this for detecting glibc version.
634 elf.PT_DYNAMIC => {634 .DYNAMIC => {
635 got_dyn_section = true;635 got_dyn_section = true;
636636
637 if (builtin.target.os.tag == .linux and result.isGnuLibC() and query.glibc_version == null) {637 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);
639 while (try dyn_it.next()) |dyn| {639 while (try dyn_it.next()) |dyn| {
640 if (dyn.d_tag == elf.DT_RUNPATH) {640 if (dyn.d_tag == elf.DT_RUNPATH) {
641 rpath_offset = dyn.d_val;641 rpath_offset = dyn.d_val;
...@@ -973,7 +973,7 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ...@@ -973,7 +973,7 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ
973 // relying on `builtin.target`.973 // relying on `builtin.target`.
974 const all_abis = comptime blk: {974 const all_abis = comptime blk: {
975 assert(@backingInt(Target.Abi.none) == 0);975 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..];
977 var array: [field_names.len]Target.Abi = undefined;977 var array: [field_names.len]Target.Abi = undefined;
978 for (field_names, 0..) |field_name, i| {978 for (field_names, 0..) |field_name, i| {
979 array[i] = @field(Target.Abi, field_name);979 array[i] = @field(Target.Abi, field_name);
lib/std/zig/target.zig+25-25
...@@ -46,6 +46,8 @@ pub const available_libcs = [_]ArchOsAbi{...@@ -46,6 +46,8 @@ pub const available_libcs = [_]ArchOsAbi{
46 .{ .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" },46 .{ .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" },
47 .{ .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" },47 .{ .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" },
48 .{ .arch = .hexagon, .os = .linux, .abi = .musl, .os_ver = .{ .major = 3, .minor = 2, .patch = 102 } },48 .{ .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" },
49 .{ .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" },51 .{ .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" },
50 .{ .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" },52 .{ .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" },
51 .{ .arch = .loongarch64, .os = .linux, .abi = .musl, .os_ver = .{ .major = 5, .minor = 19, .patch = 0 } },53 .{ .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 {...@@ -499,34 +501,32 @@ pub fn intByteSize(target: *const std.Target, bits: u16) u16 {
499}501}
500502
501pub fn intAlignment(target: *const std.Target, bits: u16) u16 {503pub fn intAlignment(target: *const std.Target, bits: u16) u16 {
502 return switch (target.cpu.arch) {504 return switch (bits) {
503 .x86 => switch (bits) {505 0 => 1,
504 0...8 => 1,506 else => @min(
505 9...16 => 2,507 std.math.ceilPowerOfTwoPromote(u16, @intCast((@as(u17, bits) + 7) / 8)),
506 17...32 => 4,508 target.cMaxIntAlignment(),
507 33...64 => switch (target.os.tag) {509 ),
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 },
527 };510 };
528}511}
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
530const std = @import("std");530const std = @import("std");
531const assert = std.debug.assert;531const assert = std.debug.assert;
532const Allocator = std.mem.Allocator;532const Allocator = std.mem.Allocator;
lib/std/zip.zig+1-1
...@@ -109,7 +109,7 @@ pub const EndRecord = extern struct {...@@ -109,7 +109,7 @@ pub const EndRecord = extern struct {
109109
110 /// TODO audit this logic110 /// TODO audit this logic
111 pub fn findBuffer(buffer: []const u8) FindBufferError!EndRecord {111 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;
113 if (pos + @sizeOf(EndRecord) > buffer.len) return error.EndOfStream;113 if (pos + @sizeOf(EndRecord) > buffer.len) return error.EndOfStream;
114 const record_ptr: *EndRecord = @ptrCast(buffer[pos..][0..@sizeOf(EndRecord)]);114 const record_ptr: *EndRecord = @ptrCast(buffer[pos..][0..@sizeOf(EndRecord)]);
115 var record = record_ptr.*;115 var record = record_ptr.*;
lib/std/zon.zig+41
...@@ -37,10 +37,51 @@...@@ -37,10 +37,51 @@
37//! ZON does not have syntax for pointers, but the parsers will allocate as needed to match the37//! ZON does not have syntax for pointers, but the parsers will allocate as needed to match the
38//! given Zig types. Similarly, the serializer will traverse pointers.38//! given Zig types. Similarly, the serializer will traverse pointers.
3939
40const std = @import("std");
41
40pub const parse = @import("zon/parse.zig");42pub const parse = @import("zon/parse.zig");
41pub const stringify = @import("zon/stringify.zig");43pub const stringify = @import("zon/stringify.zig");
42pub const Serializer = @import("zon/Serializer.zig");44pub 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
44test {85test {
45 _ = parse;86 _ = parse;
46 _ = stringify;87 _ = stringify;
lib/std/zon/parse.zig+1-6
...@@ -9,7 +9,6 @@...@@ -9,7 +9,6 @@
9//! For lower level control over parsing, see `std.zig.Zoir`.9//! For lower level control over parsing, see `std.zig.Zoir`.
1010
11const std = @import("std");11const std = @import("std");
12const builtin = @import("builtin");
13const Allocator = std.mem.Allocator;12const Allocator = std.mem.Allocator;
14const Ast = std.zig.Ast;13const Ast = std.zig.Ast;
15const Zoir = std.zig.Zoir;14const Zoir = std.zig.Zoir;
...@@ -1868,8 +1867,6 @@ test "std.zon tuples" {...@@ -1868,8 +1867,6 @@ test "std.zon tuples" {
18681867
1869// Test sizes 0 to 3 since small sizes get parsed differently1868// Test sizes 0 to 3 since small sizes get parsed differently
1870test "std.zon arrays and slices" {1869test "std.zon arrays and slices" {
1871 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/20881
1872
1873 const gpa = std.testing.allocator;1870 const gpa = std.testing.allocator;
18741871
1875 // Literals1872 // Literals
...@@ -2802,8 +2799,6 @@ test "std.zon negative char" {...@@ -2802,8 +2799,6 @@ test "std.zon negative char" {
2802}2799}
28032800
2804test "std.zon parse float" {2801test "std.zon parse float" {
2805 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
2806
2807 const gpa = std.testing.allocator;2802 const gpa = std.testing.allocator;
28082803
2809 // Test decimals2804 // Test decimals
...@@ -3135,7 +3130,7 @@ test "std.zon free on error" {...@@ -3135,7 +3130,7 @@ test "std.zon free on error" {
3135}3130}
31363131
3137test "std.zon vector" {3132test "std.zon vector" {
3138 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/153303133 const builtin = @import("builtin");
3139 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .s390x) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/259573134 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .s390x) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/25957
31403135
3141 const gpa = std.testing.allocator;3136 const gpa = std.testing.allocator;
lib/std/zon/stringify.zig-3
...@@ -1151,9 +1151,6 @@ test "std.zon depth limits" {...@@ -1151,9 +1151,6 @@ test "std.zon depth limits" {
1151}1151}
11521152
1153test "std.zon stringify primitives" {1153test "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
1157 try expectSerializeEqual(1154 try expectSerializeEqual(
1158 \\.{1155 \\.{
1159 \\ .a = 1.5,1156 \\ .a = 1.5,
lib/zig.h+3079-991
...@@ -166,6 +166,12 @@...@@ -166,6 +166,12 @@
166#endif166#endif
167#define zig_expand_has_builtin(b) zig_has_builtin(b)167#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
169#if defined(__has_attribute)175#if defined(__has_attribute)
170#define zig_has_attribute(attribute) __has_attribute(attribute)176#define zig_has_attribute(attribute) __has_attribute(attribute)
171#else177#else
...@@ -175,9 +181,9 @@...@@ -175,9 +181,9 @@
175#if __STDC_VERSION__ >= 201112L181#if __STDC_VERSION__ >= 201112L
176#define zig_static_assert(cond, msg) _Static_assert(cond, msg)182#define zig_static_assert(cond, msg) _Static_assert(cond, msg)
177#elif zig_has_attribute(unused)183#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))
179#else185#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]
181#endif187#endif
182188
183#if __STDC_VERSION__ >= 202311L189#if __STDC_VERSION__ >= 202311L
...@@ -193,10 +199,8 @@...@@ -193,10 +199,8 @@
193#endif199#endif
194200
195#if defined(zig_msvc)201#if defined(zig_msvc)
196#define zig_const_arr
197#define zig_callconv(c) __##c202#define zig_callconv(c) __##c
198#else203#else
199#define zig_const_arr static const
200#define zig_callconv(c) __attribute__((c))204#define zig_callconv(c) __attribute__((c))
201#endif205#endif
202206
...@@ -267,12 +271,20 @@...@@ -267,12 +271,20 @@
267271
268#if __STDC_VERSION__ >= 202311L272#if __STDC_VERSION__ >= 202311L
269#define zig_align(alignment) alignas(alignment)273#define zig_align(alignment) alignas(alignment)
270#elif __STDC_VERSION__ >= 201112L274#elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignas)
271#define zig_align(alignment) _Alignas(alignment)275#define zig_align(alignment) _Alignas(alignment)
272#else276#else
273#define zig_align(alignment) zig_under_align(alignment)277#define zig_align(alignment) zig_under_align(alignment)
274#endif278#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
276#if zig_has_attribute(aligned) || defined(zig_tinyc)288#if zig_has_attribute(aligned) || defined(zig_tinyc)
277#define zig_align_fn(alignment) __attribute__((aligned(alignment)))289#define zig_align_fn(alignment) __attribute__((aligned(alignment)))
278#elif defined(zig_msvc)290#elif defined(zig_msvc)
...@@ -350,11 +362,9 @@...@@ -350,11 +362,9 @@
350#define zig_export(symbol, name) __attribute__((alias(symbol)))362#define zig_export(symbol, name) __attribute__((alias(symbol)))
351#else363#else
352#define zig_export(symbol, name) ; \364#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))
354#endif366#endif
355367
356#define zig_mangled_tentative zig_mangled
357#define zig_mangled_final zig_mangled
358#if defined(zig_msvc)368#if defined(zig_msvc)
359#define zig_mangled(mangled, unmangled) ; \369#define zig_mangled(mangled, unmangled) ; \
360 zig_export(#mangled, unmangled)370 zig_export(#mangled, unmangled)
...@@ -364,7 +374,7 @@...@@ -364,7 +374,7 @@
364#else /* zig_msvc */374#else /* zig_msvc */
365#define zig_mangled(mangled, unmangled) __asm(zig_mangle_c(unmangled))375#define zig_mangled(mangled, unmangled) __asm(zig_mangle_c(unmangled))
366#define zig_mangled_export(mangled, unmangled, symbol) \376#define zig_mangled_export(mangled, unmangled, symbol) \
367 zig_mangled_final(mangled, unmangled) \377 zig_mangled(mangled, unmangled) \
368 zig_export(symbol, unmangled)378 zig_export(symbol, unmangled)
369#endif /* zig_msvc */379#endif /* zig_msvc */
370380
...@@ -550,6 +560,9 @@...@@ -550,6 +560,9 @@
550#define zig_noreturn560#define zig_noreturn
551#endif561#endif
552562
563#define zig_has_always 1
564#define zig_has_never 0
565
553#define zig_compiler_rt_abbrev_uint32_t si566#define zig_compiler_rt_abbrev_uint32_t si
554#define zig_compiler_rt_abbrev_int32_t si567#define zig_compiler_rt_abbrev_int32_t si
555#define zig_compiler_rt_abbrev_uint64_t di568#define zig_compiler_rt_abbrev_uint64_t di
...@@ -560,7 +573,11 @@...@@ -560,7 +573,11 @@
560#define zig_compiler_rt_abbrev_zig_f32 sf573#define zig_compiler_rt_abbrev_zig_f32 sf
561#define zig_compiler_rt_abbrev_zig_f64 df574#define zig_compiler_rt_abbrev_zig_f64 df
562#define zig_compiler_rt_abbrev_zig_f80 xf575#define zig_compiler_rt_abbrev_zig_f80 xf
576#ifdef zig_powerpc
577#define zig_compiler_rt_abbrev_zig_f128 kf
578#else
563#define zig_compiler_rt_abbrev_zig_f128 tf579#define zig_compiler_rt_abbrev_zig_f128 tf
580#endif
564581
565zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t);582zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t);
566zig_extern void *memset (void *, int, size_t);583zig_extern void *memset (void *, int, size_t);
...@@ -645,16 +662,6 @@ typedef signed long long int16_t;...@@ -645,16 +662,6 @@ typedef signed long long int16_t;
645#define INT16_MAX ( INT16_C(0x7FFF))662#define INT16_MAX ( INT16_C(0x7FFF))
646#define UINT16_MAX ( INT16_C(0xFFFF))663#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
658#if SCHAR_MIN == ~0x7FFFFFFF && SCHAR_MAX == 0x7FFFFFFF && UCHAR_MAX == 0xFFFFFFFF665#if SCHAR_MIN == ~0x7FFFFFFF && SCHAR_MAX == 0x7FFFFFFF && UCHAR_MAX == 0xFFFFFFFF
659typedef unsigned char uint32_t;666typedef unsigned char uint32_t;
660typedef signed char int32_t;667typedef signed char int32_t;
...@@ -685,17 +692,6 @@ typedef signed long long int32_t;...@@ -685,17 +692,6 @@ typedef signed long long int32_t;
685#define INT32_MAX ( INT32_C(0x7FFFFFFF))692#define INT32_MAX ( INT32_C(0x7FFFFFFF))
686#define UINT32_MAX ( INT32_C(0xFFFFFFFF))693#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
699#if SCHAR_MIN == ~0x7FFFFFFFFFFFFFFF && SCHAR_MAX == 0x7FFFFFFFFFFFFFFF && UCHAR_MAX == 0xFFFFFFFFFFFFFFFF695#if SCHAR_MIN == ~0x7FFFFFFFFFFFFFFF && SCHAR_MAX == 0x7FFFFFFFFFFFFFFF && UCHAR_MAX == 0xFFFFFFFFFFFFFFFF
700typedef unsigned char uint64_t;696typedef unsigned char uint64_t;
701typedef signed char int64_t;697typedef signed char int64_t;
...@@ -726,6 +722,27 @@ typedef signed long long int64_t;...@@ -726,6 +722,27 @@ typedef signed long long int64_t;
726#define INT64_MAX ( INT64_C(0x7FFFFFFFFFFFFFFF))722#define INT64_MAX ( INT64_C(0x7FFFFFFFFFFFFFFF))
727#define UINT64_MAX ( INT64_C(0xFFFFFFFFFFFFFFFF))723#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
729typedef size_t uintptr_t;746typedef size_t uintptr_t;
730typedef ptrdiff_t intptr_t;747typedef ptrdiff_t intptr_t;
731748
...@@ -739,23 +756,145 @@ typedef ptrdiff_t intptr_t;...@@ -739,23 +756,145 @@ typedef ptrdiff_t intptr_t;
739#define zig_maxInt_i16 INT16_MAX756#define zig_maxInt_i16 INT16_MAX
740#define zig_minInt_u16 UINT16_C(0)757#define zig_minInt_u16 UINT16_C(0)
741#define zig_maxInt_u16 UINT16_MAX758#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
746#define zig_minInt_i32 INT32_MIN759#define zig_minInt_i32 INT32_MIN
747#define zig_maxInt_i32 INT32_MAX760#define zig_maxInt_i32 INT32_MAX
748#define zig_minInt_u32 UINT32_C(0)761#define zig_minInt_u32 UINT32_C(0)
749#define zig_maxInt_u32 UINT32_MAX762#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
754#define zig_minInt_i64 INT64_MIN763#define zig_minInt_i64 INT64_MIN
755#define zig_maxInt_i64 INT64_MAX764#define zig_maxInt_i64 INT64_MAX
756#define zig_minInt_u64 UINT64_C(0)765#define zig_minInt_u64 UINT64_C(0)
757#define zig_maxInt_u64 UINT64_MAX766#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
759#define zig_intLimit(s, w, limit, bits) zig_shr_##s##w(zig_##limit##Int_##s##w, w - (bits))898#define zig_intLimit(s, w, limit, bits) zig_shr_##s##w(zig_##limit##Int_##s##w, w - (bits))
760#define zig_minInt_i(w, bits) zig_intLimit(i, w, min, bits)899#define zig_minInt_i(w, bits) zig_intLimit(i, w, min, bits)
761#define zig_maxInt_i(w, bits) zig_intLimit(i, w, max, bits)900#define zig_maxInt_i(w, bits) zig_intLimit(i, w, max, bits)
...@@ -770,7 +909,33 @@ typedef ptrdiff_t intptr_t;...@@ -770,7 +909,33 @@ typedef ptrdiff_t intptr_t;
770 zig_operator(Type, Type, operation, operator)909 zig_operator(Type, Type, operation, operator)
771#define zig_shift_operator(Type, operation, operator) \910#define zig_shift_operator(Type, operation, operator) \
772 zig_operator(Type, uint8_t, operation, operator)911 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) \
774 zig_basic_operator(uint##w##_t, and_u##w, &) \939 zig_basic_operator(uint##w##_t, and_u##w, &) \
775 zig_basic_operator( int##w##_t, and_i##w, &) \940 zig_basic_operator( int##w##_t, and_i##w, &) \
776 zig_basic_operator(uint##w##_t, or_u##w, |) \941 zig_basic_operator(uint##w##_t, or_u##w, |) \
...@@ -786,44 +951,48 @@ typedef ptrdiff_t intptr_t;...@@ -786,44 +951,48 @@ typedef ptrdiff_t intptr_t;
786 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \951 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \
787 } \952 } \
788\953\
789 static inline uint##w##_t zig_not_u##w(uint##w##_t val, uint8_t bits) { \954 static inline uint##w##_t zig_not_u##w(uint##w##_t arg, uint8_t bits) { \
790 return val ^ zig_maxInt_u(w, bits); \955 return arg ^ zig_maxInt_u(w, bits); \
791 } \956 } \
792\957\
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) { \
794 (void)bits; \959 (void)bits; \
795 return ~val; \960 return ~arg; \
796 } \961 } \
797\962\
798 static inline uint##w##_t zig_wrap_u##w(uint##w##_t val, uint8_t bits) { \963 zig_basic_operator(uint##w##_t, divFloor_u##w, /) \
799 return val & zig_maxInt_u(w, bits); \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)); \
800 } \967 } \
801\968\
802 static inline int##w##_t zig_wrap_i##w(int##w##_t val, uint8_t bits) { \969 static inline uint##w##_t zig_divCeil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \
803 return (val & UINT##w##_C(1) << (bits - UINT8_C(1))) != 0 \970 return lhs / rhs + (lhs % rhs != UINT##w##_C(0) ? UINT##w##_C(1) : UINT##w##_C(0)); \
804 ? val | zig_minInt_i(w, bits) : val & zig_maxInt_i(w, bits); \
805 } \971 } \
806\972\
807 static inline uint##w##_t zig_abs_i##w(int##w##_t val) { \973 static inline int##w##_t zig_divCeil_i##w(int##w##_t lhs, int##w##_t rhs) { \
808 return (val < 0) ? -(uint##w##_t)val : (uint##w##_t)val; \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)); \
809 } \976 } \
810\977\
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) \
812\980\
813 static inline int##w##_t zig_div_floor_i##w(int##w##_t lhs, int##w##_t rhs) { \981 static inline uint##w##_t zig_u##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \
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)); \982 return zig_u##w##_truncate_u##w(arg, bits); \
815 } \983 } \
816\984\
817 static inline uint##w##_t zig_div_ceil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \985 static inline uint##w##_t zig_u##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \
818 return lhs / rhs + (lhs % rhs != UINT##w##_C(0) ? UINT##w##_C(1) : UINT##w##_C(0)); \986 return zig_u##w##_bitCast_u##w((uint##w##_t)arg, bits); \
819 } \987 } \
820\988\
821 static inline int##w##_t zig_div_ceil_i##w(int##w##_t lhs, int##w##_t rhs) { \989 static inline int##w##_t zig_i##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \
822 return lhs / rhs + (lhs % rhs != INT##w##_C(0) \990 return zig_i##w##_truncate_i##w(arg, bits); \
823 ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) + INT##w##_C(1) : INT##w##_C(0)); \
824 } \991 } \
825\992\
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 } \
827\996\
828 static inline int##w##_t zig_mod_i##w(int##w##_t lhs, int##w##_t rhs) { \997 static inline int##w##_t zig_mod_i##w(int##w##_t lhs, int##w##_t rhs) { \
829 int##w##_t rem = lhs % rhs; \998 int##w##_t rem = lhs % rhs; \
...@@ -831,100 +1000,102 @@ typedef ptrdiff_t intptr_t;...@@ -831,100 +1000,102 @@ typedef ptrdiff_t intptr_t;
831 } \1000 } \
832\1001\
833 static inline uint##w##_t zig_shlw_u##w(uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \1002 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); \
835 } \1004 } \
836\1005\
837 static inline int##w##_t zig_shlw_i##w(int##w##_t lhs, uint8_t rhs, uint8_t bits) { \1006 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); \
839 } \1008 } \
840\1009\
841 static inline uint##w##_t zig_addw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \1010 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); \
843 } \1012 } \
844\1013\
845 static inline int##w##_t zig_addw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \1014 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); \
847 } \1016 } \
848\1017\
849 static inline uint##w##_t zig_subw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \1018 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); \
851 } \1020 } \
852\1021\
853 static inline int##w##_t zig_subw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \1022 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); \
855 } \1024 } \
856\1025\
857 static inline uint##w##_t zig_mulw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \1026 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); \
859 } \1028 } \
860\1029\
861 static inline int##w##_t zig_mulw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \1030 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; \
863 }1053 }
864#if UINT8_MAX <= UINT_MAX1054zig_int_operators(8)
865zig_int_helpers(8, unsigned int)1055zig_int_operators(16)
866#elif UINT8_MAX <= ULONG_MAX1056zig_int_operators(32)
867zig_int_helpers(8, unsigned long)1057zig_int_operators(64)
868#elif UINT8_MAX <= ULLONG_MAX1058#ifdef zig_ez80
869zig_int_helpers(8, unsigned long long)1059zig_int_operators(24)
870#else1060zig_int_operators(48)
871zig_int_helpers(8, uint8_t)1061#endif
872#endif1062
873#if UINT16_MAX <= UINT_MAX1063#define zig_int_casts(bw, sw) \
874zig_int_helpers(16, unsigned int)1064 static inline uint##sw##_t zig_u##sw##_intCast_u##bw(uint##bw##_t arg) { \
875#elif UINT16_MAX <= ULONG_MAX1065 return (uint##sw##_t)arg; \
876zig_int_helpers(16, unsigned long)1066 } \
877#elif UINT16_MAX <= ULLONG_MAX1067\
878zig_int_helpers(16, unsigned long long)1068 static inline uint##sw##_t zig_u##sw##_intCast_i##bw(int##bw##_t arg) { \
879#else1069 return (uint##sw##_t)arg; \
880zig_int_helpers(16, uint16_t)1070 } \
881#endif1071\
882#if defined(zig_ez80)1072 static inline int##sw##_t zig_i##sw##_intCast_u##bw(uint##bw##_t arg) { \
883#if UINT24_MAX <= UINT_MAX1073 return (int##sw##_t)arg; \
884zig_int_helpers(24, unsigned int)1074 } \
885#elif UINT24_MAX <= ULONG_MAX1075\
886zig_int_helpers(24, unsigned long)1076 static inline int##sw##_t zig_i##sw##_intCast_i##bw(int##bw##_t arg) { \
887#elif UINT24_MAX <= ULLONG_MAX1077 return (int##sw##_t)arg; \
888zig_int_helpers(24, unsigned long long)1078 } \
889#else1079\
890zig_int_helpers(24, uint24_t)1080 zig_int_casts_common(bw, sw)
891#endif1081zig_int_casts(16, 8)
892#endif1082zig_int_casts(32, 8)
893#if UINT32_MAX <= UINT_MAX1083zig_int_casts(64, 8)
894zig_int_helpers(32, unsigned int)1084zig_int_casts(32, 16)
895#elif UINT32_MAX <= ULONG_MAX1085zig_int_casts(64, 16)
896zig_int_helpers(32, unsigned long)1086zig_int_casts(64, 32)
897#elif UINT32_MAX <= ULLONG_MAX1087#ifdef zig_ez80
898zig_int_helpers(32, unsigned long long)1088zig_int_casts(32, 24)
899#else1089zig_int_casts(48, 24)
900zig_int_helpers(32, uint32_t)1090zig_int_casts(64, 24)
901#endif1091zig_int_casts(64, 48)
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)
921#endif1092#endif
9221093
923static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {1094static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
924#if zig_has_builtin(add_overflow) || defined(zig_gcc)1095#if zig_has_builtin(add_overflow) || defined(zig_gcc)
925 uint32_t full_res;1096 uint32_t full_res;
926 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1097 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);
928 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);1099 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
929#else1100#else
930 *res = zig_addw_u32(lhs, rhs, bits);1101 *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...@@ -936,19 +1107,19 @@ static inline bool zig_addo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t
936#if zig_has_builtin(add_overflow) || defined(zig_gcc)1107#if zig_has_builtin(add_overflow) || defined(zig_gcc)
937 int32_t full_res;1108 int32_t full_res;
938 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1109 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);
939#else1112#else
940 int32_t full_res = (int32_t)((uint32_t)lhs + (uint32_t)rhs);1113 *res = zig_addw_i32(lhs, rhs, bits);
941 bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0;1114 return ((*res ^ lhs) & (*res ^ rhs)) < INT32_C(0);
942#endif1115#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);
945}1116}
9461117
947static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {1118static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
948#if zig_has_builtin(add_overflow) || defined(zig_gcc)1119#if zig_has_builtin(add_overflow) || defined(zig_gcc)
949 uint64_t full_res;1120 uint64_t full_res;
950 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1121 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);
952 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);1123 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
953#else1124#else
954 *res = zig_addw_u64(lhs, rhs, bits);1125 *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...@@ -960,24 +1131,24 @@ static inline bool zig_addo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t
960#if zig_has_builtin(add_overflow) || defined(zig_gcc)1131#if zig_has_builtin(add_overflow) || defined(zig_gcc)
961 int64_t full_res;1132 int64_t full_res;
962 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1133 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);
963#else1136#else
964 int64_t full_res = (int64_t)((uint64_t)lhs + (uint64_t)rhs);1137 *res = zig_addw_i64(lhs, rhs, bits);
965 bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0;1138 return ((*res ^ lhs) & (*res ^ rhs)) < INT64_C(0);
966#endif1139#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);
969}1140}
9701141
971static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {1142static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
972#if zig_has_builtin(add_overflow) || defined(zig_gcc)1143#if zig_has_builtin(add_overflow) || defined(zig_gcc)
973 uint8_t full_res;1144 uint8_t full_res;
974 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1145 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);
976 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);1147 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
977#else1148#else
978 uint32_t full_res;1149 uint32_t full_res;
979 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);1150 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
980 *res = (uint8_t)full_res;1151 *res = zig_u8_intCast_u32(full_res);
981 return overflow;1152 return overflow;
982#endif1153#endif
983}1154}
...@@ -986,12 +1157,12 @@ static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits...@@ -986,12 +1157,12 @@ static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
986#if zig_has_builtin(add_overflow) || defined(zig_gcc)1157#if zig_has_builtin(add_overflow) || defined(zig_gcc)
987 int8_t full_res;1158 int8_t full_res;
988 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1159 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);
990 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);1161 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
991#else1162#else
992 int32_t full_res;1163 int32_t full_res;
993 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);1164 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
994 *res = (int8_t)full_res;1165 *res = zig_i8_intCast_i32(full_res);
995 return overflow;1166 return overflow;
996#endif1167#endif
997}1168}
...@@ -1000,12 +1171,12 @@ static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8...@@ -1000,12 +1171,12 @@ static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
1000#if zig_has_builtin(add_overflow) || defined(zig_gcc)1171#if zig_has_builtin(add_overflow) || defined(zig_gcc)
1001 uint16_t full_res;1172 uint16_t full_res;
1002 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1173 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);
1004 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);1175 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
1005#else1176#else
1006 uint32_t full_res;1177 uint32_t full_res;
1007 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);1178 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
1008 *res = (uint16_t)full_res;1179 *res = zig_u16_intCast_u32(full_res);
1009 return overflow;1180 return overflow;
1010#endif1181#endif
1011}1182}
...@@ -1014,27 +1185,28 @@ static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t...@@ -1014,27 +1185,28 @@ static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
1014#if zig_has_builtin(add_overflow) || defined(zig_gcc)1185#if zig_has_builtin(add_overflow) || defined(zig_gcc)
1015 int16_t full_res;1186 int16_t full_res;
1016 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1187 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);
1018 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);1189 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
1019#else1190#else
1020 int32_t full_res;1191 int32_t full_res;
1021 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);1192 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
1022 *res = (int16_t)full_res;1193 *res = zig_i16_intCast_i32(full_res);
1023 return overflow;1194 return overflow;
1024#endif1195#endif
1025}1196}
10261197
1027#if defined(zig_ez80)1198#if defined(zig_ez80)
1199
1028static inline bool zig_addo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {1200static inline bool zig_addo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {
1029#if zig_has_builtin(add_overflow) || defined(zig_gcc)1201#if zig_has_builtin(add_overflow) || defined(zig_gcc)
1030 uint24_t full_res;1202 uint24_t full_res;
1031 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1203 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);
1033 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);1205 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);
1034#else1206#else
1035 uint32_t full_res;1207 uint32_t full_res;
1036 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);1208 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
1037 *res = (uint24_t)full_res;1209 *res = zig_u24_intCast_u32(full_res);
1038 return overflow;1210 return overflow;
1039#endif1211#endif
1040}1212}
...@@ -1043,28 +1215,26 @@ static inline bool zig_addo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t...@@ -1043,28 +1215,26 @@ static inline bool zig_addo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t
1043#if zig_has_builtin(add_overflow) || defined(zig_gcc)1215#if zig_has_builtin(add_overflow) || defined(zig_gcc)
1044 int24_t full_res;1216 int24_t full_res;
1045 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1217 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);
1047 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);1219 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);
1048#else1220#else
1049 int32_t full_res;1221 int32_t full_res;
1050 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);1222 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
1051 *res = (int24_t)full_res;1223 *res = zig_i24_intCast_i32(full_res);
1052 return overflow;1224 return overflow;
1053#endif1225#endif
1054}1226}
1055#endif
10561227
1057#if defined(zig_ez80)
1058static inline bool zig_addo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {1228static inline bool zig_addo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {
1059#if zig_has_builtin(add_overflow) || defined(zig_gcc)1229#if zig_has_builtin(add_overflow) || defined(zig_gcc)
1060 uint48_t full_res;1230 uint48_t full_res;
1061 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1231 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);
1063 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);1233 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);
1064#else1234#else
1065 uint64_t full_res;1235 uint64_t full_res;
1066 bool overflow = zig_addo_u64(&full_res, lhs, rhs, bits);1236 bool overflow = zig_addo_u64(&full_res, lhs, rhs, bits);
1067 *res = (uint48_t)full_res;1237 *res = zig_u48_intCast_u64(full_res);
1068 return overflow;1238 return overflow;
1069#endif1239#endif
1070}1240}
...@@ -1073,22 +1243,23 @@ static inline bool zig_addo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t...@@ -1073,22 +1243,23 @@ static inline bool zig_addo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
1073#if zig_has_builtin(add_overflow) || defined(zig_gcc)1243#if zig_has_builtin(add_overflow) || defined(zig_gcc)
1074 int48_t full_res;1244 int48_t full_res;
1075 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1245 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);
1077 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);1247 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);
1078#else1248#else
1079 int64_t full_res;1249 int64_t full_res;
1080 bool overflow = zig_addo_i64(&full_res, lhs, rhs, bits);1250 bool overflow = zig_addo_i64(&full_res, lhs, rhs, bits);
1081 *res = (int48_t)full_res;1251 *res = zig_i48_intCast_i64(full_res);
1082 return overflow;1252 return overflow;
1083#endif1253#endif
1084}1254}
1255
1085#endif1256#endif
10861257
1087static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {1258static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
1088#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1259#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1089 uint32_t full_res;1260 uint32_t full_res;
1090 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1261 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);
1092 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);1263 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
1093#else1264#else
1094 *res = zig_subw_u32(lhs, rhs, bits);1265 *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...@@ -1100,20 +1271,19 @@ static inline bool zig_subo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t
1100#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1271#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1101 int32_t full_res;1272 int32_t full_res;
1102 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1273 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);
1103#else1276#else
1104 int32_t full_res = (int32_t)((uint32_t)lhs - (uint32_t)rhs);1277 *res = zig_subw_i32(lhs, rhs, bits);
1105 bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0;1278 return ((lhs ^ rhs) & (*res ^ lhs)) < INT32_C(0);
1106#endif1279#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);
1109}1280}
11101281
1111
1112static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {1282static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
1113#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1283#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1114 uint64_t full_res;1284 uint64_t full_res;
1115 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1285 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);
1117 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);1287 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
1118#else1288#else
1119 *res = zig_subw_u64(lhs, rhs, bits);1289 *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...@@ -1125,24 +1295,24 @@ static inline bool zig_subo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t
1125#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1295#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1126 int64_t full_res;1296 int64_t full_res;
1127 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1297 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);
1128#else1300#else
1129 int64_t full_res = (int64_t)((uint64_t)lhs - (uint64_t)rhs);1301 *res = zig_subw_i64(lhs, rhs, bits);
1130 bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0;1302 return ((lhs ^ rhs) & (*res ^ lhs)) < INT64_C(0);
1131#endif1303#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);
1134}1304}
11351305
1136static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {1306static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
1137#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1307#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1138 uint8_t full_res;1308 uint8_t full_res;
1139 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1309 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);
1141 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);1311 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
1142#else1312#else
1143 uint32_t full_res;1313 uint32_t full_res;
1144 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);1314 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
1145 *res = (uint8_t)full_res;1315 *res = zig_u8_intCast_u32(full_res);
1146 return overflow;1316 return overflow;
1147#endif1317#endif
1148}1318}
...@@ -1151,12 +1321,12 @@ static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits...@@ -1151,12 +1321,12 @@ static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
1151#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1321#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1152 int8_t full_res;1322 int8_t full_res;
1153 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1323 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);
1155 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);1325 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
1156#else1326#else
1157 int32_t full_res;1327 int32_t full_res;
1158 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);1328 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
1159 *res = (int8_t)full_res;1329 *res = zig_i8_intCast_i32(full_res);
1160 return overflow;1330 return overflow;
1161#endif1331#endif
1162}1332}
...@@ -1165,12 +1335,12 @@ static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8...@@ -1165,12 +1335,12 @@ static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
1165#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1335#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1166 uint16_t full_res;1336 uint16_t full_res;
1167 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1337 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);
1169 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);1339 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
1170#else1340#else
1171 uint32_t full_res;1341 uint32_t full_res;
1172 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);1342 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
1173 *res = (uint16_t)full_res;1343 *res = zig_u16_intCast_u32(full_res);
1174 return overflow;1344 return overflow;
1175#endif1345#endif
1176}1346}
...@@ -1179,27 +1349,28 @@ static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t...@@ -1179,27 +1349,28 @@ static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
1179#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1349#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1180 int16_t full_res;1350 int16_t full_res;
1181 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1351 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);
1183 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);1353 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
1184#else1354#else
1185 int32_t full_res;1355 int32_t full_res;
1186 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);1356 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
1187 *res = (int16_t)full_res;1357 *res = zig_i16_intCast_i32(full_res);
1188 return overflow;1358 return overflow;
1189#endif1359#endif
1190}1360}
11911361
1192#if defined(zig_ez80)1362#if defined(zig_ez80)
1363
1193static inline bool zig_subo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {1364static inline bool zig_subo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {
1194#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1365#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1195 uint24_t full_res;1366 uint24_t full_res;
1196 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1367 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);
1198 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);1369 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);
1199#else1370#else
1200 uint32_t full_res;1371 uint32_t full_res;
1201 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);1372 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
1202 *res = (uint24_t)full_res;1373 *res = zig_u24_intCast_u32(full_res);
1203 return overflow;1374 return overflow;
1204#endif1375#endif
1205}1376}
...@@ -1208,28 +1379,26 @@ static inline bool zig_subo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t...@@ -1208,28 +1379,26 @@ static inline bool zig_subo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t
1208#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1379#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1209 int24_t full_res;1380 int24_t full_res;
1210 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1381 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);
1212 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);1383 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);
1213#else1384#else
1214 int32_t full_res;1385 int32_t full_res;
1215 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);1386 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
1216 *res = (int24_t)full_res;1387 *res = zig_i24_intCast_i32(full_res);
1217 return overflow;1388 return overflow;
1218#endif1389#endif
1219}1390}
1220#endif
12211391
1222#if defined(zig_ez80)
1223static inline bool zig_subo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {1392static inline bool zig_subo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {
1224#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1393#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1225 uint48_t full_res;1394 uint48_t full_res;
1226 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1395 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);
1228 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);1397 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);
1229#else1398#else
1230 uint64_t full_res;1399 uint64_t full_res;
1231 bool overflow = zig_subo_u64(&full_res, lhs, rhs, bits);1400 bool overflow = zig_subo_u64(&full_res, lhs, rhs, bits);
1232 *res = (uint48_t)full_res;1401 *res = zig_u48_intCast_u64(full_res);
1233 return overflow;1402 return overflow;
1234#endif1403#endif
1235}1404}
...@@ -1238,22 +1407,23 @@ static inline bool zig_subo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t...@@ -1238,22 +1407,23 @@ static inline bool zig_subo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
1238#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1407#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1239 int48_t full_res;1408 int48_t full_res;
1240 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1409 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);
1242 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);1411 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);
1243#else1412#else
1244 int64_t full_res;1413 int64_t full_res;
1245 bool overflow = zig_subo_i64(&full_res, lhs, rhs, bits);1414 bool overflow = zig_subo_i64(&full_res, lhs, rhs, bits);
1246 *res = (int48_t)full_res;1415 *res = zig_i48_intCast_i64(full_res);
1247 return overflow;1416 return overflow;
1248#endif1417#endif
1249}1418}
1419
1250#endif1420#endif
12511421
1252static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {1422static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
1253#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1423#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1254 uint32_t full_res;1424 uint32_t full_res;
1255 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1425 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);
1257 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);1427 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
1258#else1428#else
1259 *res = zig_mulw_u32(lhs, rhs, bits);1429 *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...@@ -1261,8 +1431,8 @@ static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8
1261#endif1431#endif
1262}1432}
12631433
1264zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow);
1265static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) {1434static 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);
1266#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1436#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1267 int32_t full_res;1437 int32_t full_res;
1268 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1438 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...@@ -1271,7 +1441,7 @@ static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t
1271 int32_t full_res = __mulosi4(lhs, rhs, &overflow_int);1441 int32_t full_res = __mulosi4(lhs, rhs, &overflow_int);
1272 bool overflow = overflow_int != 0;1442 bool overflow = overflow_int != 0;
1273#endif1443#endif
1274 *res = zig_wrap_i32(full_res, bits);1444 *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);1445 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
1276}1446}
12771447
...@@ -1279,7 +1449,7 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8...@@ -1279,7 +1449,7 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8
1279#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1449#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1280 uint64_t full_res;1450 uint64_t full_res;
1281 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1451 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);
1283 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);1453 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
1284#else1454#else
1285 *res = zig_mulw_u64(lhs, rhs, bits);1455 *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...@@ -1287,8 +1457,8 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8
1287#endif1457#endif
1288}1458}
12891459
1290zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow);
1291static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) {1460static 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);
1292#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1462#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1293 int64_t full_res;1463 int64_t full_res;
1294 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1464 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...@@ -1297,7 +1467,7 @@ static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t
1297 int64_t full_res = __mulodi4(lhs, rhs, &overflow_int);1467 int64_t full_res = __mulodi4(lhs, rhs, &overflow_int);
1298 bool overflow = overflow_int != 0;1468 bool overflow = overflow_int != 0;
1299#endif1469#endif
1300 *res = zig_wrap_i64(full_res, bits);1470 *res = zig_i64_truncate_i64(full_res, bits);
1301 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);1471 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
1302}1472}
13031473
...@@ -1305,12 +1475,12 @@ static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b...@@ -1305,12 +1475,12 @@ static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b
1305#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1475#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1306 uint8_t full_res;1476 uint8_t full_res;
1307 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1477 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);
1309 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);1479 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
1310#else1480#else
1311 uint32_t full_res;1481 uint32_t full_res;
1312 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);1482 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
1313 *res = (uint8_t)full_res;1483 *res = zig_u8_intCast_u32(full_res);
1314 return overflow;1484 return overflow;
1315#endif1485#endif
1316}1486}
...@@ -1319,12 +1489,12 @@ static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits...@@ -1319,12 +1489,12 @@ static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
1319#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1489#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1320 int8_t full_res;1490 int8_t full_res;
1321 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1491 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);
1323 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);1493 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
1324#else1494#else
1325 int32_t full_res;1495 int32_t full_res;
1326 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);1496 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
1327 *res = (int8_t)full_res;1497 *res = zig_i8_intCast_i32(full_res);
1328 return overflow;1498 return overflow;
1329#endif1499#endif
1330}1500}
...@@ -1333,12 +1503,12 @@ static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8...@@ -1333,12 +1503,12 @@ static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
1333#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1503#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1334 uint16_t full_res;1504 uint16_t full_res;
1335 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1505 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);
1337 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);1507 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
1338#else1508#else
1339 uint32_t full_res;1509 uint32_t full_res;
1340 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);1510 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
1341 *res = (uint16_t)full_res;1511 *res = zig_u16_intCast_u32(full_res);
1342 return overflow;1512 return overflow;
1343#endif1513#endif
1344}1514}
...@@ -1347,27 +1517,28 @@ static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t...@@ -1347,27 +1517,28 @@ static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
1347#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1517#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1348 int16_t full_res;1518 int16_t full_res;
1349 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1519 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);
1351 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);1521 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
1352#else1522#else
1353 int32_t full_res;1523 int32_t full_res;
1354 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);1524 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
1355 *res = (int16_t)full_res;1525 *res = zig_i16_intCast_i32(full_res);
1356 return overflow;1526 return overflow;
1357#endif1527#endif
1358}1528}
13591529
1360#if defined(zig_ez80)1530#if defined(zig_ez80)
1531
1361static inline bool zig_mulo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {1532static inline bool zig_mulo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {
1362#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1533#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1363 uint24_t full_res;1534 uint24_t full_res;
1364 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1535 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);
1366 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);1537 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);
1367#else1538#else
1368 uint32_t full_res;1539 uint32_t full_res;
1369 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);1540 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
1370 *res = (uint24_t)full_res;1541 *res = zig_u24_intCast_u32(full_res);
1371 return overflow;1542 return overflow;
1372#endif1543#endif
1373}1544}
...@@ -1376,28 +1547,26 @@ static inline bool zig_mulo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t...@@ -1376,28 +1547,26 @@ static inline bool zig_mulo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t
1376#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1547#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1377 int24_t full_res;1548 int24_t full_res;
1378 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1549 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);
1380 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);1551 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);
1381#else1552#else
1382 int32_t full_res;1553 int32_t full_res;
1383 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);1554 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
1384 *res = (int24_t)full_res;1555 *res = zig_i24_intCast_i32(full_res);
1385 return overflow;1556 return overflow;
1386#endif1557#endif
1387}1558}
1388#endif
13891559
1390#if defined(zig_ez80)
1391static inline bool zig_mulo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {1560static inline bool zig_mulo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {
1392#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1561#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1393 uint48_t full_res;1562 uint48_t full_res;
1394 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1563 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);
1396 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);1565 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);
1397#else1566#else
1398 uint64_t full_res;1567 uint64_t full_res;
1399 bool overflow = zig_mulo_u64(&full_res, lhs, rhs, bits);1568 bool overflow = zig_mulo_u64(&full_res, lhs, rhs, bits);
1400 *res = (uint48_t)full_res;1569 *res = zig_u48_intCast_u64(full_res);
1401 return overflow;1570 return overflow;
1402#endif1571#endif
1403}1572}
...@@ -1406,18 +1575,32 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t...@@ -1406,18 +1575,32 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
1406#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1575#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1407 int48_t full_res;1576 int48_t full_res;
1408 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1577 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);
1410 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);1579 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);
1411#else1580#else
1412 int64_t full_res;1581 int64_t full_res;
1413 bool overflow = zig_mulo_i64(&full_res, lhs, rhs, bits);1582 bool overflow = zig_mulo_i64(&full_res, lhs, rhs, bits);
1414 *res = (int48_t)full_res;1583 *res = zig_i48_intCast_i64(full_res);
1415 return overflow;1584 return overflow;
1416#endif1585#endif
1417}1586}
1587
1418#endif1588#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) \
1421 static inline bool zig_shlo_u##w(uint##w##_t *res, uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \1604 static inline bool zig_shlo_u##w(uint##w##_t *res, uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \
1422 *res = zig_shlw_u##w(lhs, rhs, bits); \1605 *res = zig_shlw_u##w(lhs, rhs, bits); \
1423 return lhs > zig_maxInt_u(w, bits) >> rhs; \1606 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...@@ -1429,18 +1612,10 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
1429 return (lhs & mask) != INT##w##_C(0) && (lhs & mask) != mask; \1612 return (lhs & mask) != INT##w##_C(0) && (lhs & mask) != mask; \
1430 } \1613 } \
1431\1614\
1432 static inline uint##w##_t zig_shls_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \1615 zig_shls_builtins(w, 8) \
1433 uint##w##_t res; \1616 zig_shls_builtins(w, 16) \
1434 if (rhs < bits && !zig_shlo_u##w(&res, lhs, rhs, bits)) return res; \1617 zig_shls_builtins(w, 32) \
1435 return lhs == INT##w##_C(0) ? INT##w##_C(0) : zig_maxInt_u(w, bits); \1618 zig_shls_builtins(w, 64) \
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 } \
1444\1619\
1445 static inline uint##w##_t zig_adds_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \1620 static inline uint##w##_t zig_adds_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
1446 uint##w##_t res; \1621 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...@@ -1474,332 +1649,321 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
1474 if (!zig_mulo_i##w(&res, lhs, rhs, bits)) return res; \1649 if (!zig_mulo_i##w(&res, lhs, rhs, bits)) return res; \
1475 return (lhs ^ rhs) < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \1650 return (lhs ^ rhs) < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \
1476 }1651 }
1477zig_int_builtins(8)1652zig_int_sat_builtins(8)
1478zig_int_builtins(16)1653zig_int_sat_builtins(16)
1479#if defined(zig_ez80)1654zig_int_sat_builtins(32)
1480zig_int_builtins(24)1655zig_int_sat_builtins(64)
1481#endif
1482zig_int_builtins(32)
1483#if defined(zig_ez80)1656#if defined(zig_ez80)
1484zig_int_builtins(48)1657zig_int_sat_builtins(24)
1658zig_int_sat_builtins(48)
1485#endif1659#endif
1486zig_int_builtins(64)
14871660
1488#define zig_builtin8(name, val) __builtin_##name(val)1661#define zig_builtin8(name, arg) __builtin_##name(arg)
1489typedef unsigned int zig_Builtin8;1662typedef unsigned int zig_Builtin8;
14901663
1491#define zig_builtin16(name, val) __builtin_##name(val)1664#define zig_builtin16(name, arg) __builtin_##name(arg)
1492typedef unsigned int zig_Builtin16;1665typedef 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
1499#if INT_MIN <= INT32_MIN1667#if INT_MIN <= INT32_MIN
1500#define zig_builtin32(name, val) __builtin_##name(val)1668#define zig_builtin32(name, arg) __builtin_##name(arg)
1501typedef unsigned int zig_Builtin32;1669typedef unsigned int zig_Builtin32;
1502#elif LONG_MIN <= INT32_MIN1670#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)
1504typedef unsigned long zig_Builtin32;1672typedef unsigned long zig_Builtin32;
1505#endif1673#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
1512#if INT_MIN <= INT64_MIN1675#if INT_MIN <= INT64_MIN
1513#define zig_builtin64(name, val) __builtin_##name(val)1676#define zig_builtin64(name, arg) __builtin_##name(arg)
1514typedef unsigned int zig_Builtin64;1677typedef unsigned int zig_Builtin64;
1515#elif LONG_MIN <= INT64_MIN1678#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)
1517typedef unsigned long zig_Builtin64;1680typedef unsigned long zig_Builtin64;
1518#elif LLONG_MIN <= INT64_MIN1681#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)
1520typedef unsigned long long zig_Builtin64;1683typedef unsigned long long zig_Builtin64;
1521#endif1684#endif
15221685
1523static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) {1686#if defined(zig_ez80)
1524 return zig_wrap_u8(val >> (8 - bits), bits);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);
1525}1695}
15261696
1527static inline int8_t zig_byte_swap_i8(int8_t val, uint8_t bits) {1697static inline int8_t zig_byteSwap_i8(int8_t arg, uint8_t bits) {
1528 return zig_wrap_i8((int8_t)zig_byte_swap_u8((uint8_t)val, bits), bits);1698 return zig_i8_truncate_i8((int8_t)zig_byteSwap_u8((uint8_t)arg, bits), bits);
1529}1699}
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) {
1532 uint16_t full_res;1702 uint16_t full_res;
1533#if zig_has_builtin(bswap16) || defined(zig_gcc)1703#if zig_has_builtin(bswap16) || defined(zig_gcc)
1534 full_res = __builtin_bswap16(val);1704 full_res = __builtin_bswap16(arg);
1535#else1705#else
1536 full_res = (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 8 |1706 full_res = (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 8 |
1537 (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 8), 8) >> 0;1707 (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 8), 8) >> 0;
1538#endif1708#endif
1539 return zig_wrap_u16(full_res >> (16 - bits), bits);1709 return zig_u16_truncate_u16(full_res >> (16 - bits), bits);
1540}1710}
15411711
1542static inline int16_t zig_byte_swap_i16(int16_t val, uint8_t bits) {1712static inline int16_t zig_byteSwap_i16(int16_t arg, uint8_t bits) {
1543 return zig_wrap_i16((int16_t)zig_byte_swap_u16((uint16_t)val, bits), bits);1713 return zig_i16_truncate_i16((int16_t)zig_byteSwap_u16((uint16_t)arg, bits), bits);
1544}1714}
15451715
1546#if defined(zig_ez80)1716#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) {
1548 uint24_t full_res;1718 uint24_t full_res;
1549#if zig_has_builtin(bswap24) || defined(zig_gcc)1719#if zig_has_builtin(bswap24) || defined(zig_gcc)
1550 full_res = __builtin_bswap24(val);1720 full_res = __builtin_bswap24(arg);
1551#else1721#else
1552 full_res = (uint24_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 16 |1722 full_res = (uint24_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 16 |
1553 (uint24_t)zig_byte_swap_u16((uint16_t)(val >> 8), 16) >> 0;1723 (uint24_t)zig_byteSwap_u16((uint16_t)(arg >> 8), 16) >> 0;
1554#endif1724#endif
1555 return zig_wrap_u24(full_res >> (24 - bits), bits);1725 return zig_u24_truncate_u24(full_res >> (24 - bits), bits);
1556}1726}
15571727
1558static inline int16_t zig_byte_swap_i24(int24_t val, uint8_t bits) {1728static inline int16_t zig_byteSwap_i24(int24_t arg, uint8_t bits) {
1559 return zig_wrap_i24((int24_t)zig_byte_swap_u24((uint24_t)val, bits), bits);1729 return zig_i24_truncate_i24((int24_t)zig_byteSwap_u24((uint24_t)arg, bits), bits);
1560}1730}
1561#endif1731#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) {
1564 uint32_t full_res;1734 uint32_t full_res;
1565#if zig_has_builtin(bswap32) || defined(zig_gcc)1735#if zig_has_builtin(bswap32) || defined(zig_gcc)
1566 full_res = __builtin_bswap32(val);1736 full_res = __builtin_bswap32(arg);
1567#else1737#else
1568 full_res = (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 0), 16) << 16 |1738 full_res = (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 0), 16) << 16 |
1569 (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 16), 16) >> 0;1739 (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 16), 16) >> 0;
1570#endif1740#endif
1571 return zig_wrap_u32(full_res >> (32 - bits), bits);1741 return zig_u32_truncate_u32(full_res >> (32 - bits), bits);
1572}1742}
15731743
1574static inline int32_t zig_byte_swap_i32(int32_t val, uint8_t bits) {1744static inline int32_t zig_byteSwap_i32(int32_t arg, uint8_t bits) {
1575 return zig_wrap_i32((int32_t)zig_byte_swap_u32((uint32_t)val, bits), bits);1745 return zig_i32_truncate_i32((int32_t)zig_byteSwap_u32((uint32_t)arg, bits), bits);
1576}1746}
15771747
1578#if defined(zig_ez80)1748#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) {
1580 uint48_t full_res;1750 uint48_t full_res;
1581#if zig_has_builtin(bswap48) || defined(zig_gcc)1751#if zig_has_builtin(bswap48) || defined(zig_gcc)
1582 full_res = __builtin_bswap48(val);1752 full_res = __builtin_bswap48(arg);
1583#else1753#else
1584 full_res = (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 0), 24) << 24 |1754 full_res = (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 0), 24) << 24 |
1585 (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 24), 24) >> 0;1755 (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 24), 24) >> 0;
1586#endif1756#endif
1587 return zig_wrap_u48(full_res >> (48 - bits), bits);1757 return zig_u48_truncate_u48(full_res >> (48 - bits), bits);
1588}1758}
15891759
1590static inline int32_t zig_byte_swap_i48(int48_t val, uint8_t bits) {1760static inline int32_t zig_byteSwap_i48(int48_t arg, uint8_t bits) {
1591 return zig_wrap_i48((int48_t)zig_byte_swap_u48((uint48_t)val, bits), bits);1761 return zig_i48_truncate_i48((int48_t)zig_byteSwap_u48((uint48_t)arg, bits), bits);
1592}1762}
1593#endif1763#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) {
1596 uint64_t full_res;1766 uint64_t full_res;
1597#if zig_has_builtin(bswap64) || defined(zig_gcc)1767#if zig_has_builtin(bswap64) || defined(zig_gcc)
1598 full_res = __builtin_bswap64(val);1768 full_res = __builtin_bswap64(arg);
1599#else1769#else
1600 full_res = (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 0), 32) << 32 |1770 full_res = (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 0), 32) << 32 |
1601 (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 32), 32) >> 0;1771 (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 32), 32) >> 0;
1602#endif1772#endif
1603 return zig_wrap_u64(full_res >> (64 - bits), bits);1773 return zig_u64_truncate_u64(full_res >> (64 - bits), bits);
1604}1774}
16051775
1606static inline int64_t zig_byte_swap_i64(int64_t val, uint8_t bits) {1776static inline int64_t zig_byteSwap_i64(int64_t arg, uint8_t bits) {
1607 return zig_wrap_i64((int64_t)zig_byte_swap_u64((uint64_t)val, bits), bits);1777 return zig_i64_truncate_i64((int64_t)zig_byteSwap_u64((uint64_t)arg, bits), bits);
1608}1778}
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) {
1611 uint8_t full_res;1781 uint8_t full_res;
1612#if zig_has_builtin(bitreverse8)1782#if zig_has_builtin(bitreverse8)
1613 full_res = __builtin_bitreverse8(val);1783 full_res = __builtin_bitreverse8(arg);
1614#else1784#else
1615 static uint8_t const lut[0x10] = {1785 static uint8_t const lut[0x10] = {
1616 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,1786 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
1617 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf1787 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
1618 };1788 };
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;
1620#endif1790#endif
1621 return zig_wrap_u8(full_res >> (8 - bits), bits);1791 return zig_u8_truncate_u8(full_res >> (8 - bits), bits);
1622}1792}
16231793
1624static inline int8_t zig_bit_reverse_i8(int8_t val, uint8_t bits) {1794static inline int8_t zig_bitReverse_i8(int8_t arg, uint8_t bits) {
1625 return zig_wrap_i8((int8_t)zig_bit_reverse_u8((uint8_t)val, bits), bits);1795 return zig_i8_truncate_i8((int8_t)zig_bitReverse_u8((uint8_t)arg, bits), bits);
1626}1796}
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) {
1629 uint16_t full_res;1799 uint16_t full_res;
1630#if zig_has_builtin(bitreverse16)1800#if zig_has_builtin(bitreverse16)
1631 full_res = __builtin_bitreverse16(val);1801 full_res = __builtin_bitreverse16(arg);
1632#else1802#else
1633 full_res = (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 8 |1803 full_res = (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 8 |
1634 (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 8), 8) >> 0;1804 (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 8), 8) >> 0;
1635#endif1805#endif
1636 return zig_wrap_u16(full_res >> (16 - bits), bits);1806 return zig_u16_truncate_u16(full_res >> (16 - bits), bits);
1637}1807}
16381808
1639static inline int16_t zig_bit_reverse_i16(int16_t val, uint8_t bits) {1809static inline int16_t zig_bitReverse_i16(int16_t arg, uint8_t bits) {
1640 return zig_wrap_i16((int16_t)zig_bit_reverse_u16((uint16_t)val, bits), bits);1810 return zig_i16_truncate_i16((int16_t)zig_bitReverse_u16((uint16_t)arg, bits), bits);
1641}1811}
16421812
1643#if defined(zig_ez80)1813#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) {
1645 uint24_t full_res;1815 uint24_t full_res;
1646#if zig_has_builtin(bitreverse24)1816#if zig_has_builtin(bitreverse24)
1647 full_res = __builtin_bitreverse24(val);1817 full_res = __builtin_bitreverse24(arg);
1648#else1818#else
1649 full_res = (uint24_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 16 |1819 full_res = (uint24_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 16 |
1650 (uint24_t)zig_bit_reverse_u16((uint16_t)(val >> 8), 16) >> 0;1820 (uint24_t)zig_bitReverse_u16((uint16_t)(arg >> 8), 16) >> 0;
1651#endif1821#endif
1652 return zig_wrap_u24(full_res >> (24 - bits), bits);1822 return zig_u24_truncate_u24(full_res >> (24 - bits), bits);
1653}1823}
16541824
1655static inline int24_t zig_bit_reverse_i24(int24_t val, uint8_t bits) {1825static inline int24_t zig_bitReverse_i24(int24_t arg, uint8_t bits) {
1656 return zig_wrap_i24((int24_t)zig_bit_reverse_u24((uint24_t)val, bits), bits);1826 return zig_i24_truncate_i24((int24_t)zig_bitReverse_u24((uint24_t)arg, bits), bits);
1657}1827}
1658#endif1828#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) {
1661 uint32_t full_res;1831 uint32_t full_res;
1662#if zig_has_builtin(bitreverse32)1832#if zig_has_builtin(bitreverse32)
1663 full_res = __builtin_bitreverse32(val);1833 full_res = __builtin_bitreverse32(arg);
1664#else1834#else
1665 full_res = (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 0), 16) << 16 |1835 full_res = (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 0), 16) << 16 |
1666 (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 16), 16) >> 0;1836 (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 16), 16) >> 0;
1667#endif1837#endif
1668 return zig_wrap_u32(full_res >> (32 - bits), bits);1838 return zig_u32_truncate_u32(full_res >> (32 - bits), bits);
1669}1839}
16701840
1671static inline int32_t zig_bit_reverse_i32(int32_t val, uint8_t bits) {1841static inline int32_t zig_bitReverse_i32(int32_t arg, uint8_t bits) {
1672 return zig_wrap_i32((int32_t)zig_bit_reverse_u32((uint32_t)val, bits), bits);1842 return zig_i32_truncate_i32((int32_t)zig_bitReverse_u32((uint32_t)arg, bits), bits);
1673}1843}
16741844
1675#if defined(zig_ez80)1845#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) {
1677 uint48_t full_res;1847 uint48_t full_res;
1678#if zig_has_builtin(bitreverse48)1848#if zig_has_builtin(bitreverse48)
1679 full_res = __builtin_bitreverse48(val);1849 full_res = __builtin_bitreverse48(arg);
1680#else1850#else
1681 full_res = (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 0), 24) << 24 |1851 full_res = (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 0), 24) << 24 |
1682 (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 24), 24) >> 0;1852 (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 24), 24) >> 0;
1683#endif1853#endif
1684 return zig_wrap_u32(full_res >> (48 - bits), bits);1854 return zig_u48_truncate_u48(full_res >> (48 - bits), bits);
1685}1855}
16861856
1687static inline int32_t zig_bit_reverse_i48(int48_t val, uint8_t bits) {1857static inline int32_t zig_bitReverse_i48(int48_t arg, uint8_t bits) {
1688 return zig_wrap_i48((int48_t)zig_bit_reverse_u48((uint48_t)val, bits), bits);1858 return zig_i48_truncate_i48((int48_t)zig_bitReverse_u48((uint48_t)arg, bits), bits);
1689}1859}
1690#endif1860#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) {
1693 uint64_t full_res;1863 uint64_t full_res;
1694#if zig_has_builtin(bitreverse64)1864#if zig_has_builtin(bitreverse64)
1695 full_res = __builtin_bitreverse64(val);1865 full_res = __builtin_bitreverse64(arg);
1696#else1866#else
1697 full_res = (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 0), 32) << 32 |1867 full_res = (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 0), 32) << 32 |
1698 (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 32), 32) >> 0;1868 (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 32), 32) >> 0;
1699#endif1869#endif
1700 return zig_wrap_u64(full_res >> (64 - bits), bits);1870 return zig_u64_truncate_u64(full_res >> (64 - bits), bits);
1701}1871}
17021872
1703static inline int64_t zig_bit_reverse_i64(int64_t val, uint8_t bits) {1873static inline int64_t zig_bitReverse_i64(int64_t arg, uint8_t bits) {
1704 return zig_wrap_i64((int64_t)zig_bit_reverse_u64((uint64_t)val, bits), bits);1874 return zig_i64_truncate_i64((int64_t)zig_bitReverse_u64((uint64_t)arg, bits), bits);
1705}1875}
17061876
1707#define zig_builtin_popcount_common(w) \1877#define zig_builtin_popCount_common(w) \
1708 static inline uint8_t zig_popcount_i##w(int##w##_t val, uint8_t bits) { \1878 static inline uint8_t zig_popCount_i##w(int##w##_t arg, uint8_t bits) { \
1709 return zig_popcount_u##w((uint##w##_t)val, bits); \1879 return zig_popCount_u##w((uint##w##_t)arg, bits); \
1710 }1880 }
1711#if zig_has_builtin(popcount) || defined(zig_gcc) || defined(zig_tinyc)1881#if zig_has_builtin(popCount) || defined(zig_gcc) || defined(zig_tinyc)
1712#define zig_builtin_popcount(w) \1882#define zig_builtin_popCount(w) \
1713 static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \1883 static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \
1714 (void)bits; \1884 (void)bits; \
1715 return zig_builtin##w(popcount, val); \1885 return zig_builtin##w(popcount, arg); \
1716 } \1886 } \
1717\1887\
1718 zig_builtin_popcount_common(w)1888 zig_builtin_popCount_common(w)
1719#else1889#else
1720#define zig_builtin_popcount(w) \1890#define zig_builtin_popCount(w) \
1721 static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \1891 static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \
1722 (void)bits; \1892 (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)); \
1724 temp = (temp & (UINT##w##_MAX / 5)) + ((temp >> 2) & (UINT##w##_MAX / 5)); \1894 temp = (temp & (UINT##w##_MAX / 5)) + ((temp >> 2) & (UINT##w##_MAX / 5)); \
1725 temp = (temp + (temp >> 4)) & (UINT##w##_MAX / 17); \1895 temp = (temp + (temp >> 4)) & (UINT##w##_MAX / 17); \
1726 return temp * (UINT##w##_MAX / 255) >> (UINT8_C(w) - UINT8_C(8)); \1896 return temp * (UINT##w##_MAX / 255) >> (UINT8_C(w) - UINT8_C(8)); \
1727 } \1897 } \
1728\1898\
1729 zig_builtin_popcount_common(w)1899 zig_builtin_popCount_common(w)
1730#endif
1731zig_builtin_popcount(8)
1732zig_builtin_popcount(16)
1733#if defined(zig_ez80)
1734zig_builtin_popcount(24)
1735#endif1900#endif
1736zig_builtin_popcount(32)1901zig_builtin_popCount(8)
1902zig_builtin_popCount(16)
1903zig_builtin_popCount(32)
1904zig_builtin_popCount(64)
1737#if defined(zig_ez80)1905#if defined(zig_ez80)
1738zig_builtin_popcount(48)1906zig_builtin_popCount(24)
1907zig_builtin_popCount(48)
1739#endif1908#endif
1740zig_builtin_popcount(64)
17411909
1742#define zig_builtin_ctz_common(w) \1910#define zig_builtin_ctz_common(w) \
1743 static inline uint8_t zig_ctz_i##w(int##w##_t val, uint8_t bits) { \1911 static inline uint8_t zig_ctz_i##w(int##w##_t arg, uint8_t bits) { \
1744 return zig_ctz_u##w((uint##w##_t)val, bits); \1912 return zig_ctz_u##w((uint##w##_t)arg, bits); \
1745 }1913 }
1746#if zig_has_builtin(ctz) || defined(zig_gcc) || defined(zig_tinyc)1914#if zig_has_builtin(ctz) || defined(zig_gcc) || defined(zig_tinyc)
1747#define zig_builtin_ctz(w) \1915#define zig_builtin_ctz(w) \
1748 static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \1916 static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \
1749 if (val == 0) return bits; \1917 if (arg == 0) return bits; \
1750 return zig_builtin##w(ctz, val); \1918 return zig_builtin##w(ctz, arg); \
1751 } \1919 } \
1752\1920\
1753 zig_builtin_ctz_common(w)1921 zig_builtin_ctz_common(w)
1754#else1922#else
1755#define zig_builtin_ctz(w) \1923#define zig_builtin_ctz(w) \
1756 static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \1924 static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \
1757 return zig_popcount_u##w(zig_not_u##w(val, bits) & zig_subw_u##w(val, 1, bits), bits); \1925 return zig_popCount_u##w(zig_not_u##w(arg, bits) & zig_subw_u##w(arg, 1, bits), bits); \
1758 } \1926 } \
1759\1927\
1760 zig_builtin_ctz_common(w)1928 zig_builtin_ctz_common(w)
1761#endif1929#endif
1762zig_builtin_ctz(8)1930zig_builtin_ctz(8)
1763zig_builtin_ctz(16)1931zig_builtin_ctz(16)
1764#if defined(zig_ez80)
1765zig_builtin_ctz(24)
1766#endif
1767zig_builtin_ctz(32)1932zig_builtin_ctz(32)
1933zig_builtin_ctz(64)
1768#if defined(zig_ez80)1934#if defined(zig_ez80)
1935zig_builtin_ctz(24)
1769zig_builtin_ctz(48)1936zig_builtin_ctz(48)
1770#endif1937#endif
1771zig_builtin_ctz(64)
17721938
1773#define zig_builtin_clz_common(w) \1939#define zig_builtin_clz_common(w) \
1774 static inline uint8_t zig_clz_i##w(int##w##_t val, uint8_t bits) { \1940 static inline uint8_t zig_clz_i##w(int##w##_t arg, uint8_t bits) { \
1775 return zig_clz_u##w((uint##w##_t)val, bits); \1941 return zig_clz_u##w((uint##w##_t)arg, bits); \
1776 }1942 }
1777#if zig_has_builtin(clz) || defined(zig_gcc) || defined(zig_tinyc)1943#if zig_has_builtin(clz) || defined(zig_gcc) || defined(zig_tinyc)
1778#define zig_builtin_clz(w) \1944#define zig_builtin_clz(w) \
1779 static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \1945 static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \
1780 if (val == 0) return bits; \1946 if (arg == 0) return bits; \
1781 return zig_builtin##w(clz, val) - (zig_bitSizeOf(zig_Builtin##w) - bits); \1947 return zig_builtin##w(clz, arg) - (zig_bitSizeOf(zig_Builtin##w) - bits); \
1782 } \1948 } \
1783\1949\
1784 zig_builtin_clz_common(w)1950 zig_builtin_clz_common(w)
1785#else1951#else
1786#define zig_builtin_clz(w) \1952#define zig_builtin_clz(w) \
1787 static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \1953 static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \
1788 return zig_ctz_u##w(zig_bit_reverse_u##w(val, bits), bits); \1954 return zig_ctz_u##w(zig_bitReverse_u##w(arg, bits), bits); \
1789 } \1955 } \
1790\1956\
1791 zig_builtin_clz_common(w)1957 zig_builtin_clz_common(w)
1792#endif1958#endif
1793zig_builtin_clz(8)1959zig_builtin_clz(8)
1794zig_builtin_clz(16)1960zig_builtin_clz(16)
1795#if defined(zig_ez80)
1796zig_builtin_clz(24)
1797#endif
1798zig_builtin_clz(32)1961zig_builtin_clz(32)
1962zig_builtin_clz(64)
1799#if defined(zig_ez80)1963#if defined(zig_ez80)
1964zig_builtin_clz(24)
1800zig_builtin_clz(48)1965zig_builtin_clz(48)
1801#endif1966#endif
1802zig_builtin_clz(64)
18031967
1804/* ======================== 128-bit Integer Support ========================= */1968/* ======================== 128-bit Integer Support ========================= */
18051969
...@@ -1816,16 +1980,14 @@ zig_builtin_clz(64)...@@ -1816,16 +1980,14 @@ zig_builtin_clz(64)
1816typedef unsigned __int128 zig_u128;1980typedef unsigned __int128 zig_u128;
1817typedef signed __int128 zig_i128;1981typedef signed __int128 zig_i128;
18181982
1819#define zig_make_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))1983#define zig_init_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))
1820#define zig_make_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo))1984#define zig_init_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo))
1821#define zig_init_u128(hi, lo) zig_make_u128(hi, lo)1985#define zig_make_u128(hi, lo) zig_init_u128(hi, lo)
1822#define zig_init_i128(hi, lo) zig_make_i128(hi, lo)1986#define zig_make_i128(hi, lo) zig_init_i128(hi, lo)
1823#define zig_hi_u128(val) ((uint64_t)((val) >> 64))1987#define zig_hi_u128(arg) ((uint64_t)((arg) >> 64))
1824#define zig_lo_u128(val) ((uint64_t)((val) >> 0))1988#define zig_lo_u128(arg) ((uint64_t)((arg) >> 0))
1825#define zig_hi_i128(val) (( int64_t)((val) >> 64))1989#define zig_hi_i128(arg) (( int64_t)((arg) >> 64))
1826#define zig_lo_i128(val) ((uint64_t)((val) >> 0))1990#define zig_lo_i128(arg) ((uint64_t)((arg) >> 0))
1827#define zig_bitCast_u128(val) ((zig_u128)(val))
1828#define zig_bitCast_i128(val) ((zig_i128)(val))
1829#define zig_cmp_int128(Type) \1991#define zig_cmp_int128(Type) \
1830 static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \1992 static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
1831 return (lhs > rhs) - (lhs < rhs); \1993 return (lhs > rhs) - (lhs < rhs); \
...@@ -1835,32 +1997,49 @@ typedef signed __int128 zig_i128;...@@ -1835,32 +1997,49 @@ typedef signed __int128 zig_i128;
1835 return lhs operator rhs; \1997 return lhs operator rhs; \
1836 }1998 }
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_endian2004static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
1841typedef struct { zig_align(16) uint64_t lo; uint64_t hi; } zig_u128;2005 return lhs >> rhs;
1842typedef struct { zig_align(16) uint64_t lo; int64_t hi; } zig_i128;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;
1843#else2019#else
1844typedef struct { zig_align(16) uint64_t hi; uint64_t lo; } zig_u128;2020 zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0);
1845typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;2021 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask;
1846#endif2022#endif
2023}
18472024
1848#define zig_make_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) })2025#else /* zig_has_int128 */
1849#define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) })
18502026
1851#if defined(zig_msvc) /* MSVC doesn't allow struct literals in constant expressions */2027#if zig_little_endian
1852#define zig_init_u128(hi, lo) { .h##i = (hi), .l##o = (lo) }2028typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; uint64_t hi; } zig_u128;
1853#define zig_init_i128(hi, lo) { .h##i = (hi), .l##o = (lo) }2029typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; int64_t hi; } zig_i128;
1854#else /* But non-MSVC doesn't like the unprotected commas */2030#else
1855#define zig_init_u128(hi, lo) zig_make_u128(hi, lo)2031typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t hi; uint64_t lo; } zig_u128;
1856#define zig_init_i128(hi, lo) zig_make_i128(hi, lo)2032typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) int64_t hi; uint64_t lo; } zig_i128;
1857#endif2033#endif
1858#define zig_hi_u128(val) ((val).hi)2034
1859#define zig_lo_u128(val) ((val).lo)2035#define zig_init_u128(hi, lo) { .h##i = hi, .l##o = lo }
1860#define zig_hi_i128(val) ((val).hi)2036#define zig_init_i128(hi, lo) { .h##i = hi, .l##o = lo }
1861#define zig_lo_i128(val) ((val).lo)2037#define zig_make_u128(hi, lo) (zig_u128)zig_init_u128(hi, lo)
1862#define zig_bitCast_u128(val) zig_make_u128((uint64_t)(val).hi, (val).lo)2038#define zig_make_i128(hi, lo) (zig_i128)zig_init_i128(hi, lo)
1863#define zig_bitCast_i128(val) zig_make_i128(( int64_t)(val).hi, (val).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
1864#define zig_cmp_int128(Type) \2043#define zig_cmp_int128(Type) \
1865 static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \2044 static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
1866 return (lhs.hi == rhs.hi) \2045 return (lhs.hi == rhs.hi) \
...@@ -1872,6 +2051,30 @@ typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;...@@ -1872,6 +2051,30 @@ typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;
1872 return (zig_##Type){ .hi = lhs.hi operator rhs.hi, .lo = lhs.lo operator rhs.lo }; \2051 return (zig_##Type){ .hi = lhs.hi operator rhs.hi, .lo = lhs.lo operator rhs.lo }; \
1873 }2052 }
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
1875#endif /* zig_has_int128 */2078#endif /* zig_has_int128 */
18762079
1877#define zig_minInt_u128 zig_make_u128(zig_minInt_u64, zig_minInt_u64)2080#define zig_minInt_u128 zig_make_u128(zig_minInt_u64, zig_minInt_u64)
...@@ -1891,42 +2094,177 @@ zig_bit_int128(i128, or, |)...@@ -1891,42 +2094,177 @@ zig_bit_int128(i128, or, |)
1891zig_bit_int128(u128, xor, ^)2094zig_bit_int128(u128, xor, ^)
1892zig_bit_int128(i128, xor, ^)2095zig_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_int1282110static 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) {2123static inline uint32_t zig_u32_intCast_u128(zig_u128 arg) {
1899 return val ^ zig_maxInt_u(128, bits);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);
1900}2134}
19012135
1902static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) {2136static inline uint64_t zig_u64_intCast_u128(zig_u128 arg) {
1903 (void)bits;2137 return zig_lo_u128(arg);
1904 return ~val;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);
1905}2147}
19062148
1907static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {2149static inline zig_u128 zig_u128_intCast_u8(uint8_t arg) {
1908 return lhs >> rhs;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);
1909}2160}
19102161
1911static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {2162static inline zig_u128 zig_u128_intCast_u16(uint16_t arg) {
1912 return lhs << rhs;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);
1913}2173}
19142174
1915static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {2175static inline zig_u128 zig_u128_intCast_u32(uint32_t arg) {
1916 // This works around a GCC miscompilation, but it has the side benefit of2176 return zig_make_u128(UINT32_C(0), arg);
1917 // emitting better code. It is behind the `#if` because it depends on2177}
1918 // arithmetic right shift, which is implementation-defined in C, but should2178static inline zig_u128 zig_u128_intCast_i32(int32_t arg) {
1919 // be guaranteed on any GCC-compatible compiler.2179 return zig_make_u128(UINT32_C(0), (uint32_t)arg);
1920#if defined(zig_gnuc)2180}
1921 return lhs >> rhs;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;
1922#else2207#else
1923 zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0);2208 return zig_make_u128(zig_u64_bitCast_i64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg));
1924 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask;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));
1925#endif2219#endif
1926}2220}
19272221
1928static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {2222#define zig_int128_cast_builtins(w) \
1929 return lhs << rhs;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;
1930}2268}
19312269
1932static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) {2270static 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) {...@@ -1953,11 +2291,11 @@ static inline zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {
1953 return lhs * rhs;2291 return lhs * rhs;
1954}2292}
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) {
1957 return lhs / rhs;2295 return lhs / rhs;
1958}2296}
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) {
1961 return lhs / rhs;2299 return lhs / rhs;
1962}2300}
19632301
...@@ -1971,36 +2309,14 @@ static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {...@@ -1971,36 +2309,14 @@ static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
19712309
1972#else /* zig_has_int128 */2310#else /* zig_has_int128 */
19732311
1974static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) {2312static inline zig_u128 zig_not_u128(zig_u128 arg, 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)) };2313 if (bits <= UINT8_C(64)) return (zig_u128){ .hi = UINT64_C(0), .lo = zig_not_u64(arg.lo, bits) };
1976}2314 return (zig_u128){ .hi = zig_not_u64(arg.hi, bits - UINT8_C(64)), .lo = zig_not_u64(arg.lo, UINT8_C(64)) };
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) };
1998}2315}
19992316
2000static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {2317static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) {
2001 if (rhs == UINT8_C(0)) return lhs;2318 (void)bits;
2002 if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };2319 return (zig_i128){ .hi = ~arg.hi, .lo = ~arg.lo };
2003 return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
2004}2320}
20052321
2006static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) {2322static 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) {...@@ -2027,59 +2343,59 @@ static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) {
2027 return res;2343 return res;
2028}2344}
20292345
2030zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs);
2031static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {2346static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {
2347 zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs);
2032 return __multi3(lhs, rhs);2348 return __multi3(lhs, rhs);
2033}2349}
20342350
2035static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) {2351static 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));
2037}2353}
20382354
2039zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs);2355static zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) {
2040static zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) {2356 zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs);
2041 return __udivti3(lhs, rhs);2357 return __udivti3(lhs, rhs);
2042}2358}
20432359
2044zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs);2360static zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) {
2045static zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) {2361 zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs);
2046 return __divti3(lhs, rhs);2362 return __divti3(lhs, rhs);
2047}2363}
20482364
2049zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs);
2050static zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) {2365static zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) {
2366 zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs);
2051 return __umodti3(lhs, rhs);2367 return __umodti3(lhs, rhs);
2052}2368}
20532369
2054zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs);
2055static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {2370static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
2371 zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs);
2056 return __modti3(lhs, rhs);2372 return __modti3(lhs, rhs);
2057}2373}
20582374
2059#endif /* zig_has_int128 */2375#endif /* zig_has_int128 */
20602376
2061#define zig_div_floor_u128 zig_div_trunc_u1282377#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) {
2064 zig_i128 rem = zig_rem_i128(lhs, rhs);2380 zig_i128 rem = zig_rem_i128(lhs, rhs);
2065 int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0)2381 int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0)
2066 ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) : INT64_C(0);2382 ? 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));
2068}2384}
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) {
2071 zig_u128 rem = zig_rem_u128(lhs, rhs);2387 zig_u128 rem = zig_rem_u128(lhs, rhs);
2072 uint64_t mask = zig_or_u64(zig_hi_u128(rem), zig_lo_u128(rem)) != UINT64_C(0)2388 uint64_t mask = zig_or_u64(zig_hi_u128(rem), zig_lo_u128(rem)) != UINT64_C(0)
2073 ? UINT64_C(1) : UINT64_C(0);2389 ? 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));
2075}2391}
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) {
2078 zig_i128 rem = zig_rem_i128(lhs, rhs);2394 zig_i128 rem = zig_rem_i128(lhs, rhs);
2079 int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0)2395 int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0)
2080 ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) + INT64_C(1)2396 ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) + INT64_C(1)
2081 : INT64_C(0);2397 : 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));
2083}2399}
20842400
2085#define zig_mod_u128 zig_rem_u1282401#define zig_mod_u128 zig_rem_u128
...@@ -2107,51 +2423,41 @@ static inline zig_i128 zig_max_i128(zig_i128 lhs, zig_i128 rhs) {...@@ -2107,51 +2423,41 @@ static inline zig_i128 zig_max_i128(zig_i128 lhs, zig_i128 rhs) {
2107 return zig_cmp_i128(lhs, rhs) > INT32_C(0) ? lhs : rhs;2423 return zig_cmp_i128(lhs, rhs) > INT32_C(0) ? lhs : rhs;
2108}2424}
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
2120static inline zig_u128 zig_shlw_u128(zig_u128 lhs, uint8_t rhs, uint8_t bits) {2426static 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);
2122}2428}
21232429
2124static inline zig_i128 zig_shlw_i128(zig_i128 lhs, uint8_t rhs, uint8_t bits) {2430static 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);
2126}2432}
21272433
2128static inline zig_u128 zig_addw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {2434static 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);
2130}2436}
21312437
2132static inline zig_i128 zig_addw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {2438static 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);
2134}2440}
21352441
2136static inline zig_u128 zig_subw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {2442static 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);
2138}2444}
21392445
2140static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {2446static 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);
2142}2448}
21432449
2144static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {2450static 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);
2146}2452}
21472453
2148static inline zig_i128 zig_mulw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {2454static 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);
2150}2456}
21512457
2152static inline zig_u128 zig_abs_i128(zig_i128 val) {2458static inline zig_u128 zig_abs_i128(zig_i128 arg) {
2153 zig_i128 tmp = zig_shr_i128(val, 127);2459 zig_u128 tmp = zig_u128_bitCast_i128(zig_shr_i128(arg, 127), UINT8_C(128));
2154 return zig_bitCast_u128(zig_sub_i128(zig_xor_i128(val, tmp), tmp));2460 return zig_sub_u128(zig_xor_u128(zig_u128_bitCast_i128(arg, UINT8_C(128)), tmp), tmp);
2155}2461}
21562462
2157#if zig_has_int1282463#if zig_has_int128
...@@ -2160,7 +2466,7 @@ static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint...@@ -2160,7 +2466,7 @@ static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
2160#if zig_has_builtin(add_overflow)2466#if zig_has_builtin(add_overflow)
2161 zig_u128 full_res;2467 zig_u128 full_res;
2162 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);2468 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);
2164 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);2470 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
2165#else2471#else
2166 *res = zig_addw_u128(lhs, rhs, bits);2472 *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...@@ -2176,7 +2482,7 @@ static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint
2176 zig_i128 full_res = (zig_i128)((zig_u128)lhs + (zig_u128)rhs);2482 zig_i128 full_res = (zig_i128)((zig_u128)lhs + (zig_u128)rhs);
2177 bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0;2483 bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0;
2178#endif2484#endif
2179 *res = zig_wrap_i128(full_res, bits);2485 *res = zig_i128_truncate_i128(full_res, bits);
2180 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);2486 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
2181}2487}
21822488
...@@ -2184,7 +2490,7 @@ static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint...@@ -2184,7 +2490,7 @@ static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
2184#if zig_has_builtin(sub_overflow)2490#if zig_has_builtin(sub_overflow)
2185 zig_u128 full_res;2491 zig_u128 full_res;
2186 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);2492 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);
2188 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);2494 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
2189#else2495#else
2190 *res = zig_subw_u128(lhs, rhs, bits);2496 *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...@@ -2200,7 +2506,7 @@ static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint
2200 zig_i128 full_res = (zig_i128)((zig_u128)lhs - (zig_u128)rhs);2506 zig_i128 full_res = (zig_i128)((zig_u128)lhs - (zig_u128)rhs);
2201 bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0;2507 bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0;
2202#endif2508#endif
2203 *res = zig_wrap_i128(full_res, bits);2509 *res = zig_i128_truncate_i128(full_res, bits);
2204 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);2510 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
2205}2511}
22062512
...@@ -2208,7 +2514,7 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint...@@ -2208,7 +2514,7 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
2208#if zig_has_builtin(mul_overflow)2514#if zig_has_builtin(mul_overflow)
2209 zig_u128 full_res;2515 zig_u128 full_res;
2210 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);2516 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);
2212 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);2518 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
2213#else2519#else
2214 *res = zig_mulw_u128(lhs, rhs, bits);2520 *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...@@ -2216,8 +2522,8 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
2216#endif2522#endif
2217}2523}
22182524
2219zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
2220static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {2525static 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);
2221#if zig_has_builtin(mul_overflow)2527#if zig_has_builtin(mul_overflow)
2222 zig_i128 full_res;2528 zig_i128 full_res;
2223 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);2529 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...@@ -2226,50 +2532,78 @@ static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint
2226 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);2532 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);
2227 bool overflow = overflow_int != 0;2533 bool overflow = overflow_int != 0;
2228#endif2534#endif
2229 *res = zig_wrap_i128(full_res, bits);2535 *res = zig_i128_truncate_i128(full_res, bits);
2230 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);2536 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
2231}2537}
22322538
2233#else /* zig_has_int128 */2539#else /* zig_has_int128 */
22342540
2235static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {2541static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2236 uint64_t hi;2542 if (bits <= UINT8_C(64)) {
2237 bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - 64);2543 uint64_t lo;
2238 return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);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 }
2239}2552}
22402553
2241static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {2554static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2242 int64_t hi;2555 if (bits <= UINT8_C(64)) {
2243 bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - 64);2556 int64_t lo;
2244 return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);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 }
2245}2565}
22462566
2247static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {2567static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2248 uint64_t hi;2568 if (bits <= UINT8_C(64)) {
2249 bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - 64);2569 uint64_t lo;
2250 return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);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 }
2251}2578}
22522579
2253static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {2580static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2254 int64_t hi;2581 if (bits <= UINT8_C(64)) {
2255 bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - 64);2582 int64_t lo;
2256 return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);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 }
2257}2591}
22582592
2259static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {2593static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2260 *res = zig_mulw_u128(lhs, rhs, bits);2594 *res = zig_mulw_u128(lhs, rhs, bits);
2261 return zig_cmp_u128(*res, zig_make_u128(0, 0)) != INT32_C(0) &&2595 return zig_cmp_u128(rhs, 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);2596 zig_cmp_u128(lhs, zig_divTrunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0);
2263}2597}
22642598
2265zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
2266static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {2599static 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);
2267 int overflow_int;2601 int overflow_int;
2268 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);2602 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);
2269 bool overflow = overflow_int != 0 ||2603 bool overflow = overflow_int != 0 ||
2270 zig_cmp_i128(full_res, zig_minInt_i(128, bits)) < INT32_C(0) ||2604 zig_cmp_i128(full_res, zig_minInt_i(128, bits)) < INT32_C(0) ||
2271 zig_cmp_i128(full_res, zig_maxInt_i(128, bits)) > INT32_C(0);2605 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);
2273 return overflow;2607 return overflow;
2274}2608}
22752609
...@@ -2282,28 +2616,54 @@ static inline bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, uint8_t rhs, uint8...@@ -2282,28 +2616,54 @@ static inline bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, uint8_t rhs, uint8
22822616
2283static inline bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, uint8_t rhs, uint8_t bits) {2617static inline bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, uint8_t rhs, uint8_t bits) {
2284 *res = zig_shlw_i128(lhs, rhs, bits);2618 *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);
2286 return zig_cmp_i128(zig_and_i128(lhs, mask), zig_make_i128(0, 0)) != INT32_C(0) &&2620 return zig_cmp_i128(zig_and_i128(lhs, mask), zig_make_i128(0, 0)) != INT32_C(0) &&
2287 zig_cmp_i128(zig_and_i128(lhs, mask), mask) != INT32_C(0);2621 zig_cmp_i128(zig_and_i128(lhs, mask), mask) != INT32_C(0);
2288}2622}
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) {
2291 zig_u128 res;2651 zig_u128 res;
2292 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;2652 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;
2293 switch (zig_cmp_u128(lhs, zig_make_u128(0, 0))) {2653 switch (zig_cmp_u128(lhs, zig_make_u128(0, 0))) {
2294 case 0: return zig_make_u128(0, 0);2654 case INT32_C(0): return zig_make_u128(0, 0);
2295 case 1: return zig_maxInt_u(128, bits);2655 case INT32_C(1): return zig_maxInt_u(128, bits);
2296 default: zig_unreachable();2656 default: zig_unreachable();
2297 }2657 }
2298}2658}
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) {
2301 zig_i128 res;2661 zig_i128 res;
2302 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;2662 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;
2303 switch (zig_cmp_i128(lhs, zig_make_i128(0, 0))) {2663 switch (zig_cmp_i128(lhs, zig_make_i128(0, 0))) {
2304 case -1: return zig_minInt_i(128, bits);2664 case -INT32_C(1): return zig_minInt_i(128, bits);
2305 case 0: return zig_make_i128(0, 0);2665 case INT32_C(0): return zig_make_i128(0, 0);
2306 case 1: return zig_maxInt_i(128, bits);2666 case INT32_C(1): return zig_maxInt_i(128, bits);
2307 default: zig_unreachable();2667 default: zig_unreachable();
2308 }2668 }
2309}2669}
...@@ -2341,57 +2701,60 @@ static inline zig_i128 zig_muls_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {...@@ -2341,57 +2701,60 @@ static inline zig_i128 zig_muls_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2341 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);2701 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);
2342}2702}
23432703
2344static inline uint8_t zig_clz_u128(zig_u128 val, uint8_t bits) {2704static inline uint8_t zig_clz_u128(zig_u128 arg, uint8_t bits) {
2345 if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(val), bits);2705 if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(arg), bits);
2346 if (zig_hi_u128(val) != 0) return zig_clz_u64(zig_hi_u128(val), bits - UINT8_C(64));2706 if (zig_hi_u128(arg) != 0) return zig_clz_u64(zig_hi_u128(arg), bits - UINT8_C(64));
2347 return zig_clz_u64(zig_lo_u128(val), UINT8_C(64)) + (bits - UINT8_C(64));2707 return zig_clz_u64(zig_lo_u128(arg), UINT8_C(64)) + (bits - UINT8_C(64));
2348}2708}
23492709
2350static inline uint8_t zig_clz_i128(zig_i128 val, uint8_t bits) {2710static inline uint8_t zig_clz_i128(zig_i128 arg, uint8_t bits) {
2351 return zig_clz_u128(zig_bitCast_u128(val), bits);2711 return zig_clz_u128(zig_u128_bitCast_i128(arg, bits), bits);
2352}2712}
23532713
2354static inline uint8_t zig_ctz_u128(zig_u128 val, uint8_t bits) {2714static inline uint8_t zig_ctz_u128(zig_u128 arg, uint8_t bits) {
2355 if (zig_lo_u128(val) != 0) return zig_ctz_u64(zig_lo_u128(val), UINT8_C(64));2715 if (zig_lo_u128(arg) != 0) return zig_ctz_u64(zig_lo_u128(arg), UINT8_C(64));
2356 return zig_ctz_u64(zig_hi_u128(val), bits - UINT8_C(64)) + UINT8_C(64);2716 return zig_ctz_u64(zig_hi_u128(arg), bits - UINT8_C(64)) + UINT8_C(64);
2357}2717}
23582718
2359static inline uint8_t zig_ctz_i128(zig_i128 val, uint8_t bits) {2719static inline uint8_t zig_ctz_i128(zig_i128 arg, uint8_t bits) {
2360 return zig_ctz_u128(zig_bitCast_u128(val), bits);2720 return zig_ctz_u128(zig_u128_bitCast_i128(arg, bits), bits);
2361}2721}
23622722
2363static inline uint8_t zig_popcount_u128(zig_u128 val, uint8_t bits) {2723static inline uint8_t zig_popCount_u128(zig_u128 arg, uint8_t bits) {
2364 return zig_popcount_u64(zig_hi_u128(val), bits - UINT8_C(64)) +2724 return (bits > UINT8_C(64) ? zig_popCount_u64(zig_hi_u128(arg), bits - UINT8_C(64)) : UINT8_C(0)) +
2365 zig_popcount_u64(zig_lo_u128(val), UINT8_C(64));2725 zig_popCount_u64(zig_lo_u128(arg), UINT8_C(64));
2366}2726}
23672727
2368static inline uint8_t zig_popcount_i128(zig_i128 val, uint8_t bits) {2728static inline uint8_t zig_popCount_i128(zig_i128 arg, uint8_t bits) {
2369 return zig_popcount_u128(zig_bitCast_u128(val), bits);2729 return zig_popCount_u128(zig_u128_bitCast_i128(arg, bits), bits);
2370}2730}
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) {
2373 zig_u128 full_res;2733 zig_u128 full_res;
2374#if zig_has_builtin(bswap128)2734#if zig_has_builtin(bswap128)
2375 full_res = __builtin_bswap128(val);2735 full_res = __builtin_bswap128(arg);
2376#else2736#else
2377 full_res = zig_make_u128(zig_byte_swap_u64(zig_lo_u128(val), UINT8_C(64)),2737 full_res = zig_make_u128(
2378 zig_byte_swap_u64(zig_hi_u128(val), UINT8_C(64)));2738 zig_byteSwap_u64(zig_lo_u128(arg), UINT8_C(64)),
2739 zig_byteSwap_u64(zig_hi_u128(arg), UINT8_C(64))
2740 );
2379#endif2741#endif
2380 return zig_shr_u128(full_res, UINT8_C(128) - bits);2742 return zig_shr_u128(full_res, UINT8_C(128) - bits);
2381}2743}
23822744
2383static inline zig_i128 zig_byte_swap_i128(zig_i128 val, uint8_t bits) {2745static inline zig_i128 zig_byteSwap_i128(zig_i128 arg, uint8_t bits) {
2384 return zig_bitCast_i128(zig_byte_swap_u128(zig_bitCast_u128(val), bits));2746 return zig_i128_bitCast_u128(zig_byteSwap_u128(zig_u128_bitCast_i128(arg, bits), bits), bits);
2385}2747}
23862748
2387static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, uint8_t bits) {2749static inline zig_u128 zig_bitReverse_u128(zig_u128 arg, uint8_t bits) {
2388 return zig_shr_u128(zig_make_u128(zig_bit_reverse_u64(zig_lo_u128(val), UINT8_C(64)),2750 return zig_shr_u128(zig_make_u128(
2389 zig_bit_reverse_u64(zig_hi_u128(val), UINT8_C(64))),2751 zig_bitReverse_u64(zig_lo_u128(arg), UINT8_C(64)),
2390 UINT8_C(128) - bits);2752 zig_bitReverse_u64(zig_hi_u128(arg), UINT8_C(64))
2753 ), UINT8_C(128) - bits);
2391}2754}
23922755
2393static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) {2756static inline zig_i128 zig_bitReverse_i128(zig_i128 arg, uint8_t bits) {
2394 return zig_bitCast_i128(zig_bit_reverse_u128(zig_bitCast_u128(val), bits));2757 return zig_i128_bitCast_u128(zig_bitReverse_u128(zig_u128_bitCast_i128(arg, bits), bits), bits);
2395}2758}
23962759
2397#if zig_has_int1282760#if zig_has_int128
...@@ -2411,15 +2774,218 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) {...@@ -2411,15 +2774,218 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) {
2411/* ========================== Big Integer Support =========================== */2774/* ========================== Big Integer Support =========================== */
24122775
2413static inline uint16_t zig_int_bytes(uint16_t bits) {2776static 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);
2415 uint16_t alignment = ZIG_TARGET_MAX_INT_ALIGNMENT;2778 uint16_t alignment = ZIG_TARGET_MAX_INT_ALIGNMENT;
2779
2416 while (alignment / 2 >= bytes) alignment /= 2;2780 while (alignment / 2 >= bytes) alignment /= 2;
2417 return (bytes + alignment - 1) / alignment * alignment;2781 return (bytes + alignment - 1) / alignment * alignment;
2418}2782}
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) {
2421 const uint8_t *lhs_bytes = lhs;2988 const uint8_t *lhs_bytes = lhs;
2422 const uint8_t *rhs_bytes = rhs;
2423 uint16_t byte_offset = 0;2989 uint16_t byte_offset = 0;
2424 bool do_signed = is_signed;2990 bool do_signed = is_signed;
2425 uint16_t remaining_bytes = zig_int_bytes(bits);2991 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...@@ -2429,6 +2995,7 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
2429#endif2995#endif
24302996
2431 while (remaining_bytes >= 128 / CHAR_BIT) {2997 while (remaining_bytes >= 128 / CHAR_BIT) {
2998 uint8_t rhs_byte = remaining_bytes == 128 / CHAR_BIT ? rhs : UINT8_C(0);
2432 int32_t limb_cmp;2999 int32_t limb_cmp;
24333000
2434#if zig_little_endian3001#if zig_little_endian
...@@ -2437,18 +3004,16 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign...@@ -2437,18 +3004,16 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
24373004
2438 if (do_signed) {3005 if (do_signed) {
2439 zig_i128 lhs_limb;3006 zig_i128 lhs_limb;
2440 zig_i128 rhs_limb;3007 zig_i128 rhs_limb = zig_i128_intCast_u8(rhs_byte);
24413008
2442 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3009 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2443 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2444 limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb);3010 limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb);
2445 do_signed = false;3011 do_signed = false;
2446 } else {3012 } else {
2447 zig_u128 lhs_limb;3013 zig_u128 lhs_limb;
2448 zig_u128 rhs_limb;3014 zig_u128 rhs_limb = zig_u128_intCast_u8(rhs_byte);
24493015
2450 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3016 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2451 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2452 limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb);3017 limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb);
2453 }3018 }
24543019
...@@ -2461,24 +3026,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign...@@ -2461,24 +3026,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
2461 }3026 }
24623027
2463 while (remaining_bytes >= 64 / CHAR_BIT) {3028 while (remaining_bytes >= 64 / CHAR_BIT) {
3029 uint8_t rhs_byte = remaining_bytes == 64 / CHAR_BIT ? rhs : UINT8_C(0);
3030
2464#if zig_little_endian3031#if zig_little_endian
2465 byte_offset -= 64 / CHAR_BIT;3032 byte_offset -= 64 / CHAR_BIT;
2466#endif3033#endif
24673034
2468 if (do_signed) {3035 if (do_signed) {
2469 int64_t lhs_limb;3036 int64_t lhs_limb;
2470 int64_t rhs_limb;3037 int64_t rhs_limb = zig_i64_intCast_u8(rhs_byte);
24713038
2472 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3039 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2473 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2474 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);3040 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
2475 do_signed = false;3041 do_signed = false;
2476 } else {3042 } else {
2477 uint64_t lhs_limb;3043 uint64_t lhs_limb;
2478 uint64_t rhs_limb;3044 uint64_t rhs_limb = zig_u64_intCast_u8(rhs_byte);
24793045
2480 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3046 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2481 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2482 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);3047 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
2483 }3048 }
24843049
...@@ -2490,24 +3055,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign...@@ -2490,24 +3055,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
2490 }3055 }
24913056
2492 while (remaining_bytes >= 32 / CHAR_BIT) {3057 while (remaining_bytes >= 32 / CHAR_BIT) {
3058 uint8_t rhs_byte = remaining_bytes == 32 / CHAR_BIT ? rhs : UINT8_C(0);
3059
2493#if zig_little_endian3060#if zig_little_endian
2494 byte_offset -= 32 / CHAR_BIT;3061 byte_offset -= 32 / CHAR_BIT;
2495#endif3062#endif
24963063
2497 if (do_signed) {3064 if (do_signed) {
2498 int32_t lhs_limb;3065 int32_t lhs_limb;
2499 int32_t rhs_limb;3066 int32_t rhs_limb = zig_i32_intCast_u8(rhs_byte);
25003067
2501 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3068 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2502 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2503 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);3069 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
2504 do_signed = false;3070 do_signed = false;
2505 } else {3071 } else {
2506 uint32_t lhs_limb;3072 uint32_t lhs_limb;
2507 uint32_t rhs_limb;3073 uint32_t rhs_limb = zig_u32_intCast_u8(rhs_byte);
25083074
2509 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3075 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2510 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2511 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);3076 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
2512 }3077 }
25133078
...@@ -2519,24 +3084,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign...@@ -2519,24 +3084,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
2519 }3084 }
25203085
2521 while (remaining_bytes >= 16 / CHAR_BIT) {3086 while (remaining_bytes >= 16 / CHAR_BIT) {
3087 uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0);
3088
2522#if zig_little_endian3089#if zig_little_endian
2523 byte_offset -= 16 / CHAR_BIT;3090 byte_offset -= 16 / CHAR_BIT;
2524#endif3091#endif
25253092
2526 if (do_signed) {3093 if (do_signed) {
2527 int16_t lhs_limb;3094 int16_t lhs_limb;
2528 int16_t rhs_limb;3095 int16_t rhs_limb = zig_i16_intCast_u8(rhs_byte);
25293096
2530 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3097 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2531 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2532 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);3098 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
2533 do_signed = false;3099 do_signed = false;
2534 } else {3100 } else {
2535 uint16_t lhs_limb;3101 uint16_t lhs_limb;
2536 uint16_t rhs_limb;3102 uint16_t rhs_limb = zig_u16_intCast_u8(rhs_byte);
25373103
2538 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3104 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2539 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2540 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);3105 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
2541 }3106 }
25423107
...@@ -2548,24 +3113,26 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign...@@ -2548,24 +3113,26 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
2548 }3113 }
25493114
2550 while (remaining_bytes >= 8 / CHAR_BIT) {3115 while (remaining_bytes >= 8 / CHAR_BIT) {
3116 uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0);
3117
2551#if zig_little_endian3118#if zig_little_endian
2552 byte_offset -= 8 / CHAR_BIT;3119 byte_offset -= 8 / CHAR_BIT;
2553#endif3120#endif
25543121
2555 if (do_signed) {3122 if (do_signed) {
2556 int8_t lhs_limb;3123 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
2559 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3127 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2560 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));3128 lhs_cmp_limb = zig_i16_intCast_i8(lhs_limb);
2561 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);3129 if (lhs_cmp_limb != rhs_cmp_limb) return (lhs_cmp_limb > rhs_cmp_limb) - (lhs_cmp_limb < rhs_cmp_limb);
2562 do_signed = false;3130 do_signed = false;
2563 } else {3131 } else {
2564 uint8_t lhs_limb;3132 uint8_t lhs_limb;
2565 uint8_t rhs_limb;3133 uint8_t rhs_limb = rhs_byte;
25663134
2567 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3135 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2568 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2569 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);3136 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
2570 }3137 }
25713138
...@@ -2579,148 +3146,472 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign...@@ -2579,148 +3146,472 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
2579 return 0;3146 return 0;
2580}3147}
25813148
2582static inline void zig_and_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {3149static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2583 uint8_t *res_bytes = res;
2584 const uint8_t *lhs_bytes = lhs;3150 const uint8_t *lhs_bytes = lhs;
2585 const uint8_t *rhs_bytes = rhs;3151 const uint8_t *rhs_bytes = rhs;
2586 uint16_t byte_offset = 0;3152 uint16_t byte_offset = 0;
3153 bool do_signed = is_signed;
2587 uint16_t remaining_bytes = zig_int_bytes(bits);3154 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
2590 while (remaining_bytes >= 128 / CHAR_BIT) {3160 while (remaining_bytes >= 128 / CHAR_BIT) {
2591 zig_u128 res_limb;3161 int32_t limb_cmp;
2592 zig_u128 lhs_limb;
2593 zig_u128 rhs_limb;
25943162
2595 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3163#if zig_little_endian
2596 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));3164 byte_offset -= 128 / CHAR_BIT;
2597 res_limb = zig_and_u128(lhs_limb, rhs_limb);3165#endif
2598 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));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;
2600 remaining_bytes -= 128 / CHAR_BIT;3185 remaining_bytes -= 128 / CHAR_BIT;
3186
3187#if zig_big_endian
2601 byte_offset += 128 / CHAR_BIT;3188 byte_offset += 128 / CHAR_BIT;
3189#endif
2602 }3190 }
26033191
2604 while (remaining_bytes >= 64 / CHAR_BIT) {3192 while (remaining_bytes >= 64 / CHAR_BIT) {
2605 uint64_t res_limb;3193#if zig_little_endian
2606 uint64_t lhs_limb;3194 byte_offset -= 64 / CHAR_BIT;
2607 uint64_t rhs_limb;3195#endif
26083196
2609 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3197 if (do_signed) {
2610 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));3198 int64_t lhs_limb;
2611 res_limb = zig_and_u64(lhs_limb, rhs_limb);3199 int64_t rhs_limb;
2612 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_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
2614 remaining_bytes -= 64 / CHAR_BIT;3214 remaining_bytes -= 64 / CHAR_BIT;
3215
3216#if zig_big_endian
2615 byte_offset += 64 / CHAR_BIT;3217 byte_offset += 64 / CHAR_BIT;
3218#endif
2616 }3219 }
26173220
2618 while (remaining_bytes >= 32 / CHAR_BIT) {3221 while (remaining_bytes >= 32 / CHAR_BIT) {
2619 uint32_t res_limb;3222#if zig_little_endian
2620 uint32_t lhs_limb;3223 byte_offset -= 32 / CHAR_BIT;
2621 uint32_t rhs_limb;3224#endif
26223225
2623 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3226 if (do_signed) {
2624 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));3227 int32_t lhs_limb;
2625 res_limb = zig_and_u32(lhs_limb, rhs_limb);3228 int32_t rhs_limb;
2626 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_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
2628 remaining_bytes -= 32 / CHAR_BIT;3243 remaining_bytes -= 32 / CHAR_BIT;
3244
3245#if zig_big_endian
2629 byte_offset += 32 / CHAR_BIT;3246 byte_offset += 32 / CHAR_BIT;
3247#endif
2630 }3248 }
26313249
2632 while (remaining_bytes >= 16 / CHAR_BIT) {3250 while (remaining_bytes >= 16 / CHAR_BIT) {
2633 uint16_t res_limb;3251#if zig_little_endian
2634 uint16_t lhs_limb;3252 byte_offset -= 16 / CHAR_BIT;
2635 uint16_t rhs_limb;3253#endif
26363254
2637 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3255 if (do_signed) {
2638 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));3256 int16_t lhs_limb;
2639 res_limb = zig_and_u16(lhs_limb, rhs_limb);3257 int16_t rhs_limb;
2640 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_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
2642 remaining_bytes -= 16 / CHAR_BIT;3272 remaining_bytes -= 16 / CHAR_BIT;
3273
3274#if zig_big_endian
2643 byte_offset += 16 / CHAR_BIT;3275 byte_offset += 16 / CHAR_BIT;
3276#endif
2644 }3277 }
26453278
2646 while (remaining_bytes >= 8 / CHAR_BIT) {3279 while (remaining_bytes >= 8 / CHAR_BIT) {
2647 uint8_t res_limb;3280#if zig_little_endian
2648 uint8_t lhs_limb;3281 byte_offset -= 8 / CHAR_BIT;
2649 uint8_t rhs_limb;3282#endif
26503283
2651 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3284 if (do_signed) {
2652 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));3285 int8_t lhs_limb;
2653 res_limb = zig_and_u8(lhs_limb, rhs_limb);3286 int8_t rhs_limb;
2654 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_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
2656 remaining_bytes -= 8 / CHAR_BIT;3301 remaining_bytes -= 8 / CHAR_BIT;
3302
3303#if zig_big_endian
2657 byte_offset += 8 / CHAR_BIT;3304 byte_offset += 8 / CHAR_BIT;
3305#endif
2658 }3306 }
3307
3308 return 0;
2659}3309}
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) {
2662 uint8_t *res_bytes = res;3312 uint8_t *res_bytes = res;
2663 const uint8_t *lhs_bytes = lhs;3313 const uint8_t *arg_bytes = arg;
2664 const uint8_t *rhs_bytes = rhs;
2665 uint16_t byte_offset = 0;3314 uint16_t byte_offset = 0;
2666 uint16_t remaining_bytes = zig_int_bytes(bits);3315 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
2669 while (remaining_bytes >= 128 / CHAR_BIT) {3322 while (remaining_bytes >= 128 / CHAR_BIT) {
2670 zig_u128 res_limb;3323 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
2671 zig_u128 lhs_limb;
2672 zig_u128 rhs_limb;
26733324
2674 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3325#if zig_big_endian
2675 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));3326 byte_offset -= 128 / CHAR_BIT;
2676 res_limb = zig_or_u128(lhs_limb, rhs_limb);3327#endif
2677 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));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
2679 remaining_bytes -= 128 / CHAR_BIT;3345 remaining_bytes -= 128 / CHAR_BIT;
3346
3347#if zig_little_endian
2680 byte_offset += 128 / CHAR_BIT;3348 byte_offset += 128 / CHAR_BIT;
3349#endif
2681 }3350 }
26823351
2683 while (remaining_bytes >= 64 / CHAR_BIT) {3352 while (remaining_bytes >= 64 / CHAR_BIT) {
2684 uint64_t res_limb;3353 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
2685 uint64_t lhs_limb;
2686 uint64_t rhs_limb;
26873354
2688 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3355#if zig_big_endian
2689 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));3356 byte_offset -= 64 / CHAR_BIT;
2690 res_limb = zig_or_u64(lhs_limb, rhs_limb);3357#endif
2691 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));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
2693 remaining_bytes -= 64 / CHAR_BIT;3375 remaining_bytes -= 64 / CHAR_BIT;
3376
3377#if zig_little_endian
2694 byte_offset += 64 / CHAR_BIT;3378 byte_offset += 64 / CHAR_BIT;
3379#endif
2695 }3380 }
26963381
2697 while (remaining_bytes >= 32 / CHAR_BIT) {3382 while (remaining_bytes >= 32 / CHAR_BIT) {
2698 uint32_t res_limb;3383 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
2699 uint32_t lhs_limb;
2700 uint32_t rhs_limb;
27013384
2702 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3385#if zig_big_endian
2703 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));3386 byte_offset -= 32 / CHAR_BIT;
2704 res_limb = zig_or_u32(lhs_limb, rhs_limb);3387#endif
2705 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));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
2707 remaining_bytes -= 32 / CHAR_BIT;3405 remaining_bytes -= 32 / CHAR_BIT;
3406
3407#if zig_little_endian
2708 byte_offset += 32 / CHAR_BIT;3408 byte_offset += 32 / CHAR_BIT;
3409#endif
2709 }3410 }
27103411
2711 while (remaining_bytes >= 16 / CHAR_BIT) {3412 while (remaining_bytes >= 16 / CHAR_BIT) {
2712 uint16_t res_limb;3413 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
2713 uint16_t lhs_limb;
2714 uint16_t rhs_limb;
27153414
2716 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3415#if zig_big_endian
2717 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));3416 byte_offset -= 16 / CHAR_BIT;
2718 res_limb = zig_or_u16(lhs_limb, rhs_limb);3417#endif
2719 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
27203418
2721 remaining_bytes -= 16 / CHAR_BIT;3419 if (remaining_bytes != 16 / CHAR_BIT || is_signed) {
2722 byte_offset += 16 / CHAR_BIT;3420 int16_t res_limb;
2723 }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
2725 while (remaining_bytes >= 8 / CHAR_BIT) {3616 while (remaining_bytes >= 8 / CHAR_BIT) {
2726 uint8_t res_limb;3617 uint8_t res_limb;
...@@ -2816,13 +3707,415 @@ static inline void zig_xor_big(void *res, const void *lhs, const void *rhs, bool...@@ -2816,13 +3707,415 @@ static inline void zig_xor_big(void *res, const void *lhs, const void *rhs, bool
2816 }3707 }
2817}3708}
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
2819static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {4112static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2820 uint8_t *res_bytes = res;4113 uint8_t *res_bytes = res;
2821 const uint8_t *lhs_bytes = lhs;4114 const uint8_t *lhs_bytes = lhs;
2822 const uint8_t *rhs_bytes = rhs;4115 const uint8_t *rhs_bytes = rhs;
2823 uint16_t byte_offset = 0;4116 uint16_t byte_offset = 0;
2824 uint16_t remaining_bytes = zig_int_bytes(bits);4117 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);
2826 bool overflow = false;4119 bool overflow = false;
28274120
2828#if zig_big_endian4121#if zig_big_endian
...@@ -3038,7 +4331,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo...@@ -3038,7 +4331,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
3038 const uint8_t *rhs_bytes = rhs;4331 const uint8_t *rhs_bytes = rhs;
3039 uint16_t byte_offset = 0;4332 uint16_t byte_offset = 0;
3040 uint16_t remaining_bytes = zig_int_bytes(bits);4333 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);
3042 bool overflow = false;4335 bool overflow = false;
30434336
3044#if zig_big_endian4337#if zig_big_endian
...@@ -3238,218 +4531,890 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo...@@ -3238,218 +4531,890 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
3238 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));4531 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3239 }4532 }
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
3243#if zig_little_endian5160#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);
3245#endif5164#endif
3246 }5165 }
32475166
3248 return overflow;5167 {
3249}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) {5174 {
3252 (void)zig_addo_big(res, lhs, rhs, is_signed, bits);5175 uint8_t byte = arg_bytes[arg_byte_offset];
3253}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) {5180 res_bytes[res_byte_offset] = byte;
3256 (void)zig_subo_big(res, lhs, rhs, is_signed, bits);
3257}
32585181
3259zig_extern void __udivei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits);5182#if zig_little_endian
3260static inline void zig_div_trunc_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {5183 res_byte_offset += UINT16_C(1);
3261 if (!is_signed) {5184 memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset);
3262 __udivei4(res, lhs, rhs, bits);5185#else
3263 return;5186 memset(&res_bytes[0], fill, res_byte_offset);
5187#endif
5188 }
3264 }5189 }
3265
3266 zig_trap();
3267}5190}
32685191
3269static inline void zig_div_floor_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {5192static inline void zig_bitReverse_big(void *res, const void *arg, bool is_signed, uint16_t bits) {
3270 if (!is_signed) {5193 uint8_t *res_bytes = res;
3271 zig_div_trunc_big(res, lhs, rhs, is_signed, bits);5194 const uint8_t *arg_bytes = arg;
3272 return;5195 uint16_t size = zig_int_bytes(bits);
3273 }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();5202#if zig_big_endian
3276}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) {5208 {
3279 zig_trap();5209#if zig_little_endian
3280}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);5213 arg_prev_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8));
3283static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {5214
3284 if (!is_signed) {5215#if zig_big_endian
3285 __umodei4(res, lhs, rhs, bits);5216 arg_byte_offset += UINT16_C(1);
3286 return;5217#endif
3287 }5218 }
32885219
3289 zig_trap();5220 while (arg_byte_offset != end_byte_offset) {
3290}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) {5227 {
3293 if (!is_signed) {5228 uint8_t arg_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8));
3294 zig_rem_big(res, lhs, rhs, is_signed, bits);5229
3295 return;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
3296 }5242 }
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 }
3299}5267}
33005268
3301static inline uint16_t zig_clz_big(const void *val, bool is_signed, uint16_t bits) {5269static inline uint16_t zig_popCount_big(const void *arg, bool is_signed, uint16_t bits) {
3302 const uint8_t *val_bytes = val;5270 const uint8_t *arg_bytes = arg;
3303 uint16_t byte_offset = 0;5271 uint16_t byte_offset = 0;
3304 uint16_t remaining_bytes = zig_int_bytes(bits);5272 uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
3305 uint16_t skip_bits = remaining_bytes * 8 - bits;5273 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
3306 uint16_t total_lz = 0;5274 uint16_t total_pc = 0;
3307 uint16_t limb_lz;
3308 (void)is_signed;5275 (void)is_signed;
33095276
3310#if zig_little_endian5277#if zig_big_endian
3311 byte_offset = remaining_bytes;5278 byte_offset = zig_int_bytes(bits);
3312#endif5279#endif
33135280
3314 while (remaining_bytes >= 128 / CHAR_BIT) {5281 while (remaining_bytes >= 128 / CHAR_BIT) {
3315#if zig_little_endian5282 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
5283
5284#if zig_big_endian
3316 byte_offset -= 128 / CHAR_BIT;5285 byte_offset -= 128 / CHAR_BIT;
3317#endif5286#endif
33185287
3319 {5288 {
3320 zig_u128 val_limb;5289 zig_u128 arg_limb;
33215290
3322 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5291 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3323 limb_lz = zig_clz_u128(val_limb, 128 - skip_bits);5292 total_pc += zig_popCount_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits);
3324 }5293 }
33255294
3326 total_lz += limb_lz;
3327 if (limb_lz < 128 - skip_bits) return total_lz;
3328 skip_bits = 0;
3329 remaining_bytes -= 128 / CHAR_BIT;5295 remaining_bytes -= 128 / CHAR_BIT;
33305296
3331#if zig_big_endian5297#if zig_little_endian
3332 byte_offset += 128 / CHAR_BIT;5298 byte_offset += 128 / CHAR_BIT;
3333#endif5299#endif
3334 }5300 }
33355301
3336 while (remaining_bytes >= 64 / CHAR_BIT) {5302 while (remaining_bytes >= 64 / CHAR_BIT) {
3337#if zig_little_endian5303 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
5304
5305#if zig_big_endian
3338 byte_offset -= 64 / CHAR_BIT;5306 byte_offset -= 64 / CHAR_BIT;
3339#endif5307#endif
33405308
3341 {5309 {
3342 uint64_t val_limb;5310 uint64_t arg_limb;
33435311
3344 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5312 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3345 limb_lz = zig_clz_u64(val_limb, 64 - skip_bits);5313 total_pc += zig_popCount_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits);
3346 }5314 }
33475315
3348 total_lz += limb_lz;
3349 if (limb_lz < 64 - skip_bits) return total_lz;
3350 skip_bits = 0;
3351 remaining_bytes -= 64 / CHAR_BIT;5316 remaining_bytes -= 64 / CHAR_BIT;
33525317
3353#if zig_big_endian5318#if zig_little_endian
3354 byte_offset += 64 / CHAR_BIT;5319 byte_offset += 64 / CHAR_BIT;
3355#endif5320#endif
3356 }5321 }
33575322
3358 while (remaining_bytes >= 32 / CHAR_BIT) {5323 while (remaining_bytes >= 32 / CHAR_BIT) {
3359#if zig_little_endian5324 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
5325
5326#if zig_big_endian
3360 byte_offset -= 32 / CHAR_BIT;5327 byte_offset -= 32 / CHAR_BIT;
3361#endif5328#endif
33625329
3363 {5330 {
3364 uint32_t val_limb;5331 uint32_t arg_limb;
33655332
3366 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5333 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3367 limb_lz = zig_clz_u32(val_limb, 32 - skip_bits);5334 total_pc += zig_popCount_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits);
3368 }5335 }
33695336
3370 total_lz += limb_lz;
3371 if (limb_lz < 32 - skip_bits) return total_lz;
3372 skip_bits = 0;
3373 remaining_bytes -= 32 / CHAR_BIT;5337 remaining_bytes -= 32 / CHAR_BIT;
33745338
3375#if zig_big_endian5339#if zig_little_endian
3376 byte_offset += 32 / CHAR_BIT;5340 byte_offset += 32 / CHAR_BIT;
3377#endif5341#endif
3378 }5342 }
33795343
3380 while (remaining_bytes >= 16 / CHAR_BIT) {5344 while (remaining_bytes >= 16 / CHAR_BIT) {
3381#if zig_little_endian5345 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
5346
5347#if zig_big_endian
3382 byte_offset -= 16 / CHAR_BIT;5348 byte_offset -= 16 / CHAR_BIT;
3383#endif5349#endif
33845350
3385 {5351 {
3386 uint16_t val_limb;5352 uint16_t arg_limb;
33875353
3388 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5354 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3389 limb_lz = zig_clz_u16(val_limb, 16 - skip_bits);5355 total_pc += zig_popCount_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits);
3390 }5356 }
33915357
3392 total_lz += limb_lz;
3393 if (limb_lz < 16 - skip_bits) return total_lz;
3394 skip_bits = 0;
3395 remaining_bytes -= 16 / CHAR_BIT;5358 remaining_bytes -= 16 / CHAR_BIT;
33965359
3397#if zig_big_endian5360#if zig_little_endian
3398 byte_offset += 16 / CHAR_BIT;5361 byte_offset += 16 / CHAR_BIT;
3399#endif5362#endif
3400 }5363 }
34015364
3402 while (remaining_bytes >= 8 / CHAR_BIT) {5365 while (remaining_bytes >= 8 / CHAR_BIT) {
3403#if zig_little_endian5366 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
5367
5368#if zig_big_endian
3404 byte_offset -= 8 / CHAR_BIT;5369 byte_offset -= 8 / CHAR_BIT;
3405#endif5370#endif
34065371
3407 {5372 {
3408 uint8_t val_limb;5373 uint8_t arg_limb;
34095374
3410 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5375 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3411 limb_lz = zig_clz_u8(val_limb, 8 - skip_bits);5376 total_pc += zig_popCount_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits);
3412 }5377 }
34135378
3414 total_lz += limb_lz;
3415 if (limb_lz < 8 - skip_bits) return total_lz;
3416 skip_bits = 0;
3417 remaining_bytes -= 8 / CHAR_BIT;5379 remaining_bytes -= 8 / CHAR_BIT;
34185380
3419#if zig_big_endian5381#if zig_little_endian
3420 byte_offset += 8 / CHAR_BIT;5382 byte_offset += 8 / CHAR_BIT;
3421#endif5383#endif
3422 }5384 }
34235385
3424 return total_lz;5386 return total_pc;
3425}5387}
34265388
3427static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bits) {5389static inline uint16_t zig_ctz_big(const void *arg, bool is_signed, uint16_t bits) {
3428 const uint8_t *val_bytes = val;5390 const uint8_t *arg_bytes = arg;
3429 uint16_t byte_offset = 0;5391 uint16_t byte_offset = UINT16_C(0);
3430 uint16_t remaining_bytes = zig_int_bytes(bits);5392 uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
3431 uint16_t total_tz = 0;5393 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
5394 uint16_t total_tz = UINT16_C(0);
3432 uint16_t limb_tz;5395 uint16_t limb_tz;
3433 (void)is_signed;5396 (void)is_signed;
34345397
3435#if zig_big_endian5398#if zig_big_endian
3436 byte_offset = remaining_bytes;5399 byte_offset = zig_int_bytes(bits);
3437#endif5400#endif
34385401
3439 while (remaining_bytes >= 128 / CHAR_BIT) {5402 while (remaining_bytes >= 128 / CHAR_BIT) {
5403 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
5404
3440#if zig_big_endian5405#if zig_big_endian
3441 byte_offset -= 128 / CHAR_BIT;5406 byte_offset -= 128 / CHAR_BIT;
3442#endif5407#endif
34435408
3444 {5409 {
3445 zig_u128 val_limb;5410 zig_u128 arg_limb;
34465411
3447 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5412 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3448 limb_tz = zig_ctz_u128(val_limb, 128);5413 limb_tz = zig_ctz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits);
3449 }5414 }
34505415
3451 total_tz += limb_tz;5416 total_tz += limb_tz;
3452 if (limb_tz < 128) return total_tz;5417 if (limb_tz < limb_bits) return total_tz;
3453 remaining_bytes -= 128 / CHAR_BIT;5418 remaining_bytes -= 128 / CHAR_BIT;
34545419
3455#if zig_little_endian5420#if zig_little_endian
...@@ -3458,19 +5423,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit...@@ -3458,19 +5423,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
3458 }5423 }
34595424
3460 while (remaining_bytes >= 64 / CHAR_BIT) {5425 while (remaining_bytes >= 64 / CHAR_BIT) {
5426 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
5427
3461#if zig_big_endian5428#if zig_big_endian
3462 byte_offset -= 64 / CHAR_BIT;5429 byte_offset -= 64 / CHAR_BIT;
3463#endif5430#endif
34645431
3465 {5432 {
3466 uint64_t val_limb;5433 uint64_t arg_limb;
34675434
3468 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5435 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3469 limb_tz = zig_ctz_u64(val_limb, 64);5436 limb_tz = zig_ctz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits);
3470 }5437 }
34715438
3472 total_tz += limb_tz;5439 total_tz += limb_tz;
3473 if (limb_tz < 64) return total_tz;5440 if (limb_tz < limb_bits) return total_tz;
3474 remaining_bytes -= 64 / CHAR_BIT;5441 remaining_bytes -= 64 / CHAR_BIT;
34755442
3476#if zig_little_endian5443#if zig_little_endian
...@@ -3479,19 +5446,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit...@@ -3479,19 +5446,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
3479 }5446 }
34805447
3481 while (remaining_bytes >= 32 / CHAR_BIT) {5448 while (remaining_bytes >= 32 / CHAR_BIT) {
5449 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
5450
3482#if zig_big_endian5451#if zig_big_endian
3483 byte_offset -= 32 / CHAR_BIT;5452 byte_offset -= 32 / CHAR_BIT;
3484#endif5453#endif
34855454
3486 {5455 {
3487 uint32_t val_limb;5456 uint32_t arg_limb;
34885457
3489 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5458 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3490 limb_tz = zig_ctz_u32(val_limb, 32);5459 limb_tz = zig_ctz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits);
3491 }5460 }
34925461
3493 total_tz += limb_tz;5462 total_tz += limb_tz;
3494 if (limb_tz < 32) return total_tz;5463 if (limb_tz < limb_bits) return total_tz;
3495 remaining_bytes -= 32 / CHAR_BIT;5464 remaining_bytes -= 32 / CHAR_BIT;
34965465
3497#if zig_little_endian5466#if zig_little_endian
...@@ -3500,19 +5469,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit...@@ -3500,19 +5469,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
3500 }5469 }
35015470
3502 while (remaining_bytes >= 16 / CHAR_BIT) {5471 while (remaining_bytes >= 16 / CHAR_BIT) {
5472 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
5473
3503#if zig_big_endian5474#if zig_big_endian
3504 byte_offset -= 16 / CHAR_BIT;5475 byte_offset -= 16 / CHAR_BIT;
3505#endif5476#endif
35065477
3507 {5478 {
3508 uint16_t val_limb;5479 uint16_t arg_limb;
35095480
3510 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5481 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3511 limb_tz = zig_ctz_u16(val_limb, 16);5482 limb_tz = zig_ctz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits);
3512 }5483 }
35135484
3514 total_tz += limb_tz;5485 total_tz += limb_tz;
3515 if (limb_tz < 16) return total_tz;5486 if (limb_tz < limb_bits) return total_tz;
3516 remaining_bytes -= 16 / CHAR_BIT;5487 remaining_bytes -= 16 / CHAR_BIT;
35175488
3518#if zig_little_endian5489#if zig_little_endian
...@@ -3521,19 +5492,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit...@@ -3521,19 +5492,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
3521 }5492 }
35225493
3523 while (remaining_bytes >= 8 / CHAR_BIT) {5494 while (remaining_bytes >= 8 / CHAR_BIT) {
5495 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
5496
3524#if zig_big_endian5497#if zig_big_endian
3525 byte_offset -= 8 / CHAR_BIT;5498 byte_offset -= 8 / CHAR_BIT;
3526#endif5499#endif
35275500
3528 {5501 {
3529 uint8_t val_limb;5502 uint8_t arg_limb;
35305503
3531 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5504 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3532 limb_tz = zig_ctz_u8(val_limb, 8);5505 limb_tz = zig_ctz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits);
3533 }5506 }
35345507
3535 total_tz += limb_tz;5508 total_tz += limb_tz;
3536 if (limb_tz < 8) return total_tz;5509 if (limb_tz < limb_bits) return total_tz;
3537 remaining_bytes -= 8 / CHAR_BIT;5510 remaining_bytes -= 8 / CHAR_BIT;
35385511
3539#if zig_little_endian5512#if zig_little_endian
...@@ -3544,113 +5517,141 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit...@@ -3544,113 +5517,141 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
3544 return total_tz;5517 return total_tz;
3545}5518}
35465519
3547static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_t bits) {5520static inline uint16_t zig_clz_big(const void *arg, bool is_signed, uint16_t bits) {
3548 const uint8_t *val_bytes = val;5521 const uint8_t *arg_bytes = arg;
3549 uint16_t byte_offset = 0;5522 uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
3550 uint16_t remaining_bytes = zig_int_bytes(bits);5523 uint16_t remaining_bytes = byte_offset;
3551 uint16_t total_pc = 0;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;
3552 (void)is_signed;5528 (void)is_signed;
35535529
3554#if zig_big_endian5530#if zig_big_endian
3555 byte_offset = remaining_bytes;5531 byte_offset = zig_int_bytes(bits) - remaining_bytes;
3556#endif5532#endif
35575533
3558 while (remaining_bytes >= 128 / CHAR_BIT) {5534 while (remaining_bytes >= 128 / CHAR_BIT) {
3559#if zig_big_endian5535 uint8_t limb_bits = UINT8_C(128) - (sign_limb ? top_bits : UINT8_C(0));
5536
5537#if zig_little_endian
3560 byte_offset -= 128 / CHAR_BIT;5538 byte_offset -= 128 / CHAR_BIT;
3561#endif5539#endif
35625540
3563 {5541 {
3564 zig_u128 val_limb;5542 zig_u128 arg_limb;
35655543
3566 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5544 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3567 total_pc += zig_popcount_u128(val_limb, 128);5545 limb_lz = zig_clz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits);
3568 }5546 }
35695547
5548 total_lz += limb_lz;
5549 if (limb_lz < limb_bits) return total_lz;
5550 sign_limb = false;
3570 remaining_bytes -= 128 / CHAR_BIT;5551 remaining_bytes -= 128 / CHAR_BIT;
35715552
3572#if zig_little_endian5553#if zig_big_endian
3573 byte_offset += 128 / CHAR_BIT;5554 byte_offset += 128 / CHAR_BIT;
3574#endif5555#endif
3575 }5556 }
35765557
3577 while (remaining_bytes >= 64 / CHAR_BIT) {5558 while (remaining_bytes >= 64 / CHAR_BIT) {
3578#if zig_big_endian5559 uint8_t limb_bits = UINT8_C(64) - (sign_limb ? top_bits : UINT8_C(0));
5560
5561#if zig_little_endian
3579 byte_offset -= 64 / CHAR_BIT;5562 byte_offset -= 64 / CHAR_BIT;
3580#endif5563#endif
35815564
3582 {5565 {
3583 uint64_t val_limb;5566 uint64_t arg_limb;
35845567
3585 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5568 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3586 total_pc += zig_popcount_u64(val_limb, 64);5569 limb_lz = zig_clz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits);
3587 }5570 }
35885571
5572 total_lz += limb_lz;
5573 if (limb_lz < limb_bits) return total_lz;
5574 sign_limb = false;
3589 remaining_bytes -= 64 / CHAR_BIT;5575 remaining_bytes -= 64 / CHAR_BIT;
35905576
3591#if zig_little_endian5577#if zig_big_endian
3592 byte_offset += 64 / CHAR_BIT;5578 byte_offset += 64 / CHAR_BIT;
3593#endif5579#endif
3594 }5580 }
35955581
3596 while (remaining_bytes >= 32 / CHAR_BIT) {5582 while (remaining_bytes >= 32 / CHAR_BIT) {
3597#if zig_big_endian5583 uint8_t limb_bits = UINT8_C(32) - (sign_limb ? top_bits : UINT8_C(0));
5584
5585#if zig_little_endian
3598 byte_offset -= 32 / CHAR_BIT;5586 byte_offset -= 32 / CHAR_BIT;
3599#endif5587#endif
36005588
3601 {5589 {
3602 uint32_t val_limb;5590 uint32_t arg_limb;
36035591
3604 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5592 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3605 total_pc += zig_popcount_u32(val_limb, 32);5593 limb_lz = zig_clz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits);
3606 }5594 }
36075595
5596 total_lz += limb_lz;
5597 if (limb_lz < limb_bits) return total_lz;
5598 sign_limb = false;
3608 remaining_bytes -= 32 / CHAR_BIT;5599 remaining_bytes -= 32 / CHAR_BIT;
36095600
3610#if zig_little_endian5601#if zig_big_endian
3611 byte_offset += 32 / CHAR_BIT;5602 byte_offset += 32 / CHAR_BIT;
3612#endif5603#endif
3613 }5604 }
36145605
3615 while (remaining_bytes >= 16 / CHAR_BIT) {5606 while (remaining_bytes >= 16 / CHAR_BIT) {
3616#if zig_big_endian5607 uint8_t limb_bits = UINT8_C(16) - (sign_limb ? top_bits : UINT8_C(0));
5608
5609#if zig_little_endian
3617 byte_offset -= 16 / CHAR_BIT;5610 byte_offset -= 16 / CHAR_BIT;
3618#endif5611#endif
36195612
3620 {5613 {
3621 uint16_t val_limb;5614 uint16_t arg_limb;
36225615
3623 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5616 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3624 total_pc = zig_popcount_u16(val_limb, 16);5617 limb_lz = zig_clz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits);
3625 }5618 }
36265619
5620 total_lz += limb_lz;
5621 if (limb_lz < limb_bits) return total_lz;
5622 sign_limb = false;
3627 remaining_bytes -= 16 / CHAR_BIT;5623 remaining_bytes -= 16 / CHAR_BIT;
36285624
3629#if zig_little_endian5625#if zig_big_endian
3630 byte_offset += 16 / CHAR_BIT;5626 byte_offset += 16 / CHAR_BIT;
3631#endif5627#endif
3632 }5628 }
36335629
3634 while (remaining_bytes >= 8 / CHAR_BIT) {5630 while (remaining_bytes >= 8 / CHAR_BIT) {
3635#if zig_big_endian5631 uint8_t limb_bits = UINT8_C(8) - (sign_limb ? top_bits : UINT8_C(0));
5632
5633#if zig_little_endian
3636 byte_offset -= 8 / CHAR_BIT;5634 byte_offset -= 8 / CHAR_BIT;
3637#endif5635#endif
36385636
3639 {5637 {
3640 uint8_t val_limb;5638 uint8_t arg_limb;
36415639
3642 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5640 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3643 total_pc = zig_popcount_u8(val_limb, 8);5641 limb_lz = zig_clz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits);
3644 }5642 }
36455643
5644 total_lz += limb_lz;
5645 if (limb_lz < limb_bits) return total_lz;
5646 sign_limb = false;
3646 remaining_bytes -= 8 / CHAR_BIT;5647 remaining_bytes -= 8 / CHAR_BIT;
36475648
3648#if zig_little_endian5649#if zig_big_endian
3649 byte_offset += 8 / CHAR_BIT;5650 byte_offset += 8 / CHAR_BIT;
3650#endif5651#endif
3651 }5652 }
36525653
3653 return total_pc;5654 return total_lz;
3654}5655}
36555656
3656/* ========================= Floating Point Support ========================= */5657/* ========================= Floating Point Support ========================= */
...@@ -3687,29 +5688,29 @@ long double __cdecl nanl(char const* input);...@@ -3687,29 +5688,29 @@ long double __cdecl nanl(char const* input);
3687#define zig_make_special_f80(sign, name, arg, repr) sign zig_make_f80 (__builtin_##name, )(arg)5688#define zig_make_special_f80(sign, name, arg, repr) sign zig_make_f80 (__builtin_##name, )(arg)
3688#define zig_make_special_f128(sign, name, arg, repr) sign zig_make_f128(__builtin_##name, )(arg)5689#define zig_make_special_f128(sign, name, arg, repr) sign zig_make_f128(__builtin_##name, )(arg)
3689#else5690#else
3690#define zig_make_special_f16(sign, name, arg, repr) zig_bitCast_f16 (repr)5691#define zig_make_special_f16(sign, name, arg, repr) zig_f16_bitCast_u16 (repr)
3691#define zig_make_special_f32(sign, name, arg, repr) zig_bitCast_f32 (repr)5692#define zig_make_special_f32(sign, name, arg, repr) zig_f32_bitCast_u32 (repr)
3692#define zig_make_special_f64(sign, name, arg, repr) zig_bitCast_f64 (repr)5693#define zig_make_special_f64(sign, name, arg, repr) zig_f64_bitCast_u64 (repr)
3693#define zig_make_special_f80(sign, name, arg, repr) zig_bitCast_f80 (repr)5694#define zig_make_special_f80(sign, name, arg, repr) zig_f80_bitCast_u128(repr)
3694#define zig_make_special_f128(sign, name, arg, repr) zig_bitCast_f128(repr)5695#define zig_make_special_f128(sign, name, arg, repr) zig_f128_bitCast_u128(repr)
3695#endif5696#endif
36965697
3697#define zig_has_f16 15698#define zig_has_f16 1
3698#define zig_libc_name_f16(name) __##name##h5699#define zig_libc_name_f16(name) __##name##h
3699#define zig_init_special_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr)5700#define zig_init_special_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr)
3700#if FLT_MANT_DIG == 115701#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT_MANT_DIG == 11
3701typedef float zig_f16;5702typedef float zig_f16;
3702#define zig_make_f16(fp, repr) fp##f5703#define zig_make_f16(fp, repr) fp##f
3703#elif DBL_MANT_DIG == 115704#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && DBL_MANT_DIG == 11
3704typedef double zig_f16;5705typedef double zig_f16;
3705#define zig_make_f16(fp, repr) fp5706#define zig_make_f16(fp, repr) fp
3706#elif LDBL_MANT_DIG == 115707#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && LDBL_MANT_DIG == 11
3707typedef long double zig_f16;5708typedef long double zig_f16;
3708#define zig_make_f16(fp, repr) fp##l5709#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))
3710typedef _Float16 zig_f16;5711typedef _Float16 zig_f16;
3711#define zig_make_f16(fp, repr) fp##f165712#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__)
3713typedef __fp16 zig_f16;5714typedef __fp16 zig_f16;
3714#define zig_make_f16(fp, repr) fp##f165715#define zig_make_f16(fp, repr) fp##f16
3715#else5716#else
...@@ -3723,11 +5724,6 @@ typedef uint16_t zig_f16;...@@ -3723,11 +5724,6 @@ typedef uint16_t zig_f16;
3723#undef zig_init_special_f165724#undef zig_init_special_f16
3724#define zig_init_special_f16(sign, name, arg, repr) repr5725#define zig_init_special_f16(sign, name, arg, repr) repr
3725#endif5726#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
3732#define zig_has_f32 15728#define zig_has_f32 1
3733#define zig_libc_name_f32(name) name##f5729#define zig_libc_name_f32(name) name##f
...@@ -3736,16 +5732,16 @@ typedef zig_f16 zig_compiler_rt_f16;...@@ -3736,16 +5732,16 @@ typedef zig_f16 zig_compiler_rt_f16;
3736#else5732#else
3737#define zig_init_special_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr)5733#define zig_init_special_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr)
3738#endif5734#endif
3739#if FLT_MANT_DIG == 245735#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT_MANT_DIG == 24
3740typedef float zig_f32;5736typedef float zig_f32;
3741#define zig_make_f32(fp, repr) fp##f5737#define zig_make_f32(fp, repr) fp##f
3742#elif DBL_MANT_DIG == 245738#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && DBL_MANT_DIG == 24
3743typedef double zig_f32;5739typedef double zig_f32;
3744#define zig_make_f32(fp, repr) fp5740#define zig_make_f32(fp, repr) fp
3745#elif LDBL_MANT_DIG == 245741#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && LDBL_MANT_DIG == 24
3746typedef long double zig_f32;5742typedef long double zig_f32;
3747#define zig_make_f32(fp, repr) fp##l5743#define zig_make_f32(fp, repr) fp##l
3748#elif FLT32_MANT_DIG == 245744#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT32_MANT_DIG == 24
3749typedef _Float32 zig_f32;5745typedef _Float32 zig_f32;
3750#define zig_make_f32(fp, repr) fp##f325746#define zig_make_f32(fp, repr) fp##f32
3751#else5747#else
...@@ -3768,19 +5764,19 @@ typedef uint32_t zig_f32;...@@ -3768,19 +5764,19 @@ typedef uint32_t zig_f32;
3768#else5764#else
3769#define zig_init_special_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr)5765#define zig_init_special_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr)
3770#endif5766#endif
3771#if FLT_MANT_DIG == 535767#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT_MANT_DIG == 53
3772typedef float zig_f64;5768typedef float zig_f64;
3773#define zig_make_f64(fp, repr) fp##f5769#define zig_make_f64(fp, repr) fp##f
3774#elif DBL_MANT_DIG == 535770#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && DBL_MANT_DIG == 53
3775typedef double zig_f64;5771typedef double zig_f64;
3776#define zig_make_f64(fp, repr) fp5772#define zig_make_f64(fp, repr) fp
3777#elif LDBL_MANT_DIG == 535773#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && LDBL_MANT_DIG == 53
3778typedef long double zig_f64;5774typedef long double zig_f64;
3779#define zig_make_f64(fp, repr) fp##l5775#define zig_make_f64(fp, repr) fp##l
3780#elif FLT64_MANT_DIG == 535776#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT64_MANT_DIG == 53
3781typedef _Float64 zig_f64;5777typedef _Float64 zig_f64;
3782#define zig_make_f64(fp, repr) fp##f645778#define zig_make_f64(fp, repr) fp##f64
3783#elif FLT32X_MANT_DIG == 535779#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT32X_MANT_DIG == 53
3784typedef _Float32x zig_f64;5780typedef _Float32x zig_f64;
3785#define zig_make_f64(fp, repr) fp##f32x5781#define zig_make_f64(fp, repr) fp##f32x
3786#else5782#else
...@@ -3798,7 +5794,14 @@ typedef uint64_t zig_f64;...@@ -3798,7 +5794,14 @@ typedef uint64_t zig_f64;
3798#define zig_has_f80 15794#define zig_has_f80 1
3799#define zig_libc_name_f80(name) __##name##x5795#define zig_libc_name_f80(name) __##name##x
3800#define zig_init_special_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr)5796#define zig_init_special_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr)
3801#if FLT_MANT_DIG == 645797#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
3802typedef float zig_f80;5805typedef float zig_f80;
3803#define zig_make_f80(fp, repr) fp##f5806#define zig_make_f80(fp, repr) fp##f
3804#elif DBL_MANT_DIG == 645807#elif DBL_MANT_DIG == 64
...@@ -3818,68 +5821,91 @@ typedef __float80 zig_f80;...@@ -3818,68 +5821,91 @@ typedef __float80 zig_f80;
3818#define zig_make_f80(fp, repr) fp##l5821#define zig_make_f80(fp, repr) fp##l
3819#else5822#else
3820#undef zig_has_f805823#undef zig_has_f80
3821#define zig_has_f80 0
3822#define zig_repr_f80 u128
3823typedef zig_u128 zig_f80;5824typedef 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
3824#define zig_make_f80(fp, repr) repr5832#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
3825#undef zig_make_special_f805836#undef zig_make_special_f80
3826#define zig_make_special_f80(sign, name, arg, repr) repr5837#define zig_make_special_f80(sign, name, arg, repr) repr
3827#undef zig_init_special_f805838#undef zig_init_special_f80
3828#define zig_init_special_f80(sign, name, arg, repr) repr5839#define zig_init_special_f80(sign, name, arg, repr) repr
3829#endif5840#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
3837#define zig_has_f128 15842#define zig_has_f128 1
3838#define zig_libc_name_f128(name) name##q5843#define zig_libc_name_f128(name) name##f128
3839#define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr)5844#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 == 1135845#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
3841typedef float zig_f128;5856typedef float zig_f128;
3842#define zig_make_f128(fp, repr) fp##f5857#define zig_make_f128(fp, repr) fp##f
3843#elif !zig_f128_has_miscompilations && DBL_MANT_DIG == 1135858#elif DBL_MANT_DIG == 113
3844typedef double zig_f128;5859typedef double zig_f128;
3845#define zig_make_f128(fp, repr) fp5860#define zig_make_f128(fp, repr) fp
3846#elif !zig_f128_has_miscompilations && LDBL_MANT_DIG == 1135861#elif LDBL_MANT_DIG == 113
3847typedef long double zig_f128;5862typedef long double zig_f128;
3848#define zig_make_f128(fp, repr) fp##l5863#define zig_make_f128(fp, repr) fp##l
3849#elif !zig_f128_has_miscompilations && FLT128_MANT_DIG == 1135864#elif FLT128_MANT_DIG == 113
3850typedef _Float128 zig_f128;5865typedef _Float128 zig_f128;
3851#define zig_make_f128(fp, repr) fp##f1285866#define zig_make_f128(fp, repr) fp##f128
3852#elif !zig_f128_has_miscompilations && FLT64X_MANT_DIG == 1135867#elif FLT64X_MANT_DIG == 113
3853typedef _Float64x zig_f128;5868typedef _Float64x zig_f128;
3854#define zig_make_f128(fp, repr) fp##f64x5869#define zig_make_f128(fp, repr) fp##f64x
3855#elif !zig_f128_has_miscompilations && defined(__SIZEOF_FLOAT128__)5870#elif defined(__SIZEOF_FLOAT128__)
3856typedef __float128 zig_f128;5871typedef __float128 zig_f128;
3857#define zig_make_f128(fp, repr) fp##q5872#define zig_make_f128(fp, repr) fp##q
3858#undef zig_make_special_f1285873#undef zig_make_special_f128
3859#define zig_make_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg)5874#define zig_make_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg)
3860#else5875#else
3861#undef zig_has_f1285876#undef zig_has_f128
3862#define zig_has_f128 05877#if defined(zig_x86_64) && defined(ZIG_TARGET_ABI_MSVC)
3863#undef zig_make_special_f1285878#if defined(zig_msvc) && !defined(__clang__)
3864#undef zig_init_special_f1285879#include <emmintrin.h>
3865#if defined(zig_darwin) || defined(zig_aarch64)5880typedef __m128i zig_f128;
3866typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_v2u64;5881#define zig_init_repr_f128(hi, lo) { .m128i_u64 = { lo, hi } }
3867zig_basic_operator(zig_v2u64, xor_v2u64, ^)5882#define zig_lo_repr_f128(arg) (arg).m128i_u64[0]
3868#define zig_repr_f128 v2u645883#define zig_hi_repr_f128(arg) (arg).m128i_u64[1]
3869typedef zig_v2u64 zig_f128;5884#else
3870#define zig_make_f128_zig_make_u128(hi, lo) (zig_f128){ lo, hi }5885typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_f128;
3871#define zig_make_f128_zig_init_u128 zig_make_f128_zig_make_u1285886#define zig_init_repr_f128(hi, lo) { lo, hi }
3872#define zig_make_f128(fp, repr) zig_make_f128_##repr5887#define zig_lo_repr_f128(arg) (arg)[0]
3873#define zig_make_special_f128(sign, name, arg, repr) zig_make_f128_##repr5888#define zig_hi_repr_f128(arg) (arg)[1]
3874#define zig_init_special_f128(sign, name, arg, repr) zig_make_f128_##repr5889#endif
3875#else5890#else
3876#define zig_repr_f128 u128
3877typedef zig_u128 zig_f128;5891typedef 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
3878#define zig_make_f128(fp, repr) repr5900#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
3879#define zig_make_special_f128(sign, name, arg, repr) repr5905#define zig_make_special_f128(sign, name, arg, repr) repr
5906#undef zig_init_special_f128
3880#define zig_init_special_f128(sign, name, arg, repr) repr5907#define zig_init_special_f128(sign, name, arg, repr) repr
3881#endif5908#endif
3882#endif
38835909
3884#if !defined(zig_msvc) && defined(ZIG_TARGET_ABI_MSVC)5910#if !defined(zig_msvc) && defined(ZIG_TARGET_ABI_MSVC)
3885/* Emulate msvc abi on a gnu compiler */5911/* Emulate msvc abi on a gnu compiler */
...@@ -3892,84 +5918,141 @@ typedef zig_f128 zig_c_longdouble;...@@ -3892,84 +5918,141 @@ typedef zig_f128 zig_c_longdouble;
3892typedef long double zig_c_longdouble;5918typedef long double zig_c_longdouble;
3893#endif5919#endif
38945920
3895#define zig_bitCast_float(Type, ReprType) \5921#if __AVR__
3896 static inline zig_##Type zig_bitCast_##Type(ReprType repr) { \5922typedef signed char zig_FloatCompareResult;
3897 zig_##Type result; \5923#elif defined(zig_aarch64)
3898 memcpy(&result, &repr, sizeof(result)); \5924typedef signed int zig_FloatCompareResult;
3899 return result; \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); \
3900 }5951 }
3901zig_bitCast_float(f16, uint16_t)5952zig_bitCast_float(16, 16, uint16_t, int16_t)
3902zig_bitCast_float(f32, uint32_t)5953zig_bitCast_float(32, 32, uint32_t, int32_t)
3903zig_bitCast_float(f64, uint64_t)5954zig_bitCast_float(64, 64, uint64_t, int64_t)
3904zig_bitCast_float(f80, zig_u128)5955#if zig_has_f80
3905zig_bitCast_float(f128, zig_u128)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) \5998#define zig_convert_float_00(ResType, operation, ArgType, version) \
3908 zig_extern ExternResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \5999 zig_extern ResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
3909 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ExternArgType); \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) \
3910 static inline ResType zig_expand_concat(zig_expand_concat(zig_##operation, \6010 static inline ResType zig_expand_concat(zig_expand_concat(zig_##operation, \
3911 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType)(ArgType arg) { \6011 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType)(ArgType arg) { \
3912 ResType res; \6012 zig_expand_concat(zig_expand_concat(zig_convert_float_, zig_has_##res_when), \
3913 ExternResType extern_res; \6013 zig_has_##arg_when)(ResType, operation, ArgType, version); \
3914 ExternArgType extern_arg; \6014 }
3915 memcpy(&extern_arg, &arg, sizeof(extern_arg)); \6015
3916 extern_res = zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \6016#define zig_convert_floats(SmallType, BigType) \
3917 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(extern_arg); \6017 zig_convert_float(SmallType, zig_##SmallType, trunc, BigType, zig_##BigType, 2) \
3918 memcpy(&res, &extern_res, sizeof(res)); \6018 zig_convert_float(BigType, zig_##BigType, extend, SmallType, zig_##SmallType, 2)
3919 return extern_res; \6019zig_convert_floats(f16, f32)
3920 }6020zig_convert_floats(f16, f64)
3921zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f32, zig_f32, 2)6021zig_convert_floats(f16, f80)
3922zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f64, zig_f64, 2)6022zig_convert_floats(f16, f128)
3923zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f80, zig_f80, 2)6023zig_convert_floats(f32, f64)
3924zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f128, zig_f128, 2)6024zig_convert_floats(f32, f80)
3925zig_convert_builtin(zig_f32, zig_f32, extend, zig_compiler_rt_f16, zig_f16, 2)6025zig_convert_floats(f32, f128)
3926zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f80, zig_f80, 2)6026zig_convert_floats(f64, f80)
3927zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f128, zig_f128, 2)6027zig_convert_floats(f64, f128)
3928zig_convert_builtin(zig_f64, zig_f64, extend, zig_compiler_rt_f16, zig_f16, 2)6028zig_convert_floats(f80, f128)
3929zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f80, zig_f80, 2)6029
3930zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f128, zig_f128, 2)6030#define zig_float_negate_builtin_0(w, sb) \
3931zig_convert_builtin(zig_f80, zig_f80, extend, zig_f16, zig_f16, 2)6031 zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, sb))
3932zig_convert_builtin(zig_f80, zig_f80, extend, zig_f32, zig_f32, 2)6032#define zig_float_negate_builtin_1(w, sb) -arg
3933zig_convert_builtin(zig_f80, zig_f80, extend, zig_f64, zig_f64, 2)6033#define zig_float_negate_builtin(w, sb) \
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) \
3959 static inline zig_f##w zig_neg_f##w(zig_f##w arg) { \6034 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); \
3961 }6036 }
3962zig_float_negate_builtin(16, , UINT16_C(1) << 15 )6037zig_float_negate_builtin(16, UINT16_C(1) << 15)
3963zig_float_negate_builtin(32, , UINT32_C(1) << 31 )6038zig_float_negate_builtin(32, UINT32_C(1) << 31)
3964zig_float_negate_builtin(64, , UINT64_C(1) << 63 )6039zig_float_negate_builtin(64, UINT64_C(1) << 63)
3965zig_float_negate_builtin(80, zig_make_u128, (UINT64_C(1) << 15, UINT64_C(0)))6040
3966zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))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
3968#define zig_float_less_builtin_0(Type, operation) \6051#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, \
3970 zig_compiler_rt_abbrev_zig_##Type), 2)(zig_##Type, zig_##Type); \6053 zig_compiler_rt_abbrev_zig_##Type), 2)(zig_##Type, zig_##Type); \
3971 static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \6054 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); \
3973 }6056 }
3974#define zig_float_less_builtin_1(Type, operation) \6057#define zig_float_less_builtin_1(Type, operation) \
3975 static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \6058 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)))...@@ -3994,13 +6077,52 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))
3994 return lhs operator rhs; \6077 return lhs operator rhs; \
3995 }6078 }
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, )
3997#define zig_common_float_builtins(w) \6084#define zig_common_float_builtins(w) \
3998 zig_convert_builtin( int64_t, int64_t, fix, zig_f##w, zig_f##w, ) \6085 zig_convert_float(always, int32_t, fix, f##w, zig_f##w, ) \
3999 zig_convert_builtin(zig_i128, zig_i128, fix, zig_f##w, zig_f##w, ) \6086 zig_convert_float(always, int64_t, fix, f##w, zig_f##w, ) \
4000 zig_convert_builtin(zig_u128, zig_u128, fixuns, zig_f##w, zig_f##w, ) \6087 zig_convert_float(int128, zig_i128, fix, f##w, zig_f##w, ) \
4001 zig_convert_builtin(zig_f##w, zig_f##w, float, int64_t, int64_t, ) \6088 zig_convert_float(always, uint32_t, fixuns, f##w, zig_f##w, ) \
4002 zig_convert_builtin(zig_f##w, zig_f##w, float, zig_i128, zig_i128, ) \6089 zig_convert_float(always, uint64_t, fixuns, f##w, zig_f##w, ) \
4003 zig_convert_builtin(zig_f##w, zig_f##w, floatun, zig_u128, zig_u128, ) \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\
4004 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, cmp) \6126 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, cmp) \
4005 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, ne) \6127 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, ne) \
4006 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, eq) \6128 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)))...@@ -4031,82 +6153,48 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))
4031 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)) \6153 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)) \
4032 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)) \6154 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)) \
4033\6155\
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) { \
4035 return zig_trunc_f##w(zig_div_f##w(lhs, rhs)); \6157 return zig_trunc_f##w(zig_div_f##w(lhs, rhs)); \
4036 } \6158 } \
4037\6159\
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) { \
4039 return zig_floor_f##w(zig_div_f##w(lhs, rhs)); \6161 return zig_floor_f##w(zig_div_f##w(lhs, rhs)); \
4040 } \6162 } \
4041\6163\
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) { \
4043 return zig_ceil_f##w(zig_div_f##w(lhs, rhs)); \6165 return zig_ceil_f##w(zig_div_f##w(lhs, rhs)); \
4044 } \6166 } \
4045\6167\
4046 static inline zig_f##w zig_mod_f##w(zig_f##w lhs, zig_f##w rhs) { \6168 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)); \
4048 }6170 }
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, )
4062zig_float_builtins(16)6171zig_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
4106zig_float_builtins(32)6172zig_float_builtins(32)
4107zig_float_builtins(64)6173zig_float_builtins(64)
41086174zig_float_builtins(80)
4109#endif /* __ARM_EABI__ */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
4111/* ============================ Atomics Support ============================= */6199/* ============================ Atomics Support ============================= */
41126200
...@@ -4410,19 +6498,19 @@ typedef int zig_memory_order;...@@ -4410,19 +6498,19 @@ typedef int zig_memory_order;
4410 } \6498 } \
4411 static inline void zig_msvc_atomic_store_##ZigType(Type volatile* obj, Type value) { \6499 static inline void zig_msvc_atomic_store_##ZigType(Type volatile* obj, Type value) { \
4412 (void)_InterlockedExchange##suffix((SigType volatile*)obj, (SigType)value); \6500 (void)_InterlockedExchange##suffix((SigType volatile*)obj, (SigType)value); \
4413 } \6501 } \
4414 static inline Type zig_msvc_atomic_load_zig_memory_order_relaxed_##ZigType(Type volatile* obj) { \6502 static inline Type zig_msvc_atomic_load_zig_memory_order_relaxed_##ZigType(Type volatile* obj) { \
4415 return __iso_volatile_load##iso_suffix((SigType volatile*)obj); \6503 return __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
4416 } \6504 } \
4417 static inline Type zig_msvc_atomic_load_zig_memory_order_acquire_##ZigType(Type volatile* obj) { \6505 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); \
4419 _ReadWriteBarrier(); \6507 _ReadWriteBarrier(); \
4420 return val; \6508 return value; \
4421 } \6509 } \
4422 static inline Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##ZigType(Type volatile* obj) { \6510 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); \
4424 _ReadWriteBarrier(); \6512 _ReadWriteBarrier(); \
4425 return val; \6513 return value; \
4426 }6514 }
44276515
4428zig_msvc_atomics( u8, uint8_t, char, 8, 8)6516zig_msvc_atomics( u8, uint8_t, char, 8, 8)
...@@ -4465,14 +6553,14 @@ zig_msvc_atomics(i64, int64_t, __int64, 64, 64)...@@ -4465,14 +6553,14 @@ zig_msvc_atomics(i64, int64_t, __int64, 64, 64)
4465 zig_##Type result; \6553 zig_##Type result; \
4466 SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \6554 SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
4467 _ReadWriteBarrier(); \6555 _ReadWriteBarrier(); \
4468 memcpy(&result, &initial, sizeof(result)); \6556 memcpy(&result, &initial, sizeof(result)); \
4469 return result; \6557 return result; \
4470 } \6558 } \
4471 static inline zig_##Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##Type(zig_##Type volatile* obj) { \6559 static inline zig_##Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##Type(zig_##Type volatile* obj) { \
4472 zig_##Type result; \6560 zig_##Type result; \
4473 SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \6561 SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
4474 _ReadWriteBarrier(); \6562 _ReadWriteBarrier(); \
4475 memcpy(&result, &initial, sizeof(result)); \6563 memcpy(&result, &initial, sizeof(result)); \
4476 return result; \6564 return result; \
4477 }6565 }
44786566
...@@ -4502,9 +6590,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p32(void volat...@@ -4502,9 +6590,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p32(void volat
4502}6590}
45036591
4504static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p32(void volatile* obj) {6592static 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);
4506 _ReadWriteBarrier();6594 _ReadWriteBarrier();
4507 return val;6595 return value;
4508}6596}
45096597
4510static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p32(void volatile* obj) {6598static 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...@@ -4532,9 +6620,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p64(void volat
4532}6620}
45336621
4534static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p64(void volatile* obj) {6622static 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);
4536 _ReadWriteBarrier();6624 _ReadWriteBarrier();
4537 return val;6625 return value;
4538}6626}
45396627
4540static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p64(void volatile* obj) {6628static 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) {...@@ -1907,7 +1907,7 @@ pub const NullTerminatedString = enum(u32) {
1907 pub fn toSlice(nts: NullTerminatedString, air: Air) [:0]const u8 {1907 pub fn toSlice(nts: NullTerminatedString, air: Air) [:0]const u8 {
1908 if (nts == .none) return "";1908 if (nts == .none) return "";
1909 const bytes = std.mem.sliceAsBytes(air.extra.items[@backingInt(nts)..]);1909 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];
1911 }1911 }
1912};1912};
19131913
src/Air/Legalize.zig+8-1
...@@ -2906,12 +2906,18 @@ fn packedAggregateInitBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Erro...@@ -2906,12 +2906,18 @@ fn packedAggregateInitBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Erro
2906 const orig_ty_pl = l.air_instructions.items(.data)[@backingInt(orig_inst)].ty_pl;2906 const orig_ty_pl = l.air_instructions.items(.data)[@backingInt(orig_inst)].ty_pl;
2907 const agg_ty = orig_ty_pl.ty.toType();2907 const agg_ty = orig_ty_pl.ty.toType();
2908 const agg_field_count = agg_ty.structFieldCount(zcu);2908 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
2910 var bfa_buf: [4 * 32 + 2]Air.Inst.Index = undefined;2916 var bfa_buf: [4 * 32 + 2]Air.Inst.Index = undefined;
2911 var bfa_state: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), gpa);2917 var bfa_state: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), gpa);
2912 const bfa = bfa_state.allocator();2918 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);
2915 defer bfa.free(inst_buf);2921 defer bfa.free(inst_buf);
29162922
2917 var main_block: Block = .init(inst_buf);2923 var main_block: Block = .init(inst_buf);
...@@ -2927,6 +2933,7 @@ fn packedAggregateInitBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Erro...@@ -2927,6 +2933,7 @@ fn packedAggregateInitBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Erro
2927 field_idx -= 1;2933 field_idx -= 1;
2928 const field_ty = agg_ty.fieldType(field_idx, zcu);2934 const field_ty = agg_ty.fieldType(field_idx, zcu);
2929 const field_bits: u16 = @intCast(field_ty.bitSize(zcu));2935 const field_bits: u16 = @intCast(field_ty.bitSize(zcu));
2936 if (field_bits == 0) continue;
2930 assert(field_bits < num_bits);2937 assert(field_bits < num_bits);
2931 const field_uint_ty = try pt.intType(.unsigned, field_bits);2938 const field_uint_ty = try pt.intType(.unsigned, field_bits);
2932 const field_bit_size_ref: Air.Inst.Ref = .fromValue(try pt.intValue(shift_ty, field_bits));2939 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 {...@@ -351,7 +351,7 @@ const Analysis = struct {
351 extra: std.ArrayList(u32),351 extra: std.ArrayList(u32),
352352
353 fn addExtra(a: *Analysis, extra: anytype) Allocator.Error!u32 {353 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;
355 try a.extra.ensureUnusedCapacity(a.gpa, field_count);355 try a.extra.ensureUnusedCapacity(a.gpa, field_count);
356 return addExtraAssumeCapacity(a, extra);356 return addExtraAssumeCapacity(a, extra);
357 }357 }
...@@ -1012,7 +1012,7 @@ fn analyzeInstBlock(...@@ -1012,7 +1012,7 @@ fn analyzeInstBlock(
1012 const block_scope = data.block_scopes.get(inst).?;1012 const block_scope = data.block_scopes.get(inst).?;
1013 const num_deaths = data.live_set.count() - block_scope.live_set.count();1013 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);
1016 const extra_index = a.addExtraAssumeCapacity(Block{1016 const extra_index = a.addExtraAssumeCapacity(Block{
1017 .death_count = num_deaths,1017 .death_count = num_deaths,
1018 });1018 });
...@@ -1275,7 +1275,7 @@ fn analyzeInstCondBr(...@@ -1275,7 +1275,7 @@ fn analyzeInstCondBr(
1275 // Write the mirrored deaths to `extra`1275 // Write the mirrored deaths to `extra`
1276 const then_death_count = @as(u32, @intCast(then_mirrored_deaths.items.len));1276 const then_death_count = @as(u32, @intCast(then_mirrored_deaths.items.len));
1277 const else_death_count = @as(u32, @intCast(else_mirrored_deaths.items.len));1277 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);
1279 const extra_index = a.addExtraAssumeCapacity(CondBr{1279 const extra_index = a.addExtraAssumeCapacity(CondBr{
1280 .then_death_count = then_death_count,1280 .then_death_count = then_death_count,
1281 .else_death_count = else_death_count,1281 .else_death_count = else_death_count,
src/Builtin.zig+8-2
...@@ -7,7 +7,7 @@ is_test: bool,...@@ -7,7 +7,7 @@ is_test: bool,
7single_threaded: bool,7single_threaded: bool,
8link_libc: bool,8link_libc: bool,
9link_libcpp: bool,9link_libcpp: bool,
10optimize_mode: std.lang.OptimizeMode,10optimize_mode: std.lang.Optimize,
11error_tracing: bool,11error_tracing: bool,
12valgrind: bool,12valgrind: bool,
13sanitize_thread: bool,13sanitize_thread: bool,
...@@ -64,7 +64,9 @@ pub fn append(opts: @This(), buffer: *std.array_list.Managed(u8)) Allocator.Erro...@@ -64,7 +64,9 @@ pub fn append(opts: @This(), buffer: *std.array_list.Managed(u8)) Allocator.Erro
64 \\pub const unwind_tables: std.lang.UnwindTables = .{f};64 \\pub const unwind_tables: std.lang.UnwindTables = .{f};
65 \\pub const is_test = {};65 \\pub const is_test = {};
66 \\pub const single_threaded = {};66 \\pub const single_threaded = {};
67 \\/// Deprecated; to be removed in 0.18.0. Use `target.abi` instead.
67 \\pub const abi: std.Target.Abi = .{f};68 \\pub const abi: std.Target.Abi = .{f};
69 \\/// Deprecated; to be removed in 0.18.0. Use `target.cpu` instead.
68 \\pub const cpu: std.Target.Cpu = .{{70 \\pub const cpu: std.Target.Cpu = .{{
69 \\ .arch = .{f},71 \\ .arch = .{f},
70 \\ .model = &std.Target.{f}.cpu.{f},72 \\ .model = &std.Target.{f}.cpu.{f},
...@@ -95,6 +97,7 @@ pub fn append(opts: @This(), buffer: *std.array_list.Managed(u8)) Allocator.Erro...@@ -95,6 +97,7 @@ pub fn append(opts: @This(), buffer: *std.array_list.Managed(u8)) Allocator.Erro
95 try buffer.print(97 try buffer.print(
96 \\ }}),98 \\ }}),
97 \\}};99 \\}};
100 \\/// Deprecated; to be removed in 0.18.0. Use `target.os` instead.
98 \\pub const os: std.Target.Os = .{{101 \\pub const os: std.Target.Os = .{{
99 \\ .tag = .{f},102 \\ .tag = .{f},
100 \\ .version_range = .{{103 \\ .version_range = .{{
...@@ -238,8 +241,11 @@ pub fn append(opts: @This(), buffer: *std.array_list.Managed(u8)) Allocator.Erro...@@ -238,8 +241,11 @@ pub fn append(opts: @This(), buffer: *std.array_list.Managed(u8)) Allocator.Erro
238 const link_libc = opts.link_libc;241 const link_libc = opts.link_libc;
239242
240 try buffer.print(243 try buffer.print(
244 \\/// Deprecated; to be removed in 0.18.0. Use `target.ofmt` instead.
241 \\pub const object_format: std.Target.ObjectFormat = .{f};245 \\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};
243 \\pub const link_libc = {};249 \\pub const link_libc = {};
244 \\pub const link_libcpp = {};250 \\pub const link_libcpp = {};
245 \\pub const have_error_return_tracing = {};251 \\pub const have_error_return_tracing = {};
src/Compilation.zig+63-37
...@@ -172,7 +172,7 @@ verbose_link: bool,...@@ -172,7 +172,7 @@ verbose_link: bool,
172link_depfile: ?[]const u8,172link_depfile: ?[]const u8,
173disable_c_depfile: bool,173disable_c_depfile: bool,
174stack_report: bool,174stack_report: bool,
175debug_compiler_runtime_libs: ?std.lang.OptimizeMode,175debug_compiler_runtime_libs: ?std.lang.Optimize,
176debug_compile_errors: bool,176debug_compile_errors: bool,
177/// Do not check this field directly. Instead, use the `debugIncremental` wrapper function.177/// Do not check this field directly. Instead, use the `debugIncremental` wrapper function.
178debug_incremental: bool,178debug_incremental: bool,
...@@ -1232,7 +1232,6 @@ pub const cache_helpers = struct {...@@ -1232,7 +1232,6 @@ pub const cache_helpers = struct {
1232 hh.add(mod.sanitize_thread);1232 hh.add(mod.sanitize_thread);
1233 hh.add(mod.fuzz);1233 hh.add(mod.fuzz);
1234 hh.add(mod.unwind_tables);1234 hh.add(mod.unwind_tables);
1235 hh.add(mod.structured_cfg);
1236 hh.add(mod.no_builtin);1235 hh.add(mod.no_builtin);
1237 hh.addListOfBytes(mod.cc_argv);1236 hh.addListOfBytes(mod.cc_argv);
1238 }1237 }
...@@ -1506,7 +1505,7 @@ pub const CreateOptions = struct {...@@ -1506,7 +1505,7 @@ pub const CreateOptions = struct {
1506 verbose_llvm_bc: ?[]const u8 = null,1505 verbose_llvm_bc: ?[]const u8 = null,
1507 link_depfile: ?[]const u8 = null,1506 link_depfile: ?[]const u8 = null,
1508 verbose_llvm_cpu_features: bool = false,1507 verbose_llvm_cpu_features: bool = false,
1509 debug_compiler_runtime_libs: ?std.lang.OptimizeMode = null,1508 debug_compiler_runtime_libs: ?std.lang.Optimize = null,
1510 debug_compile_errors: bool = false,1509 debug_compile_errors: bool = false,
1511 debug_incremental: bool = false,1510 debug_incremental: bool = false,
1512 /// Normally when you create a `Compilation`, Zig will automatically build1511 /// 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,...@@ -2134,6 +2133,9 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
2134 comp.config.any_fuzz = any_fuzz;2133 comp.config.any_fuzz = any_fuzz;
21352134
2136 if (opt_zcu) |zcu| {2135 if (opt_zcu) |zcu| {
2136 // Finish initializing the `zcu` after the fields on `comp` have been initialized.
2137 zcu.initAfterCompilation();
2138
2137 // Populate `zcu.module_roots`.2139 // Populate `zcu.module_roots`.
2138 const active = zcu.acquire();2140 const active = zcu.acquire();
2139 defer active.release();2141 defer active.release();
...@@ -2160,7 +2162,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -2160,7 +2162,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
2160 .framework_dirs = options.framework_dirs,2162 .framework_dirs = options.framework_dirs,
2161 .rpath_list = options.rpath_list,2163 .rpath_list = options.rpath_list,
2162 .symbol_wrap_set = options.symbol_wrap_set,2164 .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),
2164 .allow_shlib_undefined = options.linker_allow_shlib_undefined,2166 .allow_shlib_undefined = options.linker_allow_shlib_undefined,
2165 .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false,2167 .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false,
2166 .compress_debug_sections = options.linker_compress_debug_sections orelse .none,2168 .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...@@ -2911,7 +2913,20 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
2911 // The linker progress node is set up here instead of in `performAllTheWork`, because2913 // The linker progress node is set up here instead of in `performAllTheWork`, because
2912 // we also want it around during `flush`.2914 // we also want it around during `flush`.
2913 if (comp.bin_file) |lf| {2915 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);
2915 lf.startProgress(comp.link_prog_node);2930 lf.startProgress(comp.link_prog_node);
2916 }2931 }
2917 defer if (comp.bin_file) |lf| {2932 defer if (comp.bin_file) |lf| {
...@@ -3189,8 +3204,8 @@ fn flush(comp: *Compilation, arena: Allocator) (Io.Cancelable || Allocator.Error...@@ -3189,8 +3204,8 @@ fn flush(comp: *Compilation, arena: Allocator) (Io.Cancelable || Allocator.Error
3189 break :p try p.toStringZ(arena);3204 break :p try p.toStringZ(arena);
3190 },3205 },
31913206
3192 .is_debug = comp.root_mod.optimize_mode == .Debug,3207 .is_debug = comp.root_mod.optimize_mode == .debug,
3193 .is_small = comp.root_mod.optimize_mode == .ReleaseSmall,3208 .is_small = comp.root_mod.optimize_mode == .small,
3194 .time_report = if (comp.time_report) |*p| p else null,3209 .time_report = if (comp.time_report) |*p| p else null,
3195 .sanitize_thread = comp.config.any_sanitize_thread,3210 .sanitize_thread = comp.config.any_sanitize_thread,
3196 .fuzz = comp.config.any_fuzz,3211 .fuzz = comp.config.any_fuzz,
...@@ -3660,11 +3675,11 @@ pub fn saveState(comp: *Compilation) !void {...@@ -3660,11 +3675,11 @@ pub fn saveState(comp: *Compilation) !void {
3660 addBuf(&bufs, @ptrCast(wasm.object_relocations_table.values()));3675 addBuf(&bufs, @ptrCast(wasm.object_relocations_table.values()));
3661 addBuf(&bufs, @ptrCast(wasm.object_comdat_symbols.items(.kind)));3676 addBuf(&bufs, @ptrCast(wasm.object_comdat_symbols.items(.kind)));
3662 addBuf(&bufs, @ptrCast(wasm.object_comdat_symbols.items(.index)));3677 addBuf(&bufs, @ptrCast(wasm.object_comdat_symbols.items(.index)));
3663 addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.tag)));3678 addBuf(&bufs, @ptrCast(wasm.zcu_relocations.items(.tag)));
3664 addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.offset)));3679 addBuf(&bufs, @ptrCast(wasm.zcu_relocations.items(.offset)));
3665 // TODO handle the union safety field3680 // TODO handle the union safety field
3666 //addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.pointee)));3681 //addBuf(&bufs, @ptrCast(wasm.zcu_relocations.items(.pointee)));
3667 addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.addend)));3682 addBuf(&bufs, @ptrCast(wasm.zcu_relocations.items(.addend)));
3668 addBuf(&bufs, @ptrCast(wasm.uav_fixups.items));3683 addBuf(&bufs, @ptrCast(wasm.uav_fixups.items));
3669 addBuf(&bufs, @ptrCast(wasm.nav_fixups.items));3684 addBuf(&bufs, @ptrCast(wasm.nav_fixups.items));
3670 addBuf(&bufs, @ptrCast(wasm.func_table_fixups.items));3685 addBuf(&bufs, @ptrCast(wasm.func_table_fixups.items));
...@@ -4061,7 +4076,14 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle {...@@ -4061,7 +4076,14 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle {
4061 ref = refs.get(r.referencer).?;4076 ref = refs.get(r.referencer).?;
4062 }4077 }
4063 }4078 }
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 }
4065 }4087 }
4066 };4088 };
40674089
...@@ -4744,7 +4766,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU...@@ -4744,7 +4766,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU
4744 defer arena_allocator.deinit();4766 defer arena_allocator.deinit();
4745 const arena = arena_allocator.allocator();4767 const arena = arena_allocator.allocator();
47464768
4747 const optimize_mode = std.lang.OptimizeMode.ReleaseSmall;4769 const optimize_mode: std.lang.Optimize = .small;
4748 const output_mode = std.lang.OutputMode.Exe;4770 const output_mode = std.lang.OutputMode.Exe;
4749 const resolved_target: Module.ResolvedTarget = .{4771 const resolved_target: Module.ResolvedTarget = .{
4750 .result = std.zig.system.resolveTargetQuery(io, .{4772 .result = std.zig.system.resolveTargetQuery(io, .{
...@@ -5910,8 +5932,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -5910,8 +5932,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
5910 // them being defined matches the behavior of how MSVC calls rc.exe which is the more5932 // them being defined matches the behavior of how MSVC calls rc.exe which is the more
5911 // relevant behavior in this case.5933 // relevant behavior in this case.
5912 switch (rc_src.owner.optimize_mode) {5934 switch (rc_src.owner.optimize_mode) {
5913 .Debug, .ReleaseSafe => {},5935 .debug, .safe => {},
5914 .ReleaseFast, .ReleaseSmall => try argv.append("-DNDEBUG"),5936 .fast, .small => try argv.append("-DNDEBUG"),
5915 }5937 }
5916 try argv.appendSlice(rc_src.extra_flags);5938 try argv.appendSlice(rc_src.extra_flags);
5917 try argv.appendSlice(&.{ "--", rc_src.src_path, out_res_path });5939 try argv.appendSlice(&.{ "--", rc_src.src_path, out_res_path });
...@@ -6006,26 +6028,30 @@ fn spawnZigRc(...@@ -6006,26 +6028,30 @@ fn spawnZigRc(
6006 multi_reader.init(gpa, io, multi_reader_buffer.toStreams(), &.{ child.stdout.?, child.stderr.? });6028 multi_reader.init(gpa, io, multi_reader_buffer.toStreams(), &.{ child.stdout.?, child.stderr.? });
6007 defer multi_reader.deinit();6029 defer multi_reader.deinit();
60086030
6009 const stdout = multi_reader.fileReader(0);6031 const stdout = multi_reader.reader(0);
6010 const MessageHeader = std.zig.Server.Message.Header;
60116032
6012 var eos_err: error{EndOfStream}!void = {};6033 var eos_err: error{EndOfStream}!void = {};
60136034
6035 var client: std.zig.Client = .{
6036 .in = stdout,
6037 .out = undefined,
6038 };
6039
6014 while (true) {6040 while (true) {
6015 const header = stdout.interface.takeStruct(MessageHeader, .little) catch |err| switch (err) {6041 const header = client.receiveMessageWithMultiReader(&multi_reader, .none) catch |err| switch (err) {
6016 error.EndOfStream => break,6042 error.Timeout => unreachable,
6017 error.ReadFailed => return stdout.err.?,
6018 };
6019 const body = stdout.interface.take(header.bytes_len) catch |err| switch (err) {
6020 error.EndOfStream => |e| {6043 error.EndOfStream => |e| {
6044 if (client.in.bufferedLen() == 0) break;
6021 // Better to report the crash with stderr below, but we set6045 // Better to report the crash with stderr below, but we set
6022 // this in case the child exits successfully while violating6046 // this in case the child exits successfully while violating
6023 // this protocol.6047 // this protocol.
6024 eos_err = e;6048 eos_err = e;
6025 break;6049 break;
6026 },6050 },
6027 error.ReadFailed => return stdout.err.?,6051 else => |e| return e,
6028 };6052 };
6053 const body = client.in.take(header.bytes_len) catch unreachable;
6054
6029 switch (header.tag) {6055 switch (header.tag) {
6030 // We expect exactly one ErrorBundle, and if any error_bundle header is6056 // We expect exactly one ErrorBundle, and if any error_bundle header is
6031 // sent then it's a fatal error.6057 // sent then it's a fatal error.
...@@ -6178,11 +6204,11 @@ fn addCommonCCArgs(...@@ -6178,11 +6204,11 @@ fn addCommonCCArgs(
6178 // LLVM IR files don't support these flags.6204 // LLVM IR files don't support these flags.
6179 if (ext != .ll and ext != .bc) {6205 if (ext != .ll and ext != .bc) {
6180 switch (mod.optimize_mode) {6206 switch (mod.optimize_mode) {
6181 .Debug => {},6207 .debug => {},
6182 .ReleaseSafe => {6208 .safe => {
6183 try argv.append("-D_FORTIFY_SOURCE=2");6209 try argv.append("-D_FORTIFY_SOURCE=2");
6184 },6210 },
6185 .ReleaseFast, .ReleaseSmall => {6211 .fast, .small => {
6186 try argv.append("-DNDEBUG");6212 try argv.append("-DNDEBUG");
6187 },6213 },
6188 }6214 }
...@@ -6333,7 +6359,7 @@ fn addCommonCCArgs(...@@ -6333,7 +6359,7 @@ fn addCommonCCArgs(
6333 }6359 }
6334 }6360 }
63356361
6336 if (mod.optimize_mode != .Debug) {6362 if (mod.optimize_mode != .debug) {
6337 try argv.append("-Werror=date-time");6363 try argv.append("-Werror=date-time");
6338 }6364 }
6339 },6365 },
...@@ -6412,18 +6438,18 @@ fn addCommonCCArgs(...@@ -6412,18 +6438,18 @@ fn addCommonCCArgs(
6412 }6438 }
64136439
6414 switch (mod.optimize_mode) {6440 switch (mod.optimize_mode) {
6415 .Debug => {6441 .debug => {
6416 // Clang has -Og for compatibility with GCC, but currently it is just equivalent6442 // Clang has -Og for compatibility with GCC, but currently it is just equivalent
6417 // to -O1. Besides potentially impairing debugging, -O1/-Og significantly6443 // to -O1. Besides potentially impairing debugging, -O1/-Og significantly
6418 // increases compile times.6444 // increases compile times.
6419 try argv.append("-O0");6445 try argv.append("-O0");
6420 },6446 },
6421 .ReleaseSafe => {6447 .safe => {
6422 // See the comment in the BuildModeFastRelease case for why we pass -O2 rather6448 // See the comment in the BuildModeFastRelease case for why we pass -O2 rather
6423 // than -O3 here.6449 // than -O3 here.
6424 try argv.append("-O2");6450 try argv.append("-O2");
6425 },6451 },
6426 .ReleaseFast => {6452 .fast => {
6427 // Here we pass -O2 rather than -O3 because, although we do the equivalent of6453 // Here we pass -O2 rather than -O3 because, although we do the equivalent of
6428 // -O3 in Zig code, the justification for the difference here is that Zig6454 // -O3 in Zig code, the justification for the difference here is that Zig
6429 // has better detection and prevention of undefined behavior, so -O3 is safer for6455 // has better detection and prevention of undefined behavior, so -O3 is safer for
...@@ -6431,7 +6457,7 @@ fn addCommonCCArgs(...@@ -6431,7 +6457,7 @@ fn addCommonCCArgs(
6431 // running in -O2 and thus the -O3 path has been tested less.6457 // running in -O2 and thus the -O3 path has been tested less.
6432 try argv.append("-O2");6458 try argv.append("-O2");
6433 },6459 },
6434 .ReleaseSmall => {6460 .small => {
6435 try argv.append("-Os");6461 try argv.append("-Os");
6436 },6462 },
6437 }6463 }
...@@ -6641,6 +6667,8 @@ pub fn addCCArgs(...@@ -6641,6 +6667,8 @@ pub fn addCCArgs(
66416667
6642 // Only compiled files support these flags.6668 // Only compiled files support these flags.
6643 switch (ext) {6669 switch (ext) {
6670 .assembly,
6671 .assembly_with_cpp,
6644 .c,6672 .c,
6645 .h,6673 .h,
6646 .cpp,6674 .cpp,
...@@ -7254,7 +7282,6 @@ fn buildOutputFromZig(...@@ -7254,7 +7282,6 @@ fn buildOutputFromZig(
7254 .unwind_tables = comp.root_mod.unwind_tables,7282 .unwind_tables = comp.root_mod.unwind_tables,
7255 .pic = comp.root_mod.pic,7283 .pic = comp.root_mod.pic,
7256 .optimize_mode = optimize_mode,7284 .optimize_mode = optimize_mode,
7257 .structured_cfg = comp.root_mod.structured_cfg,
7258 .no_builtin = true,7285 .no_builtin = true,
7259 .code_model = comp.root_mod.code_model,7286 .code_model = comp.root_mod.code_model,
7260 .error_tracing = false,7287 .error_tracing = false,
...@@ -7403,7 +7430,6 @@ pub fn build_crt_file(...@@ -7403,7 +7430,6 @@ pub fn build_crt_file(
7403 // Some CRT objects (e.g. musl's rcrt1.o and Scrt1.o) are opinionated about PIC.7430 // Some CRT objects (e.g. musl's rcrt1.o and Scrt1.o) are opinionated about PIC.
7404 .pic = options.pic orelse comp.root_mod.pic,7431 .pic = options.pic orelse comp.root_mod.pic,
7405 .optimize_mode = comp.compilerRtOptMode(),7432 .optimize_mode = comp.compilerRtOptMode(),
7406 .structured_cfg = comp.root_mod.structured_cfg,
7407 // Some libcs (e.g. musl) are opinionated about -fno-builtin.7433 // Some libcs (e.g. musl) are opinionated about -fno-builtin.
7408 .no_builtin = options.no_builtin orelse comp.root_mod.no_builtin,7434 .no_builtin = options.no_builtin orelse comp.root_mod.no_builtin,
7409 .code_model = comp.root_mod.code_model,7435 .code_model = comp.root_mod.code_model,
...@@ -7557,15 +7583,15 @@ pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -7557,15 +7583,15 @@ pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void {
75577583
7558/// This decides the optimization mode for all zig-provided libraries, including7584/// This decides the optimization mode for all zig-provided libraries, including
7559/// compiler-rt, libcxx, libc, libunwind, etc.7585/// compiler-rt, libcxx, libc, libunwind, etc.
7560pub fn compilerRtOptMode(comp: Compilation) std.lang.OptimizeMode {7586pub fn compilerRtOptMode(comp: Compilation) std.lang.Optimize {
7561 if (comp.debug_compiler_runtime_libs) |mode| {7587 if (comp.debug_compiler_runtime_libs) |mode| {
7562 return mode;7588 return mode;
7563 }7589 }
7564 const target = &comp.root_mod.resolved_target.result;7590 const target = &comp.root_mod.resolved_target.result;
7565 switch (comp.root_mod.optimize_mode) {7591 switch (comp.root_mod.optimize_mode) {
7566 .Debug, .ReleaseSafe => return target_util.defaultCompilerRtOptimizeMode(target),7592 .debug, .safe => return target_util.defaultCompilerRtOptimizeMode(target),
7567 .ReleaseFast => return .ReleaseFast,7593 .fast => return .fast,
7568 .ReleaseSmall => return .ReleaseSmall,7594 .small => return .small,
7569 }7595 }
7570}7596}
75717597
src/Compilation/Config.zig+7-7
...@@ -59,7 +59,7 @@ export_memory: bool,...@@ -59,7 +59,7 @@ export_memory: bool,
59shared_memory: bool,59shared_memory: bool,
60is_test: bool,60is_test: bool,
61debug_format: DebugFormat,61debug_format: DebugFormat,
62root_optimize_mode: std.lang.OptimizeMode,62root_optimize_mode: std.lang.Optimize,
63root_strip: bool,63root_strip: bool,
64root_error_tracing: bool,64root_error_tracing: bool,
65dll_export_fns: bool,65dll_export_fns: bool,
...@@ -80,7 +80,7 @@ pub const Options = struct {...@@ -80,7 +80,7 @@ pub const Options = struct {
80 is_test: bool,80 is_test: bool,
81 have_zcu: bool,81 have_zcu: bool,
82 emit_bin: bool,82 emit_bin: bool,
83 root_optimize_mode: ?std.lang.OptimizeMode = null,83 root_optimize_mode: ?std.lang.Optimize = null,
84 root_strip: ?bool = null,84 root_strip: ?bool = null,
85 root_error_tracing: ?bool = null,85 root_error_tracing: ?bool = null,
86 link_mode: ?std.lang.LinkMode = null,86 link_mode: ?std.lang.LinkMode = null,
...@@ -196,7 +196,7 @@ pub fn resolve(options: Options) ResolveError!Config {...@@ -196,7 +196,7 @@ pub fn resolve(options: Options) ResolveError!Config {
196 break :b options.use_lib_llvm orelse true;196 break :b options.use_lib_llvm orelse true;
197 };197 };
198198
199 const root_optimize_mode = options.root_optimize_mode orelse .Debug;199 const root_optimize_mode = options.root_optimize_mode orelse .debug;
200200
201 // Make a decision on whether to use Clang or Aro for translate-c and compiling C files.201 // Make a decision on whether to use Clang or Aro for translate-c and compiling C files.
202 const c_frontend: CFrontend = b: {202 const c_frontend: CFrontend = b: {
...@@ -357,7 +357,7 @@ pub fn resolve(options: Options) ResolveError!Config {...@@ -357,7 +357,7 @@ pub fn resolve(options: Options) ResolveError!Config {
357 if (!use_lib_llvm and options.emit_bin) break :b false;357 if (!use_lib_llvm and options.emit_bin) break :b false;
358358
359 // Prefer LLVM for release builds.359 // Prefer LLVM for release builds.
360 if (root_optimize_mode != .Debug) break :b true;360 if (root_optimize_mode != .debug) break :b true;
361361
362 // load_dynamic_library standalone test not passing on this combination362 // load_dynamic_library standalone test not passing on this combination
363 // https://github.com/ziglang/zig/issues/24080363 // https://github.com/ziglang/zig/issues/24080
...@@ -486,7 +486,7 @@ pub fn resolve(options: Options) ResolveError!Config {...@@ -486,7 +486,7 @@ pub fn resolve(options: Options) ResolveError!Config {
486486
487 const root_strip = b: {487 const root_strip = b: {
488 if (options.root_strip) |x| break :b x;488 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;
490 if (!target_util.hasDebugInfo(target)) break :b true;490 if (!target_util.hasDebugInfo(target)) break :b true;
491 break :b false;491 break :b false;
492 };492 };
...@@ -512,8 +512,8 @@ pub fn resolve(options: Options) ResolveError!Config {...@@ -512,8 +512,8 @@ pub fn resolve(options: Options) ResolveError!Config {
512 if (root_strip) break :b false;512 if (root_strip) break :b false;
513 if (!backend_supports_error_tracing) break :b false;513 if (!backend_supports_error_tracing) break :b false;
514 break :b switch (root_optimize_mode) {514 break :b switch (root_optimize_mode) {
515 .Debug => true,515 .debug => true,
516 .ReleaseSafe, .ReleaseFast, .ReleaseSmall => false,516 .safe, .fast, .small => false,
517 };517 };
518 };518 };
519519
src/IncrementalDebugServer.zig+24-11
...@@ -130,7 +130,7 @@ fn serveStream(...@@ -130,7 +130,7 @@ fn serveStream(
130 try stream_writer.writeAll("zig> ");130 try stream_writer.writeAll("zig> ");
131 const untrimmed = try stream_reader.takeSentinel('\n');131 const untrimmed = try stream_reader.takeSentinel('\n');
132 const cmd_and_arg = std.mem.trim(u8, untrimmed, " \t\r\n");132 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|
134 .{ cmd_and_arg[0..i], cmd_and_arg[i + 1 ..] }134 .{ cmd_and_arg[0..i], cmd_and_arg[i + 1 ..] }
135 else135 else
136 .{ cmd_and_arg, "" };136 .{ cmd_and_arg, "" };
...@@ -244,7 +244,7 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const...@@ -244,7 +244,7 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const
244 const ty: Type = .fromInterned(type_ip_index);244 const ty: Type = .fromInterned(type_ip_index);
245 const ty_name = ty.containerTypeName(ip).toSlice(ip);245 const ty_name = ty.containerTypeName(ip).toSlice(ip);
246 const success = switch (@as(u2, @intFromBool(anchor_start)) << 1 | @intFromBool(anchor_end)) {246 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,
248 0b01 => std.mem.endsWith(u8, ty_name, query),248 0b01 => std.mem.endsWith(u8, ty_name, query),
249 0b10 => std.mem.startsWith(u8, ty_name, query),249 0b10 => std.mem.startsWith(u8, ty_name, query),
250 0b11 => std.mem.eql(u8, ty_name, query),250 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...@@ -265,7 +265,7 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const
265 const nav = ip.getNav(nav_index);265 const nav = ip.getNav(nav_index);
266 const nav_fqn = nav.fqn.toSlice(ip);266 const nav_fqn = nav.fqn.toSlice(ip);
267 const success = switch (@as(u2, @intFromBool(anchor_start)) << 1 | @intFromBool(anchor_end)) {267 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,
269 0b01 => std.mem.endsWith(u8, nav_fqn, query),269 0b01 => std.mem.endsWith(u8, nav_fqn, query),
270 0b10 => std.mem.startsWith(u8, nav_fqn, query),270 0b10 => std.mem.startsWith(u8, nav_fqn, query),
271 0b11 => std.mem.eql(u8, nav_fqn, query),271 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...@@ -286,21 +286,34 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const
286 const referencer = (ref orelse break :ref "<analysis root>").referencer;286 const referencer = (ref orelse break :ref "<analysis root>").referencer;
287 break :ref printAnalUnit(referencer, &ref_str_buf);287 break :ref printAnalUnit(referencer, &ref_str_buf);
288 };288 };
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 };
294 try w.print(289 try w.print(
295 \\last update generation: {d}290 \\last update generation: {d}
296 \\current referencer: {s}291 \\current referencer: {s}
297 \\has error: {s}
298 \\292 \\
299 , .{293 , .{
300 unit_info.last_update_gen,294 unit_info.last_update_gen,
301 ref_str,295 ref_str,
302 has_err,
303 });296 });
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 }
304 } else if (std.mem.eql(u8, cmd_str, "unit_dependencies")) {317 } else if (std.mem.eql(u8, cmd_str, "unit_dependencies")) {
305 const unit = parseAnalUnit(arg_str) orelse return w.writeAll("malformed anal unit");318 const unit = parseAnalUnit(arg_str) orelse return w.writeAll("malformed anal unit");
306 const unit_info = zcu.incremental_debug_state.units.get(unit) orelse return w.writeAll("unknown anal unit");319 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 {...@@ -365,7 +378,7 @@ fn parseIndex(str: []const u8) ?u32 {
365 return std.fmt.parseInt(u32, str, 10) catch null;378 return std.fmt.parseInt(u32, str, 10) catch null;
366}379}
367fn parseAnalUnit(str: []const u8) ?AnalUnit {380fn 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;
369 const kind = str[0..split_idx];382 const kind = str[0..split_idx];
370 const idx_str = str[split_idx + 1 ..];383 const idx_str = str[split_idx + 1 ..];
371 if (std.mem.eql(u8, kind, "comptime")) {384 if (std.mem.eql(u8, kind, "comptime")) {
src/InternPool.zig+30-30
...@@ -1737,7 +1737,7 @@ pub const String = enum(u32) {...@@ -1737,7 +1737,7 @@ pub const String = enum(u32) {
1737 }1737 }
17381738
1739 pub fn toNullTerminatedString(string: String, len: u64, ip: *const InternPool) NullTerminatedString {1739 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);
1741 assert(string.at(len, ip) == 0);1741 assert(string.at(len, ip) == 0);
1742 return @fromBackingInt(@intCast(@backingInt(string)));1742 return @fromBackingInt(@intCast(@backingInt(string)));
1743 }1743 }
...@@ -1864,7 +1864,7 @@ pub const NullTerminatedString = enum(u32) {...@@ -1864,7 +1864,7 @@ pub const NullTerminatedString = enum(u32) {
1864 pub fn toUnsigned(string: NullTerminatedString, ip: *const InternPool) ?u32 {1864 pub fn toUnsigned(string: NullTerminatedString, ip: *const InternPool) ?u32 {
1865 const slice = string.toSlice(ip);1865 const slice = string.toSlice(ip);
1866 if (slice.len > 1 and slice[0] == '0') return null;1866 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;
1868 return std.fmt.parseUnsigned(u32, slice, 10) catch null;1868 return std.fmt.parseUnsigned(u32, slice, 10) catch null;
1869 }1869 }
18701870
...@@ -4193,7 +4193,7 @@ pub const Index = enum(u32) {...@@ -4193,7 +4193,7 @@ pub const Index = enum(u32) {
4193 };4193 };
4194 }4194 }
41954195
4196 /// This function is used in the debugger pretty formatters in tools/ to fetch the4196 /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the
4197 /// Tag to encoding mapping to facilitate fancy debug printing for this type.4197 /// Tag to encoding mapping to facilitate fancy debug printing for this type.
4198 fn dbHelper(self: *Index, tag_to_encoding_map: *struct {4198 fn dbHelper(self: *Index, tag_to_encoding_map: *struct {
4199 const DataIsIndex = struct { data: Index };4199 const DataIsIndex = struct { data: Index };
...@@ -4219,26 +4219,17 @@ pub const Index = enum(u32) {...@@ -4219,26 +4219,17 @@ pub const Index = enum(u32) {
4219 type_inferred_error_set: DataIsIndex,4219 type_inferred_error_set: DataIsIndex,
4220 simple_type: void,4220 simple_type: void,
4221 type_function: struct {4221 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 {};
4225 const @"data.params_len" = opaque {};4222 const @"data.params_len" = opaque {};
4226 data: *Tag.TypeFunction,4223 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()",
4230 @"trailing.param_types.len": *@"data.params_len",4224 @"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 },
4232 },4226 },
4233 type_tuple: struct {4227 type_tuple: struct {
4234 const @"data.fields_len" = opaque {};4228 const @"data.fields_len" = opaque {};
4235 data: *TypeTuple,4229 data: *TypeTuple,
4236 @"trailing.types.len": *@"data.fields_len",4230 @"trailing.types.len": *@"data.fields_len",
4237 @"trailing.values.len": *@"data.fields_len",4231 @"trailing.values.len": *@"data.fields_len",
4238 trailing: struct {4232 trailing: struct { types: []Index, values: []Index },
4239 types: []Index,
4240 values: []Index,
4241 },
4242 },4233 },
42434234
4244 type_struct: struct { data: *Tag.TypeStruct },4235 type_struct: struct { data: *Tag.TypeStruct },
...@@ -4350,7 +4341,7 @@ pub const Index = enum(u32) {...@@ -4350,7 +4341,7 @@ pub const Index = enum(u32) {
4350 const encoding = @field(Tag.encodings, tag_name);4341 const encoding = @field(Tag.encodings, tag_name);
4351 if (@hasField(@TypeOf(encoding), "trailing")) {4342 if (@hasField(@TypeOf(encoding), "trailing")) {
4352 const trailing_info = @typeInfo(encoding.trailing).@"struct";4343 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| {
4354 struct {4345 struct {
4355 fn checkConfig(name: []const u8) void {4346 fn checkConfig(name: []const u8) void {
4356 if (!@hasField(@TypeOf(encoding.config), name)) @compileError("missing field: " ++ @typeName(Tag) ++ ".encodings." ++ tag_name ++ ".config.@\"" ++ name ++ "\"");4347 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) {...@@ -4359,22 +4350,30 @@ pub const Index = enum(u32) {
4359 }4350 }
4360 fn checkField(name: []const u8, Type: type) void {4351 fn checkField(name: []const u8, Type: type) void {
4361 switch (@typeInfo(Type)) {4352 switch (@typeInfo(Type)) {
4362 .int => {},4353 .int, .@"enum" => return,
4363 .@"enum" => {},4354 .@"struct" => |info| switch (info.layout) {
4364 .@"struct" => |info| assert(info.layout == .@"packed"),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 },
4365 .optional => |info| {4362 .optional => |info| {
4366 checkConfig(name ++ ".?");4363 checkConfig(name ++ ".?");
4367 checkField(name ++ ".?", info.child);4364 checkField(name ++ ".?", info.child);
4365 return;
4368 },4366 },
4369 .pointer => |info| {4367 .pointer => |info| if (info.size == .slice) {
4370 assert(info.size == .slice);
4371 checkConfig(name ++ ".len");4368 checkConfig(name ++ ".len");
4372 checkField(name ++ "[0]", info.child);4369 checkField(name ++ "[0]", info.child);
4370 return;
4373 },4371 },
4374 else => @compileError("unsupported type: " ++ @typeName(Tag) ++ ".encodings." ++ tag_name ++ "." ++ name ++ ": " ++ @typeName(Type)),4372 else => {},
4375 }4373 }
4374 @compileError("unsupported type: " ++ @typeName(Tag) ++ ".encodings." ++ tag_name ++ "." ++ name ++ ": " ++ @typeName(Type));
4376 }4375 }
4377 }.checkField("trailing." ++ field_name, field_type);4376 }.checkField("trailing." ++ trailing_field_name, trailing_field_type);
4378 }4377 }
4379 }4378 }
4380 },4379 },
...@@ -5186,17 +5185,18 @@ pub const Tag = enum(u8) {...@@ -5186,17 +5185,18 @@ pub const Tag = enum(u8) {
5186 .trailing = struct {5185 .trailing = struct {
5187 param_comptime_bits: ?[]u32,5186 param_comptime_bits: ?[]u32,
5188 param_noalias_bits: ?[]u32,5187 param_noalias_bits: ?[]u32,
5189 param_cc_bits: ?[]u32,5188 spirv_kernel_options: ?extern struct { x: u32, y: u32, z: u32 },
5190 param_type: []Index,5189 spirv_mesh_options: ?extern struct { max_primitives: u32, max_vertices: u32 },
5190 param_types: []Index,
5191 },5191 },
5192 .config = .{5192 .config = .{
5193 .@"trailing.param_comptime_bits.?" = .@"payload.flags.has_comptime_bits",5193 .@"trailing.param_comptime_bits.?" = .@"payload.flags.has_comptime_bits",
5194 .@"trailing.param_comptime_bits.?.len" = .@"(payload.params_len + 31) / 32",5194 .@"trailing.param_comptime_bits.?.len" = .@"(payload.params_len + 31) / 32",
5195 .@"trailing.param_noalias_bits.?" = .@"payload.flags.has_noalias_bits",5195 .@"trailing.param_noalias_bits.?" = .@"payload.flags.has_noalias_bits",
5196 .@"trailing.param_noalias_bits.?.len" = .@"(payload.params_len + 31) / 32",5196 .@"trailing.param_noalias_bits.?.len" = .@"(payload.params_len + 31) / 32",
5197 .@"trailing.param_cc_bits.?" = .@"payload.flags.cc.extraLen() != 0",5197 .@"trailing.spirv_kernel_options.?" = .@"payload.flags.cc.tag == .spirv_kernel or payload.flags.cc.tag == .spirv_task",
5198 .@"trailing.param_cc_bits.?.len" = .@"payload.flags.cc.extraLen()",5198 .@"trailing.spirv_mesh_options.?" = .@"payload.flags.cc.tag == .spirv_mesh",
5199 .@"trailing.param_type.len" = .@"payload.params_len",5199 .@"trailing.param_types.len" = .@"payload.params_len",
5200 },5200 },
5201 },5201 },
52025202
...@@ -5225,7 +5225,7 @@ pub const Tag = enum(u8) {...@@ -5225,7 +5225,7 @@ pub const Tag = enum(u8) {
5225 .@"trailing.field_defaults.?" = .@"payload.flags.any_field_defaults",5225 .@"trailing.field_defaults.?" = .@"payload.flags.any_field_defaults",
5226 .@"trailing.field_defaults.?.len" = .@"payload.fields_len",5226 .@"trailing.field_defaults.?.len" = .@"payload.fields_len",
5227 .@"trailing.field_aligns.?" = .@"payload.flags.any_field_aligns",5227 .@"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",
5229 .@"trailing.field_is_comptime_bits.?" = .@"payload.flags.any_comptime_fields",5229 .@"trailing.field_is_comptime_bits.?" = .@"payload.flags.any_comptime_fields",
5230 .@"trailing.field_is_comptime_bits.?.len" = .@"(payload.fields_len + 31) / 32",5230 .@"trailing.field_is_comptime_bits.?.len" = .@"(payload.fields_len + 31) / 32",
5231 .@"trailing.field_runtime_order.?" = .@"payload.flags.layout == .auto",5231 .@"trailing.field_runtime_order.?" = .@"payload.flags.layout == .auto",
...@@ -5254,7 +5254,7 @@ pub const Tag = enum(u8) {...@@ -5254,7 +5254,7 @@ pub const Tag = enum(u8) {
5254 .@"trailing.captures.?.len" = .@"trailing.captures_len.?",5254 .@"trailing.captures.?.len" = .@"trailing.captures_len.?",
5255 .@"trailing.field_types.len" = .@"payload.fields_len",5255 .@"trailing.field_types.len" = .@"payload.fields_len",
5256 .@"trailing.field_aligns.?" = .@"payloads.flags.any_field_aligns",5256 .@"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",
5258 },5258 },
5259 },5259 },
5260 .type_union_packed_auto = union_packed_encoding,5260 .type_union_packed_auto = union_packed_encoding,
...@@ -11428,7 +11428,7 @@ pub fn getOrPutTrailingString(...@@ -11428,7 +11428,7 @@ pub fn getOrPutTrailingString(
11428 .tid = tid,11428 .tid = tid,
11429 .index = strings.mutate.len - 1,11429 .index = strings.mutate.len - 1,
11430 }).wrap(ip))));11430 }).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;
11432 switch (embedded_nulls) {11432 switch (embedded_nulls) {
11433 .no_embedded_nulls => assert(!has_embedded_null),11433 .no_embedded_nulls => assert(!has_embedded_null),
11434 .maybe_embedded_nulls => if (has_embedded_null) {11434 .maybe_embedded_nulls => if (has_embedded_null) {
src/Module.zig+9-26
...@@ -26,7 +26,7 @@ fully_qualified_name: []const u8,...@@ -26,7 +26,7 @@ fully_qualified_name: []const u8,
26deps: Deps = .{},26deps: Deps = .{},
2727
28resolved_target: ResolvedTarget,28resolved_target: ResolvedTarget,
29optimize_mode: std.lang.OptimizeMode,29optimize_mode: std.lang.Optimize,
30code_model: std.lang.CodeModel,30code_model: std.lang.CodeModel,
31single_threaded: bool,31single_threaded: bool,
32error_tracing: bool,32error_tracing: bool,
...@@ -42,8 +42,6 @@ sanitize_thread: bool,...@@ -42,8 +42,6 @@ sanitize_thread: bool,
42fuzz: bool,42fuzz: bool,
43unwind_tables: std.lang.UnwindTables,43unwind_tables: std.lang.UnwindTables,
44cc_argv: []const []const u8,44cc_argv: []const []const u8,
45/// (SPIR-V) whether to generate a structured control flow graph or not
46structured_cfg: bool,
47no_builtin: bool,45no_builtin: bool,
4846
49pub const Deps = std.array_hash_map.String(*Module);47pub const Deps = std.array_hash_map.String(*Module);
...@@ -67,7 +65,7 @@ pub const CreateOptions = struct {...@@ -67,7 +65,7 @@ pub const CreateOptions = struct {
67 pub const Inherited = struct {65 pub const Inherited = struct {
68 /// If this is null then `parent` must be non-null.66 /// If this is null then `parent` must be non-null.
69 resolved_target: ?ResolvedTarget = null,67 resolved_target: ?ResolvedTarget = null,
70 optimize_mode: ?std.lang.OptimizeMode = null,68 optimize_mode: ?std.lang.Optimize = null,
71 code_model: ?std.lang.CodeModel = null,69 code_model: ?std.lang.CodeModel = null,
72 single_threaded: ?bool = null,70 single_threaded: ?bool = null,
73 error_tracing: ?bool = null,71 error_tracing: ?bool = null,
...@@ -85,7 +83,6 @@ pub const CreateOptions = struct {...@@ -85,7 +83,6 @@ pub const CreateOptions = struct {
85 sanitize_c: ?std.zig.SanitizeC = null,83 sanitize_c: ?std.zig.SanitizeC = null,
86 sanitize_thread: ?bool = null,84 sanitize_thread: ?bool = null,
87 fuzz: ?bool = null,85 fuzz: ?bool = null,
88 structured_cfg: ?bool = null,
89 no_builtin: ?bool = null,86 no_builtin: ?bool = null,
90 };87 };
91};88};
...@@ -144,7 +141,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {...@@ -144,7 +141,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {
144 if (options.inherited.valgrind) |x| break :b x;141 if (options.inherited.valgrind) |x| break :b x;
145 if (options.parent) |p| break :b p.valgrind;142 if (options.parent) |p| break :b p.valgrind;
146 if (strip) break :b false;143 if (strip) break :b false;
147 break :b optimize_mode == .Debug;144 break :b optimize_mode == .debug;
148 };145 };
149146
150 const single_threaded = b: {147 const single_threaded = b: {
...@@ -212,7 +209,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {...@@ -212,7 +209,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {
212 const omit_frame_pointer = b: {209 const omit_frame_pointer = b: {
213 if (options.inherited.omit_frame_pointer) |x| break :b x;210 if (options.inherited.omit_frame_pointer) |x| break :b x;
214 if (options.parent) |p| break :b p.omit_frame_pointer;211 if (options.parent) |p| break :b p.omit_frame_pointer;
215 if (optimize_mode == .ReleaseSmall) {212 if (optimize_mode == .small) {
216 // On x86, in most cases, keeping the frame pointer usually results in smaller binary size.213 // On x86, in most cases, keeping the frame pointer usually results in smaller binary size.
217 // This has to do with how instructions for memory access via the stack base pointer register (when keeping the frame pointer)214 // This has to do with how instructions for memory access via the stack base pointer register (when keeping the frame pointer)
218 // are smaller than instructions for memory access via the stack pointer register (when omitting the frame pointer).215 // 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 {...@@ -251,21 +248,21 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {
251 };248 };
252249
253 const is_safe_mode = switch (optimize_mode) {250 const is_safe_mode = switch (optimize_mode) {
254 .Debug, .ReleaseSafe => true,251 .debug, .safe => true,
255 .ReleaseFast, .ReleaseSmall => false,252 .fast, .small => false,
256 };253 };
257254
258 const sanitize_c: std.zig.SanitizeC = b: {255 const sanitize_c: std.zig.SanitizeC = b: {
259 if (options.inherited.sanitize_c) |x| break :b x;256 if (options.inherited.sanitize_c) |x| break :b x;
260 if (options.parent) |p| break :b p.sanitize_c;257 if (options.parent) |p| break :b p.sanitize_c;
261 break :b switch (optimize_mode) {258 break :b switch (optimize_mode) {
262 .Debug => .full,259 .debug => .full,
263 // It's recommended to use the minimal runtime in production260 // It's recommended to use the minimal runtime in production
264 // environments due to the security implications of the full runtime.261 // environments due to the security implications of the full runtime.
265 // The minimal runtime doesn't provide much benefit over simply262 // The minimal runtime doesn't provide much benefit over simply
266 // trapping, however, so we do that instead.263 // trapping, however, so we do that instead.
267 .ReleaseSafe => .trap,264 .safe => .trap,
268 .ReleaseFast, .ReleaseSmall => .off,265 .fast, .small => .off,
269 };266 };
270 };267 };
271268
...@@ -320,17 +317,6 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {...@@ -320,17 +317,6 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {
320 break :sp target_util.default_stack_protector_buffer_size;317 break :sp target_util.default_stack_protector_buffer_size;
321 };318 };
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
334 const no_builtin = b: {320 const no_builtin = b: {
335 if (options.inherited.no_builtin) |x| break :b x;321 if (options.inherited.no_builtin) |x| break :b x;
336 if (options.parent) |p| break :b p.no_builtin;322 if (options.parent) |p| break :b p.no_builtin;
...@@ -411,7 +397,6 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {...@@ -411,7 +397,6 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {
411 .fuzz = fuzz,397 .fuzz = fuzz,
412 .unwind_tables = unwind_tables,398 .unwind_tables = unwind_tables,
413 .cc_argv = options.cc_argv,399 .cc_argv = options.cc_argv,
414 .structured_cfg = structured_cfg,
415 .no_builtin = no_builtin,400 .no_builtin = no_builtin,
416 };401 };
417 return mod;402 return mod;
...@@ -450,7 +435,6 @@ pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*M...@@ -450,7 +435,6 @@ pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*M
450 .fuzz = undefined,435 .fuzz = undefined,
451 .unwind_tables = undefined,436 .unwind_tables = undefined,
452 .cc_argv = undefined,437 .cc_argv = undefined,
453 .structured_cfg = undefined,
454 .no_builtin = undefined,438 .no_builtin = undefined,
455 };439 };
456 return mod;440 return mod;
...@@ -489,7 +473,6 @@ pub fn createBuiltin(arena: Allocator, opts: Builtin, dirs: std.zig.Directories)...@@ -489,7 +473,6 @@ pub fn createBuiltin(arena: Allocator, opts: Builtin, dirs: std.zig.Directories)
489 .stack_protector = 0,473 .stack_protector = 0,
490 .red_zone = false,474 .red_zone = false,
491 .sanitize_c = .off,475 .sanitize_c = .off,
492 .structured_cfg = false,
493 .no_builtin = false,476 .no_builtin = false,
494 };477 };
495 return new;478 return new;
src/RangeSet.zig+18-23
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const RangeSet = @This();1const RangeSet = @This();
22
3ranges: std.MultiArrayList(Range),3list: std.MultiArrayList(Range),
44
5pub const Range = struct {5pub const Range = struct {
6 first: Value,6 first: Value,
...@@ -8,41 +8,36 @@ pub const Range = struct {...@@ -8,41 +8,36 @@ pub const Range = struct {
8 src: LazySrcLoc,8 src: LazySrcLoc,
9};9};
1010
11pub const empty: RangeSet = .{ .ranges = .empty };11pub const empty: RangeSet = .{ .list = .empty };
1212
13pub fn deinit(self: *RangeSet, allocator: Allocator) void {13pub fn deinit(self: *RangeSet, allocator: Allocator) void {
14 self.ranges.deinit(allocator);14 self.list.deinit(allocator);
15 self.* = undefined;15 self.* = undefined;
16}16}
1717
18pub fn ensureUnusedCapacity(self: *RangeSet, allocator: Allocator, additional_count: usize) Allocator.Error!void {18pub fn ensureUnusedCapacity(set: *RangeSet, allocator: Allocator, additional_count: usize) Allocator.Error!void {
19 return self.ranges.ensureUnusedCapacity(allocator, additional_count);19 return set.list.ensureUnusedCapacity(allocator, additional_count);
20}20}
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 {
23 assert(new.first.typeOf(zcu).eql(ty));23 assert(new.first.typeOf(zcu).eql(ty));
24 assert(new.last.typeOf(zcu).eql(ty));24 assert(new.last.typeOf(zcu).eql(ty));
25 assert(new.first.compareScalar(.lte, new.last, ty, zcu));25 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, .{
28 .val = new.first,28 .val = new.first,
29 .zcu = zcu,29 .zcu = zcu,
30 }), compare);30 }), compare);
3131
32 if (idx != set.ranges.len and // `new.first` is *not* greater than all `old.last`32 if (idx != set.list.len and // `new.first` is *not* greater than all `old.last`
33 new.last.compareScalar(.gte, set.ranges.items(.first)[idx], ty, zcu))33 new.last.compareScalar(.gte, set.list.items(.first)[idx], ty, zcu))
34 {34 {
35 return set.ranges.items(.src)[idx]; // `new` overlaps with existing range.35 return set.list.get(idx); // `new` overlaps with existing range.
36 }36 }
37 set.ranges.insertAssumeCapacity(idx, new);37 set.list.insertAssumeCapacity(idx, new);
38 return null;38 return null;
39}39}
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
46pub fn spans(41pub fn spans(
47 set: *RangeSet,42 set: *RangeSet,
48 allocator: Allocator,43 allocator: Allocator,
...@@ -53,13 +48,13 @@ pub fn spans(...@@ -53,13 +48,13 @@ pub fn spans(
53) Allocator.Error!bool {48) Allocator.Error!bool {
54 assert(first.typeOf(zcu).eql(ty));49 assert(first.typeOf(zcu).eql(ty));
55 assert(last.typeOf(zcu).eql(ty));50 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));53 assert(std.sort.isSorted(Value, set.list.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));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) or56 if (!set.list.items(.first)[0].eql(first, ty, zcu) or
62 !set.ranges.items(.last)[set.ranges.len - 1].eql(last, ty, zcu))57 !set.list.items(.last)[set.list.len - 1].eql(last, ty, zcu))
63 {58 {
64 return false;59 return false;
65 }60 }
...@@ -75,8 +70,8 @@ pub fn spans(...@@ -75,8 +70,8 @@ pub fn spans(
7570
76 // look for gaps71 // look for gaps
77 for (72 for (
78 set.ranges.items(.first)[1..],73 set.list.items(.first)[1..],
79 set.ranges.items(.last)[0 .. set.ranges.len - 1],74 set.list.items(.last)[0 .. set.list.len - 1],
80 ) |cur_first, prev_last| {75 ) |cur_first, prev_last| {
81 // prev_last + 1 == cur_first76 // prev_last + 1 == cur_first
82 counter.copy(prev_last.toBigInt(&space, zcu));77 counter.copy(prev_last.toBigInt(&space, zcu));
src/Sema.zig+551-262
...@@ -532,20 +532,20 @@ pub const Block = struct {...@@ -532,20 +532,20 @@ pub const Block = struct {
532532
533 fn wantSafeTypes(block: *const Block) bool {533 fn wantSafeTypes(block: *const Block) bool {
534 return block.want_safety orelse switch (block.ownerModule().optimize_mode) {534 return block.want_safety orelse switch (block.ownerModule().optimize_mode) {
535 .Debug => true,535 .debug => true,
536 .ReleaseSafe => true,536 .safe => true,
537 .ReleaseFast => false,537 .fast => false,
538 .ReleaseSmall => false,538 .small => false,
539 };539 };
540 }540 }
541541
542 fn wantSafety(block: *const Block) bool {542 fn wantSafety(block: *const Block) bool {
543 if (block.isComptime()) return false; // runtime safety checks are pointless in comptime blocks543 if (block.isComptime()) return false; // runtime safety checks are pointless in comptime blocks
544 return block.want_safety orelse switch (block.ownerModule().optimize_mode) {544 return block.want_safety orelse switch (block.ownerModule().optimize_mode) {
545 .Debug => true,545 .debug => true,
546 .ReleaseSafe => true,546 .safe => true,
547 .ReleaseFast => false,547 .fast => false,
548 .ReleaseSmall => false,548 .small => false,
549 };549 };
550 }550 }
551551
...@@ -1472,7 +1472,7 @@ fn analyzeBodyInner(...@@ -1472,7 +1472,7 @@ fn analyzeBodyInner(
1472 i += 1;1472 i += 1;
1473 continue;1473 continue;
1474 },1474 },
1475 .astgen_error => return error.AnalysisFail,1475 .astgen_error => return sema.failTransitive(.astgen_error),
1476 .float_op_result_ty => try sema.zirFloatOpResultType(block, extended),1476 .float_op_result_ty => try sema.zirFloatOpResultType(block, extended),
1477 };1477 };
1478 },1478 },
...@@ -2247,7 +2247,7 @@ fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) ?Value {...@@ -2247,7 +2247,7 @@ fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) ?Value {
2247 .inferred_alloc_comptime => unreachable, // assertion failure2247 .inferred_alloc_comptime => unreachable, // assertion failure
2248 else => {},2248 else => {},
2249 }2249 }
2250 // LLVM fails to eliminate this `classify` call in ReleaseFast, which hurts performance, so2250 // LLVM fails to eliminate this `classify` call in -Ofast, which hurts performance, so
2251 // we must explicitly check for `std.debug.runtime_safety`.2251 // we must explicitly check for `std.debug.runtime_safety`.
2252 if (std.debug.runtime_safety) switch (sema.typeOf(inst).classify(zcu)) {2252 if (std.debug.runtime_safety) switch (sema.typeOf(inst).classify(zcu)) {
2253 .no_possible_value => unreachable, // values of this type do not exist2253 .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...@@ -2352,6 +2352,10 @@ pub fn failWithUseOfUndef(sema: *Sema, block: *Block, src: LazySrcLoc, vector_in
2352 });2352 });
2353}2353}
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
2355pub fn failWithDivideByZero(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError {2359pub fn failWithDivideByZero(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError {
2356 return sema.fail(block, src, "division by zero here causes illegal behavior", .{});2360 return sema.fail(block, src, "division by zero here causes illegal behavior", .{});
2357}2361}
...@@ -2697,13 +2701,15 @@ fn failWithTypeMismatch(sema: *Sema, block: *Block, src: LazySrcLoc, expected: T...@@ -2697,13 +2701,15 @@ fn failWithTypeMismatch(sema: *Sema, block: *Block, src: LazySrcLoc, expected: T
2697 });2701 });
2698}2702}
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 {
2701 @branchHint(.cold);2705 @branchHint(.cold);
2702 const zcu = sema.pt.zcu;2706 const zcu = sema.pt.zcu;
2703 const comp = zcu.comp;2707 const comp = zcu.comp;
2704 const gpa = comp.gpa;2708 const gpa = comp.gpa;
2705 const io = comp.io;2709 const io = comp.io;
27062710
2711 assert(sema.err == null);
2712
2707 if (build_options.enable_debug_extensions and comp.debug_compile_errors) {2713 if (build_options.enable_debug_extensions and comp.debug_compile_errors) {
2708 var wip_errors: std.zig.ErrorBundle.Wip = undefined;2714 var wip_errors: std.zig.ErrorBundle.Wip = undefined;
2709 wip_errors.init(gpa) catch @panic("out of memory");2715 wip_errors.init(gpa) catch @panic("out of memory");
...@@ -2729,17 +2735,11 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg...@@ -2729,17 +2735,11 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg
27292735
2730 err_msg.reference_trace_root = sema.owner.toOptional();2736 err_msg.reference_trace_root = sema.owner.toOptional();
27312737
2732 const gop = try zcu.failed_analysis.getOrPut(gpa, sema.owner);2738 try zcu.failed_analysis.putNoClobber(gpa, sema.owner, err_msg);
2733 if (gop.found_existing) {2739 assert(!zcu.transitive_failed_analysis.contains(sema.owner));
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 }
27412740
2742 return error.AnalysisFail;2741 sema.err = err_msg;
2742 return error.AlreadyReported;
2743}2743}
27442744
2745/// Given an ErrorMsg, modify its message and source location to the given values, turning the2745/// 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...@@ -3117,9 +3117,14 @@ fn zirRefDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
3117 try sema.validateDeref(block, src, operand, operand_ty);3117 try sema.validateDeref(block, src, operand, operand_ty);
31183118
3119 const ptr_info = operand_ty.ptrInfo(zcu);3119 const ptr_info = operand_ty.ptrInfo(zcu);
3120 return switch (ptr_info.flags.size) {3120 return single_ptr: switch (ptr_info.flags.size) {
3121 .many, .slice => unreachable, // cannot be dereferenced3121 .many => unreachable, // cannot be dereferenced directly
3122 .c => single_ptr: {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 => {
3123 const single_ptr_ty = try pt.ptrType(p: {3128 const single_ptr_ty = try pt.ptrType(p: {
3124 var p = ptr_info;3129 var p = ptr_info;
3125 p.flags.size = .one;3130 p.flags.size = .one;
...@@ -3153,18 +3158,26 @@ fn validateDeref(...@@ -3153,18 +3158,26 @@ fn validateDeref(
3153) CompileError!void {3158) CompileError!void {
3154 const pt = sema.pt;3159 const pt = sema.pt;
3155 const zcu = pt.zcu;3160 const zcu = pt.zcu;
3161 const ip = &zcu.intern_pool;
3156 if (ty.zigTypeTag(zcu) != .pointer) {3162 if (ty.zigTypeTag(zcu) != .pointer) {
3157 return sema.fail(block, src, "cannot dereference non-pointer type '{f}'", .{ty.fmt(pt)});3163 return sema.fail(block, src, "cannot dereference non-pointer type '{f}'", .{ty.fmt(pt)});
3158 } else switch (ty.ptrSize(zcu)) {3164 }
3159 .one, .c => {},3165 const size = ty.ptrSize(zcu);
3166 switch (size) {
3160 .many => return sema.fail(block, src, "index syntax required for unknown-length pointer type '{f}'", .{ty.fmt(pt)}),3167 .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 => {},
3162 }3169 }
3163 if (sema.resolveValue(ref)) |val| {3170 if (sema.resolveValue(ref)) |val| {
3164 // Error for deref of undef pointer, unless the pointee is OPV in which case it's legal.3171 // Error for deref of undef pointer, unless the pointee is OPV in which case it's legal.
3165 if (val.isUndef(zcu) and ty.childType(zcu).classify(zcu) != .one_possible_value) {3172 if (val.isUndef(zcu) and ty.childType(zcu).classify(zcu) != .one_possible_value) {
3166 return sema.fail(block, src, "cannot dereference undefined value", .{});3173 return sema.fail(block, src, "cannot dereference undefined value", .{});
3167 }3174 }
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", .{});
3168 }3181 }
3169}3182}
31703183
...@@ -3186,10 +3199,12 @@ fn ensureResultUsed(...@@ -3186,10 +3199,12 @@ fn ensureResultUsed(
3186 const zcu = pt.zcu;3199 const zcu = pt.zcu;
3187 switch (ty.zigTypeTag(zcu)) {3200 switch (ty.zigTypeTag(zcu)) {
3188 .void, .noreturn => return,3201 .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 },
3190 .error_union => {3205 .error_union => {
3191 const msg = msg: {3206 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)});
3193 errdefer msg.destroy(sema.gpa);3208 errdefer msg.destroy(sema.gpa);
3194 try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{});3209 try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{});
3195 break :msg msg;3210 break :msg msg;
...@@ -4745,11 +4760,14 @@ fn failWithBadMemberAccess(...@@ -4745,11 +4760,14 @@ fn failWithBadMemberAccess(
4745 .@"enum" => "enum",4760 .@"enum" => "enum",
4746 else => unreachable,4761 else => unreachable,
4747 };4762 };
4748 if (agg_ty.typeDeclInst(zcu)) |inst| if ((inst.resolve(ip) orelse return error.AnalysisFail) == .main_struct_inst) {4763 if (agg_ty.typeDeclInst(zcu)) |inst| {
4749 return sema.fail(block, field_src, "root source file struct '{f}' has no member named '{f}'", .{4764 const inst_index = inst.resolve(ip) orelse return sema.failTransitive(.{ .lost_tracking = inst });
4750 agg_ty.fmt(pt), field_name.fmt(ip),4765 if (inst_index == .main_struct_inst) {
4751 });4766 return sema.fail(block, field_src, "root source file struct '{f}' has no member named '{f}'", .{
4752 };4767 agg_ty.fmt(pt), field_name.fmt(ip),
4768 });
4769 }
4770 }
47534771
4754 return sema.fail(block, field_src, "{s} '{f}' has no member named '{f}'", .{4772 return sema.fail(block, field_src, "{s} '{f}' has no member named '{f}'", .{
4755 kw_name, agg_ty.fmt(pt), field_name.fmt(ip),4773 kw_name, agg_ty.fmt(pt), field_name.fmt(ip),
...@@ -5997,7 +6015,14 @@ fn lookupInNamespace(...@@ -5997,7 +6015,14 @@ fn lookupInNamespace(
5997 const pt = sema.pt;6015 const pt = sema.pt;
5998 const zcu = pt.zcu;6016 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
6002 const namespace = zcu.namespacePtr(namespace_index);6027 const namespace = zcu.namespacePtr(namespace_index);
60036028
...@@ -6062,7 +6087,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref...@@ -6062,7 +6087,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref
6062 const stack_trace_ty = try sema.getStdLangType(block.nodeOffset(.zero), .StackTrace);6087 const stack_trace_ty = try sema.getStdLangType(block.nodeOffset(.zero), .StackTrace);
6063 const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls);6088 const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls);
6064 const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) {6089 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"),
6066 error.ComptimeReturn, error.ComptimeBreak => unreachable,6091 error.ComptimeReturn, error.ComptimeBreak => unreachable,
6067 error.OutOfMemory, error.Canceled => |e| return e,6092 error.OutOfMemory, error.Canceled => |e| return e,
6068 };6093 };
...@@ -6724,7 +6749,9 @@ fn analyzeCall(...@@ -6724,7 +6749,9 @@ fn analyzeCall(
6724 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: {6749 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: {
6725 const info = ip.indexToKey(f.toIntern()).func;6750 const info = ip.indexToKey(f.toIntern()).func;
6726 const nav = ip.getNav(info.owner_nav);6751 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 };
6728 const file = zcu.fileByIndex(resolved_func_inst.file);6755 const file = zcu.fileByIndex(resolved_func_inst.file);
6729 const zir_info = file.zir.?.getFnInfo(resolved_func_inst.inst);6756 const zir_info = file.zir.?.getFnInfo(resolved_func_inst.inst);
6730 break :b .{ nav, file.zir.?, info.zir_body_inst, resolved_func_inst.inst, zir_info };6757 break :b .{ nav, file.zir.?, info.zir_body_inst, resolved_func_inst.inst, zir_info };
...@@ -8355,7 +8382,10 @@ fn zirFunc(...@@ -8355,7 +8382,10 @@ fn zirFunc(
8355 const cc: std.lang.CallingConvention = if (has_body) cc: {8382 const cc: std.lang.CallingConvention = if (has_body) cc: {
8356 const func_decl_nav = sema.owner.unwrap().nav_val;8383 const func_decl_nav = sema.owner.unwrap().nav_val;
8357 const fn_is_exported = exported: {8384 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 };
8359 const zir_decl = sema.code.getDeclaration(decl_inst);8389 const zir_decl = sema.code.getDeclaration(decl_inst);
8360 break :exported zir_decl.linkage == .@"export";8390 break :exported zir_decl.linkage == .@"export";
8361 };8391 };
...@@ -8501,6 +8531,7 @@ const calling_conventions_supporting_var_args = [_]std.lang.CallingConvention.Ta...@@ -8501,6 +8531,7 @@ const calling_conventions_supporting_var_args = [_]std.lang.CallingConvention.Ta
8501 .x86_64_win,8531 .x86_64_win,
8502 .x86_sysv,8532 .x86_sysv,
8503 .x86_win,8533 .x86_win,
8534 .x86_mingw,
8504 .aarch64_aapcs,8535 .aarch64_aapcs,
8505 .aarch64_aapcs_darwin,8536 .aarch64_aapcs_darwin,
8506 .aarch64_aapcs_win,8537 .aarch64_aapcs_win,
...@@ -10760,7 +10791,7 @@ fn finishSwitchBr(...@@ -10760,7 +10791,7 @@ fn finishSwitchBr(
10760 .@"enum" => if (else_is_named_only or10791 .@"enum" => if (else_is_named_only or
10761 !item_ty.isNonexhaustiveEnum(zcu) or tagged_union_originally)10792 !item_ty.isNonexhaustiveEnum(zcu) or tagged_union_originally)
10762 {10793 {
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));
10764 break :check_enumerable .{ undefined, undefined };10795 break :check_enumerable .{ undefined, undefined };
10765 },10796 },
10766 .error_set => if (!operand_ty.isAnyError(zcu)) {10797 .error_set => if (!operand_ty.isAnyError(zcu)) {
...@@ -10881,13 +10912,13 @@ fn finishSwitchBr(...@@ -10881,13 +10912,13 @@ fn finishSwitchBr(
10881 try branch_hints.append(gpa, prong_hint);10912 try branch_hints.append(gpa, prong_hint);
1088210913
10883 try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".field_names.len +10914 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 _
10885 case_block.instructions.items.len);10916 case_block.instructions.items.len);
10886 const extra_case = cases_extra.addManyAsArrayAssumeCapacity(10917 const extra_case = cases_extra.addManyAsArrayAssumeCapacity(
10887 @typeInfo(Air.SwitchBr.Case).@"struct".field_names.len,10918 @typeInfo(Air.SwitchBr.Case).@"struct".field_names.len,
10888 );10919 );
10889 var items_len: u32 = 0;10920 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| {
10891 if (seen_field != null) continue;10922 if (seen_field != null) continue;
10892 const item_val = try pt.enumValueFieldIndex(item_ty, @intCast(field_i));10923 const item_val = try pt.enumValueFieldIndex(item_ty, @intCast(field_i));
10893 const item_ref: Air.Inst.Ref = .fromValue(item_val);10924 const item_ref: Air.Inst.Ref = .fromValue(item_val);
...@@ -10920,7 +10951,7 @@ fn finishSwitchBr(...@@ -10920,7 +10951,7 @@ fn finishSwitchBr(
10920 }10951 }
10921 if (tagged_union_originally) {10952 if (tagged_union_originally) {
10922 const union_obj = zcu.typeToUnion(operand_ty).?;10953 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| {
10924 if (seen_field != null) continue;10955 if (seen_field != null) continue;
10925 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_i]);10956 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_i]);
10926 if (!field_ty.isNoReturn(zcu)) break :analyze_body true;10957 if (!field_ty.isNoReturn(zcu)) break :analyze_body true;
...@@ -11004,17 +11035,21 @@ fn finishSwitchBr(...@@ -11004,17 +11035,21 @@ fn finishSwitchBr(
11004}11035}
1100511036
11006const ValidatedSwitchBlock = struct {11037const ValidatedSwitchBlock = struct {
11007 seen_enum_fields: []const ?LazySrcLoc,11038 seen: Seen,
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
11014 case_vals: []const Air.Inst.Ref,11039 case_vals: []const Air.Inst.Ref,
11015 else_case: Zir.UnwrappedSwitchBlock.Case.Else,11040 else_case: Zir.UnwrappedSwitchBlock.Case.Else,
11016 else_err_ty: ?Type,11041 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
11018 fn iterateUnhandledItems(11053 fn iterateUnhandledItems(
11019 validated_switch: *const ValidatedSwitchBlock,11054 validated_switch: *const ValidatedSwitchBlock,
11020 /// May be `undefined` if `item_ty` isn't an `error_set`.11055 /// May be `undefined` if `item_ty` isn't an `error_set`.
...@@ -11023,28 +11058,26 @@ const ValidatedSwitchBlock = struct {...@@ -11023,28 +11058,26 @@ const ValidatedSwitchBlock = struct {
11023 min_int: Value,11058 min_int: Value,
11024 ) UnhandledIterator {11059 ) UnhandledIterator {
11025 return .{11060 return .{
11061 .error_names = error_names,
11062 .seen = &validated_switch.seen,
11063
11026 .next_idx = 0,11064 .next_idx = 0,
11027 .next_val = min_int,11065 .next_val = min_int,
11028 .error_names = error_names,11066 .handled_true = validated_switch.seen.true_src != null,
11029 .seen_enum_fields = validated_switch.seen_enum_fields,11067 .handled_false = validated_switch.seen.false_src != null,
11030 .seen_errors = &validated_switch.seen_errors,11068 .handled_void = validated_switch.seen.void_src != null,
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,
11035 };11069 };
11036 }11070 }
1103711071
11038 const UnhandledIterator = struct {11072 const UnhandledIterator = struct {
11073 error_names: InternPool.NullTerminatedString.Slice,
11074 seen: *const Seen,
11075
11039 next_idx: u32,11076 next_idx: u32,
11040 next_val: ?Value,11077 next_val: ?Value,
11041 error_names: InternPool.NullTerminatedString.Slice,11078 handled_true: bool,
11042 seen_enum_fields: []const ?LazySrcLoc,11079 handled_false: bool,
11043 seen_errors: *const std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, LazySrcLoc),11080 handled_void: bool,
11044 seen_ranges: std.MultiArrayList(RangeSet.Range).Slice,
11045 seen_true: bool,
11046 seen_false: bool,
11047 seen_void: bool,
1104811081
11049 fn next(it: *UnhandledIterator, sema: *Sema, item_ty: Type) CompileError!?Value {11082 fn next(it: *UnhandledIterator, sema: *Sema, item_ty: Type) CompileError!?Value {
11050 const pt = sema.pt;11083 const pt = sema.pt;
...@@ -11052,7 +11085,7 @@ const ValidatedSwitchBlock = struct {...@@ -11052,7 +11085,7 @@ const ValidatedSwitchBlock = struct {
11052 const ip = &zcu.intern_pool;11085 const ip = &zcu.intern_pool;
11053 switch (item_ty.zigTypeTag(zcu)) {11086 switch (item_ty.zigTypeTag(zcu)) {
11054 .@"enum" => {11087 .@"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| {
11056 if (seen_field != null) continue;11089 if (seen_field != null) continue;
11057 it.next_idx = @intCast(field_i + 1);11090 it.next_idx = @intCast(field_i + 1);
11058 return try pt.enumValueFieldIndex(item_ty, @intCast(field_i));11091 return try pt.enumValueFieldIndex(item_ty, @intCast(field_i));
...@@ -11061,7 +11094,7 @@ const ValidatedSwitchBlock = struct {...@@ -11061,7 +11094,7 @@ const ValidatedSwitchBlock = struct {
11061 },11094 },
11062 .error_set => {11095 .error_set => {
11063 for (it.error_names.get(ip)[it.next_idx..], it.next_idx..) |err_name, name_i| {11096 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;
11065 it.next_idx = @intCast(name_i + 1);11098 it.next_idx = @intCast(name_i + 1);
11066 return .fromInterned(try pt.intern(.{ .err = .{11099 return .fromInterned(try pt.intern(.{ .err = .{
11067 .ty = item_ty.toIntern(),11100 .ty = item_ty.toIntern(),
...@@ -11077,14 +11110,14 @@ const ValidatedSwitchBlock = struct {...@@ -11077,14 +11110,14 @@ const ValidatedSwitchBlock = struct {
11077 .@"union", .@"struct" => item_ty.backingIntType(zcu),11110 .@"union", .@"struct" => item_ty.backingIntType(zcu),
11078 else => unreachable,11111 else => unreachable,
11079 };11112 };
11080 while (it.next_idx < it.seen_ranges.len and11113 while (it.next_idx < it.seen.ranges.list.len and
11081 cur_val.eql(it.seen_ranges.items(.first)[it.next_idx], int_ty, zcu))11114 cur_val.eql(it.seen.ranges.list.items(.first)[it.next_idx], int_ty, zcu))
11082 {11115 {
11083 defer it.next_idx += 1;11116 defer it.next_idx += 1;
11084 const incr = try arith.incrementDefinedInt(11117 const incr = try arith.incrementDefinedInt(
11085 sema,11118 sema,
11086 int_ty,11119 int_ty,
11087 it.seen_ranges.items(.last)[it.next_idx],11120 it.seen.ranges.list.items(.last)[it.next_idx],
11088 );11121 );
11089 if (incr.overflow) {11122 if (incr.overflow) {
11090 it.next_val = null;11123 it.next_val = null;
...@@ -11101,19 +11134,19 @@ const ValidatedSwitchBlock = struct {...@@ -11101,19 +11134,19 @@ const ValidatedSwitchBlock = struct {
11101 };11134 };
11102 },11135 },
11103 .bool => {11136 .bool => {
11104 if (!it.seen_true) {11137 if (!it.handled_true) {
11105 it.seen_true = true;11138 it.handled_true = true;
11106 return .true;11139 return .true;
11107 }11140 }
11108 if (!it.seen_false) {11141 if (!it.handled_false) {
11109 it.seen_false = true;11142 it.handled_false = true;
11110 return .false;11143 return .false;
11111 }11144 }
11112 return null;11145 return null;
11113 },11146 },
11114 .void => {11147 .void => {
11115 if (!it.seen_void) {11148 if (!it.handled_void) {
11116 it.seen_void = true;11149 it.handled_void = true;
11117 return .void;11150 return .void;
11118 }11151 }
11119 return null;11152 return null;
...@@ -11186,14 +11219,8 @@ fn validateSwitchBlock(...@@ -11186,14 +11219,8 @@ fn validateSwitchBlock(
11186 operand_ty.assertHasLayout(zcu);11219 operand_ty.assertHasLayout(zcu);
11187 const union_obj = ip.loadUnionType(operand_ty.toIntern());11220 const union_obj = ip.loadUnionType(operand_ty.toIntern());
11188 switch (union_obj.tag_usage) {11221 switch (union_obj.tag_usage) {
11189 .tagged => {11222 .tagged => break :item_ty .fromInterned(union_obj.enum_tag_type),
11190 break :item_ty .fromInterned(union_obj.enum_tag_type);11223 .none => if (union_obj.layout == .@"packed") break :item_ty operand_ty,
11191 },
11192 .none => {
11193 if (union_obj.layout == .@"packed") {
11194 break :item_ty operand_ty;
11195 }
11196 },
11197 .safety => {},11224 .safety => {},
11198 }11225 }
11199 return sema.failWithOwnedErrorMsg(block, msg: {11226 return sema.failWithOwnedErrorMsg(block, msg: {
...@@ -11208,27 +11235,47 @@ fn validateSwitchBlock(...@@ -11208,27 +11235,47 @@ fn validateSwitchBlock(
1120811235
11209 .@"struct" => {11236 .@"struct" => {
11210 operand_ty.assertHasLayout(zcu);11237 operand_ty.assertHasLayout(zcu);
11211 const layout = operand_ty.containerLayout(zcu);11238 if (operand_ty.containerLayout(zcu) == .@"packed") break :item_ty operand_ty;
11212 if (layout == .@"packed") {
11213 break :item_ty operand_ty;
11214 }
11215 return sema.failWithOwnedErrorMsg(block, msg: {11239 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", .{});
11217 errdefer msg.destroy(sema.gpa);11241 errdefer msg.destroy(sema.gpa);
11218 if (operand_ty.srcLocOrNull(zcu)) |struct_src| {11242 try sema.addDeclaredHereNote(msg, operand_ty);
11219 try sema.errNote(struct_src, msg, "consider 'packed struct' here", .{});
11220 }
11221 break :msg msg;11243 break :msg msg;
11222 });11244 });
11223 },11245 },
1122411246
11225 .pointer => {11247 .pointer => if (!operand_ty.isSlice(zcu)) break :item_ty operand_ty,
11226 if (!operand_ty.isSlice(zcu)) {
11227 break :item_ty operand_ty;
11228 }
11229 },
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 => {},
11232 }11279 }
11233 return sema.fail(block, operand_src, "switch on type '{f}'", .{operand_ty.fmt(pt)});11280 return sema.fail(block, operand_src, "switch on type '{f}'", .{operand_ty.fmt(pt)});
11234 };11281 };
...@@ -11253,13 +11300,15 @@ fn validateSwitchBlock(...@@ -11253,13 +11300,15 @@ fn validateSwitchBlock(
11253 var case_vals: std.ArrayList(Air.Inst.Ref) = try .initCapacity(arena, zir_switch.item_infos.len);11300 var case_vals: std.ArrayList(Air.Inst.Ref) = try .initCapacity(arena, zir_switch.item_infos.len);
1125411301
11255 // Duplicate checking variables later also used for `inline else`.11302 // Duplicate checking variables later also used for `inline else`.
11256 var seen_enum_fields: []?LazySrcLoc = &.{};11303 var seen: ValidatedSwitchBlock.Seen = .{
11257 var seen_errors: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, LazySrcLoc) = .empty;11304 .enum_fields = &.{},
11258 var seen_sparse_values: std.AutoHashMapUnmanaged(InternPool.Index, LazySrcLoc) = .empty;11305 .errors = .empty,
11259 var range_set: RangeSet = .empty;11306 .sparse_values = .empty,
11260 var true_src: ?LazySrcLoc = null;11307 .ranges = .empty,
11261 var false_src: ?LazySrcLoc = null;11308 .true_src = null,
11262 var void_src: ?LazySrcLoc = null;11309 .false_src = null,
11310 .void_src = null,
11311 };
1126311312
11264 var else_err_ty: ?Type = null;11313 var else_err_ty: ?Type = null;
1126511314
...@@ -11267,20 +11316,20 @@ fn validateSwitchBlock(...@@ -11267,20 +11316,20 @@ fn validateSwitchBlock(
1126711316
11268 switch (item_ty.zigTypeTag(zcu)) {11317 switch (item_ty.zigTypeTag(zcu)) {
11269 .@"enum" => {11318 .@"enum" => {
11270 seen_enum_fields = try arena.alloc(?LazySrcLoc, item_ty.enumFieldCount(zcu));11319 seen.enum_fields = try arena.alloc(?LazySrcLoc, item_ty.enumFieldCount(zcu));
11271 @memset(seen_enum_fields, null);11320 @memset(seen.enum_fields, null);
11272 // `range_set` is used for non-exhaustive enum values that do not11321 // `seen.ranges` is used for non-exhaustive enum values that do not
11273 // correspond to any tags. Since this is rare, we only allocate on11322 // correspond to any tags. Since this is rare, we only allocate on
11274 // demand in `validateSwitchItem`.11323 // demand in `validateSwitchItem`.
11275 },11324 },
11276 .error_set => {11325 .error_set => {
11277 try seen_errors.ensureUnusedCapacity(arena, zir_switch.totalItemsLen());11326 try seen.errors.ensureUnusedCapacity(arena, zir_switch.totalItemsLen());
11278 },11327 },
11279 .int, .comptime_int, .@"union", .@"struct" => {11328 .int, .comptime_int, .@"union", .@"struct" => {
11280 try range_set.ensureUnusedCapacity(arena, zir_switch.totalItemsLen());11329 try seen.ranges.ensureUnusedCapacity(arena, zir_switch.totalItemsLen());
11281 },11330 },
11282 .enum_literal, .@"fn", .pointer, .type => {11331 .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());
11284 },11333 },
11285 .bool, .void => {},11334 .bool, .void => {},
1128611335
...@@ -11323,7 +11372,7 @@ fn validateSwitchBlock(...@@ -11323,7 +11372,7 @@ fn validateSwitchBlock(
11323 case_vals.appendAssumeCapacity(.none);11372 case_vals.appendAssumeCapacity(.none);
11324 } else {11373 } else {
11325 const item, extra_index = try sema.resolveSwitchItem(block, item_src, item_ty, item_info, extra_index, switch_inst, prong_info.is_comptime_unreach);11374 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);
11327 case_vals.appendAssumeCapacity(item.ref);11376 case_vals.appendAssumeCapacity(item.ref);
11328 }11377 }
11329 }11378 }
...@@ -11338,7 +11387,7 @@ fn validateSwitchBlock(...@@ -11338,7 +11387,7 @@ fn validateSwitchBlock(
11338 const last_src = block.src(.{ .switch_case_item_range_last = range_offset });11387 const last_src = block.src(.{ .switch_case_item_range_last = range_offset });
11339 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);11388 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);
11340 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);11389 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);
11342 case_vals.appendSliceAssumeCapacity(&.{ first_item.ref, last_item.ref });11391 case_vals.appendSliceAssumeCapacity(&.{ first_item.ref, last_item.ref });
11343 }11392 }
11344 }11393 }
...@@ -11369,13 +11418,13 @@ fn validateSwitchBlock(...@@ -11369,13 +11418,13 @@ fn validateSwitchBlock(
11369 // Validate for missing special prongs.11418 // Validate for missing special prongs.
11370 switch (item_ty.zigTypeTag(zcu)) {11419 switch (item_ty.zigTypeTag(zcu)) {
11371 .@"enum" => {11420 .@"enum" => {
11372 const all_tags_handled = for (seen_enum_fields) |seen_src| {11421 const all_tags_handled = for (seen.enum_fields) |seen_src| {
11373 if (seen_src == null) break false;11422 if (seen_src == null) break false;
11374 } else true;11423 } else true;
1137511424
11376 if (has_else) {11425 if (has_else) {
11377 if (all_tags_handled) {11426 if (all_tags_handled) {
11378 if (item_ty.isNonexhaustiveEnum(zcu)) {11427 if (operand_ty.isNonexhaustiveEnum(zcu)) {
11379 if (has_under) return sema.fail(11428 if (has_under) return sema.fail(
11380 block,11429 block,
11381 else_prong_src,11430 else_prong_src,
...@@ -11397,7 +11446,7 @@ fn validateSwitchBlock(...@@ -11397,7 +11446,7 @@ fn validateSwitchBlock(
11397 .{},11446 .{},
11398 );11447 );
11399 errdefer msg.destroy(sema.gpa);11448 errdefer msg.destroy(sema.gpa);
11400 for (seen_enum_fields, 0..) |seen_src, i| {11449 for (seen.enum_fields, 0..) |seen_src, i| {
11401 if (seen_src != null) continue;11450 if (seen_src != null) continue;
1140211451
11403 const field_name = item_ty.enumFieldName(i, zcu);11452 const field_name = item_ty.enumFieldName(i, zcu);
...@@ -11449,7 +11498,7 @@ fn validateSwitchBlock(...@@ -11449,7 +11498,7 @@ fn validateSwitchBlock(
1144911498
11450 var seen_errors_from_set: u32 = 0;11499 var seen_errors_from_set: u32 = 0;
11451 for (error_names.get(ip)) |error_name| {11500 for (error_names.get(ip)) |error_name| {
11452 if (seen_errors.contains(error_name)) {11501 if (seen.errors.contains(error_name)) {
11453 seen_errors_from_set += 1;11502 seen_errors_from_set += 1;
11454 } else if (!has_else) {11503 } else if (!has_else) {
11455 const msg = maybe_msg orelse blk: {11504 const msg = maybe_msg orelse blk: {
...@@ -11491,7 +11540,7 @@ fn validateSwitchBlock(...@@ -11491,7 +11540,7 @@ fn validateSwitchBlock(
11491 var names: InferredErrorSet.NameMap = .{};11540 var names: InferredErrorSet.NameMap = .{};
11492 try names.ensureUnusedCapacity(sema.arena, error_names.len);11541 try names.ensureUnusedCapacity(sema.arena, error_names.len);
11493 for (error_names.get(ip)) |error_name| {11542 for (error_names.get(ip)) |error_name| {
11494 if (seen_errors.contains(error_name)) continue;11543 if (seen.errors.contains(error_name)) continue;
11495 names.putAssumeCapacityNoClobber(error_name, {});11544 names.putAssumeCapacityNoClobber(error_name, {});
11496 }11545 }
11497 // No need to keep the hash map metadata correct; here we11546 // No need to keep the hash map metadata correct; here we
...@@ -11509,7 +11558,7 @@ fn validateSwitchBlock(...@@ -11509,7 +11558,7 @@ fn validateSwitchBlock(
11509 };11558 };
11510 const min_int = try int_ty.minInt(pt, int_ty);11559 const min_int = try int_ty.minInt(pt, int_ty);
11511 const max_int = try int_ty.maxInt(pt, int_ty);11560 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)) {
11513 if (has_else) {11562 if (has_else) {
11514 return sema.fail(11563 return sema.fail(
11515 block,11564 block,
...@@ -11542,8 +11591,8 @@ fn validateSwitchBlock(...@@ -11542,8 +11591,8 @@ fn validateSwitchBlock(
11542 },11591 },
11543 .bool, .void => |type_tag| {11592 .bool, .void => |type_tag| {
11544 const all_values_handled = switch (type_tag) {11593 const all_values_handled = switch (type_tag) {
11545 .bool => true_src != null and false_src != null,11594 .bool => seen.true_src != null and seen.false_src != null,
11546 .void => void_src != null,11595 .void => seen.void_src != null,
11547 else => unreachable,11596 else => unreachable,
11548 };11597 };
11549 if (has_else) {11598 if (has_else) {
...@@ -11570,13 +11619,7 @@ fn validateSwitchBlock(...@@ -11570,13 +11619,7 @@ fn validateSwitchBlock(
11570 }11619 }
1157111620
11572 return .{11621 return .{
11573 .seen_enum_fields = seen_enum_fields,11622 .seen = seen,
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
11580 .case_vals = case_vals.items,11623 .case_vals = case_vals.items,
11581 .else_case = else_case,11624 .else_case = else_case,
11582 .else_err_ty = else_err_ty,11625 .else_err_ty = else_err_ty,
...@@ -11754,7 +11797,7 @@ fn resolveSwitchBlock(...@@ -11754,7 +11797,7 @@ fn resolveSwitchBlock(
11754 .{ else_case.index, else_case.body, else_case.capture, else_case.has_tag_capture, else_case.is_inline };11797 .{ else_case.index, else_case.body, else_case.capture, else_case.has_tag_capture, else_case.is_inline };
11755 if (err_set) try sema.maybeErrorUnwrapComptime(child_block, body, cond_ref);11798 if (err_set) try sema.maybeErrorUnwrapComptime(child_block, body, cond_ref);
11756 if (tagged_union_originally) {11799 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| {
11758 if (maybe_seen != null) continue;11801 if (maybe_seen != null) continue;
11759 if (!operand_ty.unionFieldTypeByIndex(field_i, zcu).isNoReturn(zcu)) break;11802 if (!operand_ty.unionFieldTypeByIndex(field_i, zcu).isNoReturn(zcu)) break;
11760 } else {11803 } else {
...@@ -12276,10 +12319,11 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(...@@ -12276,10 +12319,11 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
12276 dummy_captures,12319 dummy_captures,
12277 .{ .override = item_srcs },12320 .{ .override = item_srcs },
12278 ) catch |err| switch (err) {12321 ) catch |err| switch (err) {
12279 error.AnalysisFail => {12322 error.AlreadyReported => |e| {
12280 const msg = sema.err orelse return error.AnalysisFail;12323 if (sema.err) |msg| {
12281 try sema.reparentOwnedErrorMsg(capture_src, msg, "capture group with incompatible types", .{});12324 try sema.reparentOwnedErrorMsg(capture_src, msg, "capture group with incompatible types", .{});
12282 return error.AnalysisFail;12325 }
12326 return e;
12283 },12327 },
12284 else => |e| return e,12328 else => |e| return e,
12285 };12329 };
...@@ -12315,11 +12359,12 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(...@@ -12315,11 +12359,12 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
12315 dummy_captures,12359 dummy_captures,
12316 .{ .override = item_srcs },12360 .{ .override = item_srcs },
12317 ) catch |err| switch (err) {12361 ) catch |err| switch (err) {
12318 error.AnalysisFail => {12362 error.AlreadyReported => |e| {
12319 const msg = sema.err orelse return error.AnalysisFail;12363 if (sema.err) |msg| {
12320 try sema.errNote(capture_src, msg, "this coercion is only possible when capturing by value", .{});12364 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", .{});12365 try sema.reparentOwnedErrorMsg(capture_src, msg, "capture group with incompatible types", .{});
12322 return error.AnalysisFail;12366 }
12367 return e;
12323 },12368 },
12324 else => |e| return e,12369 else => |e| return e,
12325 };12370 };
...@@ -12559,13 +12604,7 @@ fn validateSwitchItemOrRange(...@@ -12559,13 +12604,7 @@ fn validateSwitchItemOrRange(
12559 item_val: Value,12604 item_val: Value,
12560 opt_last_val: ?Value,12605 opt_last_val: ?Value,
12561 item_ty: Type,12606 item_ty: Type,
12562 seen_enum_fields: []?LazySrcLoc,12607 seen: *ValidatedSwitchBlock.Seen,
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,
12569) CompileError!void {12608) CompileError!void {
12570 const pt = sema.pt;12609 const pt = sema.pt;
12571 const zcu = pt.zcu;12610 const zcu = pt.zcu;
...@@ -12574,88 +12613,117 @@ fn validateSwitchItemOrRange(...@@ -12574,88 +12613,117 @@ fn validateSwitchItemOrRange(
12574 .@"enum" => {12613 .@"enum" => {
12575 const int = ip.indexToKey(item_val.toIntern()).enum_tag.int;12614 const int = ip.indexToKey(item_val.toIntern()).enum_tag.int;
12576 if (ip.loadEnumType(item_ty.toIntern()).tagValueIndex(ip, int)) |field_index| {12615 if (ip.loadEnumType(item_ty.toIntern()).tagValueIndex(ip, int)) |field_index| {
12577 const maybe_prev_src = seen_enum_fields[field_index];12616 const maybe_prev_src = seen.enum_fields[field_index];
12578 seen_enum_fields[field_index] = item_src;12617 seen.enum_fields[field_index] = item_src;
12579 break :maybe_prev_src maybe_prev_src;12618 break :maybe_prev_src maybe_prev_src;
12580 } else {12619 } 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(.{
12582 .first = .fromInterned(int),12622 .first = .fromInterned(int),
12583 .last = .fromInterned(int),12623 .last = .fromInterned(int),
12584 .src = item_src,12624 .src = item_src,
12585 }, .fromInterned(ip.typeOf(int)), zcu);12625 }, .fromInterned(ip.typeOf(int)), zcu)) |prev| prev.src else null;
12586 }12626 }
12587 },12627 },
12588 .error_set => {12628 .error_set => {
12589 const error_name = ip.indexToKey(item_val.toIntern()).err.name;12629 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|
12591 prev.value12631 prev.value
12592 else12632 else
12593 null;12633 null;
12594 },12634 },
12595 .int, .comptime_int => {12635 .int, .comptime_int => {
12596 if (opt_last_val) |last_val| {12636 const first_val = item_val;
12597 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;
12598 if (try first_val.compareAll(.gt, last_val, item_ty, pt)) {12639 if (try first_val.compareAll(.gt, last_val, item_ty, pt)) {
12599 return sema.fail(block, item_src, "range start value is greater than the end value", .{});12640 return sema.fail(block, item_src, "range start value is greater than the end value", .{});
12600 }12641 }
12601 break :maybe_prev_src range_set.addAssumeCapacity(.{12642 break :last_val last_val;
12602 .first = first_val,12643 };
12603 .last = last_val,12644 if (seen.ranges.addAssumeCapacity(.{
12604 .src = item_src,12645 .first = first_val,
12605 }, item_ty, zcu);12646 .last = last_val,
12606 } else {12647 .src = item_src,
12607 break :maybe_prev_src range_set.addAssumeCapacity(.{12648 }, item_ty, zcu)) |prev_range| {
12608 .first = item_val,12649 const overlap_start = first_val.numberMax(prev_range.first, zcu);
12609 .last = item_val,12650 const overlap_end = last_val.numberMin(prev_range.last, zcu);
12610 .src = item_src,12651 if (overlap_start.eql(overlap_end, item_ty, zcu)) {
12611 }, 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 });
12612 }12681 }
12682 break :maybe_prev_src null;
12613 },12683 },
12614 .@"union", .@"struct" => {12684 .@"union", .@"struct" => {
12615 const backing_int_val = ip.indexToKey(item_val.toIntern()).bitpack.backing_int_val;12685 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(.{
12617 .first = .fromInterned(backing_int_val),12687 .first = .fromInterned(backing_int_val),
12618 .last = .fromInterned(backing_int_val),12688 .last = .fromInterned(backing_int_val),
12619 .src = item_src,12689 .src = item_src,
12620 }, item_ty.backingIntType(zcu), zcu);12690 }, item_ty.backingIntType(zcu), zcu)) |prev| prev.src else null;
12621 },12691 },
12622 .enum_literal, .@"fn", .pointer, .type => {12692 .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|
12624 prev.value12694 prev.value
12625 else12695 else
12626 null;12696 null;
12627 },12697 },
12628 .bool => {12698 .bool => {
12629 if (item_val.toBool()) {12699 if (item_val.toBool()) {
12630 if (true_src.*) |prev_src| break :maybe_prev_src prev_src;12700 if (seen.true_src) |prev_src| break :maybe_prev_src prev_src;
12631 true_src.* = item_src;12701 seen.true_src = item_src;
12632 } else {12702 } else {
12633 if (false_src.*) |prev_src| break :maybe_prev_src prev_src;12703 if (seen.false_src) |prev_src| break :maybe_prev_src prev_src;
12634 false_src.* = item_src;12704 seen.false_src = item_src;
12635 }12705 }
12636 break :maybe_prev_src null;12706 break :maybe_prev_src null;
12637 },12707 },
12638 .void => {12708 .void => {
12639 if (void_src.*) |prev_src| break :maybe_prev_src prev_src;12709 if (seen.void_src) |prev_src| break :maybe_prev_src prev_src;
12640 void_src.* = item_src;12710 seen.void_src = item_src;
12641 break :maybe_prev_src null;12711 break :maybe_prev_src null;
12642 },12712 },
12643 else => unreachable, // should have already checked for invalid types12713 else => unreachable, // should have already checked for invalid types
12644 };12714 };
12645 if (maybe_prev_src) |prev_src| {12715 if (maybe_prev_src) |prev_src| {
12646 return sema.failWithOwnedErrorMsg(block, msg: {12716 return sema.failWithOwnedErrorMsg(block, msg: {
12647 const msg = try sema.errMsg(12717 const msg = try sema.errMsg(item_src, "duplicate switch value '{f}'", .{
12648 item_src,12718 item_val.fmtValueSema(pt, sema),
12649 "duplicate switch value",12719 });
12650 .{},
12651 );
12652 errdefer msg.destroy(sema.gpa);12720 errdefer msg.destroy(sema.gpa);
12653 try sema.errNote(12721 try sema.errNote(prev_src, msg, "previous value here", .{});
12654 prev_src,12722 if (item_ty.zigTypeTag(zcu) == .type) {
12655 msg,12723 try sema.addDeclaredHereNote(msg, item_val.toType());
12656 "previous value here",12724 } else {
12657 .{},12725 try sema.addDeclaredHereNote(msg, item_ty);
12658 );12726 }
12659 break :msg msg;12727 break :msg msg;
12660 });12728 });
12661 }12729 }
...@@ -17171,7 +17239,14 @@ fn typeInfoNamespaceDecls(...@@ -17171,7 +17239,14 @@ fn typeInfoNamespaceDecls(
17171 const ip = &zcu.intern_pool;17239 const ip = &zcu.intern_pool;
1717217240
17173 const namespace_index = opt_namespace_index.unwrap() orelse return;17241 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 };
17175 const namespace = zcu.namespacePtr(namespace_index);17250 const namespace = zcu.namespacePtr(namespace_index);
1717617251
17177 const gop = try seen_namespaces.getOrPut(namespace);17252 const gop = try seen_namespaces.getOrPut(namespace);
...@@ -17897,11 +17972,12 @@ fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -17897,11 +17972,12 @@ fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
17897 }17972 }
17898 // TODO Add compile error for @optimizeFor occurring too late in a scope.17973 // TODO Add compile error for @optimizeFor occurring too late in a scope.
17899 sema.analyzeUnreachable(block, src, true) catch |err| switch (err) {17974 sema.analyzeUnreachable(block, src, true) catch |err| switch (err) {
17900 error.AnalysisFail => {17975 error.AlreadyReported => |e| {
17901 const msg = sema.err orelse return err;17976 if (sema.err) |msg| {
17902 if (!mem.eql(u8, msg.msg, "runtime safety check not allowed in naked function")) return err;17977 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", .{});17978 try sema.errNote(src, msg, "the end of a naked function is implicitly unreachable", .{});
17904 return err;17979 }
17980 return e;
17905 },17981 },
17906 else => |e| return e,17982 else => |e| return e,
17907 };17983 };
...@@ -18317,11 +18393,16 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -18317,11 +18393,16 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1831718393
18318 const elem_ty = blk: {18394 const elem_ty = blk: {
18319 const air_inst = sema.resolveInst(extra.data.elem_type);18395 const air_inst = sema.resolveInst(extra.data.elem_type);
18320 const ty = sema.analyzeAsType(block, elem_ty_src, .type, air_inst) catch |err| {18396 const ty = sema.analyzeAsType(block, elem_ty_src, .type, air_inst) catch |err| switch (err) {
18321 if (err == error.AnalysisFail and sema.err != null and sema.typeOf(air_inst).isSinglePointer(zcu)) {18397 error.AlreadyReported => |e| {
18322 try sema.errNote(elem_ty_src, sema.err.?, "use '.*' to dereference pointer", .{});18398 if (sema.err) |msg| {
18323 }18399 if (sema.typeOf(air_inst).isSinglePointer(zcu)) {
18324 return err;18400 try sema.errNote(elem_ty_src, msg, "use '.*' to dereference pointer", .{});
18401 }
18402 }
18403 return e;
18404 },
18405 else => |e| return e,
18325 };18406 };
18326 assert(!ty.isGenericPoison());18407 assert(!ty.isGenericPoison());
18327 break :blk ty;18408 break :blk ty;
...@@ -21103,7 +21184,10 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -21103,7 +21184,10 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
21103 const dest_scalar_ty = dest_ty.scalarType(zcu);21184 const dest_scalar_ty = dest_ty.scalarType(zcu);
21104 const operand_scalar_ty = operand_ty.scalarType(zcu);21185 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 }
21107 try sema.checkFloatType(block, operand_src, operand_scalar_ty);21191 try sema.checkFloatType(block, operand_src, operand_scalar_ty);
2110821192
21109 if (sema.resolveValue(operand)) |operand_val| {21193 if (sema.resolveValue(operand)) |operand_val| {
...@@ -21279,7 +21363,10 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -21279,7 +21363,10 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
21279 const dest_scalar_ty = dest_ty.scalarType(zcu);21363 const dest_scalar_ty = dest_ty.scalarType(zcu);
21280 const operand_scalar_ty = operand_ty.scalarType(zcu);21364 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 }
21283 _ = try sema.checkIntType(block, operand_src, operand_scalar_ty);21370 _ = try sema.checkIntType(block, operand_src, operand_scalar_ty);
2128421371
21285 if (sema.resolveValue(operand)) |operand_val| {21372 if (sema.resolveValue(operand)) |operand_val| {
...@@ -21594,16 +21681,16 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData...@@ -21594,16 +21681,16 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
21594 const is_zero = try block.addBinOp(.cmp_eq, err_int_inst, zero_err);21681 const is_zero = try block.addBinOp(.cmp_eq, err_int_inst, zero_err);
21595 if (result == .disjoint) {21682 if (result == .disjoint) {
21596 // Error must be zero.21683 // 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});
21598 } else {21685 } else {
21599 // Error must be in destination set or zero.21686 // Error must be in destination set or zero.
21600 const has_value = try block.addTyOp(.error_set_has_value, dest_err_ty, err_int_inst);21687 const has_value = try block.addTyOp(.error_set_has_value, dest_err_ty, err_int_inst);
21601 const ok = try block.addBinOp(.bit_or, has_value, is_zero);21688 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});
21603 }21690 }
21604 } else {21691 } else {
21605 const ok = try block.addTyOp(.error_set_has_value, dest_err_ty, err_int_inst);21692 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});
21607 }21694 }
21608 }21695 }
2160921696
...@@ -23460,7 +23547,9 @@ fn analyzeShuffle(...@@ -23460,7 +23547,9 @@ fn analyzeShuffle(
23460 // `InternPool.Index` values using the known operands.23547 // `InternPool.Index` values using the known operands.
23461 for (mask_shuffle_two, mask_ip_index) |in, *out| {23548 for (mask_shuffle_two, mask_ip_index) |in, *out| {
23462 const val: Value = switch (in.unwrap()) {23549 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),
23464 .a_elem => |idx| try maybe_a_val.?.elemValue(pt, idx),23553 .a_elem => |idx| try maybe_a_val.?.elemValue(pt, idx),
23465 .b_elem => |idx| try maybe_b_val.?.elemValue(pt, idx),23554 .b_elem => |idx| try maybe_b_val.?.elemValue(pt, idx),
23466 };23555 };
...@@ -23509,6 +23598,9 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C...@@ -23509,6 +23598,9 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
23509 const a = try sema.coerce(block, vec_ty, sema.resolveInst(extra.a), a_src);23598 const a = try sema.coerce(block, vec_ty, sema.resolveInst(extra.a), a_src);
23510 const b = try sema.coerce(block, vec_ty, sema.resolveInst(extra.b), b_src);23599 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
23512 const maybe_pred = sema.resolveValue(pred);23604 const maybe_pred = sema.resolveValue(pred);
23513 const maybe_a = sema.resolveValue(a);23605 const maybe_a = sema.resolveValue(a);
23514 const maybe_b = sema.resolveValue(b);23606 const maybe_b = sema.resolveValue(b);
...@@ -24873,7 +24965,10 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -24873,7 +24965,10 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
24873 } else cc: {24965 } else cc: {
24874 if (has_body) {24966 if (has_body) {
24875 const func_decl_nav = sema.owner.unwrap().nav_val;24967 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 };
24877 const zir_decl = sema.code.getDeclaration(func_decl_inst);24972 const zir_decl = sema.code.getDeclaration(func_decl_inst);
24878 if (zir_decl.linkage == .@"export") {24973 if (zir_decl.linkage == .@"export") {
24879 break :cc target.cCallingConvention() orelse {24974 break :cc target.cCallingConvention() orelse {
...@@ -25458,10 +25553,10 @@ fn zirRoundOpType(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDa...@@ -25458,10 +25553,10 @@ fn zirRoundOpType(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDa
25458 return .generic_poison_type;25553 return .generic_poison_type;
25459 };25554 };
2546025555
25461 const float_ty = dest_ty.optEuBaseType(zcu);25556 const dest_base_ty = dest_ty.optEuBaseType(zcu);
25462 switch (float_ty.scalarType(zcu).zigTypeTag(zcu)) {25557 switch (dest_base_ty.scalarType(zcu).zigTypeTag(zcu)) {
25463 .float, .comptime_float => return .fromType(float_ty),25558 .float, .comptime_float => return .fromType(dest_base_ty),
25464 else => return .comptime_float_type,25559 else => return .generic_poison_type,
25465 }25560 }
25466}25561}
2546725562
...@@ -25640,7 +25735,6 @@ pub fn explainWhyTypeIsNotExtern(...@@ -25640,7 +25735,6 @@ pub fn explainWhyTypeIsNotExtern(
2564025735
25641 .@"opaque",25736 .@"opaque",
25642 .bool,25737 .bool,
25643 .float,
25644 .@"anyframe",25738 .@"anyframe",
25645 => unreachable, // these *are* allowed25739 => unreachable, // these *are* allowed
2564625740
...@@ -25649,6 +25743,7 @@ pub fn explainWhyTypeIsNotExtern(...@@ -25649,6 +25743,7 @@ pub fn explainWhyTypeIsNotExtern(
25649 try sema.errNote(src_loc, msg, "SPIR-V runtime arrays must be the last field of an extern struct", .{});25743 try sema.errNote(src_loc, msg, "SPIR-V runtime arrays must be the last field of an extern struct", .{});
25650 },25744 },
2565125745
25746 .float => try sema.errNote(src_loc, msg, "'{f}' is not extern compatible on this target", .{ty.fmt(pt)}),
25652 .pointer => if (ty.isSlice(zcu)) {25747 .pointer => if (ty.isSlice(zcu)) {
25653 try sema.errNote(src_loc, msg, "slices have no guaranteed in-memory representation", .{});25748 try sema.errNote(src_loc, msg, "slices have no guaranteed in-memory representation", .{});
25654 } else {25749 } else {
...@@ -28174,9 +28269,94 @@ fn coerceExtra(...@@ -28174,9 +28269,94 @@ fn coerceExtra(
28174 },28269 },
28175 else => {},28270 else => {},
28176 },28271 },
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 },
28178 .slice => to_slice: {28357 .slice => to_slice: {
28179 if (inst_ty.zigTypeTag(zcu) == .array) {28358 if (inst_ty.zigTypeTag(zcu) == .array) {
28359 if (!opts.report_err) return error.NotCoercible;
28180 return sema.fail(28360 return sema.fail(
28181 block,28361 block,
28182 inst_src,28362 inst_src,
...@@ -28204,6 +28384,7 @@ fn coerceExtra(...@@ -28204,6 +28384,7 @@ fn coerceExtra(
2820428384
28205 // pointer to tuple to slice28385 // pointer to tuple to slice
28206 if (!dest_info.flags.is_const) {28386 if (!dest_info.flags.is_const) {
28387 if (!opts.report_err) return error.NotCoercible;
28207 const err_msg = err_msg: {28388 const err_msg = err_msg: {
28208 const err_msg = try sema.errMsg(inst_src, "cannot cast pointer to tuple to '{f}'", .{dest_ty.fmt(pt)});28389 const err_msg = try sema.errMsg(inst_src, "cannot cast pointer to tuple to '{f}'", .{dest_ty.fmt(pt)});
28209 errdefer err_msg.destroy(sema.gpa);28390 errdefer err_msg.destroy(sema.gpa);
...@@ -28299,6 +28480,7 @@ fn coerceExtra(...@@ -28299,6 +28480,7 @@ fn coerceExtra(
28299 if (maybe_inst_val) |val| {28480 if (maybe_inst_val) |val| {
28300 const result_val = try val.floatCast(dest_ty, pt);28481 const result_val = try val.floatCast(dest_ty, pt);
28301 if (!val.eql(try result_val.floatCast(inst_ty, pt), inst_ty, zcu)) {28482 if (!val.eql(try result_val.floatCast(inst_ty, pt), inst_ty, zcu)) {
28483 if (!opts.report_err) return error.NotCoercible;
28302 return sema.fail(28484 return sema.fail(
28303 block,28485 block,
28304 inst_src,28486 inst_src,
...@@ -28356,12 +28538,15 @@ fn coerceExtra(...@@ -28356,12 +28538,15 @@ fn coerceExtra(
28356 break :fits result_big_int.toConst().eql(operand_big_int);28538 break :fits result_big_int.toConst().eql(operand_big_int);
28357 },28539 },
28358 };28540 };
28359 if (!fits) return sema.fail(28541 if (!fits) {
28360 block,28542 if (!opts.report_err) return error.NotCoercible;
28361 inst_src,28543 return sema.fail(
28362 "type '{f}' cannot represent integer value '{f}'",28544 block,
28363 .{ dest_ty.fmt(pt), val.fmtValue(pt) },28545 inst_src,
28364 );28546 "type '{f}' cannot represent integer value '{f}'",
28547 .{ dest_ty.fmt(pt), val.fmtValue(pt) },
28548 );
28549 }
28365 return .fromValue(result_val);28550 return .fromValue(result_val);
28366 },28551 },
28367 else => {},28552 else => {},
...@@ -28372,6 +28557,7 @@ fn coerceExtra(...@@ -28372,6 +28557,7 @@ fn coerceExtra(
28372 const val = sema.resolveValue(inst).?;28557 const val = sema.resolveValue(inst).?;
28373 const string = zcu.intern_pool.indexToKey(val.toIntern()).enum_literal;28558 const string = zcu.intern_pool.indexToKey(val.toIntern()).enum_literal;
28374 const field_index = dest_ty.enumFieldIndex(string, zcu) orelse {28559 const field_index = dest_ty.enumFieldIndex(string, zcu) orelse {
28560 if (!opts.report_err) return error.NotCoercible;
28375 return sema.fail(block, inst_src, "no field named '{f}' in enum '{f}'", .{28561 return sema.fail(block, inst_src, "no field named '{f}' in enum '{f}'", .{
28376 string.fmt(&zcu.intern_pool), dest_ty.fmt(pt),28562 string.fmt(&zcu.intern_pool), dest_ty.fmt(pt),
28377 });28563 });
...@@ -29622,7 +29808,7 @@ fn coerceVarArgParam(...@@ -29622,7 +29808,7 @@ fn coerceVarArgParam(
29622 .array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}),29808 .array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}),
29623 .float => float: {29809 .float => float: {
29624 const target = zcu.getTarget();29810 const target = zcu.getTarget();
29625 const double_bits = target.cTypeBitSize(.double);29811 const double_bits = target.cTypeBitSize(.double) orelse break :float inst;
29626 const inst_bits = uncasted_ty.floatBits(target);29812 const inst_bits = uncasted_ty.floatBits(target);
29627 if (inst_bits >= double_bits) break :float inst;29813 if (inst_bits >= double_bits) break :float inst;
29628 switch (double_bits) {29814 switch (double_bits) {
...@@ -29638,21 +29824,21 @@ fn coerceVarArgParam(...@@ -29638,21 +29824,21 @@ fn coerceVarArgParam(
29638 if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) {29824 if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) {
29639 .signed => .int,29825 .signed => .int,
29640 .unsigned => .uint,29826 .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) {
29642 .signed => .c_int,29828 .signed => .c_int,
29643 .unsigned => .c_uint,29829 .unsigned => .c_uint,
29644 }, inst, inst_src);29830 }, inst, inst_src);
29645 if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) {29831 if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) {
29646 .signed => .long,29832 .signed => .long,
29647 .unsigned => .ulong,29833 .unsigned => .ulong,
29648 })) break :int try sema.coerce(block, switch (uncasted_info.signedness) {29834 }).?) break :int try sema.coerce(block, switch (uncasted_info.signedness) {
29649 .signed => .c_long,29835 .signed => .c_long,
29650 .unsigned => .c_ulong,29836 .unsigned => .c_ulong,
29651 }, inst, inst_src);29837 }, inst, inst_src);
29652 if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) {29838 if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) {
29653 .signed => .longlong,29839 .signed => .longlong,
29654 .unsigned => .ulonglong,29840 .unsigned => .ulonglong,
29655 })) break :int try sema.coerce(block, switch (uncasted_info.signedness) {29841 }).?) break :int try sema.coerce(block, switch (uncasted_info.signedness) {
29656 .signed => .c_longlong,29842 .signed => .c_longlong,
29657 .unsigned => .c_ulonglong,29843 .unsigned => .c_ulonglong,
29658 }, inst, inst_src);29844 }, inst, inst_src);
...@@ -30048,6 +30234,19 @@ fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_resul...@@ -30048,6 +30234,19 @@ fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_resul
30048 } };30234 } };
30049 return false;30235 return false;
30050 }30236 }
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
30051 if (inst_info.flags.alignment == .none and dest_info.flags.alignment == .none) return true;30250 if (inst_info.flags.alignment == .none and dest_info.flags.alignment == .none) return true;
30052 if (len0) return true;30251 if (len0) return true;
3005330252
...@@ -30068,19 +30267,6 @@ fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_resul...@@ -30068,19 +30267,6 @@ fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_resul
30068 } };30267 } };
30069 return false;30268 return false;
30070 }30269 }
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
30084 return true;30270 return true;
30085}30271}
3008630272
...@@ -30606,7 +30792,10 @@ fn ensureMemoizedStateResolved(sema: *Sema, src: LazySrcLoc, stage: InternPool.M...@@ -30606,7 +30792,10 @@ fn ensureMemoizedStateResolved(sema: *Sema, src: LazySrcLoc, stage: InternPool.M
30606 if (pt.zcu.analysis_in_progress.contains(unit)) {30792 if (pt.zcu.analysis_in_progress.contains(unit)) {
30607 return sema.failWithDependencyLoop(unit, &reason);30793 return sema.failWithDependencyLoop(unit, &reason);
30608 }30794 }
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 };
30610}30799}
3061130800
30612pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: InternPool.Nav.Index, kind: enum { type, fully }) CompileError!void {30801pub 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:...@@ -30642,9 +30831,15 @@ pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index:
30642 switch (kind) {30831 switch (kind) {
30643 .type => {30832 .type => {
30644 try zcu.ensureNavValAnalysisQueued(nav_index);30833 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,
30646 },30842 },
30647 .fully => return pt.ensureNavValUpToDate(nav_index, &reason),
30648 }30843 }
30649}30844}
3065030845
...@@ -30856,7 +31051,18 @@ fn analyzeLoad(...@@ -30856,7 +31051,18 @@ fn analyzeLoad(
30856 const comptime_only = switch (elem_ty.classify(zcu)) {31051 const comptime_only = switch (elem_ty.classify(zcu)) {
30857 .no_possible_value => switch (elem_ty.zigTypeTag(zcu)) {31052 .no_possible_value => switch (elem_ty.zigTypeTag(zcu)) {
30858 .@"opaque" => return sema.fail(block, src, "cannot load opaque type '{f}'", .{elem_ty.fmt(pt)}),31053 .@"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 },
30860 },31066 },
30861 .one_possible_value => return .fromValue((try elem_ty.onePossibleValue(pt)).?),31067 .one_possible_value => return .fromValue((try elem_ty.onePossibleValue(pt)).?),
30862 .runtime => false,31068 .runtime => false,
...@@ -30864,8 +31070,11 @@ fn analyzeLoad(...@@ -30864,8 +31070,11 @@ fn analyzeLoad(
30864 };31070 };
3086531071
30866 if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {31072 if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {
30867 if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| {31073 if (switch (ptr_ty.ptrSize(zcu)) {
30868 return Air.internedToRef(elem_val.toIntern());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);
30869 }31078 }
30870 }31079 }
3087131080
...@@ -33707,7 +33916,10 @@ fn ensureFuncIesResolved(...@@ -33707,7 +33916,10 @@ fn ensureFuncIesResolved(
33707 return sema.failWithDependencyLoop(.wrap(.{ .func = func_index }), &reason);33916 return sema.failWithDependencyLoop(.wrap(.{ .func = func_index }), &reason);
33708 }33917 }
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 };
33711}33923}
3371233924
33713pub fn resolveInferredErrorSetPtr(33925pub fn resolveInferredErrorSetPtr(
...@@ -33821,7 +34033,7 @@ pub fn getTmpAir(sema: Sema) Air {...@@ -33821,7 +34033,7 @@ pub fn getTmpAir(sema: Sema) Air {
33821}34033}
3382234034
33823pub fn addExtra(sema: *Sema, extra: anytype) Allocator.Error!u32 {34035pub 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;
33825 try sema.air_extra.ensureUnusedCapacity(sema.gpa, field_count);34037 try sema.air_extra.ensureUnusedCapacity(sema.gpa, field_count);
33826 return sema.addExtraAssumeCapacity(extra);34038 return sema.addExtraAssumeCapacity(extra);
33827}34039}
...@@ -34536,7 +34748,6 @@ fn maybeDerefSliceAsArray(...@@ -34536,7 +34748,6 @@ fn maybeDerefSliceAsArray(
34536) CompileError!?Value {34748) CompileError!?Value {
34537 const pt = sema.pt;34749 const pt = sema.pt;
34538 const zcu = pt.zcu;34750 const zcu = pt.zcu;
34539 const ip = &zcu.intern_pool;
34540 const slice_ty = slice_val.typeOf(zcu);34751 const slice_ty = slice_val.typeOf(zcu);
34541 assert(slice_ty.zigTypeTag(zcu) == .pointer);34752 assert(slice_ty.zigTypeTag(zcu) == .pointer);
34542 switch (slice_ty.ptrInfo(zcu).flags.size) {34753 switch (slice_ty.ptrInfo(zcu).flags.size) {
...@@ -34544,26 +34755,14 @@ fn maybeDerefSliceAsArray(...@@ -34544,26 +34755,14 @@ fn maybeDerefSliceAsArray(
34544 .one => return sema.pointerDeref(block, src, slice_val, slice_ty),34755 .one => return sema.pointerDeref(block, src, slice_val, slice_ty),
34545 .many, .c => unreachable,34756 .many, .c => unreachable,
34546 }34757 }
34547 const slice = switch (ip.indexToKey(slice_val.toIntern())) {34758 const slice = switch (zcu.intern_pool.indexToKey(slice_val.toIntern())) {
34548 .undef => return sema.failWithUseOfUndef(block, src, null),34759 .undef => return sema.failWithUseOfUndef(block, src, null),
34549 .slice => |slice| slice,34760 .slice => |slice| slice,
34550 else => unreachable,34761 else => unreachable,
34551 };34762 };
34552 const elem_ty = Type.fromInterned(slice.ty).childType(zcu);34763 if (slice.len == .undef_usize) return sema.failWithUndefSliceLen(block, src);
34553 const len = Value.fromInterned(slice.len).toUnsignedInt(zcu);34764 const casted_ptr = try pt.sliceToArrayPtr(slice);
34554 const array_ty = try pt.arrayType(.{34765 return sema.pointerDeref(block, src, casted_ptr, casted_ptr.typeOf(zcu));
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);
34567}34766}
3456834767
34569fn analyzeUnreachable(sema: *Sema, block: *Block, src: LazySrcLoc, safety_check: bool) !void {34768fn analyzeUnreachable(sema: *Sema, block: *Block, src: LazySrcLoc, safety_check: bool) !void {
...@@ -34668,7 +34867,7 @@ pub fn resolveNavPtrModifiers(...@@ -34668,7 +34867,7 @@ pub fn resolveNavPtrModifiers(
34668 const linksection_body = zir_decl.linksection_body orelse break :ls .none;34867 const linksection_body = zir_decl.linksection_body orelse break :ls .none;
34669 const linksection_ref = try sema.resolveInlineBody(block, linksection_body, decl_inst);34868 const linksection_ref = try sema.resolveInlineBody(block, linksection_body, decl_inst);
34670 const bytes = try sema.toConstString(block, section_src, linksection_ref, .{ .simple = .@"linksection" });34869 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) {
34672 return sema.fail(block, section_src, "linksection cannot contain null bytes", .{});34871 return sema.fail(block, section_src, "linksection cannot contain null bytes", .{});
34673 } else if (bytes.len == 0) {34872 } else if (bytes.len == 0) {
34674 return sema.fail(block, section_src, "linksection cannot be empty", .{});34873 return sema.fail(block, section_src, "linksection cannot be empty", .{});
...@@ -34843,7 +35042,9 @@ fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.StdLangDecl) CompileError!Typ...@@ -34843,7 +35042,9 @@ fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.StdLangDecl) CompileError!Typ
34843 }),35042 }),
3484435043
34845 // `fn (anyerror) noreturn`35044 // `fn (anyerror) noreturn`
34846 .@"panic.unwrapError" => try pt.funcType(.{35045 .@"panic.unwrapError",
35046 .@"panic.unexpectedErrorCode",
35047 => try pt.funcType(.{
34847 .param_types = &.{.anyerror_type},35048 .param_types = &.{.anyerror_type},
34848 .return_type = .noreturn_type,35049 .return_type = .noreturn_type,
34849 }),35050 }),
...@@ -34882,12 +35083,60 @@ fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.StdLangDecl) CompileError!Typ...@@ -34882,12 +35083,60 @@ fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.StdLangDecl) CompileError!Typ
34882 .@"panic.copyLenMismatch",35083 .@"panic.copyLenMismatch",
34883 .@"panic.memcpyAlias",35084 .@"panic.memcpyAlias",
34884 .@"panic.noreturnReturned",35085 .@"panic.noreturnReturned",
35086 .@"panic.loadUninstantiableType",
34885 => try pt.funcType(.{35087 => try pt.funcType(.{
34886 .param_types = &.{},35088 .param_types = &.{},
34887 .return_type = .noreturn_type,35089 .return_type = .noreturn_type,
34888 }),35090 }),
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`)
34891 };35140 };
34892}35141}
3489335142
...@@ -34926,7 +35175,9 @@ pub fn setTypeName(...@@ -34926,7 +35175,9 @@ pub fn setTypeName(
34926 },35175 },
34927 .parent => wip.setName(ip, block.type_name_ctx, sema.owner.unwrap().nav_val.toOptional()),35176 .parent => wip.setName(ip, block.type_name_ctx, sema.owner.unwrap().nav_val.toOptional()),
34928 .func => {35177 .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 });
34930 const zir_tags = sema.code.instructions.items(.tag);35181 const zir_tags = sema.code.instructions.items(.tag);
3493135182
34932 var aw: std.Io.Writer.Allocating = .init(gpa);35183 var aw: std.Io.Writer.Allocating = .init(gpa);
...@@ -35042,7 +35293,10 @@ fn zirStructDecl(...@@ -35042,7 +35293,10 @@ fn zirStructDecl(
35042 };35293 };
3504335294
35044 try sema.addTypeReferenceEntry(src, ty);35295 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
35047 return .fromType(ty);35301 return .fromType(ty);
35048}35302}
...@@ -35115,7 +35369,10 @@ fn zirUnionDecl(...@@ -35115,7 +35369,10 @@ fn zirUnionDecl(
35115 };35369 };
3511635370
35117 try sema.addTypeReferenceEntry(src, ty);35371 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
35120 return .fromType(ty);35377 return .fromType(ty);
35121}35378}
...@@ -35167,7 +35424,10 @@ fn zirEnumDecl(...@@ -35167,7 +35424,10 @@ fn zirEnumDecl(
35167 };35424 };
3516835425
35169 try sema.addTypeReferenceEntry(src, ty);35426 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
35172 return .fromType(ty);35432 return .fromType(ty);
35173}35433}
...@@ -35216,7 +35476,10 @@ fn zirOpaqueDecl(...@@ -35216,7 +35476,10 @@ fn zirOpaqueDecl(
35216 };35476 };
3521735477
35218 try sema.addTypeReferenceEntry(src, ty);35478 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
35221 return .fromType(ty);35484 return .fromType(ty);
35222}35485}
...@@ -35257,5 +35520,31 @@ pub fn failWithDependencyLoop(...@@ -35257,5 +35520,31 @@ pub fn failWithDependencyLoop(
35257 }35520 }
3525835521
35259 // A dependency loop error will be reported. Mark us all as transitive failures.35522 // 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;
35261}35550}
src/Sema/LowerZon.zig+2-2
...@@ -320,7 +320,7 @@ fn failUnsupportedResultType(...@@ -320,7 +320,7 @@ fn failUnsupportedResultType(
320 self: *LowerZon,320 self: *LowerZon,
321 ty: Type,321 ty: Type,
322 opt_note: ?[]const u8,322 opt_note: ?[]const u8,
323) error{ AnalysisFail, OutOfMemory } {323) Zcu.SemaError {
324 @branchHint(.cold);324 @branchHint(.cold);
325 const sema = self.sema;325 const sema = self.sema;
326 const gpa = sema.gpa;326 const gpa = sema.gpa;
...@@ -338,7 +338,7 @@ fn fail(...@@ -338,7 +338,7 @@ fn fail(
338 node: Zoir.Node.Index,338 node: Zoir.Node.Index,
339 comptime format: []const u8,339 comptime format: []const u8,
340 args: anytype,340 args: anytype,
341) error{ AnalysisFail, OutOfMemory } {341) Zcu.SemaError {
342 @branchHint(.cold);342 @branchHint(.cold);
343 const err_msg = try Zcu.ErrorMsg.create(self.sema.pt.zcu.gpa, self.nodeSrc(node), format, args);343 const err_msg = try Zcu.ErrorMsg.create(self.sema.pt.zcu.gpa, self.nodeSrc(node), format, args);
344 try self.sema.pt.zcu.errNote(self.import_loc, err_msg, "imported here", .{});344 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...@@ -116,7 +116,10 @@ fn ensureLayoutResolvedInner(sema: *Sema, ty: Type, orig_ty: Type, reason: *cons
116 if (zcu.analysis_in_progress.contains(.wrap(.{ .type_layout = ty.toIntern() }))) {116 if (zcu.analysis_in_progress.contains(.wrap(.{ .type_layout = ty.toIntern() }))) {
117 return sema.failWithDependencyLoop(.wrap(.{ .type_layout = ty.toIntern() }), reason);117 return sema.failWithDependencyLoop(.wrap(.{ .type_layout = ty.toIntern() }), reason);
118 }118 }
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 };
120 },123 },
121124
122 // values, not types125 // values, not types
...@@ -166,7 +169,10 @@ pub fn ensureStructDefaultsResolved(sema: *Sema, ty: Type, src: LazySrcLoc) Sema...@@ -166,7 +169,10 @@ pub fn ensureStructDefaultsResolved(sema: *Sema, ty: Type, src: LazySrcLoc) Sema
166 return sema.failWithDependencyLoop(.wrap(.{ .struct_defaults = ty.toIntern() }), &reason);169 return sema.failWithDependencyLoop(.wrap(.{ .struct_defaults = ty.toIntern() }), &reason);
167 }170 }
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 };
170}176}
171177
172/// Asserts that `struct_ty` is a non-packed non-tuple struct, and that `sema.owner` is that type.178/// 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 {...@@ -188,7 +194,9 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
188194
189 const struct_obj = ip.loadStructType(struct_ty.toIntern());195 const struct_obj = ip.loadStructType(struct_ty.toIntern());
190 assert(struct_obj.want_layout);196 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
193 var block: Block = .{201 var block: Block = .{
194 .parent = null,202 .parent = null,
...@@ -364,7 +372,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {...@@ -364,7 +372,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
364 const a = struct_obj.field_aligns.get(ip)[field_idx];372 const a = struct_obj.field_aligns.get(ip)[field_idx];
365 if (a != .none) break :a a;373 if (a != .none) break :a a;
366 }374 }
367 break :a field_ty.defaultStructFieldAlignment(struct_obj.layout, zcu);375 break :a field_ty.abiAlignment(zcu);
368 };376 };
369 align_out.* = field_align;377 align_out.* = field_align;
370 if (struct_obj.field_is_comptime_bits.get(ip, field_idx)) {378 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 {...@@ -606,7 +614,7 @@ pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void {
606 struct_ty.assertHasLayout(zcu);614 struct_ty.assertHasLayout(zcu);
607 const layout_unit: InternPool.AnalUnit = .wrap(.{ .type_layout = struct_ty.toIntern() });615 const layout_unit: InternPool.AnalUnit = .wrap(.{ .type_layout = struct_ty.toIntern() });
608 if (zcu.failed_analysis.contains(layout_unit) or zcu.transitive_failed_analysis.contains(layout_unit)) {616 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 });
610 }618 }
611619
612 const struct_obj = ip.loadStructType(struct_ty.toIntern());620 const struct_obj = ip.loadStructType(struct_ty.toIntern());
...@@ -656,7 +664,9 @@ fn resolveStructDefaultsInner(...@@ -656,7 +664,9 @@ fn resolveStructDefaultsInner(
656 assert(struct_obj.field_defaults.len > 0);664 assert(struct_obj.field_defaults.len > 0);
657665
658 // We'll need to map the struct decl instruction to provide result types666 // 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 };
660 try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index});670 try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index});
661671
662 const field_types = struct_obj.field_types.get(ip);672 const field_types = struct_obj.field_types.get(ip);
...@@ -713,7 +723,9 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void {...@@ -713,7 +723,9 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void {
713723
714 const union_obj = ip.loadUnionType(union_ty.toIntern());724 const union_obj = ip.loadUnionType(union_ty.toIntern());
715 assert(union_obj.want_layout);725 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
718 var block: Block = .{730 var block: Block = .{
719 .parent = null,731 .parent = null,
...@@ -1212,7 +1224,9 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void {...@@ -1212,7 +1224,9 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void {
1212 };1224 };
12131225
1214 const tracked_inst = enum_obj.zir_index.unwrap() orelse maybe_parent_union_obj.?.zir_index;1226 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
1217 var block: Block = .{1231 var block: Block = .{
1218 .parent = null,1232 .parent = null,
src/Type.zig+107-86
...@@ -957,12 +957,27 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment {...@@ -957,12 +957,27 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment {
957 if (vector_type.len == 0) return .@"1";957 if (vector_type.len == 0) return .@"1";
958 switch (zcu.comp.getZigBackend()) {958 switch (zcu.comp.getZigBackend()) {
959 else => {959 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));
961 if (elem_bits == 0) return .@"1";969 if (elem_bits == 0) return .@"1";
962 const bytes = ((elem_bits * vector_type.len) + 7) / 8;970 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 ));
964 },979 },
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),
966 .stage2_x86_64 => {981 .stage2_x86_64 => {
967 if (vector_type.child == .bool_type) {982 if (vector_type.child == .bool_type) {
968 if (vector_type.len > 256 and target.cpu.has(.x86, .avx512f)) return .@"64";983 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 {...@@ -1018,19 +1033,33 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment {
1018 .c_ulonglong => cTypeAlign(target, .ulonglong),1033 .c_ulonglong => cTypeAlign(target, .ulonglong),
1019 .c_longdouble => cTypeAlign(target, .longdouble),1034 .c_longdouble => cTypeAlign(target, .longdouble),
10201035
1021 .f16 => .@"2",1036 .f16 => .fromByteUnits(std.zig.target.intAlignment(target, 16)), // repr: u16
1022 .f32 => if (target.os.tag == .opengl) .@"4" else cTypeAlign(target, .float),1037 .f32 => if (target.cTypeBitSize(.float) == 32)
1023 .f64 => if (target.os.tag == .opengl) .@"8" else switch (target.cTypeBitSize(.double)) {1038 cTypeAlign(target, .float) // abi: c_float,
1024 64 => cTypeAlign(target, .double),1039 else
1025 else => .@"8",1040 .fromByteUnits(std.zig.target.intAlignment(target, 32)), // repr: u32,
1026 },1041 .f64 => if (target.cTypeBitSize(.double) == 64)
1027 .f80 => switch (target.cTypeBitSize(.longdouble)) {1042 cTypeAlign(target, .double) // abi: c_double,
1028 80 => cTypeAlign(target, .longdouble),1043 else
1029 else => Type.u80.abiAlignment(zcu),1044 .fromByteUnits(std.zig.target.intAlignment(target, 64)), // repr: u64,
1030 },1045 .f80 => if (target.cTypeBitSize(.longdouble) == 80)
1031 .f128 => switch (target.cTypeBitSize(.longdouble)) {1046 cTypeAlign(target, .longdouble) // abi: c_longdouble,
1032 128 => cTypeAlign(target, .longdouble),1047 else
1033 else => .@"16",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,
1034 },1063 },
10351064
1036 .generic_poison => unreachable,1065 .generic_poison => unreachable,
...@@ -1111,7 +1140,13 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 {...@@ -1111,7 +1140,13 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 {
1111 .vector_type => |vec| {1140 .vector_type => |vec| {
1112 const elem_ty: Type = .fromInterned(vec.child);1141 const elem_ty: Type = .fromInterned(vec.child);
1113 const bytes = switch (zcu.comp.getZigBackend()) {1142 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 },
1115 .stage2_c, .stage2_wasm => vec.len * elem_ty.abiSize(zcu),1150 .stage2_c, .stage2_wasm => vec.len * elem_ty.abiSize(zcu),
1116 .stage2_x86_64 => switch (elem_ty.toIntern()) {1151 .stage2_x86_64 => switch (elem_ty.toIntern()) {
1117 .bool_type => @divCeil(vec.len, 8),1152 .bool_type => @divCeil(vec.len, 8),
...@@ -1167,25 +1202,44 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 {...@@ -1167,25 +1202,44 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 {
1167 .anyerror, .adhoc_inferred_error_set => errorAbiSize(zcu),1202 .anyerror, .adhoc_inferred_error_set => errorAbiSize(zcu),
1168 .usize, .isize => ptrAbiSize(target),1203 .usize, .isize => ptrAbiSize(target),
11691204
1170 .c_char => target.cTypeByteSize(.char),1205 .c_char => target.cTypeByteSize(.char).?,
1171 .c_short => target.cTypeByteSize(.short),1206 .c_short => target.cTypeByteSize(.short).?,
1172 .c_ushort => target.cTypeByteSize(.ushort),1207 .c_ushort => target.cTypeByteSize(.ushort).?,
1173 .c_int => target.cTypeByteSize(.int),1208 .c_int => target.cTypeByteSize(.int).?,
1174 .c_uint => target.cTypeByteSize(.uint),1209 .c_uint => target.cTypeByteSize(.uint).?,
1175 .c_long => target.cTypeByteSize(.long),1210 .c_long => target.cTypeByteSize(.long).?,
1176 .c_ulong => target.cTypeByteSize(.ulong),1211 .c_ulong => target.cTypeByteSize(.ulong).?,
1177 .c_longlong => target.cTypeByteSize(.longlong),1212 .c_longlong => target.cTypeByteSize(.longlong).?,
1178 .c_ulonglong => target.cTypeByteSize(.ulonglong),1213 .c_ulonglong => target.cTypeByteSize(.ulonglong).?,
1179 .c_longdouble => target.cTypeByteSize(.longdouble),1214 .c_longdouble => target.cTypeByteSize(.longdouble).?,
11801215
1181 .f16 => 2,1216 .f16 => std.zig.target.intByteSize(target, 16), // repr: u16
1182 .f32 => 4,1217 .f32 => if (target.cTypeBitSize(.float) == 32)
1183 .f64 => 8,1218 target.cTypeByteSize(.float).? // abi: c_float,
1184 .f80 => switch (target.cTypeBitSize(.longdouble)) {1219 else
1185 80 => target.cTypeByteSize(.longdouble),1220 std.zig.target.intByteSize(target, 32), // repr: u32,
1186 else => Type.u80.abiSize(zcu),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,
1187 },1242 },
1188 .f128 => 16,
11891243
1190 .anyopaque => unreachable,1244 .anyopaque => unreachable,
1191 .generic_poison => unreachable,1245 .generic_poison => unreachable,
...@@ -1733,7 +1787,7 @@ pub fn isInt(self: Type, zcu: *const Zcu) bool {...@@ -1733,7 +1787,7 @@ pub fn isInt(self: Type, zcu: *const Zcu) bool {
1733/// Returns true if and only if the type is a fixed-width, signed integer.1787/// Returns true if and only if the type is a fixed-width, signed integer.
1734pub fn isSignedInt(ty: Type, zcu: *const Zcu) bool {1788pub fn isSignedInt(ty: Type, zcu: *const Zcu) bool {
1735 return switch (ty.toIntern()) {1789 return switch (ty.toIntern()) {
1736 .c_char_type => zcu.getTarget().cCharSignedness() == .signed,1790 .c_char_type => zcu.getTarget().cCharSignedness().? == .signed,
1737 .isize_type, .c_short_type, .c_int_type, .c_long_type, .c_longlong_type => true,1791 .isize_type, .c_short_type, .c_int_type, .c_long_type, .c_longlong_type => true,
1738 else => switch (zcu.intern_pool.indexToKey(ty.toIntern())) {1792 else => switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
1739 .int_type => |int_type| int_type.signedness == .signed,1793 .int_type => |int_type| int_type.signedness == .signed,
...@@ -1745,7 +1799,7 @@ pub fn isSignedInt(ty: Type, zcu: *const Zcu) bool {...@@ -1745,7 +1799,7 @@ pub fn isSignedInt(ty: Type, zcu: *const Zcu) bool {
1745/// Returns true if and only if the type is a fixed-width, unsigned integer.1799/// Returns true if and only if the type is a fixed-width, unsigned integer.
1746pub fn isUnsignedInt(ty: Type, zcu: *const Zcu) bool {1800pub fn isUnsignedInt(ty: Type, zcu: *const Zcu) bool {
1747 return switch (ty.toIntern()) {1801 return switch (ty.toIntern()) {
1748 .c_char_type => zcu.getTarget().cCharSignedness() == .unsigned,1802 .c_char_type => zcu.getTarget().cCharSignedness().? == .unsigned,
1749 .usize_type, .c_ushort_type, .c_uint_type, .c_ulong_type, .c_ulonglong_type => true,1803 .usize_type, .c_ushort_type, .c_uint_type, .c_ulong_type, .c_ulonglong_type => true,
1750 else => switch (zcu.intern_pool.indexToKey(ty.toIntern())) {1804 else => switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
1751 .int_type => |int_type| int_type.signedness == .unsigned,1805 .int_type => |int_type| int_type.signedness == .unsigned,
...@@ -1776,15 +1830,15 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType {...@@ -1776,15 +1830,15 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType {
1776 },1830 },
1777 .usize_type => return .{ .signedness = .unsigned, .bits = target.ptrBitWidth() },1831 .usize_type => return .{ .signedness = .unsigned, .bits = target.ptrBitWidth() },
1778 .isize_type => return .{ .signedness = .signed, .bits = target.ptrBitWidth() },1832 .isize_type => return .{ .signedness = .signed, .bits = target.ptrBitWidth() },
1779 .c_char_type => return .{ .signedness = zcu.getTarget().cCharSignedness(), .bits = target.cTypeBitSize(.char) },1833 .c_char_type => return .{ .signedness = target.cCharSignedness().?, .bits = target.cTypeBitSize(.char).? },
1780 .c_short_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.short) },1834 .c_short_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.short).? },
1781 .c_ushort_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ushort) },1835 .c_ushort_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ushort).? },
1782 .c_int_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.int) },1836 .c_int_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.int).? },
1783 .c_uint_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.uint) },1837 .c_uint_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.uint).? },
1784 .c_long_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.long) },1838 .c_long_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.long).? },
1785 .c_ulong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulong) },1839 .c_ulong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulong).? },
1786 .c_longlong_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.longlong) },1840 .c_longlong_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.longlong).? },
1787 .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulonglong) },1841 .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulonglong).? },
1788 else => switch (ip.indexToKey(ty.toIntern())) {1842 else => switch (ip.indexToKey(ty.toIntern())) {
1789 .int_type => |int_type| return int_type,1843 .int_type => |int_type| return int_type,
1790 .struct_type => {1844 .struct_type => {
...@@ -1882,7 +1936,7 @@ pub fn floatBits(ty: Type, target: *const Target) u16 {...@@ -1882,7 +1936,7 @@ pub fn floatBits(ty: Type, target: *const Target) u16 {
1882 .f64_type => 64,1936 .f64_type => 64,
1883 .f80_type => 80,1937 .f80_type => 80,
1884 .f128_type, .comptime_float_type => 128,1938 .f128_type, .comptime_float_type => 128,
1885 .c_longdouble_type => target.cTypeBitSize(.longdouble),1939 .c_longdouble_type => target.cTypeBitSize(.longdouble).?,
18861940
1887 else => unreachable,1941 else => unreachable,
1888 };1942 };
...@@ -2147,13 +2201,6 @@ pub fn isVector(ty: Type, zcu: *const Zcu) bool {...@@ -2147,13 +2201,6 @@ pub fn isVector(ty: Type, zcu: *const Zcu) bool {
2147 return ty.zigTypeTag(zcu) == .vector;2201 return ty.zigTypeTag(zcu) == .vector;
2148}2202}
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
2157pub fn isArrayOrVector(ty: Type, zcu: *const Zcu) bool {2204pub fn isArrayOrVector(ty: Type, zcu: *const Zcu) bool {
2158 return switch (ty.zigTypeTag(zcu)) {2205 return switch (ty.zigTypeTag(zcu)) {
2159 .array, .vector => true,2206 .array, .vector => true,
...@@ -2416,34 +2463,6 @@ pub fn explicitFieldAlignment(ty: Type, index: usize, zcu: *const Zcu) Alignment...@@ -2416,34 +2463,6 @@ pub fn explicitFieldAlignment(ty: Type, index: usize, zcu: *const Zcu) Alignment
2416 };2463 };
2417}2464}
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
2447pub fn structFieldDefaultValue(ty: Type, index: usize, zcu: *const Zcu) ?Value {2466pub fn structFieldDefaultValue(ty: Type, index: usize, zcu: *const Zcu) ?Value {
2448 const ip = &zcu.intern_pool;2467 const ip = &zcu.intern_pool;
2449 switch (ip.indexToKey(ty.toIntern())) {2468 switch (ip.indexToKey(ty.toIntern())) {
...@@ -2961,8 +2980,7 @@ pub fn fieldPtrType(ptr_ty: Type, field_index: u32, pt: Zcu.PerThread) Allocator...@@ -2961,8 +2980,7 @@ pub fn fieldPtrType(ptr_ty: Type, field_index: u32, pt: Zcu.PerThread) Allocator
2961 }2980 }
2962 const actual_field_align = switch (field_align) {2981 const actual_field_align = switch (field_align) {
2963 .none => switch (ip.indexToKey(aggregate_ty.toIntern())) {2982 .none => switch (ip.indexToKey(aggregate_ty.toIntern())) {
2964 .tuple_type, .union_type => field_ty.abiAlignment(zcu),2983 .struct_type, .tuple_type, .union_type => field_ty.abiAlignment(zcu),
2965 .struct_type => field_ty.defaultStructFieldAlignment(.auto, zcu),
2966 .ptr_type => Type.usize.abiAlignment(zcu),2984 .ptr_type => Type.usize.abiAlignment(zcu),
2967 else => unreachable,2985 else => unreachable,
2968 },2986 },
...@@ -3122,7 +3140,6 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool...@@ -3122,7 +3140,6 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool
31223140
3123 .@"opaque",3141 .@"opaque",
3124 .bool,3142 .bool,
3125 .float,
3126 .@"anyframe",3143 .@"anyframe",
3127 => true,3144 => true,
31283145
...@@ -3144,6 +3161,10 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool...@@ -3144,6 +3161,10 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool
3144 24, 48 => zcu.getTarget().cpu.arch == .ez80,3161 24, 48 => zcu.getTarget().cpu.arch == .ez80,
3145 else => false,3162 else => false,
3146 },3163 },
3164 .float => switch (ty.floatBits(zcu.getTarget())) {
3165 else => true,
3166 80 => zcu.getTarget().cTypeBitSize(.longdouble) == 80,
3167 },
3147 .@"fn" => {3168 .@"fn" => {
3148 if (position != .other) return false;3169 if (position != .other) return false;
3149 return validateExternCallconv(ty.fnCallingConvention(zcu));3170 return validateExternCallconv(ty.fnCallingConvention(zcu));
...@@ -3600,5 +3621,5 @@ pub fn smallestUnsignedBits(max: u64) u16 {...@@ -3600,5 +3621,5 @@ pub fn smallestUnsignedBits(max: u64) u16 {
3600pub const packed_struct_layout_version = 2;3621pub const packed_struct_layout_version = 2;
36013622
3602fn cTypeAlign(target: *const Target, c_type: Target.CType) Alignment {3623fn cTypeAlign(target: *const Target, c_type: Target.CType) Alignment {
3603 return Alignment.fromByteUnits(target.cTypeAlignment(c_type));3624 return .fromByteUnits(target.cTypeAlignment(c_type).?);
3604}3625}
src/Value.zig+2-7
...@@ -611,12 +611,7 @@ pub fn toFloat(val: Value, comptime T: type, zcu: *const Zcu) T {...@@ -611,12 +611,7 @@ pub fn toFloat(val: Value, comptime T: type, zcu: *const Zcu) T {
611 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {611 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {
612 .int => |int| switch (int.storage) {612 .int => |int| switch (int.storage) {
613 .big_int => |big_int| big_int.toFloat(T, .nearest_even)[0],613 .big_int => |big_int| big_int.toFloat(T, .nearest_even)[0],
614 inline .u64, .i64 => |x| {614 inline .u64, .i64 => |x| @floatFromInt(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 },
620 },615 },
621 .float => |float| switch (float.storage) {616 .float => |float| switch (float.storage) {
622 inline else => |x| @floatCast(x),617 inline else => |x| @floatCast(x),
...@@ -959,7 +954,7 @@ pub fn anyScalarIsZero(val: Value, zcu: *Zcu) bool {...@@ -959,7 +954,7 @@ pub fn anyScalarIsZero(val: Value, zcu: *Zcu) bool {
959 .bytes => |str| {954 .bytes => |str| {
960 const len = Type.fromInterned(agg.ty).vectorLen(zcu);955 const len = Type.fromInterned(agg.ty).vectorLen(zcu);
961 const slice = str.toSlice(len, &zcu.intern_pool);956 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;
963 },958 },
964 .elems => |elems| {959 .elems => |elems| {
965 for (elems) |elem| {960 for (elems) |elem| {
src/Zcu.zig+41-29
...@@ -182,7 +182,10 @@ analysis_in_progress: std.array_hash_map.Auto(AnalUnit, ?*const DependencyReason...@@ -182,7 +182,10 @@ analysis_in_progress: std.array_hash_map.Auto(AnalUnit, ?*const DependencyReason
182/// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator.182/// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator.
183failed_analysis: std.array_hash_map.Auto(AnalUnit, *ErrorMsg) = .empty,183failed_analysis: std.array_hash_map.Auto(AnalUnit, *ErrorMsg) = .empty,
184/// This `AnalUnit` failed semantic analysis because it required analysis of another `AnalUnit` which itself failed.184/// 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,
186/// This `Nav` succeeded analysis, but failed codegen.189/// This `Nav` succeeded analysis, but failed codegen.
187/// This may be a simple "value" `Nav`, or it may be a function.190/// This may be a simple "value" `Nav`, or it may be a function.
188/// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator.191/// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator.
...@@ -351,6 +354,18 @@ pub const DependencyReason = struct {...@@ -351,6 +354,18 @@ pub const DependencyReason = struct {
351 type_layout_reason: Sema.type_resolution.LayoutResolveReason,354 type_layout_reason: Sema.type_resolution.LayoutResolveReason,
352};355};
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
354pub const IncrementalDebugState = struct {369pub const IncrementalDebugState = struct {
355 /// All container types in the ZCU, even dead ones.370 /// All container types in the ZCU, even dead ones.
356 /// Value is the generation the type was created on.371 /// Value is the generation the type was created on.
...@@ -488,6 +503,7 @@ pub const StdLangDecl = enum {...@@ -488,6 +503,7 @@ pub const StdLangDecl = enum {
488 @"panic.castToNull",503 @"panic.castToNull",
489 @"panic.incorrectAlignment",504 @"panic.incorrectAlignment",
490 @"panic.invalidErrorCode",505 @"panic.invalidErrorCode",
506 @"panic.unexpectedErrorCode",
491 @"panic.integerOutOfBounds",507 @"panic.integerOutOfBounds",
492 @"panic.integerOverflow",508 @"panic.integerOverflow",
493 @"panic.shlOverflow",509 @"panic.shlOverflow",
...@@ -502,6 +518,7 @@ pub const StdLangDecl = enum {...@@ -502,6 +518,7 @@ pub const StdLangDecl = enum {
502 @"panic.copyLenMismatch",518 @"panic.copyLenMismatch",
503 @"panic.memcpyAlias",519 @"panic.memcpyAlias",
504 @"panic.noreturnReturned",520 @"panic.noreturnReturned",
521 @"panic.loadUninstantiableType",
505522
506 VaList,523 VaList,
507524
...@@ -577,6 +594,7 @@ pub const StdLangDecl = enum {...@@ -577,6 +594,7 @@ pub const StdLangDecl = enum {
577 .@"panic.castToNull",594 .@"panic.castToNull",
578 .@"panic.incorrectAlignment",595 .@"panic.incorrectAlignment",
579 .@"panic.invalidErrorCode",596 .@"panic.invalidErrorCode",
597 .@"panic.unexpectedErrorCode",
580 .@"panic.integerOutOfBounds",598 .@"panic.integerOutOfBounds",
581 .@"panic.integerOverflow",599 .@"panic.integerOverflow",
582 .@"panic.shlOverflow",600 .@"panic.shlOverflow",
...@@ -591,6 +609,7 @@ pub const StdLangDecl = enum {...@@ -591,6 +609,7 @@ pub const StdLangDecl = enum {
591 .@"panic.copyLenMismatch",609 .@"panic.copyLenMismatch",
592 .@"panic.memcpyAlias",610 .@"panic.memcpyAlias",
593 .@"panic.noreturnReturned",611 .@"panic.noreturnReturned",
612 .@"panic.loadUninstantiableType",
594 => .func,613 => .func,
595 };614 };
596 }615 }
...@@ -633,7 +652,7 @@ pub const StdLangDecl = enum {...@@ -633,7 +652,7 @@ pub const StdLangDecl = enum {
633 return switch (decl) {652 return switch (decl) {
634 inline else => |tag| {653 inline else => |tag| {
635 const name = @tagName(tag);654 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 };
637 const parent = @field(StdLangDecl, name[0..split]);656 const parent = @field(StdLangDecl, name[0..split]);
638 comptime assert(@backingInt(parent) < @backingInt(tag)); // dependencies ordered correctly657 comptime assert(@backingInt(parent) < @backingInt(tag)); // dependencies ordered correctly
639 return .{ .nested = .{ parent, name[split + 1 ..] } };658 return .{ .nested = .{ parent, name[split + 1 ..] } };
...@@ -664,6 +683,7 @@ pub const SimplePanicId = enum {...@@ -664,6 +683,7 @@ pub const SimplePanicId = enum {
664 copy_len_mismatch,683 copy_len_mismatch,
665 memcpy_alias,684 memcpy_alias,
666 noreturn_returned,685 noreturn_returned,
686 load_uninstantiable_type,
667687
668 pub fn toStdLangDecl(id: SimplePanicId) StdLangDecl {688 pub fn toStdLangDecl(id: SimplePanicId) StdLangDecl {
669 return switch (id) {689 return switch (id) {
...@@ -687,6 +707,7 @@ pub const SimplePanicId = enum {...@@ -687,6 +707,7 @@ pub const SimplePanicId = enum {
687 .copy_len_mismatch => .@"panic.copyLenMismatch",707 .copy_len_mismatch => .@"panic.copyLenMismatch",
688 .memcpy_alias => .@"panic.memcpyAlias",708 .memcpy_alias => .@"panic.memcpyAlias",
689 .noreturn_returned => .@"panic.noreturnReturned",709 .noreturn_returned => .@"panic.noreturnReturned",
710 .load_uninstantiable_type => .@"panic.loadUninstantiableType",
690 // zig fmt: on711 // zig fmt: on
691 };712 };
692 }713 }
...@@ -2808,13 +2829,13 @@ pub const LazySrcLoc = struct {...@@ -2808,13 +2829,13 @@ pub const LazySrcLoc = struct {
2808 }2829 }
2809};2830};
28102831
2811pub const SemaError = error{ OutOfMemory, Canceled, AnalysisFail };2832pub const SemaError = error{ OutOfMemory, Canceled, AlreadyReported };
2812pub const CompileError = error{2833pub const CompileError = error{
2813 OutOfMemory,2834 OutOfMemory,
2814 /// The compilation update is no longer desired.2835 /// The compilation update is no longer desired.
2815 Canceled,2836 Canceled,
2816 /// When this is returned, the compile error for the failure has already been recorded.2837 /// When this is returned, the compile error for the failure has already been recorded.
2817 AnalysisFail,2838 AlreadyReported,
2818 /// In a comptime scope, a return instruction was encountered. This error is only seen when2839 /// In a comptime scope, a return instruction was encountered. This error is only seen when
2819 /// doing a comptime function call.2840 /// doing a comptime function call.
2820 ComptimeReturn,2841 ComptimeReturn,
...@@ -2825,6 +2846,11 @@ pub const CompileError = error{...@@ -2825,6 +2846,11 @@ pub const CompileError = error{
28252846
2826pub fn init(zcu: *Zcu, gpa: Allocator, io: Io, thread_count: usize) !void {2847pub fn init(zcu: *Zcu, gpa: Allocator, io: Io, thread_count: usize) !void {
2827 try zcu.intern_pool.init(gpa, io, thread_count);2848 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 {
2828 zcu.initTracyPlots();2854 zcu.initTracyPlots();
2829}2855}
28302856
...@@ -4273,7 +4299,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.array_hash_map.Auto(Ana...@@ -4273,7 +4299,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.array_hash_map.Auto(Ana
4273 const fqn_slice = nav.fqn.toSlice(ip);4299 const fqn_slice = nav.fqn.toSlice(ip);
4274 if (comp.test_filters.len > 0) {4300 if (comp.test_filters.len > 0) {
4275 for (comp.test_filters) |test_filter| {4301 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;
4277 } else break :a false;4303 } else break :a false;
4278 }4304 }
4279 break :a true;4305 break :a true;
...@@ -4597,6 +4623,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)...@@ -4597,6 +4623,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)
4597 .x86_64_regcall_v3_sysv,4623 .x86_64_regcall_v3_sysv,
4598 .x86_64_regcall_v4_win,4624 .x86_64_regcall_v4_win,
4599 .x86_64_interrupt,4625 .x86_64_interrupt,
4626 .x86_64_preserve_none,
4600 .x86_fastcall,4627 .x86_fastcall,
4601 .x86_thiscall,4628 .x86_thiscall,
4602 .x86_vectorcall,4629 .x86_vectorcall,
...@@ -4605,6 +4632,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)...@@ -4605,6 +4632,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)
4605 .x86_interrupt,4632 .x86_interrupt,
4606 .aarch64_vfabi,4633 .aarch64_vfabi,
4607 .aarch64_vfabi_sve,4634 .aarch64_vfabi_sve,
4635 .aarch64_preserve_none,
4608 .arm_aapcs,4636 .arm_aapcs,
4609 .csky_interrupt,4637 .csky_interrupt,
4610 .riscv64_lp64_v,4638 .riscv64_lp64_v,
...@@ -4612,43 +4640,26 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)...@@ -4612,43 +4640,26 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)
4612 .m68k_rtd,4640 .m68k_rtd,
4613 .m68k_interrupt,4641 .m68k_interrupt,
4614 .msp430_interrupt,4642 .msp430_interrupt,
4615 => |opts| opts.incoming_stack_alignment == null,
4616
4617 .arm_aapcs_vfp,4643 .arm_aapcs_vfp,
4618 => |opts| opts.incoming_stack_alignment == null,
4619
4620 .arc_interrupt,4644 .arc_interrupt,
4621 => |opts| opts.incoming_stack_alignment == null,
4622
4623 .arm_interrupt,4645 .arm_interrupt,
4624 => |opts| opts.incoming_stack_alignment == null,
4625
4626 .microblaze_interrupt,4646 .microblaze_interrupt,
4627 => |opts| opts.incoming_stack_alignment == null,
4628
4629 .mips_interrupt,4647 .mips_interrupt,
4630 .mips64_interrupt,4648 .mips64_interrupt,
4631 => |opts| opts.incoming_stack_alignment == null,
4632
4633 .riscv32_interrupt,4649 .riscv32_interrupt,
4634 .riscv64_interrupt,4650 .riscv64_interrupt,
4635 => |opts| opts.incoming_stack_alignment == null,
4636
4637 .sh_interrupt,4651 .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
4640 .x86_sysv,4658 .x86_sysv,
4641 .x86_win,4659 .x86_win,
4660 .x86_mingw,
4642 .x86_stdcall,4661 .x86_stdcall,
4643 => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0,4662 => |opts| opts.register_params == 0, // incoming stack alignment supported
4644
4645 .avr_interrupt,
4646 .avr_signal,
4647 => true,
4648
4649 .ez80_tiflags => true,
4650
4651 .naked => true,
46524663
4653 else => false,4664 else => false,
4654 };4665 };
...@@ -4673,6 +4684,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)...@@ -4673,6 +4684,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)
4673 .stage2_x86 => switch (cc) {4684 .stage2_x86 => switch (cc) {
4674 .x86_sysv,4685 .x86_sysv,
4675 .x86_win,4686 .x86_win,
4687 .x86_mingw,
4676 => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0,4688 => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0,
4677 .naked => true,4689 .naked => true,
4678 else => false,4690 else => false,
src/Zcu/PerThread.zig+96-93
...@@ -320,7 +320,7 @@ pub fn update(...@@ -320,7 +320,7 @@ pub fn update(
320 // Zig compilation pipeline. It selects some `AnalUnit` which we know needs to be analyzed,320 // Zig compilation pipeline. It selects some `AnalUnit` which we know needs to be analyzed,
321 // and analyzes it, which may in turn discover more `AnalUnit`s which we need to analyze.321 // and analyzes it, which may in turn discover more `AnalUnit`s which we need to analyze.
322 while (try zcu.findOutdatedToAnalyze()) |unit| {322 while (try zcu.findOutdatedToAnalyze()) |unit| {
323 const maybe_err: Zcu.SemaError!void = switch (unit.unwrap()) {323 const maybe_err: UpdateUnitError!void = switch (unit.unwrap()) {
324 .@"comptime" => |cu| pt.ensureComptimeUnitUpToDate(cu),324 .@"comptime" => |cu| pt.ensureComptimeUnitUpToDate(cu),
325 .nav_ty => |nav| pt.ensureNavTypeUpToDate(nav, null),325 .nav_ty => |nav| pt.ensureNavTypeUpToDate(nav, null),
326 .nav_val => |nav| pt.ensureNavValUpToDate(nav, null),326 .nav_val => |nav| pt.ensureNavValUpToDate(nav, null),
...@@ -332,7 +332,7 @@ pub fn update(...@@ -332,7 +332,7 @@ pub fn update(
332 error.Canceled,332 error.Canceled,
333 => |e| return e,333 => |e| return e,
334334
335 error.AnalysisFail => {}, // already reported335 error.AnalysisFail => {},
336 };336 };
337 break :res pt.ensureStructDefaultsUpToDate(.fromInterned(ty), null);337 break :res pt.ensureStructDefaultsUpToDate(.fromInterned(ty), null);
338 },338 },
...@@ -344,7 +344,7 @@ pub fn update(...@@ -344,7 +344,7 @@ pub fn update(
344 error.Canceled,344 error.Canceled,
345 => |e| return e,345 => |e| return e,
346346
347 error.AnalysisFail => {}, // already reported347 error.AnalysisFail => {},
348 };348 };
349 }349 }
350}350}
...@@ -455,7 +455,7 @@ fn detectEmbedFileUpdate(comp: *Compilation, tid: Zcu.PerThread.Id, ef_index: Zc...@@ -455,7 +455,7 @@ fn detectEmbedFileUpdate(comp: *Compilation, tid: Zcu.PerThread.Id, ef_index: Zc
455455
456/// Ensures that `file` has up-to-date ZIR. If not, loads the ZIR cache or runs456/// Ensures that `file` has up-to-date ZIR. If not, loads the ZIR cache or runs
457/// AstGen as needed. Also updates `file.status`. Does not assume that `file.mod`457/// 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.
459pub fn updateFile(459pub fn updateFile(
460 pt: Zcu.PerThread,460 pt: Zcu.PerThread,
461 file_index: Zcu.File.Index,461 file_index: Zcu.File.Index,
...@@ -876,6 +876,7 @@ fn updateZirRefs(pt: Zcu.PerThread) (Io.Cancelable || Allocator.Error)!void {...@@ -876,6 +876,7 @@ fn updateZirRefs(pt: Zcu.PerThread) (Io.Cancelable || Allocator.Error)!void {
876 const old_line = old_zir.getDeclaration(old_inst).src_line;876 const old_line = old_zir.getDeclaration(old_inst).src_line;
877 const new_line = new_zir.getDeclaration(new_inst).src_line;877 const new_line = new_zir.getDeclaration(new_inst).src_line;
878 if (old_line != new_line) {878 if (old_line != new_line) {
879 comp.link_prog_node.increaseEstimatedTotalItems(1);
879 try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .debug_update_line_number = tracked_inst_index });880 try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .debug_update_line_number = tracked_inst_index });
880 }881 }
881 },882 },
...@@ -1035,6 +1036,11 @@ pub fn ensureFilePopulated(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Alloc...@@ -1035,6 +1036,11 @@ pub fn ensureFilePopulated(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Alloc
1035 zcu.setFileRootType(file_index, wip.finish(ip, new_namespace_index));1036 zcu.setFileRootType(file_index, wip.finish(ip, new_namespace_index));
1036}1037}
10371038
1039const UpdateUnitError = Allocator.Error || Io.Cancelable || error{
1040 /// Semantic analysis of this `AnalUnit` failed.
1041 AnalysisFail,
1042};
1043
1038/// Ensures that all memoized state on `Zcu` is up-to-date, performing re-analysis if necessary.1044/// Ensures that all memoized state on `Zcu` is up-to-date, performing re-analysis if necessary.
1039/// Returns `error.AnalysisFail` if an analysis error is encountered; the caller is free to ignore1045/// Returns `error.AnalysisFail` if an analysis error is encountered; the caller is free to ignore
1040/// this, since the error is already registered, but it must not use the value of memoized fields.1046/// this, since the error is already registered, but it must not use the value of memoized fields.
...@@ -1043,7 +1049,7 @@ pub fn ensureMemoizedStateUpToDate(...@@ -1043,7 +1049,7 @@ pub fn ensureMemoizedStateUpToDate(
1043 stage: InternPool.MemoizedStateStage,1049 stage: InternPool.MemoizedStateStage,
1044 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.1050 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
1045 reason: ?*const Zcu.DependencyReason,1051 reason: ?*const Zcu.DependencyReason,
1046) Zcu.SemaError!void {1052) UpdateUnitError!void {
1047 const zcu = pt.zcu;1053 const zcu = pt.zcu;
1048 const gpa = zcu.gpa;1054 const gpa = zcu.gpa;
10491055
...@@ -1077,15 +1083,7 @@ pub fn ensureMemoizedStateUpToDate(...@@ -1077,15 +1083,7 @@ pub fn ensureMemoizedStateUpToDate(
1077 const any_changed: bool, const new_failed: bool = if (pt.analyzeMemoizedState(stage, reason)) |any_changed|1083 const any_changed: bool, const new_failed: bool = if (pt.analyzeMemoizedState(stage, reason)) |any_changed|
1078 .{ any_changed or prev_failed, false }1084 .{ any_changed or prev_failed, false }
1079 else |err| switch (err) {1085 else |err| switch (err) {
1080 error.AnalysisFail => res: {1086 error.AlreadyReported => .{ !prev_failed, true },
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 },
1089 error.OutOfMemory => {1087 error.OutOfMemory => {
1090 // TODO: same as for `ensureComptimeUnitUpToDate` etc1088 // TODO: same as for `ensureComptimeUnitUpToDate` etc
1091 return error.OutOfMemory;1089 return error.OutOfMemory;
...@@ -1153,7 +1151,7 @@ fn analyzeMemoizedState(...@@ -1153,7 +1151,7 @@ fn analyzeMemoizedState(
1153/// Ensures that the state of the given `ComptimeUnit` is fully up-to-date, performing re-analysis1151/// Ensures that the state of the given `ComptimeUnit` is fully up-to-date, performing re-analysis
1154/// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is1152/// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is
1155/// free to ignore this, since the error is already registered.1153/// 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 {
1157 const zcu = pt.zcu;1155 const zcu = pt.zcu;
1158 const gpa = zcu.gpa;1156 const gpa = zcu.gpa;
11591157
...@@ -1194,15 +1192,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU...@@ -1194,15 +1192,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU
1194 defer unit_tracking.end(zcu);1192 defer unit_tracking.end(zcu);
11951193
1196 return pt.analyzeComptimeUnit(cu_id) catch |err| switch (err) {1194 return pt.analyzeComptimeUnit(cu_id) catch |err| switch (err) {
1197 error.AnalysisFail => {1195 error.AlreadyReported => return 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 },
1206 error.OutOfMemory => {1196 error.OutOfMemory => {
1207 // TODO: it's unclear how to gracefully handle this.1197 // TODO: it's unclear how to gracefully handle this.
1208 // To report the error cleanly, we need to add a message to `failed_analysis` and a1198 // 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...@@ -1220,8 +1210,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU
12201210
1221/// Re-analyzes a `ComptimeUnit`. The unit has already been determined to be out-of-date, and old1211/// Re-analyzes a `ComptimeUnit`. The unit has already been determined to be out-of-date, and old
1222/// side effects (exports/references/etc) have been dropped. If semantic analysis fails, this1212/// 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 entry1213/// function will return `error.AlreadyReported`.
1224/// to `transitive_failed_analysis` if necessary.
1225fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.CompileError!void {1214fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.CompileError!void {
1226 const zcu = pt.zcu;1215 const zcu = pt.zcu;
1227 const ip = &zcu.intern_pool;1216 const ip = &zcu.intern_pool;
...@@ -1238,7 +1227,14 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu...@@ -1238,7 +1227,14 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu
1238 defer tracy_trace.end();1227 defer tracy_trace.end();
1239 tracy_trace.addTextFmt("cu_id={d}", .{cu_id});1228 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 };
1242 const file = zcu.fileByIndex(inst_resolved.file);1238 const file = zcu.fileByIndex(inst_resolved.file);
1243 const zir = file.zir.?;1239 const zir = file.zir.?;
12441240
...@@ -1313,7 +1309,7 @@ pub fn ensureTypeLayoutUpToDate(...@@ -1313,7 +1309,7 @@ pub fn ensureTypeLayoutUpToDate(
1313 ty: Type,1309 ty: Type,
1314 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.1310 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
1315 reason: ?*const Zcu.DependencyReason,1311 reason: ?*const Zcu.DependencyReason,
1316) Zcu.SemaError!void {1312) UpdateUnitError!void {
1317 const zcu = pt.zcu;1313 const zcu = pt.zcu;
1318 const ip = &zcu.intern_pool;1314 const ip = &zcu.intern_pool;
1319 const comp = zcu.comp;1315 const comp = zcu.comp;
...@@ -1398,15 +1394,7 @@ pub fn ensureTypeLayoutUpToDate(...@@ -1398,15 +1394,7 @@ pub fn ensureTypeLayoutUpToDate(
1398 const new_failed: bool = if (result) failed: {1394 const new_failed: bool = if (result) failed: {
1399 break :failed false;1395 break :failed false;
1400 } else |err| switch (err) {1396 } else |err| switch (err) {
1401 error.AnalysisFail => failed: {1397 error.AlreadyReported => true,
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 },
1410 error.OutOfMemory,1398 error.OutOfMemory,
1411 error.Canceled,1399 error.Canceled,
1412 => |e| return e,1400 => |e| return e,
...@@ -1441,7 +1429,7 @@ pub fn ensureStructDefaultsUpToDate(...@@ -1441,7 +1429,7 @@ pub fn ensureStructDefaultsUpToDate(
1441 ty: Type,1429 ty: Type,
1442 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.1430 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
1443 reason: ?*const Zcu.DependencyReason,1431 reason: ?*const Zcu.DependencyReason,
1444) Zcu.SemaError!void {1432) UpdateUnitError!void {
1445 const zcu = pt.zcu;1433 const zcu = pt.zcu;
1446 const ip = &zcu.intern_pool;1434 const ip = &zcu.intern_pool;
1447 const comp = zcu.comp;1435 const comp = zcu.comp;
...@@ -1512,15 +1500,7 @@ pub fn ensureStructDefaultsUpToDate(...@@ -1512,15 +1500,7 @@ pub fn ensureStructDefaultsUpToDate(
1512 const new_failed: bool = if (Sema.type_resolution.resolveStructDefaults(&sema, ty)) failed: {1500 const new_failed: bool = if (Sema.type_resolution.resolveStructDefaults(&sema, ty)) failed: {
1513 break :failed false;1501 break :failed false;
1514 } else |err| switch (err) {1502 } else |err| switch (err) {
1515 error.AnalysisFail => failed: {1503 error.AlreadyReported => true,
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 },
1524 error.OutOfMemory,1504 error.OutOfMemory,
1525 error.Canceled,1505 error.Canceled,
1526 => |e| return e,1506 => |e| return e,
...@@ -1546,7 +1526,7 @@ pub fn ensureNavValUpToDate(...@@ -1546,7 +1526,7 @@ pub fn ensureNavValUpToDate(
1546 nav_id: InternPool.Nav.Index,1526 nav_id: InternPool.Nav.Index,
1547 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.1527 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
1548 reason: ?*const Zcu.DependencyReason,1528 reason: ?*const Zcu.DependencyReason,
1549) Zcu.SemaError!void {1529) UpdateUnitError!void {
1550 const zcu = pt.zcu;1530 const zcu = pt.zcu;
1551 const gpa = zcu.gpa;1531 const gpa = zcu.gpa;
1552 const ip = &zcu.intern_pool;1532 const ip = &zcu.intern_pool;
...@@ -1593,15 +1573,7 @@ pub fn ensureNavValUpToDate(...@@ -1593,15 +1573,7 @@ pub fn ensureNavValUpToDate(
1593 false,1573 false,
1594 };1574 };
1595 } else |err| switch (err) {1575 } else |err| switch (err) {
1596 error.AnalysisFail => res: {1576 error.AlreadyReported => .{ !prev_failed, true },
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 },
1605 error.OutOfMemory => {1577 error.OutOfMemory => {
1606 // TODO: it's unclear how to gracefully handle this.1578 // TODO: it's unclear how to gracefully handle this.
1607 // To report the error cleanly, we need to add a message to `failed_analysis` and a1579 // To report the error cleanly, we need to add a message to `failed_analysis` and a
...@@ -1654,7 +1626,14 @@ fn analyzeNavVal(...@@ -1654,7 +1626,14 @@ fn analyzeNavVal(
1654 tracy_trace.addText(old_nav.fqn.toSlice(ip));1626 tracy_trace.addText(old_nav.fqn.toSlice(ip));
1655 tracy_trace.addTextFmt("nav_id={d}", .{nav_id});1627 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 };
1658 const file = zcu.fileByIndex(inst_resolved.file);1637 const file = zcu.fileByIndex(inst_resolved.file);
1659 const zir = file.zir.?;1638 const zir = file.zir.?;
1660 const zir_decl = zir.getDeclaration(inst_resolved.inst);1639 const zir_decl = zir.getDeclaration(inst_resolved.inst);
...@@ -1915,7 +1894,7 @@ pub fn ensureNavTypeUpToDate(...@@ -1915,7 +1894,7 @@ pub fn ensureNavTypeUpToDate(
1915 nav_id: InternPool.Nav.Index,1894 nav_id: InternPool.Nav.Index,
1916 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.1895 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
1917 reason: ?*const Zcu.DependencyReason,1896 reason: ?*const Zcu.DependencyReason,
1918) Zcu.SemaError!void {1897) UpdateUnitError!void {
1919 const zcu = pt.zcu;1898 const zcu = pt.zcu;
1920 const gpa = zcu.gpa;1899 const gpa = zcu.gpa;
1921 const ip = &zcu.intern_pool;1900 const ip = &zcu.intern_pool;
...@@ -1962,15 +1941,7 @@ pub fn ensureNavTypeUpToDate(...@@ -1962,15 +1941,7 @@ pub fn ensureNavTypeUpToDate(
1962 false,1941 false,
1963 };1942 };
1964 } else |err| switch (err) {1943 } else |err| switch (err) {
1965 error.AnalysisFail => res: {1944 error.AlreadyReported => .{ !prev_failed, true },
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 },
1974 error.OutOfMemory => {1945 error.OutOfMemory => {
1975 // TODO: it's unclear how to gracefully handle this.1946 // TODO: it's unclear how to gracefully handle this.
1976 // To report the error cleanly, we need to add a message to `failed_analysis` and a1947 // To report the error cleanly, we need to add a message to `failed_analysis` and a
...@@ -2023,7 +1994,14 @@ fn analyzeNavType(...@@ -2023,7 +1994,14 @@ fn analyzeNavType(
2023 tracy_trace.addText(old_nav.fqn.toSlice(ip));1994 tracy_trace.addText(old_nav.fqn.toSlice(ip));
2024 tracy_trace.addTextFmt("nav_id={d}", .{nav_id});1995 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 };
2027 const file = zcu.fileByIndex(inst_resolved.file);2005 const file = zcu.fileByIndex(inst_resolved.file);
2028 const zir = file.zir.?;2006 const zir = file.zir.?;
20292007
...@@ -2159,7 +2137,7 @@ pub fn ensureFuncBodyUpToDate(...@@ -2159,7 +2137,7 @@ pub fn ensureFuncBodyUpToDate(
2159 func_index: InternPool.Index,2137 func_index: InternPool.Index,
2160 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.2138 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
2161 reason: ?*const Zcu.DependencyReason,2139 reason: ?*const Zcu.DependencyReason,
2162) Zcu.SemaError!void {2140) UpdateUnitError!void {
2163 dev.check(.sema);2141 dev.check(.sema);
21642142
2165 const zcu = pt.zcu;2143 const zcu = pt.zcu;
...@@ -2203,18 +2181,10 @@ pub fn ensureFuncBodyUpToDate(...@@ -2203,18 +2181,10 @@ pub fn ensureFuncBodyUpToDate(
2203 const ies_outdated, const new_failed = if (pt.analyzeFuncBody(func_index, reason)) |result|2181 const ies_outdated, const new_failed = if (pt.analyzeFuncBody(func_index, reason)) |result|
2204 .{ prev_failed or result.ies_outdated, false }2182 .{ prev_failed or result.ies_outdated, false }
2205 else |err| switch (err) {2183 else |err| switch (err) {
2206 error.AnalysisFail => res: {2184 // We consider the IES to be outdated if the function previously succeeded analysis; in this case,
2207 if (!zcu.failed_analysis.contains(anal_unit)) {2185 // we need to re-analyze dependants to ensure they hit a transitive error here, rather than reporting
2208 // If this function caused the error, it would have an entry in `failed_analysis`.2186 // a different error later (which may now be invalid).
2209 // Since it does not, this must be a transitive failure.2187 error.AlreadyReported => .{ !prev_failed, true },
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 },
2218 error.OutOfMemory => {2188 error.OutOfMemory => {
2219 // TODO: it's unclear how to gracefully handle this.2189 // TODO: it's unclear how to gracefully handle this.
2220 // To report the error cleanly, we need to add a message to `failed_analysis` and a2190 // To report the error cleanly, we need to add a message to `failed_analysis` and a
...@@ -3206,7 +3176,7 @@ const ScanDeclIter = struct {...@@ -3206,7 +3176,7 @@ const ScanDeclIter = struct {
3206 if (is_named and comp.test_filters.len > 0) {3176 if (is_named and comp.test_filters.len > 0) {
3207 const fqn_slice = fqn.toSlice(ip);3177 const fqn_slice = fqn.toSlice(ip);
3208 for (comp.test_filters) |test_filter| {3178 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;
3210 } else break :a false;3180 } else break :a false;
3211 }3181 }
3212 try zcu.test_functions.put(gpa, nav, {});3182 try zcu.test_functions.put(gpa, nav, {});
...@@ -3292,9 +3262,7 @@ fn analyzeFuncBodyInner(...@@ -3292,9 +3262,7 @@ fn analyzeFuncBodyInner(
3292 defer sema.deinit();3262 defer sema.deinit();
32933263
3294 // Every runtime function has a dependency on the source of the Decl it originates from.3264 // 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.
3296 try sema.declareDependency(.{ .src_hash = decl_analysis.zir_index });3265 try sema.declareDependency(.{ .src_hash = decl_analysis.zir_index });
3297 try sema.declareDependency(.{ .nav_val = func.owner_nav });
32983266
3299 // Make sure that the declaration `Nav` still refers to this function (or its generic owner).3267 // Make sure that the declaration `Nav` still refers to this function (or its generic owner).
3300 // This will not be the case if the incremental update has changed a function type or turned a3268 // This will not be the case if the incremental update has changed a function type or turned a
...@@ -3305,15 +3273,23 @@ fn analyzeFuncBodyInner(...@@ -3305,15 +3273,23 @@ fn analyzeFuncBodyInner(
3305 // If we *are* still owned by the right NAV, this analysis updates `zir_body_inst` if necessary.3273 // If we *are* still owned by the right NAV, this analysis updates `zir_body_inst` if necessary.
33063274
3307 if (func.generic_owner == .none) {3275 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 };
3309 if (ip.getNav(func.owner_nav).resolved.?.value != func_index) {3281 if (ip.getNav(func.owner_nav).resolved.?.value != func_index) {
3310 return error.AnalysisFail;3282 return sema.failTransitive(.{ .func_nav_val_changed = func_index });
3311 }3283 }
3312 } else {3284 } else {
3313 const go_nav = zcu.funcInfo(func.generic_owner).owner_nav;3285 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 };
3315 if (ip.getNav(go_nav).resolved.?.value != func.generic_owner) {3291 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 });
3317 }3293 }
3318 }3294 }
33193295
...@@ -3343,7 +3319,9 @@ fn analyzeFuncBodyInner(...@@ -3343,7 +3319,9 @@ fn analyzeFuncBodyInner(
3343 };3319 };
3344 defer inner_block.instructions.deinit(gpa);3320 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
3348 // Here we are performing "runtime semantic analysis" for a function body, which means3326 // Here we are performing "runtime semantic analysis" for a function body, which means
3349 // we must map the parameter ZIR instructions to `arg` AIR instructions.3327 // 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...@@ -3520,6 +3498,25 @@ pub fn getErrorValueFromSlice(pt: Zcu.PerThread, name: []const u8) Allocator.Err
3520 return pt.getErrorValue(try pt.zcu.intern_pool.getOrPutString(gpa, io, name));3498 return pt.getErrorValue(try pt.zcu.intern_pool.getOrPutString(gpa, io, name));
3521}3499}
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
3523/// Removes any entry from `Zcu.failed_files` associated with `file`. Acquires `Compilation.mutex` as needed.3520/// Removes any entry from `Zcu.failed_files` associated with `file`. Acquires `Compilation.mutex` as needed.
3524/// `file.zir` must be unchanged from the last update, as it is used to determine if there is such an entry.3521/// `file.zir` must be unchanged from the last update, as it is used to determine if there is such an entry.
3525fn lockAndClearFileCompileError(pt: Zcu.PerThread, file_index: Zcu.File.Index, file: *Zcu.File) void {3522fn 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 |...@@ -4377,12 +4374,18 @@ pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) (Io.Cancelable |
4377 return result.index;4374 return result.index;
4378}4375}
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
4380/// Given a namespace, re-scan its declarations from the type definition if they have not4383/// Given a namespace, re-scan its declarations from the type definition if they have not
4381/// yet been re-scanned on this update.4384/// 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`.
4383/// This will effectively short-circuit the caller, which will be semantic analysis of a4386/// This will effectively short-circuit the caller, which will be semantic analysis of a
4384/// guaranteed-unreferenced `AnalUnit`, to trigger a transitive analysis error.4387/// 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 {
4386 const zcu = pt.zcu;4389 const zcu = pt.zcu;
4387 const ip = &zcu.intern_pool;4390 const ip = &zcu.intern_pool;
4388 const namespace = zcu.namespacePtr(namespace_index);4391 const namespace = zcu.namespacePtr(namespace_index);
...@@ -4409,7 +4412,7 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace...@@ -4409,7 +4412,7 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace
44094412
4410 // Namespace outdated -- re-scan the type if necessary.4413 // 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;
4413 const file = zcu.fileByIndex(inst_info.file);4416 const file = zcu.fileByIndex(inst_info.file);
4414 const zir = &file.zir.?;4417 const zir = &file.zir.?;
44154418
src/codegen.zig+196-30
...@@ -767,11 +767,9 @@ fn lowerNavRef(...@@ -767,11 +767,9 @@ fn lowerNavRef(
767 offset: u64,767 offset: u64,
768) (Error || std.Io.Writer.Error)!void {768) (Error || std.Io.Writer.Error)!void {
769 const zcu = pt.zcu;769 const zcu = pt.zcu;
770 const gpa = zcu.gpa;
771 const ip = &zcu.intern_pool;770 const ip = &zcu.intern_pool;
772 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;771 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;
773 const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8);772 const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8);
774 const is_obj = lf.comp.config.output_mode == .Obj;
775 const nav_ty = Type.fromInterned(ip.getNav(nav_index).resolved.?.type);773 const nav_ty = Type.fromInterned(ip.getNav(nav_index).resolved.?.type);
776774
777 if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) and ip.getNav(nav_index).getExtern(ip) == null) {775 if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) and ip.getNav(nav_index).getExtern(ip) == null) {
...@@ -786,34 +784,7 @@ fn lowerNavRef(...@@ -786,34 +784,7 @@ fn lowerNavRef(
786 dev.check(link.File.Tag.wasm.devFeature());784 dev.check(link.File.Tag.wasm.devFeature());
787 const wasm = lf.cast(.wasm).?;785 const wasm = lf.cast(.wasm).?;
788 assert(reloc_parent == .none);786 assert(reloc_parent == .none);
789 if (nav_ty.zigTypeTag(zcu) == .@"fn") {787 try wasm.addNavReloc(w.end, nav_index, nav_ty, @intCast(offset));
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 }
817 try w.splatByteAll(0, ptr_width_bytes);788 try w.splatByteAll(0, ptr_width_bytes);
818 return;789 return;
819 },790 },
...@@ -1124,6 +1095,201 @@ pub fn fieldOffset(ptr_agg_ty: Type, ptr_field_ty: Type, field_index: u32, zcu:...@@ -1124,6 +1095,201 @@ pub fn fieldOffset(ptr_agg_ty: Type, ptr_field_ty: Type, field_index: u32, zcu:
1124 };1095 };
1125}1096}
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
1127test {1293test {
1128 _ = aarch64;1294 _ = aarch64;
1129}1295}
src/codegen/aarch64/Assemble.zig+1-1
...@@ -163,7 +163,7 @@ const matchers = matchers: {...@@ -163,7 +163,7 @@ const matchers = matchers: {
163 arg.* = zonCast(param_type.?, instruction.encode[encode_index], symbols);163 arg.* = zonCast(param_type.?, instruction.encode[encode_index], symbols);
164 return @call(.auto, encode, args);164 return @call(.auto, encode, args);
165 } else if (pattern_token[0] == '<') {165 } else if (pattern_token[0] == '<') {
166 const symbol_name = comptime pattern_token[1 .. std.mem.indexOfScalarPos(u8, pattern_token, 1, '|') orelse166 const symbol_name = comptime pattern_token[1 .. std.mem.findScalarPos(u8, pattern_token, 1, '|') orelse
167 pattern_token.len - 1];167 pattern_token.len - 1];
168 const symbol = @field(Symbol, symbol_name);168 const symbol = @field(Symbol, symbol_name);
169 const symbol_ptr = &@field(symbols, symbol_name);169 const symbol_ptr = &@field(symbols, symbol_name);
src/codegen/aarch64/Mir.zig+2-2
...@@ -70,8 +70,8 @@ pub fn emit(...@@ -70,8 +70,8 @@ pub fn emit(
7070
71 const func_align = switch (nav.resolved.?.@"align") {71 const func_align = switch (nav.resolved.?.@"align") {
72 .none => switch (mod.optimize_mode) {72 .none => switch (mod.optimize_mode) {
73 .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),73 .debug, .safe, .fast => target_util.defaultFunctionAlignment(target),
74 .ReleaseSmall => target_util.minFunctionAlignment(target),74 .small => target_util.minFunctionAlignment(target),
75 },75 },
76 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),76 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
77 };77 };
src/codegen/aarch64/Select.zig+23-27
...@@ -2099,7 +2099,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -2099,7 +2099,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
2099 32 => "truncf",2099 32 => "truncf",
2100 64 => "trunc",2100 64 => "trunc",
2101 80 => "__truncx",2101 80 => "__truncx",
2102 128 => "truncq",2102 128 => "truncf128",
2103 },2103 },
2104 .reloc = .{ .label = @intCast(isel.instructions.items.len) },2104 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
2105 });2105 });
...@@ -2113,7 +2113,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -2113,7 +2113,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
2113 32 => "floorf",2113 32 => "floorf",
2114 64 => "floor",2114 64 => "floor",
2115 80 => "__floorx",2115 80 => "__floorx",
2116 128 => "floorq",2116 128 => "floorf128",
2117 },2117 },
2118 .reloc = .{ .label = @intCast(isel.instructions.items.len) },2118 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
2119 });2119 });
...@@ -2431,7 +2431,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -2431,7 +2431,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
2431 32 => "fmodf",2431 32 => "fmodf",
2432 64 => "fmod",2432 64 => "fmod",
2433 80 => "__fmodx",2433 80 => "__fmodx",
2434 128 => "fmodq",2434 128 => "fmodf128",
2435 },2435 },
2436 .reloc = .{ .label = @intCast(isel.instructions.items.len) },2436 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
2437 });2437 });
...@@ -2599,7 +2599,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -2599,7 +2599,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
2599 32 => "fmaxf",2599 32 => "fmaxf",
2600 64 => "fmax",2600 64 => "fmax",
2601 80 => "__fmaxx",2601 80 => "__fmaxx",
2602 128 => "fmaxq",2602 128 => "fmaxf128",
2603 },2603 },
2604 .min => switch (bits) {2604 .min => switch (bits) {
2605 else => unreachable,2605 else => unreachable,
...@@ -2607,7 +2607,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -2607,7 +2607,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
2607 32 => "fminf",2607 32 => "fminf",
2608 64 => "fmin",2608 64 => "fmin",
2609 80 => "__fminx",2609 80 => "__fminx",
2610 128 => "fminq",2610 128 => "fminf128",
2611 },2611 },
2612 },2612 },
2613 .reloc = .{ .label = @intCast(isel.instructions.items.len) },2613 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
...@@ -2856,7 +2856,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -2856,7 +2856,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
2856 const remaining_source = std.mem.span(as.source);2856 const remaining_source = std.mem.span(as.source);
2857 return isel.fail("unable to assemble: '{s}'", .{std.mem.trim(2857 return isel.fail("unable to assemble: '{s}'", .{std.mem.trim(
2858 u8,2858 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],
2860 &std.ascii.whitespace,2860 &std.ascii.whitespace,
2861 )});2861 )});
2862 },2862 },
...@@ -4055,7 +4055,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -4055,7 +4055,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
4055 32 => "sqrtf",4055 32 => "sqrtf",
4056 64 => "sqrt",4056 64 => "sqrt",
4057 80 => "__sqrtx",4057 80 => "__sqrtx",
4058 128 => "sqrtq",4058 128 => "sqrtf128",
4059 },4059 },
4060 .floor => switch (bits) {4060 .floor => switch (bits) {
4061 else => unreachable,4061 else => unreachable,
...@@ -4063,7 +4063,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -4063,7 +4063,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
4063 32 => "floorf",4063 32 => "floorf",
4064 64 => "floor",4064 64 => "floor",
4065 80 => "__floorx",4065 80 => "__floorx",
4066 128 => "floorq",4066 128 => "floorf128",
4067 },4067 },
4068 .ceil => switch (bits) {4068 .ceil => switch (bits) {
4069 else => unreachable,4069 else => unreachable,
...@@ -4071,7 +4071,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -4071,7 +4071,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
4071 32 => "ceilf",4071 32 => "ceilf",
4072 64 => "ceil",4072 64 => "ceil",
4073 80 => "__ceilx",4073 80 => "__ceilx",
4074 128 => "ceilq",4074 128 => "ceilf128",
4075 },4075 },
4076 .round => switch (bits) {4076 .round => switch (bits) {
4077 else => unreachable,4077 else => unreachable,
...@@ -4079,7 +4079,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -4079,7 +4079,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
4079 32 => "roundf",4079 32 => "roundf",
4080 64 => "round",4080 64 => "round",
4081 80 => "__roundx",4081 80 => "__roundx",
4082 128 => "roundq",4082 128 => "roundf128",
4083 },4083 },
4084 .trunc_float => switch (bits) {4084 .trunc_float => switch (bits) {
4085 else => unreachable,4085 else => unreachable,
...@@ -4087,7 +4087,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -4087,7 +4087,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
4087 32 => "truncf",4087 32 => "truncf",
4088 64 => "trunc",4088 64 => "trunc",
4089 80 => "__truncx",4089 80 => "__truncx",
4090 128 => "truncq",4090 128 => "truncf128",
4091 },4091 },
4092 },4092 },
4093 .reloc = .{ .label = @intCast(isel.instructions.items.len) },4093 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
...@@ -4147,7 +4147,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -4147,7 +4147,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
4147 32 => "sinf",4147 32 => "sinf",
4148 64 => "sin",4148 64 => "sin",
4149 80 => "__sinx",4149 80 => "__sinx",
4150 128 => "sinq",4150 128 => "sinf128",
4151 },4151 },
4152 .cos => switch (bits) {4152 .cos => switch (bits) {
4153 else => unreachable,4153 else => unreachable,
...@@ -4155,7 +4155,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -4155,7 +4155,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
4155 32 => "cosf",4155 32 => "cosf",
4156 64 => "cos",4156 64 => "cos",
4157 80 => "__cosx",4157 80 => "__cosx",
4158 128 => "cosq",4158 128 => "cosf128",
4159 },4159 },
4160 .tan => switch (bits) {4160 .tan => switch (bits) {
4161 else => unreachable,4161 else => unreachable,
...@@ -4163,7 +4163,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -4163,7 +4163,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
4163 32 => "tanf",4163 32 => "tanf",
4164 64 => "tan",4164 64 => "tan",
4165 80 => "__tanx",4165 80 => "__tanx",
4166 128 => "tanq",4166 128 => "tanf128",
4167 },4167 },
4168 .exp => switch (bits) {4168 .exp => switch (bits) {
4169 else => unreachable,4169 else => unreachable,
...@@ -4171,7 +4171,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -4171,7 +4171,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
4171 32 => "expf",4171 32 => "expf",
4172 64 => "exp",4172 64 => "exp",
4173 80 => "__expx",4173 80 => "__expx",
4174 128 => "expq",4174 128 => "expf128",
4175 },4175 },
4176 .exp2 => switch (bits) {4176 .exp2 => switch (bits) {
4177 else => unreachable,4177 else => unreachable,
...@@ -4179,7 +4179,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -4179,7 +4179,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
4179 32 => "exp2f",4179 32 => "exp2f",
4180 64 => "exp2",4180 64 => "exp2",
4181 80 => "__exp2x",4181 80 => "__exp2x",
4182 128 => "exp2q",4182 128 => "exp2f128",
4183 },4183 },
4184 .log => switch (bits) {4184 .log => switch (bits) {
4185 else => unreachable,4185 else => unreachable,
...@@ -4187,7 +4187,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -4187,7 +4187,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
4187 32 => "logf",4187 32 => "logf",
4188 64 => "log",4188 64 => "log",
4189 80 => "__logx",4189 80 => "__logx",
4190 128 => "logq",4190 128 => "logf128",
4191 },4191 },
4192 .log2 => switch (bits) {4192 .log2 => switch (bits) {
4193 else => unreachable,4193 else => unreachable,
...@@ -4195,7 +4195,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -4195,7 +4195,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
4195 32 => "log2f",4195 32 => "log2f",
4196 64 => "log2",4196 64 => "log2",
4197 80 => "__log2x",4197 80 => "__log2x",
4198 128 => "log2q",4198 128 => "log2f128",
4199 },4199 },
4200 .log10 => switch (bits) {4200 .log10 => switch (bits) {
4201 else => unreachable,4201 else => unreachable,
...@@ -4203,7 +4203,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -4203,7 +4203,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
4203 32 => "log10f",4203 32 => "log10f",
4204 64 => "log10",4204 64 => "log10",
4205 80 => "__log10x",4205 80 => "__log10x",
4206 128 => "log10q",4206 128 => "log10f128",
4207 },4207 },
4208 },4208 },
4209 .reloc = .{ .label = @intCast(isel.instructions.items.len) },4209 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
...@@ -7118,7 +7118,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -7118,7 +7118,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
7118 32 => "fmaf",7118 32 => "fmaf",
7119 64 => "fma",7119 64 => "fma",
7120 80 => "__fmax",7120 80 => "__fmax",
7121 128 => "fmaq",7121 128 => "fmaf128",
7122 },7122 },
7123 .reloc = .{ .label = @intCast(isel.instructions.items.len) },7123 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
7124 });7124 });
...@@ -12176,9 +12176,7 @@ pub const CallAbiIterator = struct {...@@ -12176,9 +12176,7 @@ pub const CallAbiIterator = struct {
12176 const loaded_struct = ip.loadStructType(ty.toIntern());12176 const loaded_struct = ip.loadStructType(ty.toIntern());
12177 switch (loaded_struct.layout) {12177 switch (loaded_struct.layout) {
12178 .auto, .@"extern" => {},12178 .auto, .@"extern" => {},
12179 .@"packed" => continue :type_key .{12179 .@"packed" => continue :type_key ip.indexToKey(loaded_struct.packed_backing_int_type),
12180 .int_type = ip.indexToKey(loaded_struct.packed_backing_int_type).int_type,
12181 },
12182 }12180 }
12183 const size = wip_vi.size(isel);12181 const size = wip_vi.size(isel);
12184 if (size <= 16 * 4) homogeneous_aggregate: {12182 if (size <= 16 * 4) homogeneous_aggregate: {
...@@ -12300,9 +12298,7 @@ pub const CallAbiIterator = struct {...@@ -12300,9 +12298,7 @@ pub const CallAbiIterator = struct {
12300 }12298 }
12301 },12299 },
12302 .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque },12300 .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque },
12303 .enum_type => continue :type_key .{12301 .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).int_tag_type),
12304 .int_type = ip.indexToKey(ip.loadEnumType(ty.toIntern()).int_tag_type).int_type,
12305 },
12306 .error_set_type,12302 .error_set_type,
12307 .inferred_error_set_type,12303 .inferred_error_set_type,
12308 => continue :type_key .{ .simple_type = .anyerror },12304 => continue :type_key .{ .simple_type = .anyerror },
...@@ -12388,7 +12384,7 @@ pub const CallAbiIterator = struct {...@@ -12388,7 +12384,7 @@ pub const CallAbiIterator = struct {
12388 .f32 => .single,12384 .f32 => .single,
12389 .f64 => .double,12385 .f64 => .double,
12390 .f128 => .quad,12386 .f128 => .quad,
12391 .c_longdouble => switch (zcu.getTarget().cTypeBitSize(.longdouble)) {12387 .c_longdouble => switch (zcu.getTarget().cTypeBitSize(.longdouble).?) {
12392 else => unreachable,12388 else => unreachable,
12393 64 => .double,12389 64 => .double,
12394 80 => null,12390 80 => null,
src/codegen/aarch64/abi.zig+7-2
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1const assert = @import("std").debug.assert;1const assert = std.debug.assert;
2const std = @import("std");2const std = @import("std");
3const InternPool = @import("../../InternPool.zig");3const InternPool = @import("../../InternPool.zig");
4const Type = @import("../../Type.zig");4const Type = @import("../../Type.zig");
...@@ -35,7 +35,12 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class {...@@ -35,7 +35,12 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class {
35 if (bit_size > 64) return .double_integer;35 if (bit_size > 64) return .double_integer;
36 return .integer;36 return .integer;
37 },37 },
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 },
39 .vector => {44 .vector => {
40 const bit_size = ty.bitSize(zcu);45 const bit_size = ty.bitSize(zcu);
41 // TODO is this controlled by a cpu feature?46 // 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 {...@@ -39,7 +39,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
39 const float_count = countFloats(ty, zcu, &maybe_float_bits);39 const float_count = countFloats(ty, zcu, &maybe_float_bits);
40 if (float_count <= byval_float_count) return .byval;40 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")) {
43 return Class.arrSize(bit_size, 64);43 return Class.arrSize(bit_size, 64);
44 }44 }
4545
...@@ -62,7 +62,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {...@@ -62,7 +62,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
62 const float_count = countFloats(ty, zcu, &maybe_float_bits);62 const float_count = countFloats(ty, zcu, &maybe_float_bits);
63 if (float_count <= byval_float_count) return .byval;63 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")) {
66 return Class.arrSize(bit_size, 64);66 return Class.arrSize(bit_size, 64);
67 }67 }
6868
...@@ -73,14 +73,16 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {...@@ -73,14 +73,16 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
73 }73 }
74 return Class.arrSize(bit_size, 32);74 return Class.arrSize(bit_size, 32);
75 },75 },
76 .bool, .float => return .byval,76 .bool => return .byval,
77 .int => {77 .int => {
78 // TODO this is incorrect for _BitInt(128) but implementing78 if (ctx == .ret and ty.intInfo(zcu).bits > 64) return .memory;
79 // this correctly makes implementing compiler-rt impossible.
80 // const bit_size = ty.bitSize(zcu);
81 // if (bit_size > 64) return .memory;
82 return .byval;79 return .byval;
83 },80 },
81 .float => return switch (ty.floatBits(zcu.getTarget())) {
82 else => unreachable,
83 16, 32, 64 => .byval,
84 80, 128 => .{ .i64_array = 2 },
85 },
84 .@"enum", .error_set => {86 .@"enum", .error_set => {
85 const bit_size = ty.bitSize(zcu);87 const bit_size = ty.bitSize(zcu);
86 if (bit_size > 64) return .memory;88 if (bit_size > 64) return .memory;
src/codegen/c.zig+751-610
...@@ -164,7 +164,8 @@ const BlockData = struct {...@@ -164,7 +164,8 @@ const BlockData = struct {
164164
165const LocalType = struct {165const LocalType = struct {
166 type: Type,166 type: Type,
167 alignment: Alignment,167 alignment: Alignment = .none,
168 array_len: u2 = 1,
168};169};
169170
170const LocalIndex = u16;171const LocalIndex = u16;
...@@ -184,13 +185,11 @@ const ValueRenderLocation = enum {...@@ -184,13 +185,11 @@ const ValueRenderLocation = enum {
184 }185 }
185};186};
186187
187const BuiltinInfo = enum { none, bits };188const BuiltinInfo = enum { none, bits, bits_none, big_temp_bits };
188189
189const reserved_idents = std.StaticStringMap(void).initComptime(.{190const reserved_idents = std.StaticStringMap(void).initComptime(.{
190 // C language191 // C language
191 .{ "alignas", {192 .{ "alignas", {} },
192 @setEvalBranchQuota(4000);
193 } },
194 .{ "alignof", {} },193 .{ "alignof", {} },
195 .{ "asm", {} },194 .{ "asm", {} },
196 .{ "atomic_bool", {} },195 .{ "atomic_bool", {} },
...@@ -302,7 +301,100 @@ const reserved_idents = std.StaticStringMap(void).initComptime(.{...@@ -302,7 +301,100 @@ const reserved_idents = std.StaticStringMap(void).initComptime(.{
302 // stddef.h301 // stddef.h
303 .{ "offsetof", {} },302 .{ "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
305 // windows.h382 // 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"},
306 .{ "max", {} },398 .{ "max", {} },
307 .{ "min", {} },399 .{ "min", {} },
308});400});
...@@ -316,13 +408,6 @@ fn isReservedIdent(ident: []const u8) bool {...@@ -316,13 +408,6 @@ fn isReservedIdent(ident: []const u8) bool {
316 }408 }
317 }409 }
318410
319 // windows.h
320 if (mem.startsWith(u8, ident, "DUMMYSTRUCTNAME") or
321 mem.startsWith(u8, ident, "DUMMYUNIONNAME"))
322 {
323 return true;
324 }
325
326 // CType411 // CType
327 if (mem.startsWith(u8, ident, "enum__") or412 if (mem.startsWith(u8, ident, "enum__") or
328 mem.startsWith(u8, ident, "bitpack__") or413 mem.startsWith(u8, ident, "bitpack__") or
...@@ -453,8 +538,8 @@ pub const Function = struct {...@@ -453,8 +538,8 @@ pub const Function = struct {
453538
454 fn wantSafety(f: *Function) bool {539 fn wantSafety(f: *Function) bool {
455 return switch (f.dg.mod.optimize_mode) {540 return switch (f.dg.mod.optimize_mode) {
456 .Debug, .ReleaseSafe => true,541 .debug, .safe => true,
457 .ReleaseFast, .ReleaseSmall => false,542 .fast, .small => false,
458 };543 };
459 }544 }
460545
...@@ -469,10 +554,7 @@ pub const Function = struct {...@@ -469,10 +554,7 @@ pub const Function = struct {
469 }554 }
470555
471 fn allocLocal(f: *Function, inst: ?Air.Inst.Index, ty: Type) !CValue {556 fn allocLocal(f: *Function, inst: ?Air.Inst.Index, ty: Type) !CValue {
472 return f.allocAlignedLocal(inst, .{557 return f.allocAlignedLocal(inst, .{ .type = ty });
473 .type = ty,
474 .alignment = .none,
475 });
476 }558 }
477559
478 /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should560 /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should
...@@ -564,10 +646,6 @@ pub const Function = struct {...@@ -564,10 +646,6 @@ pub const Function = struct {
564 return f.dg.renderType(w, ty);646 return f.dg.renderType(w, ty);
565 }647 }
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
571 fn fmtIntLiteralDec(f: *Function, val: Value) !std.fmt.Alt(FormatIntLiteralContext, formatIntLiteral) {649 fn fmtIntLiteralDec(f: *Function, val: Value) !std.fmt.Alt(FormatIntLiteralContext, formatIntLiteral) {
572 return f.dg.fmtIntLiteralDec(val, .other);650 return f.dg.fmtIntLiteralDec(val, .other);
573 }651 }
...@@ -672,7 +750,9 @@ pub const DeclGen = struct {...@@ -672,7 +750,9 @@ pub const DeclGen = struct {
672 // Render an undefined pointer if we have a pointer to a zero-bit or comptime type.750 // Render an undefined pointer if we have a pointer to a zero-bit or comptime type.
673 const ptr_ty: Type = .fromInterned(uav.orig_ty);751 const ptr_ty: Type = .fromInterned(uav.orig_ty);
674 if (ptr_ty.isPtrAtRuntime(zcu) and !uav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {752 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(')');
676 }756 }
677757
678 switch (ip.indexToKey(uav.val)) {758 switch (ip.indexToKey(uav.val)) {
...@@ -737,8 +817,10 @@ pub const DeclGen = struct {...@@ -737,8 +817,10 @@ pub const DeclGen = struct {
737 // Render an undefined pointer if we have a pointer to a zero-bit or comptime type.817 // Render an undefined pointer if we have a pointer to a zero-bit or comptime type.
738 const nav_ty: Type = .fromInterned(ip.getNav(owner_nav).resolved.?.type);818 const nav_ty: Type = .fromInterned(ip.getNav(owner_nav).resolved.?.type);
739 const ptr_ty = try pt.navPtrType(owner_nav);819 const ptr_ty = try pt.navPtrType(owner_nav);
740 if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {820 if (nav_ty.zigTypeTag(zcu) != .@"opaque" and !nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {
741 return dg.renderUndefValue(w, ptr_ty, location);821 try w.writeByte('(');
822 try dg.renderOpvPointer(w, ptr_ty, location);
823 return w.writeByte(')');
742 }824 }
743825
744 // We shouldn't cast C function pointers as this is UB (when you call826 // We shouldn't cast C function pointers as this is UB (when you call
...@@ -758,6 +840,26 @@ pub const DeclGen = struct {...@@ -758,6 +840,26 @@ pub const DeclGen = struct {
758 if (need_cast) try w.writeByte(')');840 if (need_cast) try w.writeByte(')');
759 }841 }
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
761 fn renderPointer(863 fn renderPointer(
762 dg: *DeclGen,864 dg: *DeclGen,
763 w: *Writer,865 w: *Writer,
...@@ -959,9 +1061,6 @@ pub const DeclGen = struct {...@@ -959,9 +1061,6 @@ pub const DeclGen = struct {
959 const bits = ty.floatBits(target);1061 const bits = ty.floatBits(target);
960 const f128_val = val.toFloat(f128, zcu);1062 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
965 assert(bits <= 128);1064 assert(bits <= 128);
966 var repr_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined;1065 var repr_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined;
967 var repr_val_big = BigInt.Mutable{1066 var repr_val_big = BigInt.Mutable{
...@@ -971,29 +1070,27 @@ pub const DeclGen = struct {...@@ -971,29 +1070,27 @@ pub const DeclGen = struct {
971 };1070 };
9721071
973 switch (bits) {1072 switch (bits) {
1073 else => unreachable,
974 16 => repr_val_big.set(@as(u16, @bitCast(val.toFloat(f16, zcu)))),1074 16 => repr_val_big.set(@as(u16, @bitCast(val.toFloat(f16, zcu)))),
975 32 => repr_val_big.set(@as(u32, @bitCast(val.toFloat(f32, zcu)))),1075 32 => repr_val_big.set(@as(u32, @bitCast(val.toFloat(f32, zcu)))),
976 64 => repr_val_big.set(@as(u64, @bitCast(val.toFloat(f64, zcu)))),1076 64 => repr_val_big.set(@as(u64, @bitCast(val.toFloat(f64, zcu)))),
977 80 => repr_val_big.set(@as(u80, @bitCast(val.toFloat(f80, zcu)))),1077 80 => repr_val_big.set(@as(u80, @bitCast(val.toFloat(f80, zcu)))),
978 128 => repr_val_big.set(@as(u128, @bitCast(f128_val))),1078 128 => repr_val_big.set(@as(u128, @bitCast(f128_val))),
979 else => unreachable,
980 }1079 }
9811080
982 var empty = true;
983 if (std.math.isFinite(f128_val)) {1081 if (std.math.isFinite(f128_val)) {
984 try w.writeAll("zig_make_");1082 try w.writeAll("zig_make_");
985 try dg.renderTypeForBuiltinFnName(w, ty);1083 try dg.renderTypeForBuiltinFnName(w, ty);
986 try w.writeByte('(');1084 try w.writeByte('(');
987 switch (bits) {1085 switch (bits) {
1086 else => unreachable,
988 16 => try w.print("{x}", .{val.toFloat(f16, zcu)}),1087 16 => try w.print("{x}", .{val.toFloat(f16, zcu)}),
989 32 => try w.print("{x}", .{val.toFloat(f32, zcu)}),1088 32 => try w.print("{x}", .{val.toFloat(f32, zcu)}),
990 64 => try w.print("{x}", .{val.toFloat(f64, zcu)}),1089 64 => try w.print("{x}", .{val.toFloat(f64, zcu)}),
991 80 => try w.print("{x}", .{val.toFloat(f80, zcu)}),1090 80 => try w.print("{x}", .{val.toFloat(f80, zcu)}),
992 128 => try w.print("{x}", .{f128_val}),1091 128 => try w.print("{x}", .{f128_val}),
993 else => unreachable,
994 }1092 }
995 try w.writeAll(", ");1093 try w.writeAll(", ");
996 empty = false;
997 } else {1094 } else {
998 // isSignalNan is equivalent to isNan currently, and MSVC doesn't have nans, so prefer nan1095 // isSignalNan is equivalent to isNan currently, and MSVC doesn't have nans, so prefer nan
999 const operation = if (std.math.isNan(f128_val))1096 const operation = if (std.math.isNan(f128_val))
...@@ -1028,6 +1125,7 @@ pub const DeclGen = struct {...@@ -1028,6 +1125,7 @@ pub const DeclGen = struct {
1028 try w.writeAll(operation);1125 try w.writeAll(operation);
1029 try w.writeAll(", ");1126 try w.writeAll(", ");
1030 if (std.math.isNan(f128_val)) switch (bits) {1127 if (std.math.isNan(f128_val)) switch (bits) {
1128 else => unreachable,
1031 // We only actually need to pass the significand, but it will get1129 // We only actually need to pass the significand, but it will get
1032 // properly masked anyway, so just pass the whole value.1130 // properly masked anyway, so just pass the whole value.
1033 16 => try w.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, zcu)))}),1131 16 => try w.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, zcu)))}),
...@@ -1035,16 +1133,23 @@ pub const DeclGen = struct {...@@ -1035,16 +1133,23 @@ pub const DeclGen = struct {
1035 64 => try w.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, zcu)))}),1133 64 => try w.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, zcu)))}),
1036 80 => try w.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, zcu)))}),1134 80 => try w.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, zcu)))}),
1037 128 => try w.print("\"0x{x}\"", .{@as(u128, @bitCast(f128_val))}),1135 128 => try w.print("\"0x{x}\"", .{@as(u128, @bitCast(f128_val))}),
1038 else => unreachable,
1039 };1136 };
1040 try w.writeAll(", ");1137 try w.writeAll(", ");
1041 empty = false;
1042 }1138 }
1043 try w.print("{f}", .{try dg.fmtIntLiteralHex(1139 switch (bits) {
1044 try pt.intValue_big(repr_ty, repr_val_big.toConst()),1140 else => unreachable,
1045 location,1141 16, 32, 64 => {
1046 )});1142 // All unsigned ints matching float types are pre-allocated.
1047 if (!empty) try w.writeByte(')');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(')');
1048 },1153 },
1049 .slice => |slice| {1154 .slice => |slice| {
1050 if (!location.isInitializer()) {1155 if (!location.isInitializer()) {
...@@ -1306,8 +1411,8 @@ pub const DeclGen = struct {...@@ -1306,8 +1411,8 @@ pub const DeclGen = struct {
1306 };1411 };
13071412
1308 const safety_on = switch (dg.mod.optimize_mode) {1413 const safety_on = switch (dg.mod.optimize_mode) {
1309 .Debug, .ReleaseSafe => true,1414 .debug, .safe => true,
1310 .ReleaseFast, .ReleaseSmall => false,1415 .fast, .small => false,
1311 };1416 };
13121417
1313 switch (ty.toIntern()) {1418 switch (ty.toIntern()) {
...@@ -1319,22 +1424,29 @@ pub const DeclGen = struct {...@@ -1319,22 +1424,29 @@ pub const DeclGen = struct {
1319 .f128_type,1424 .f128_type,
1320 => {1425 => {
1321 const bits = ty.floatBits(target);1426 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
1325 try w.writeAll("zig_make_");1428 try w.writeAll("zig_make_");
1326 try dg.renderTypeForBuiltinFnName(w, ty);1429 try dg.renderTypeForBuiltinFnName(w, ty);
1327 try w.writeByte('(');1430 try w.writeByte('(');
1328 switch (bits) {1431 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)))}),
1334 else => unreachable,1432 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)}),
1335 }1438 }
1336 try w.writeAll(", ");1439 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 }
1338 return w.writeByte(')');1450 return w.writeByte(')');
1339 },1451 },
1340 .bool_type => try w.writeAll(if (safety_on) "0xaa" else "false"),1452 .bool_type => try w.writeAll(if (safety_on) "0xaa" else "false"),
...@@ -1638,8 +1750,6 @@ pub const DeclGen = struct {...@@ -1638,8 +1750,6 @@ pub const DeclGen = struct {
1638 try w.writeAll("zig_no_builtin ");1750 try w.writeAll("zig_no_builtin ");
1639 }1751 }
16401752
1641 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
1642
1643 // While incomplete types are usually an acceptable substitute for "void", this is not true1753 // While incomplete types are usually an acceptable substitute for "void", this is not true
1644 // in function return types, where "void" is the only incomplete type permitted.1754 // in function return types, where "void" is the only incomplete type permitted.
1645 const actual_return_type: Type = .fromInterned(fn_info.return_type);1755 const actual_return_type: Type = .fromInterned(fn_info.return_type);
...@@ -1651,8 +1761,9 @@ pub const DeclGen = struct {...@@ -1651,8 +1761,9 @@ pub const DeclGen = struct {
16511761
1652 const ret_cty: CType = try .lower(effective_return_type, &dg.ctype_deps, dg.arena, zcu);1762 const ret_cty: CType = try .lower(effective_return_type, &dg.ctype_deps, dg.arena, zcu);
1653 try w.print("{f}", .{ret_cty.fmtDeclaratorPrefix(zcu)});1763 try w.print("{f}", .{ret_cty.fmtDeclaratorPrefix(zcu)});
1654 if (toCallingConvention(fn_info.cc, zcu)) |call_conv| {1764 switch (CType.CallingConvention.fromLang(fn_info.cc, zcu.getTarget())) {
1655 try w.print("zig_callconv({s}) ", .{call_conv});1765 .c => {},
1766 else => |cc| try w.print("zig_callconv({t}) ", .{cc}),
1656 }1767 }
1657 switch (name) {1768 switch (name) {
1658 .nav => |nav| try renderNavName(w, nav, ip),1769 .nav => |nav| try renderNavName(w, nav, ip),
...@@ -1726,136 +1837,6 @@ pub const DeclGen = struct {...@@ -1726,136 +1837,6 @@ pub const DeclGen = struct {
1726 try w.print("{f}", .{cty.fmtTypeName(zcu)});1837 try w.print("{f}", .{cty.fmtTypeName(zcu)});
1727 }1838 }
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
1859 /// Renders to `w` a C declarator whose type is the C lowering of the given Zig type.1840 /// Renders to `w` a C declarator whose type is the C lowering of the given Zig type.
1860 fn renderTypeAndName(1841 fn renderTypeAndName(
1861 dg: *DeclGen,1842 dg: *DeclGen,
...@@ -2000,6 +1981,7 @@ pub const DeclGen = struct {...@@ -2000,6 +1981,7 @@ pub const DeclGen = struct {
2000 switch (info) {1981 switch (info) {
2001 .none => if (!is_big) return,1982 .none => if (!is_big) return,
2002 .bits => {},1983 .bits => {},
1984 .bits_none, .big_temp_bits => unreachable,
2003 }1985 }
20041986
2005 const int_info: std.lang.Type.Int = if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else .{1987 const int_info: std.lang.Type.Int = if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else .{
...@@ -2056,6 +2038,72 @@ const CQualifiers = packed struct {...@@ -2056,6 +2038,72 @@ const CQualifiers = packed struct {
2056 restrict: bool = false,2038 restrict: bool = false,
2057};2039};
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
2059pub fn genGlobalAsm(zcu: *Zcu, w: *Writer) !void {2107pub fn genGlobalAsm(zcu: *Zcu, w: *Writer) !void {
2060 for (zcu.global_assembly.values()) |asm_source| {2108 for (zcu.global_assembly.values()) |asm_source| {
2061 try w.print("__asm({f});\n", .{fmtStringLiteral(asm_source, null)});2109 try w.print("__asm({f});\n", .{fmtStringLiteral(asm_source, null)});
...@@ -2070,16 +2118,16 @@ pub fn genErrDecls(...@@ -2070,16 +2118,16 @@ pub fn genErrDecls(
2070 const ip = &zcu.intern_pool;2118 const ip = &zcu.intern_pool;
20712119
2072 const names = ip.global_error_set.getNamesFromMainThread();2120 const names = ip.global_error_set.getNamesFromMainThread();
2073 // Don't generate an invalid empty enum if the global error set is empty!2121 // Don't generate an invalid empty enum/array if the global error set is empty!
2074 if (names.len > 0) {2122 if (names.len == 0) return;
2075 try w.writeAll("enum {\n");2123
2076 for (names, 1..) |name_nts, value| {2124 try w.writeAll("enum {\n");
2077 try w.writeByte(' ');2125 for (names, 1..) |name_nts, value| {
2078 try renderErrorName(w, name_nts.toSlice(ip));2126 try w.writeByte(' ');
2079 try w.print(" = {d}u,\n", .{value});2127 try renderErrorName(w, name_nts.toSlice(ip));
2080 }2128 try w.print(" = {d}u,\n", .{value});
2081 try w.writeAll("};\n");
2082 }2129 }
2130 try w.writeAll("};\n");
20832131
2084 for (names) |name_nts| {2132 for (names) |name_nts| {
2085 const name = name_nts.toSlice(ip);2133 const name = name_nts.toSlice(ip);
...@@ -2093,7 +2141,7 @@ pub fn genErrDecls(...@@ -2093,7 +2141,7 @@ pub fn genErrDecls(
2093 "static {s} const zig_errorName[{d}] = {{",2141 "static {s} const zig_errorName[{d}] = {{",
2094 .{ slice_const_u8_sentinel_0_type_name, names.len },2142 .{ slice_const_u8_sentinel_0_type_name, names.len },
2095 );2143 );
2096 if (names.len > 0) try w.writeByte('\n');2144 try w.writeByte('\n');
2097 for (names) |name_nts| {2145 for (names) |name_nts| {
2098 const name = name_nts.toSlice(ip);2146 const name = name_nts.toSlice(ip);
2099 try w.print(2147 try w.print(
...@@ -2114,10 +2162,18 @@ pub fn genTagNameFn(...@@ -2114,10 +2162,18 @@ pub fn genTagNameFn(
2114 const ip = &zcu.intern_pool;2162 const ip = &zcu.intern_pool;
2115 const loaded_enum = ip.loadEnumType(enum_ty.toIntern());2163 const loaded_enum = ip.loadEnumType(enum_ty.toIntern());
2116 assert(loaded_enum.field_names.len > 0);2164 assert(loaded_enum.field_names.len > 0);
2117 if (Type.fromInterned(loaded_enum.int_tag_type).bitSize(zcu) > 64) {2165 switch (CType.classifyInt(enum_ty, zcu)) {
2118 @panic("TODO CBE: tagName for enum over 64 bits");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"),
2119 }2172 }
21202173
2174 if (!zcu.comp.config.root_strip) try w.print("/* @tagName({f}) */\n", .{
2175 loaded_enum.name.fmt(ip),
2176 });
2121 try w.print("static {s} zig_tagName_{f}__{d}({s} tag) {{\n", .{2177 try w.print("static {s} zig_tagName_{f}__{d}({s} tag) {{\n", .{
2122 slice_const_u8_sentinel_0_type_name,2178 slice_const_u8_sentinel_0_type_name,
2123 fmtIdentUnsolo(loaded_enum.name.toSlice(ip)),2179 fmtIdentUnsolo(loaded_enum.name.toSlice(ip)),
...@@ -2164,6 +2220,7 @@ pub fn genLazyCallModifierFn(...@@ -2164,6 +2220,7 @@ pub fn genLazyCallModifierFn(
21642220
2165 const fn_val = zcu.navValue(fn_nav);2221 const fn_val = zcu.navValue(fn_nav);
21662222
2223 if (fn_val.typeOf(zcu).fnReturnType(zcu).isNoReturn(zcu)) try w.writeAll("zig_noreturn ");
2167 try w.print("static zig_{t} ", .{kind});2224 try w.print("static zig_{t} ", .{kind});
2168 try dg.renderFunctionSignature(w, fn_val, .none, .definition, switch (kind) {2225 try dg.renderFunctionSignature(w, fn_val, .none, .definition, switch (kind) {
2169 .never_tail => .{ .nav_never_tail = fn_nav },2226 .never_tail => .{ .nav_never_tail = fn_nav },
...@@ -2269,8 +2326,10 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E...@@ -2269,8 +2326,10 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E
2269 const gpa = f.dg.gpa;2326 const gpa = f.dg.gpa;
2270 const nav_index = f.dg.owner_nav.unwrap().?;2327 const nav_index = f.dg.owner_nav.unwrap().?;
2271 const nav_val = zcu.navValue(nav_index);2328 const nav_val = zcu.navValue(nav_index);
2329 const fn_info = zcu.typeToFunc(nav_val.typeOf(zcu)).?;
2272 const nav = ip.getNav(nav_index);2330 const nav = ip.getNav(nav_index);
22732331
2332 if (Type.fromInterned(fn_info.return_type).isNoReturn(zcu)) try fwd_decl_writer.writeAll("zig_noreturn ");
2274 try fwd_decl_writer.writeAll("static ");2333 try fwd_decl_writer.writeAll("static ");
2275 try f.dg.renderFunctionSignature(2334 try f.dg.renderFunctionSignature(
2276 fwd_decl_writer,2335 fwd_decl_writer,
...@@ -2291,11 +2350,41 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E...@@ -2291,11 +2350,41 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E
2291 .{ .nav = nav_index },2350 .{ .nav = nav_index },
2292 );2351 );
2293 try header_writer.writeAll(" {\n ");2352 try header_writer.writeAll(" {\n ");
2353 if (!f.dg.mod.strip) try header_writer.print("/* {f} */\n ", .{nav.fqn.fmt(ip)});
22942354
2295 f.free_locals_map.clearRetainingCapacity();2355 f.free_locals_map.clearRetainingCapacity();
22962356
2297 const main_body = f.air.getMainBody();2357 const main_body = f.air.getMainBody();
2298 f.indent();2358 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 }
2299 try genBodyResolveState(f, undefined, &.{}, main_body, true);2388 try genBodyResolveState(f, undefined, &.{}, main_body, true);
2300 try f.outdent();2389 try f.outdent();
2301 try f.code.writer.writeByte('}');2390 try f.code.writer.writeByte('}');
...@@ -2346,6 +2435,7 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E...@@ -2346,6 +2435,7 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E
2346 for (list.keys()) |local_index| {2435 for (list.keys()) |local_index| {
2347 const local = f.locals.items[local_index];2436 const local = f.locals.items[local_index];
2348 try f.dg.renderTypeAndName(header_writer, local.type, .{ .local = local_index }, .{}, local.alignment);2437 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});
2349 try header_writer.writeAll(";\n ");2439 try header_writer.writeAll(";\n ");
2350 }2440 }
2351 }2441 }
...@@ -2397,10 +2487,12 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void {...@@ -2397,10 +2487,12 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void {
23972487
2398 .@"extern" => |@"extern"| switch (nav_ty.zigTypeTag(zcu)) {2488 .@"extern" => |@"extern"| switch (nav_ty.zigTypeTag(zcu)) {
2399 .@"fn" => {2489 .@"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 ");
2400 try w.writeAll("zig_extern ");2492 try w.writeAll("zig_extern ");
2401 try dg.renderFunctionSignature(2493 try dg.renderFunctionSignature(
2402 w,2494 w,
2403 .fromInterned(nav.resolved.?.value),2495 fn_val,
2404 nav.resolved.?.@"align",2496 nav.resolved.?.@"align",
2405 .forward_decl,2497 .forward_decl,
2406 .{ .@"export" = .{2498 .{ .@"export" = .{
...@@ -2461,7 +2553,12 @@ pub fn genDeclValue(dg: *DeclGen, w: *Writer, options: struct {...@@ -2461,7 +2553,12 @@ pub fn genDeclValue(dg: *DeclGen, w: *Writer, options: struct {
2461 try dg.renderTypeAndName(w, ty, options.name, .{ .@"const" = options.@"const" }, .none);2553 try dg.renderTypeAndName(w, ty, options.name, .{ .@"const" = options.@"const" }, .none);
2462 try w.writeAll(" = ");2554 try w.writeAll(" = ");
2463 try dg.renderValue(w, options.init_val, .static_initializer);2555 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');
2465}2562}
2466pub fn genDeclValueFwd(dg: *DeclGen, w: *Writer, options: struct {2563pub fn genDeclValueFwd(dg: *DeclGen, w: *Writer, options: struct {
2467 name: CValue,2564 name: CValue,
...@@ -2496,11 +2593,13 @@ pub fn genExports(dg: *DeclGen, w: *Writer, exported: Zcu.Exported, export_indic...@@ -2496,11 +2593,13 @@ pub fn genExports(dg: *DeclGen, w: *Writer, exported: Zcu.Exported, export_indic
2496 const exported_val = exported.getValue(zcu);2593 const exported_val = exported.getValue(zcu);
2497 if (ip.isFunctionType(exported_val.typeOf(zcu).toIntern())) return for (export_indices) |export_index| {2594 if (ip.isFunctionType(exported_val.typeOf(zcu).toIntern())) return for (export_indices) |export_index| {
2498 const @"export" = export_index.ptr(zcu);2595 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 ");
2499 try w.writeAll("zig_extern ");2598 try w.writeAll("zig_extern ");
2500 if (@"export".opts.linkage == .weak) try w.writeAll("zig_weak_linkage_fn ");2599 if (@"export".opts.linkage == .weak) try w.writeAll("zig_weak_linkage_fn ");
2501 try dg.renderFunctionSignature(2600 try dg.renderFunctionSignature(
2502 w,2601 w,
2503 exported.getValue(zcu),2602 fn_val,
2504 exported.getAlign(zcu),2603 exported.getAlign(zcu),
2505 .forward_decl,2604 .forward_decl,
2506 .{ .@"export" = .{2605 .{ .@"export" = .{
...@@ -2662,22 +2761,22 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {...@@ -2662,22 +2761,22 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {
2662 .mul => try airBinOp(f, inst, "*", "mul", .none),2761 .mul => try airBinOp(f, inst, "*", "mul", .none),
26632762
2664 .neg => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "neg", .none),2763 .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),
2668 .rem => blk: {2767 .rem => blk: {
2669 const bin_op = air_datas[@intFromEnum(inst)].bin_op;2768 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
2670 const lhs_scalar_ty = f.typeOf(bin_op.lhs).scalarType(zcu);2769 const lhs_scalar_ty = f.typeOf(bin_op.lhs).scalarType(zcu);
2671 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),2770 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
2672 // so we only check one.2771 // so we only check one.
2673 break :blk if (lhs_scalar_ty.isInt(zcu))2772 break :blk if (lhs_scalar_ty.isInt(zcu))
2674 try airBinOp(f, inst, "%", "rem", .none)2773 try airBinOp(f, inst, "%", "rem", .big_temp_bits)
2675 else2774 else
2676 try airBinBuiltinCall(f, inst, "fmod", .none);2775 try airBinBuiltinCall(f, inst, "fmod", .none);
2677 },2776 },
2678 .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .none),2777 .div_floor => try airBinBuiltinCall(f, inst, "divFloor", .big_temp_bits),
2679 .div_ceil => try airBinBuiltinCall(f, inst, "div_ceil", .none),2778 .div_ceil => try airBinBuiltinCall(f, inst, "divCeil", .big_temp_bits),
2680 .mod => try airBinBuiltinCall(f, inst, "mod", .none),2779 .mod => try airBinBuiltinCall(f, inst, "mod", .big_temp_bits),
2681 .abs => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "abs", .none),2780 .abs => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "abs", .none),
26822781
2683 .add_wrap => try airBinBuiltinCall(f, inst, "addw", .bits),2782 .add_wrap => try airBinBuiltinCall(f, inst, "addw", .bits),
...@@ -2687,7 +2786,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {...@@ -2687,7 +2786,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {
2687 .add_sat => try airBinBuiltinCall(f, inst, "adds", .bits),2786 .add_sat => try airBinBuiltinCall(f, inst, "adds", .bits),
2688 .sub_sat => try airBinBuiltinCall(f, inst, "subs", .bits),2787 .sub_sat => try airBinBuiltinCall(f, inst, "subs", .bits),
2689 .mul_sat => try airBinBuiltinCall(f, inst, "muls", .bits),2788 .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
2692 .sqrt => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "sqrt", .none),2791 .sqrt => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "sqrt", .none),
2693 .sin => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "sin", .none),2792 .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 {...@@ -2764,8 +2863,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {
2764 .int_from_error => try airNopCast(f, inst),2863 .int_from_error => try airNopCast(f, inst),
2765 .union_from_enum => try airUnionFromEnum(f, inst),2864 .union_from_enum => try airUnionFromEnum(f, inst),
2766 .bit_cast => try airBitCast(f, inst),2865 .bit_cast => try airBitCast(f, inst),
2767 .int_cast => try airIntCast(f, inst),2866 .int_cast => try airIntCast(f, inst, "intCast", .none),
2768 .trunc => try airTrunc(f, inst),2867 .trunc => try airIntCast(f, inst, "truncate", .bits),
2769 .load => try airLoad(f, inst),2868 .load => try airLoad(f, inst),
2770 .store => try airStore(f, inst, false),2869 .store => try airStore(f, inst, false),
2771 .store_safe => try airStore(f, inst, true),2870 .store_safe => try airStore(f, inst, true),
...@@ -2783,9 +2882,9 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {...@@ -2783,9 +2882,9 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {
2783 .get_union_tag => try airGetUnionTag(f, inst),2882 .get_union_tag => try airGetUnionTag(f, inst),
2784 .clz => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "clz", .bits),2883 .clz => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "clz", .bits),
2785 .ctz => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "ctz", .bits),2884 .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),2885 .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),2886 .byte_swap => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "byteSwap", .bits),
2788 .bit_reverse => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "bit_reverse", .bits),2887 .bit_reverse => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "bitReverse", .bits),
2789 .tag_name => try airTagName(f, inst),2888 .tag_name => try airTagName(f, inst),
2790 .error_name => try airErrorName(f, inst),2889 .error_name => try airErrorName(f, inst),
2791 .splat => try airSplat(f, inst),2890 .splat => try airSplat(f, inst),
...@@ -3124,7 +3223,16 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3124,7 +3223,16 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {
3124 const zcu = pt.zcu;3223 const zcu = pt.zcu;
3125 const inst_ty = f.typeOfIndex(inst);3224 const inst_ty = f.typeOfIndex(inst);
3126 const elem_ty = inst_ty.childType(zcu);3225 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
3129 const local = try f.allocLocalValue(.{3237 const local = try f.allocLocalValue(.{
3130 .type = elem_ty,3238 .type = elem_ty,
...@@ -3298,120 +3406,57 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void {...@@ -3298,120 +3406,57 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void {
3298 }3406 }
3299}3407}
33003408
3301fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {3409fn airIntCast(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !CValue {
3302 const pt = f.dg.pt;3410 const pt = f.dg.pt;
3303 const zcu = pt.zcu;3411 const zcu = pt.zcu;
3304 const ty_op = f.air.instructions.items(.data)[@backingInt(inst)].ty_op;3412 const ty_op = f.air.instructions.items(.data)[@backingInt(inst)].ty_op;
33053413
3306 const operand = try f.resolveInst(ty_op.operand);3414 const inst_ty = ty_op.ty.toType();
3307 try reap(f, inst, &.{ty_op.operand});
3308
3309 const inst_ty = f.typeOfIndex(inst);
3310 const inst_scalar_ty = inst_ty.scalarType(zcu);3415 const inst_scalar_ty = inst_ty.scalarType(zcu);
3311 const operand_ty = f.typeOf(ty_op.operand);3416 const operand_ty = f.typeOf(ty_op.operand);
3312 const scalar_ty = operand_ty.scalarType(zcu);3417 const operand_scalar_ty = operand_ty.scalarType(zcu);
33133418 const is_big = lowersToBigInt(operand_ty, zcu);
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;
33363419
3337 const operand = try f.resolveInst(ty_op.operand);3420 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);3423 const ref_ret = lowersToBigInt(inst_scalar_ty, zcu);
3341 const inst_scalar_ty = inst_ty.scalarType(zcu);3424 const ref_arg = lowersToBigInt(operand_scalar_ty, 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);
33543425
3355 const w = &f.code.writer;3426 const w = &f.code.writer;
3356 const local = try f.allocLocal(inst, inst_ty);3427 const local = try f.allocLocal(inst, inst_ty);
3428 if (is_big) try reap(f, inst, &.{ty_op.operand});
3357 const v = try Vectorize.start(f, inst, w, operand_ty);3429 const v = try Vectorize.start(f, inst, w, operand_ty);
3358 try f.writeCValue(w, local, .other);3430 if (!ref_ret) {
3359 try v.elem(f, w);3431 try f.writeCValue(w, local, .other);
3360 try w.writeAll(" = ");3432 try v.elem(f, w);
3361 if (need_cast) {3433 try w.writeAll(" = ");
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('(');
3370 }3434 }
3371 if (!need_mask) {3435 try w.writeAll("zig_");
3372 try f.writeCValue(w, operand, .other);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);
3373 try v.elem(f, w);3443 try v.elem(f, w);
3374 } else switch (dest_int_info.signedness) {3444 try w.writeAll(", ");
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 },
3410 }3445 }
3411 if (need_lo) try w.writeByte(')');3446 if (ref_arg) {
3412 try w.writeByte(';');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(");");
3413 try f.newline();3457 try f.newline();
3414 try v.end(f, inst, w);3458 try v.end(f, inst, w);
3459
3415 return local;3460 return local;
3416}3461}
34173462
...@@ -3525,39 +3570,46 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:...@@ -3525,39 +3570,46 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
3525 const ty_pl = f.air.instructions.items(.data)[@backingInt(inst)].ty_pl;3570 const ty_pl = f.air.instructions.items(.data)[@backingInt(inst)].ty_pl;
3526 const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;3571 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
3528 const lhs = try f.resolveInst(bin_op.lhs);3577 const lhs = try f.resolveInst(bin_op.lhs);
3529 const rhs = try f.resolveInst(bin_op.rhs);3578 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);3581 const lhs_scalar_ty = lhs_ty.scalarType(zcu);
3533 const operand_ty = f.typeOf(bin_op.lhs);3582 const rhs_scalar_ty = rhs_ty.scalarType(zcu);
3534 const scalar_ty = operand_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
3538 const w = &f.code.writer;3587 const w = &f.code.writer;
3539 const local = try f.allocLocal(inst, inst_ty);3588 const local = try f.allocLocal(inst, f.typeOfIndex(inst));
3540 const v = try Vectorize.start(f, inst, w, operand_ty);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);
3541 try f.writeCValueMember(w, local, .{ .field = 1 });3591 try f.writeCValueMember(w, local, .{ .field = 1 });
3542 try v.elem(f, w);3592 try v.elem(f, w);
3543 try w.writeAll(" = zig_");3593 try w.writeAll(" = ");
3594 try w.writeAll("zig_");
3544 try w.writeAll(operation);3595 try w.writeAll(operation);
3545 try w.writeAll("o_");3596 try w.writeAll("o_");
3546 try f.dg.renderTypeForBuiltinFnName(w, scalar_ty);3597 try f.dg.renderTypeForBuiltinFnName(w, lhs_scalar_ty);
3547 try w.writeByte('(');3598 try w.writeByte('(');
35483599
3549 // '&dest', possibly preceded by a cast3600 // '&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())) {
3551 .int_type => {}, // we already have a '[u]intX_t *'3602 .int_type => {}, // we already have a '[u]intX_t *'
3552 .simple_type => {3603 .simple_type => {
3553 // '&dest' will be something like a 'uintptr_t *', which might be a different C type to3604 // '&dest' will be something like a 'uintptr_t *', which might be a different C type to
3554 // the equivalent sized integer (e.g. 'uint64_t *'), so we need a cast. We don't need a3605 // the equivalent sized integer (e.g. 'uint64_t *'), so we need a cast. We don't need a
3555 // cast on the *operands* because they are passed by value (except for big integers,3606 // cast on the *operands* because they are passed by value (except for big integers,
3556 // where this issue doesn't exist because no "simple" int type needs bigint repr).3607 // where this issue doesn't exist because no "simple" int type needs bigint repr).
3557 try w.print("({s}int{d}_t *)", .{3608 const inst_int_info = lhs_scalar_ty.intInfo(zcu);
3558 if (scalar_ty.isUnsignedInt(zcu)) "u" else "",3609 try w.print("({s}int{d}_t *)", .{ switch (inst_int_info.signedness) {
3559 scalar_ty.abiSize(zcu) * 8,3610 .signed => "",
3560 });3611 .unsigned => "u",
3612 }, inst_int_info.bits });
3561 },3613 },
3562 else => unreachable,3614 else => unreachable,
3563 }3615 }
...@@ -3566,14 +3618,24 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:...@@ -3566,14 +3618,24 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
3566 try v.elem(f, w);3618 try v.elem(f, w);
35673619
3568 try w.writeAll(", ");3620 try w.writeAll(", ");
3569 if (ref_arg) try w.writeByte('&');3621 if (ref_lhs) {
3570 try f.writeCValue(w, lhs, .other);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);
3571 try v.elem(f, w);3628 try v.elem(f, w);
3572 try w.writeAll(", ");3629 try w.writeAll(", ");
3573 if (ref_arg) try w.writeByte('&');3630 if (ref_rhs) {
3574 try f.writeCValue(w, rhs, .other);3631 try w.writeByte('&');
3575 if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w);3632 switch (rhs) {
3576 try f.dg.renderBuiltinInfo(w, scalar_ty, info);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);
3577 try w.writeAll(");");3639 try w.writeAll(");");
3578 try f.newline();3640 try f.newline();
3579 try v.end(f, inst, w);3641 try v.end(f, inst, w);
...@@ -3622,8 +3684,18 @@ fn airBinOp(...@@ -3622,8 +3684,18 @@ fn airBinOp(
3622 const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op;3684 const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op;
3623 const operand_ty = f.typeOf(bin_op.lhs);3685 const operand_ty = f.typeOf(bin_op.lhs);
3624 const scalar_ty = operand_ty.scalarType(zcu);3686 const scalar_ty = operand_ty.scalarType(zcu);
3625 if ((scalar_ty.isInt(zcu) and scalar_ty.bitSize(zcu) > 64) or scalar_ty.isRuntimeFloat())3687
3626 return try airBinBuiltinCall(f, inst, operation, info);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
3628 const lhs = try f.resolveInst(bin_op.lhs);3700 const lhs = try f.resolveInst(bin_op.lhs);
3629 const rhs = try f.resolveInst(bin_op.rhs);3701 const rhs = try f.resolveInst(bin_op.rhs);
...@@ -3662,19 +3734,21 @@ fn airCmpOp(...@@ -3662,19 +3734,21 @@ fn airCmpOp(
3662 const lhs_ty = f.typeOf(data.lhs);3734 const lhs_ty = f.typeOf(data.lhs);
3663 const scalar_ty = lhs_ty.scalarType(zcu);3735 const scalar_ty = lhs_ty.scalarType(zcu);
36643736
3665 if (scalar_ty.isInt(zcu)) {3737 builtin: {
3666 const scalar_bits = scalar_ty.bitSize(zcu);3738 if (scalar_ty.isInt(zcu)) {
3667 if (scalar_bits > 64) return airCmpBuiltinCall(3739 switch (CType.classifyInt(scalar_ty, zcu)) {
3668 f,3740 .void => unreachable,
3669 inst,3741 .small => |int| switch (int) {
3670 data,3742 else => break :builtin,
3671 operator,3743 .zig_u128, .zig_i128 => {},
3672 .cmp,3744 },
3673 if (scalar_bits > 128) .bits else .none,3745 .big => {},
3674 );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);
3675 }3751 }
3676 if (scalar_ty.isRuntimeFloat())
3677 return airCmpBuiltinCall(f, inst, data, operator, .operator, .none);
36783752
3679 const inst_ty = f.typeOfIndex(inst);3753 const inst_ty = f.typeOfIndex(inst);
3680 const lhs = try f.resolveInst(data.lhs);3754 const lhs = try f.resolveInst(data.lhs);
...@@ -3716,21 +3790,23 @@ fn airEquality(...@@ -3716,21 +3790,23 @@ fn airEquality(
3716 const pt = f.dg.pt;3790 const pt = f.dg.pt;
3717 const zcu = pt.zcu;3791 const zcu = pt.zcu;
3718 const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op;3792 const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op;
3719
3720 const operand_ty = f.typeOf(bin_op.lhs);3793 const operand_ty = f.typeOf(bin_op.lhs);
3721 if (operand_ty.isAbiInt(zcu)) {3794
3722 const operand_bits = operand_ty.bitSize(zcu);3795 builtin: {
3723 if (operand_bits > 64) return airCmpBuiltinCall(3796 if (operand_ty.isAbiInt(zcu)) {
3724 f,3797 switch (CType.classifyInt(operand_ty, zcu)) {
3725 inst,3798 .void => unreachable,
3726 bin_op,3799 .small => |int| switch (int) {
3727 operator,3800 else => break :builtin,
3728 .cmp,3801 .zig_u128, .zig_i128 => {},
3729 if (operand_bits > 128) .bits else .none,3802 },
3730 );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);
3731 }3809 }
3732 if (operand_ty.isRuntimeFloat())
3733 return airCmpBuiltinCall(f, inst, bin_op, operator, .operator, .none);
37343810
3735 const lhs = try f.resolveInst(bin_op.lhs);3811 const lhs = try f.resolveInst(bin_op.lhs);
3736 const rhs = try f.resolveInst(bin_op.rhs);3812 const rhs = try f.resolveInst(bin_op.rhs);
...@@ -3809,7 +3885,7 @@ fn airCmpLteErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3809,7 +3885,7 @@ fn airCmpLteErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {
3809 try f.writeCValue(w, local, .other);3885 try f.writeCValue(w, local, .other);
3810 try w.writeAll(" = ");3886 try w.writeAll(" = ");
3811 try f.writeCValue(w, operand, .other);3887 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);");
3813 try f.newline();3889 try f.newline();
3814 return local;3890 return local;
3815}3891}
...@@ -3862,8 +3938,17 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons...@@ -3862,8 +3938,17 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons
3862 const inst_ty = f.typeOfIndex(inst);3938 const inst_ty = f.typeOfIndex(inst);
3863 const inst_scalar_ty = inst_ty.scalarType(zcu);3939 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())3941 builtin: {
3866 return try airBinBuiltinCall(f, inst, operation, .none);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
3868 const lhs = try f.resolveInst(bin_op.lhs);3953 const lhs = try f.resolveInst(bin_op.lhs);
3869 const rhs = try f.resolveInst(bin_op.rhs);3954 const rhs = try f.resolveInst(bin_op.rhs);
...@@ -3979,10 +4064,7 @@ fn airCall(...@@ -3979,10 +4064,7 @@ fn airCall(
3979 try w.writeAll("(void)");4064 try w.writeAll("(void)");
3980 break :result .none;4065 break :result .none;
3981 } else {4066 } else {
3982 const local = try f.allocAlignedLocal(inst, .{4067 const local = try f.allocAlignedLocal(inst, .{ .type = ret_ty });
3983 .type = ret_ty,
3984 .alignment = .none,
3985 });
3986 try f.writeCValue(w, local, .other);4068 try f.writeCValue(w, local, .other);
3987 try w.writeAll(" = ");4069 try w.writeAll(" = ");
3988 break :result local;4070 break :result local;
...@@ -4058,16 +4140,7 @@ fn airCall(...@@ -4058,16 +4140,7 @@ fn airCall(
4058fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {4140fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
4059 const dbg_stmt = f.air.instructions.items(.data)[@backingInt(inst)].dbg_stmt;4141 const dbg_stmt = f.air.instructions.items(.data)[@backingInt(inst)].dbg_stmt;
4060 const w = &f.code.writer;4142 const w = &f.code.writer;
4061 // TODO re-evaluate whether to emit these or not. If we naively emit4143 try w.print("/* {d}:{d} */", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 });
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 });
4071 try f.newline();4144 try f.newline();
4072 return .none;4145 return .none;
4073}4146}
...@@ -4433,12 +4506,12 @@ fn airBitCast(f: *Function, inst: Air.Inst.Index) Error!CValue {...@@ -4433,12 +4506,12 @@ fn airBitCast(f: *Function, inst: Air.Inst.Index) Error!CValue {
4433 const operand_scalar_ty = operand_ty.scalarType(zcu);4506 const operand_scalar_ty = operand_ty.scalarType(zcu);
4434 const dest_scalar_ty = dest_ty.scalarType(zcu);4507 const dest_scalar_ty = dest_ty.scalarType(zcu);
44354508
4436 // Some cases are handled with a simple cast:
4437 // * float -> float
4438 // * bool -> int
4439 if ((operand_scalar_ty.isRuntimeFloat() and dest_scalar_ty.isRuntimeFloat()) or4509 if ((operand_scalar_ty.isRuntimeFloat() and dest_scalar_ty.isRuntimeFloat()) or
4440 (operand_scalar_ty.toIntern() == .bool_type and dest_scalar_ty.isAbiInt(zcu)))4510 (operand_scalar_ty.toIntern() == .bool_type and dest_scalar_ty.isAbiInt(zcu)))
4441 {4511 {
4512 // Some cases are handled with a simple cast:
4513 // * float -> float
4514 // * bool -> int
4442 try f.writeCValue(w, dest_local, .other);4515 try f.writeCValue(w, dest_local, .other);
4443 try v.elem(f, w);4516 try v.elem(f, w);
4444 try w.writeAll(" = (");4517 try w.writeAll(" = (");
...@@ -4458,85 +4531,44 @@ fn airBitCast(f: *Function, inst: Air.Inst.Index) Error!CValue {...@@ -4458,85 +4531,44 @@ fn airBitCast(f: *Function, inst: Air.Inst.Index) Error!CValue {
4458 try v.elem(f, w);4531 try v.elem(f, w);
4459 try w.writeAll(" != 0;");4532 try w.writeAll(" != 0;");
4460 try f.newline();4533 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();
4475 } else {4534 } 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));
4479 assert(operand_scalar_ty.isRuntimeFloat() or operand_scalar_ty.isAbiInt(zcu));4535 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...4538 const ref_ret = lowersToBigInt(dest_scalar_ty, zcu);
4482 try w.writeAll("memcpy(&");4539 const ref_arg = lowersToBigInt(operand_scalar_ty, zcu);
4483 try f.writeCValue(w, dest_local, .other);4540
4484 try v.elem(f, w);4541 if (!ref_ret) {
4485 try w.writeAll(", &");4542 try f.writeCValue(w, dest_local, .other);
4486 switch (operand) {4543 try v.elem(f, w);
4487 .constant => |val| try f.dg.renderValueAsLvalue(w, val),4544 try w.writeAll(" = ");
4488 else => try f.writeCValue(w, operand, .other),
4489 }4545 }
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);
4490 try v.elem(f, w);4564 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(");");
4492 try f.newline();4571 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 }
4540 }4572 }
45414573
4542 try v.end(f, inst, w);4574 try v.end(f, inst, w);
...@@ -4906,11 +4938,9 @@ fn lowerSwitchCmp(...@@ -4906,11 +4938,9 @@ fn lowerSwitchCmp(
49064938
4907fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool {4939fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool {
4908 const dg = f.dg;4940 const dg = f.dg;
4909 const target = &dg.mod.resolved_target.result;
4910 return switch (constraint[0]) {4941 return switch (constraint[0]) {
4911 '{' => true,4942 '{' => true,
4912 'i', 'r' => false,4943 'r', 'i', 'n', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P' => false,
4913 'I' => !target.cpu.arch.isArm(),
4914 else => switch (value) {4944 else => switch (value) {
4915 .constant => |val| switch (dg.pt.zcu.intern_pool.indexToKey(val.toIntern())) {4945 .constant => |val| switch (dg.pt.zcu.intern_pool.indexToKey(val.toIntern())) {
4916 .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) {4946 .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) {
...@@ -4937,10 +4967,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4937,10 +4967,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
4937 const w = &f.code.writer;4967 const w = &f.code.writer;
4938 const inst_ty = f.typeOfIndex(inst);4968 const inst_ty = f.typeOfIndex(inst);
4939 const inst_local = if (inst_ty.hasRuntimeBits(zcu)) local: {4969 const inst_local = if (inst_ty.hasRuntimeBits(zcu)) local: {
4940 const inst_local = try f.allocLocalValue(.{4970 const inst_local = try f.allocLocalValue(.{ .type = inst_ty });
4941 .type = inst_ty,
4942 .alignment = .none,
4943 });
4944 if (f.wantSafety()) {4971 if (f.wantSafety()) {
4945 try f.writeCValue(w, inst_local, .other);4972 try f.writeCValue(w, inst_local, .other);
4946 try w.writeAll(" = ");4973 try w.writeAll(" = ");
...@@ -4967,10 +4994,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4967,10 +4994,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
4967 if (is_reg) {4994 if (is_reg) {
4968 const output_ty = if (output.operand == .none) inst_ty else f.typeOf(output.operand).childType(zcu);4995 const output_ty = if (output.operand == .none) inst_ty else f.typeOf(output.operand).childType(zcu);
4969 try w.writeAll("register ");4996 try w.writeAll("register ");
4970 const output_local = try f.allocLocalValue(.{4997 const output_local = try f.allocLocalValue(.{ .type = output_ty });
4971 .type = output_ty,
4972 .alignment = .none,
4973 });
4974 try f.allocs.put(gpa, output_local.new_local, false);4998 try f.allocs.put(gpa, output_local.new_local, false);
4975 try f.dg.renderTypeAndName(w, output_ty, output_local, .{}, .none);4999 try f.dg.renderTypeAndName(w, output_ty, output_local, .{}, .none);
4976 try w.writeAll(" __asm(\"");5000 try w.writeAll(" __asm(\"");
...@@ -4989,7 +5013,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4989,7 +5013,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
4989 while (it.next()) |input| {5013 while (it.next()) |input| {
4990 const constraint = input.constraint;5014 const constraint = input.constraint;
49915015
4992 if (constraint.len < 1 or mem.indexOfScalar(u8, "=+&%", constraint[0]) != null or5016 if (constraint.len < 1 or mem.findScalar(u8, "=+&%", constraint[0]) != null or
4993 (constraint[0] == '{' and constraint[constraint.len - 1] != '}'))5017 (constraint[0] == '{' and constraint[constraint.len - 1] != '}'))
4994 {5018 {
4995 return f.fail("CBE: constraint not supported: '{s}'", .{constraint});5019 return f.fail("CBE: constraint not supported: '{s}'", .{constraint});
...@@ -5000,10 +5024,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5000,10 +5024,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
5000 if (asmInputNeedsLocal(f, constraint, input_val)) {5024 if (asmInputNeedsLocal(f, constraint, input_val)) {
5001 const input_ty = f.typeOf(input.operand);5025 const input_ty = f.typeOf(input.operand);
5002 if (is_reg) try w.writeAll("register ");5026 if (is_reg) try w.writeAll("register ");
5003 const input_local = try f.allocLocalValue(.{5027 const input_local = try f.allocLocalValue(.{ .type = input_ty });
5004 .type = input_ty,
5005 .alignment = .none,
5006 });
5007 try f.allocs.put(gpa, input_local.new_local, false);5028 try f.allocs.put(gpa, input_local.new_local, false);
5008 // Do not render the declaration as `const` qualified if we're generating an5029 // Do not render the declaration as `const` qualified if we're generating an
5009 // explicit `register` local, as GCC will ignore the constraint completely.5030 // explicit `register` local, as GCC will ignore the constraint completely.
...@@ -5056,7 +5077,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5056,7 +5077,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
5056 }5077 }
50575078
5058 const desc = mem.sliceTo(asm_source[src_i..], ']');5079 const desc = mem.sliceTo(asm_source[src_i..], ']');
5059 if (mem.indexOfScalar(u8, desc, ':')) |colon| {5080 if (mem.findScalar(u8, desc, ':')) |colon| {
5060 const name = desc[0..colon];5081 const name = desc[0..colon];
5061 const modifier = desc[colon + 1 ..];5082 const modifier = desc[colon + 1 ..];
50625083
...@@ -5853,28 +5874,124 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5853,28 +5874,124 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
5853 else5874 else
5854 unreachable;5875 unreachable;
58555876
5877 const ref_ret = lowersToBigInt(inst_scalar_ty, zcu);
5878 const ref_operand = lowersToBigInt(scalar_ty, zcu);
5879
5856 const w = &f.code.writer;5880 const w = &f.code.writer;
5857 const local = try f.allocLocal(inst, inst_ty);5881 const local = try f.allocLocal(inst, inst_ty);
5858 const v = try Vectorize.start(f, inst, w, operand_ty);5882 const v = try Vectorize.start(f, inst, w, operand_ty);
5859 try f.writeCValue(w, local, .other);5883 if (ref_ret) {
5860 try v.elem(f, w);5884 const inst_int_info = inst_scalar_ty.intInfo(zcu);
5861 try w.writeAll(" = ");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 }
5862 if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) {5905 if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) {
5863 try w.writeAll("zig_wrap_");5906 const inst_int_info = inst_scalar_ty.intInfo(zcu);
5864 try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty);5907 if (inst_int_info.bits <= 128) try w.print("zig_{c}{d}_truncate_{[0]c}{[1]d}(", .{
5865 try w.writeByte('(');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 });
5866 }5914 }
5867 try w.writeAll("zig_");5915 try w.writeAll("zig_");
5868 try w.writeAll(operation);5916 try w.writeAll(operation);
5869 try w.writeAll(compilerRtAbbrev(scalar_ty, zcu, target));5917 try w.writeAll(compilerRtAbbrev(scalar_ty, zcu, target));
5870 try w.writeAll(compilerRtAbbrev(inst_scalar_ty, zcu, target));5918 try w.writeAll(compilerRtAbbrev(inst_scalar_ty, zcu, target));
5871 try w.writeByte('(');5919 try w.writeByte('(');
5872 try f.writeCValue(w, operand, .other);5920 if (ref_ret) {
5873 try v.elem(f, w);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 }
5874 try w.writeByte(')');5979 try w.writeByte(')');
5875 if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) {5980 if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) {
5876 try f.dg.renderBuiltinInfo(w, inst_scalar_ty, .bits);5981 const inst_int_info = inst_scalar_ty.intInfo(zcu);
5877 try w.writeByte(')');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 }
5878 }5995 }
5879 try w.writeByte(';');5996 try w.writeByte(';');
5880 try f.newline();5997 try f.newline();
...@@ -5893,18 +6010,21 @@ fn airUnBuiltinCall(...@@ -5893,18 +6010,21 @@ fn airUnBuiltinCall(
5893 const pt = f.dg.pt;6010 const pt = f.dg.pt;
5894 const zcu = pt.zcu;6011 const zcu = pt.zcu;
58956012
5896 const operand = try f.resolveInst(operand_ref);
5897 try reap(f, inst, &.{operand_ref});
5898 const inst_ty = f.typeOfIndex(inst);6013 const inst_ty = f.typeOfIndex(inst);
5899 const inst_scalar_ty = inst_ty.scalarType(zcu);6014 const inst_scalar_ty = inst_ty.scalarType(zcu);
5900 const operand_ty = f.typeOf(operand_ref);6015 const operand_ty = f.typeOf(operand_ref);
5901 const scalar_ty = operand_ty.scalarType(zcu);6016 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
5903 const ref_ret = lowersToBigInt(inst_scalar_ty, zcu);6022 const ref_ret = lowersToBigInt(inst_scalar_ty, zcu);
5904 const ref_arg = lowersToBigInt(scalar_ty, zcu);6023 const ref_arg = lowersToBigInt(scalar_ty, zcu);
59056024
5906 const w = &f.code.writer;6025 const w = &f.code.writer;
5907 const local = try f.allocLocal(inst, inst_ty);6026 const local = try f.allocLocal(inst, inst_ty);
6027 if (is_big) try reap(f, inst, &.{operand_ref});
5908 const v = try Vectorize.start(f, inst, w, operand_ty);6028 const v = try Vectorize.start(f, inst, w, operand_ty);
5909 if (!ref_ret) {6029 if (!ref_ret) {
5910 try f.writeCValue(w, local, .other);6030 try f.writeCValue(w, local, .other);
...@@ -5920,8 +6040,13 @@ fn airUnBuiltinCall(...@@ -5920,8 +6040,13 @@ fn airUnBuiltinCall(
5920 try v.elem(f, w);6040 try v.elem(f, w);
5921 try w.writeAll(", ");6041 try w.writeAll(", ");
5922 }6042 }
5923 if (ref_arg) try w.writeByte('&');6043 if (ref_arg) {
5924 try f.writeCValue(w, operand, .other);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);
5925 try v.elem(f, w);6050 try v.elem(f, w);
5926 try f.dg.renderBuiltinInfo(w, scalar_ty, info);6051 try f.dg.renderBuiltinInfo(w, scalar_ty, info);
5927 try w.writeAll(");");6052 try w.writeAll(");");
...@@ -5941,8 +6066,9 @@ fn airBinBuiltinCall(...@@ -5941,8 +6066,9 @@ fn airBinBuiltinCall(
5941 const zcu = pt.zcu;6066 const zcu = pt.zcu;
5942 const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op;6067 const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op;
59436068
5944 const operand_ty = f.typeOf(bin_op.lhs);6069 const lhs_ty = f.typeOf(bin_op.lhs);
5945 const is_big = lowersToBigInt(operand_ty, zcu);6070 const rhs_ty = f.typeOf(bin_op.rhs);
6071 const is_big = lowersToBigInt(lhs_ty, zcu);
59466072
5947 const lhs = try f.resolveInst(bin_op.lhs);6073 const lhs = try f.resolveInst(bin_op.lhs);
5948 const rhs = try f.resolveInst(bin_op.rhs);6074 const rhs = try f.resolveInst(bin_op.rhs);
...@@ -5950,22 +6076,31 @@ fn airBinBuiltinCall(...@@ -5950,22 +6076,31 @@ fn airBinBuiltinCall(
59506076
5951 const inst_ty = f.typeOfIndex(inst);6077 const inst_ty = f.typeOfIndex(inst);
5952 const inst_scalar_ty = inst_ty.scalarType(zcu);6078 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
5955 const ref_ret = lowersToBigInt(inst_scalar_ty, zcu);6082 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
5958 const w = &f.code.writer;6086 const w = &f.code.writer;
5959 const local = try f.allocLocal(inst, inst_ty);6087 const local = try f.allocLocal(inst, inst_ty);
5960 if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });6088 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);
5962 if (!ref_ret) {6090 if (!ref_ret) {
5963 try f.writeCValue(w, local, .other);6091 try f.writeCValue(w, local, .other);
5964 try v.elem(f, w);6092 try v.elem(f, w);
5965 try w.writeAll(" = ");6093 try w.writeAll(" = ");
5966 }6094 }
5967 try w.print("zig_{s}_", .{operation});6095 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 }
5969 try w.writeByte('(');6104 try w.writeByte('(');
5970 if (ref_ret) {6105 if (ref_ret) {
5971 try w.writeByte('&');6106 try w.writeByte('&');
...@@ -5973,15 +6108,45 @@ fn airBinBuiltinCall(...@@ -5973,15 +6108,45 @@ fn airBinBuiltinCall(
5973 try v.elem(f, w);6108 try v.elem(f, w);
5974 try w.writeAll(", ");6109 try w.writeAll(", ");
5975 }6110 }
5976 if (ref_arg) try w.writeByte('&');6111 if (ref_lhs) {
5977 try f.writeCValue(w, lhs, .other);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);
5978 try v.elem(f, w);6118 try v.elem(f, w);
5979 try w.writeAll(", ");6119 try w.writeAll(", ");
5980 if (ref_arg) try w.writeByte('&');6120 if (ref_rhs) {
5981 try f.writeCValue(w, rhs, .other);6121 try w.writeByte('&');
5982 if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w);6122 switch (rhs) {
5983 try f.dg.renderBuiltinInfo(w, scalar_ty, info);6123 .constant => |rhs_val| try f.dg.renderValueAsLvalue(w, rhs_val),
5984 try w.writeAll(");\n");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();
5985 try v.end(f, inst, w);6150 try v.end(f, inst, w);
59866151
5987 return local;6152 return local;
...@@ -6029,12 +6194,22 @@ fn airCmpBuiltinCall(...@@ -6029,12 +6194,22 @@ fn airCmpBuiltinCall(
6029 try v.elem(f, w);6194 try v.elem(f, w);
6030 try w.writeAll(", ");6195 try w.writeAll(", ");
6031 }6196 }
6032 if (ref_arg) try w.writeByte('&');6197 if (ref_arg) {
6033 try f.writeCValue(w, lhs, .other);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);
6034 try v.elem(f, w);6204 try v.elem(f, w);
6035 try w.writeAll(", ");6205 try w.writeAll(", ");
6036 if (ref_arg) try w.writeByte('&');6206 if (ref_arg) {
6037 try f.writeCValue(w, rhs, .other);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);
6038 try v.elem(f, w);6213 try v.elem(f, w);
6039 try f.dg.renderBuiltinInfo(w, scalar_ty, info);6214 try f.dg.renderBuiltinInfo(w, scalar_ty, info);
6040 try w.writeByte(')');6215 try w.writeByte(')');
...@@ -6595,7 +6770,8 @@ fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6595,7 +6770,8 @@ fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue {
6595 },6770 },
6596 .value => |val| try f.dg.renderValue(w, .fromInterned(val), .other),6771 .value => |val| try f.dg.renderValue(w, .fromInterned(val), .other),
6597 }6772 }
6598 try w.writeAll(";\n");6773 try w.writeByte(';');
6774 try f.newline();
6599 }6775 }
66006776
6601 return local;6777 return local;
...@@ -6653,7 +6829,14 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6653,7 +6829,14 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
6653 const operand_ty = f.typeOf(reduce.operand);6829 const operand_ty = f.typeOf(reduce.operand);
6654 const w = &f.code.writer;6830 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 };
6657 const op: union(enum) {6840 const op: union(enum) {
6658 const Func = struct { operation: []const u8, info: BuiltinInfo = .none };6841 const Func = struct { operation: []const u8, info: BuiltinInfo = .none };
6659 builtin: Func,6842 builtin: Func,
...@@ -6742,25 +6925,57 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6742,25 +6925,57 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
6742 try f.newline();6925 try f.newline();
67436926
6744 const v = try Vectorize.start(f, inst, w, operand_ty);6927 const v = try Vectorize.start(f, inst, w, operand_ty);
6745 try f.writeCValue(w, accum, .other);
6746 switch (op) {6928 switch (op) {
6747 .builtin => |func| {6929 .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});
6749 try f.dg.renderTypeForBuiltinFnName(w, scalar_ty);6944 try f.dg.renderTypeForBuiltinFnName(w, scalar_ty);
6750 try w.writeByte('(');6945 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);
6752 try w.writeAll(", ");6958 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);
6754 try v.elem(f, w);6966 try v.elem(f, w);
6755 try f.dg.renderBuiltinInfo(w, scalar_ty, func.info);6967 try f.dg.renderBuiltinInfo(w, scalar_ty, func.info);
6756 try w.writeByte(')');6968 try w.writeByte(')');
6969 if (is_big) try freeLocal(f, inst, prev_accum.new_local, null);
6757 },6970 },
6758 .infix => |ass| {6971 .infix => |ass| {
6972 try f.writeCValue(w, accum, .other);
6759 try w.writeAll(ass);6973 try w.writeAll(ass);
6760 try f.writeCValue(w, operand, .other);6974 try f.writeCValue(w, operand, .other);
6761 try v.elem(f, w);6975 try v.elem(f, w);
6762 },6976 },
6763 .ternary => |cmp| {6977 .ternary => |cmp| {
6978 try f.writeCValue(w, accum, .other);
6764 try w.writeAll(" = ");6979 try w.writeAll(" = ");
6765 try f.writeCValue(w, accum, .other);6980 try f.writeCValue(w, accum, .other);
6766 try w.writeAll(cmp);6981 try w.writeAll(cmp);
...@@ -7097,101 +7312,6 @@ fn writeMemoryOrder(w: *Writer, order: std.lang.AtomicOrder) !void {...@@ -7097,101 +7312,6 @@ fn writeMemoryOrder(w: *Writer, order: std.lang.AtomicOrder) !void {
7097 return w.writeAll(toMemoryOrder(order));7312 return w.writeAll(toMemoryOrder(order));
7098}7313}
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
7195fn toAtomicRmwSuffix(order: std.lang.AtomicRmwOp) []const u8 {7315fn toAtomicRmwSuffix(order: std.lang.AtomicRmwOp) []const u8 {
7196 return switch (order) {7316 return switch (order) {
7197 .Xchg => "xchg",7317 .Xchg => "xchg",
...@@ -7224,17 +7344,18 @@ fn signAbbrev(signedness: std.lang.Signedness) u8 {...@@ -7224,17 +7344,18 @@ fn signAbbrev(signedness: std.lang.Signedness) u8 {
72247344
7225fn compilerRtAbbrev(ty: Type, zcu: *Zcu, target: *const std.Target) []const u8 {7345fn compilerRtAbbrev(ty: Type, zcu: *Zcu, target: *const std.Target) []const u8 {
7226 return if (ty.isInt(zcu)) switch (ty.intInfo(zcu).bits) {7346 return if (ty.isInt(zcu)) switch (ty.intInfo(zcu).bits) {
7347 0 => unreachable,
7227 1...32 => "si",7348 1...32 => "si",
7228 33...64 => "di",7349 33...64 => "di",
7229 65...128 => "ti",7350 65...128 => "ti",
7230 else => unreachable,7351 else => "ei",
7231 } else if (ty.isRuntimeFloat()) switch (ty.floatBits(target)) {7352 } else if (ty.isRuntimeFloat()) switch (ty.floatBits(target)) {
7353 else => unreachable,
7232 16 => "hf",7354 16 => "hf",
7233 32 => "sf",7355 32 => "sf",
7234 64 => "df",7356 64 => "df",
7235 80 => "xf",7357 80 => "xf",
7236 128 => "tf",7358 128 => if (target.cpu.arch.isPowerPC()) "kf" else "tf",
7237 else => unreachable,
7238 } else unreachable;7359 } else unreachable;
7239}7360}
72407361
...@@ -7390,10 +7511,8 @@ fn fmtStringLiteral(str: []const u8, sentinel: ?u8) std.fmt.Alt(FormatStringCont...@@ -7390,10 +7511,8 @@ fn fmtStringLiteral(str: []const u8, sentinel: ?u8) std.fmt.Alt(FormatStringCont
7390 return .{ .data = .{ .str = str, .sentinel = sentinel } };7511 return .{ .data = .{ .str = str, .sentinel = sentinel } };
7391}7512}
73927513
7393fn undefPattern(comptime IntType: type) IntType {7514fn undefPattern(comptime Result: type) Result {
7394 const int_info = @typeInfo(IntType).int;7515 return @bitCast(@as(@Int(.unsigned, @bitSizeOf(Result)), (1 << (@bitSizeOf(Result) | 1)) / 3));
7395 const UnsignedType = @Int(.unsigned, int_info.bits);
7396 return @bitCast(@as(UnsignedType, (1 << (int_info.bits | 1)) / 3));
7397}7516}
73987517
7399const FormatIntLiteralContext = struct {7518const FormatIntLiteralContext = struct {
...@@ -7580,11 +7699,9 @@ const FormatSignedIntLiteralSmall = struct {...@@ -7580,11 +7699,9 @@ const FormatSignedIntLiteralSmall = struct {
7580 case: std.fmt.Case,7699 case: std.fmt.Case,
7581 pub fn format(data: FormatSignedIntLiteralSmall, w: *Writer) Writer.Error!void {7700 pub fn format(data: FormatSignedIntLiteralSmall, w: *Writer) Writer.Error!void {
7582 const bits = data.int_cty.bits(data.target);7701 const bits = data.int_cty.bits(data.target);
7583 const max_int: i64 = @bitCast((@as(u64, 1) << @intCast(bits - 1)) - 1);7702 if (data.val == @as(i64, std.math.maxInt(i64)) >> @intCast(64 - bits)) {
7584 const min_int: i64 = @bitCast(@as(u64, 1) << @intCast(bits - 1));
7585 if (data.val == max_int) {
7586 return w.print("{s}_MAX", .{minMaxMacroPrefix(data.int_cty)});7703 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)) {
7588 return w.print("{s}_MIN", .{minMaxMacroPrefix(data.int_cty)});7705 return w.print("{s}_MIN", .{minMaxMacroPrefix(data.int_cty)});
7589 }7706 }
7590 if (data.val < 0) try w.writeByte('-');7707 if (data.val < 0) try w.writeByte('-');
...@@ -7596,7 +7713,7 @@ const FormatSignedIntLiteralSmall = struct {...@@ -7596,7 +7713,7 @@ const FormatSignedIntLiteralSmall = struct {
7596 16 => try w.writeAll("0x"),7713 16 => try w.writeAll("0x"),
7597 else => unreachable,7714 else => unreachable,
7598 }7715 }
7599 // This `@abs` is safe thanks to the `min_int` case above.7716 // This `@abs` is safe thanks to the min int check above.
7600 try w.printInt(@abs(data.val), data.base, data.case, .{});7717 try w.printInt(@abs(data.val), data.base, data.case, .{});
7601 try w.writeAll(intLiteralSuffix(data.int_cty));7718 try w.writeAll(intLiteralSuffix(data.int_cty));
7602 }7719 }
...@@ -7610,8 +7727,7 @@ const FormatUnsignedIntLiteralSmall = struct {...@@ -7610,8 +7727,7 @@ const FormatUnsignedIntLiteralSmall = struct {
7610 case: std.fmt.Case,7727 case: std.fmt.Case,
7611 pub fn format(data: FormatUnsignedIntLiteralSmall, w: *Writer) Writer.Error!void {7728 pub fn format(data: FormatUnsignedIntLiteralSmall, w: *Writer) Writer.Error!void {
7612 const bits = data.int_cty.bits(data.target);7729 const bits = data.int_cty.bits(data.target);
7613 const max_int: u64 = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - bits);7730 if (data.val == @as(u64, std.math.maxInt(u64)) >> @intCast(64 - bits)) {
7614 if (data.val == max_int) {
7615 return w.print("{s}_MAX", .{minMaxMacroPrefix(data.int_cty)});7731 return w.print("{s}_MAX", .{minMaxMacroPrefix(data.int_cty)});
7616 }7732 }
7617 try w.writeAll(intLiteralPrefix(data.int_cty, data.is_global));7733 try w.writeAll(intLiteralPrefix(data.int_cty, data.is_global));
...@@ -7735,6 +7851,31 @@ fn intLiteralSuffix(cty: CType.Int) []const u8 {...@@ -7735,6 +7851,31 @@ fn intLiteralSuffix(cty: CType.Int) []const u8 {
7735 };7851 };
7736}7852}
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
7738const Materialize = struct {7879const Materialize = struct {
7739 local: CValue,7880 local: CValue,
77407881
src/codegen/c/type.zig+204-23
...@@ -44,8 +44,181 @@ pub const CType = union(enum) {...@@ -44,8 +44,181 @@ pub const CType = union(enum) {
44 param_tys: []const CType,44 param_tys: []const CType,
45 ret_ty: *const CType,45 ret_ty: *const CType,
46 varargs: bool,46 varargs: bool,
47 cc: CallingConvention,
47 },48 },
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
49 /// Returns `true` if this node has a postfix operator, meaning an `[...]` or `(...)` appears222 /// Returns `true` if this node has a postfix operator, meaning an `[...]` or `(...)` appears
50 /// after the identifier in a declarator with this type. In this case, if this node is wrapped223 /// after the identifier in a declarator with this type. In this case, if this node is wrapped
51 /// in a pointer type, we will need to add parentheses due to operator precedence.224 /// in a pointer type, we will need to add parentheses due to operator precedence.
...@@ -130,28 +303,28 @@ pub const CType = union(enum) {...@@ -130,28 +303,28 @@ pub const CType = union(enum) {
130 pub fn bits(int: Int, target: *const std.Target) u16 {303 pub fn bits(int: Int, target: *const std.Target) u16 {
131 return switch (int) {304 return switch (int) {
132 // zig fmt: off305 // zig fmt: off
133 .char => target.cTypeBitSize(.char),306 .char => target.cTypeBitSize(.char).?,
134307
135 .@"unsigned short" => target.cTypeBitSize(.ushort),308 .@"unsigned short" => target.cTypeBitSize(.ushort).?,
136 .@"unsigned int" => target.cTypeBitSize(.uint),309 .@"unsigned int" => target.cTypeBitSize(.uint).?,
137 .@"unsigned long" => target.cTypeBitSize(.ulong),310 .@"unsigned long" => target.cTypeBitSize(.ulong).?,
138 .@"unsigned long long" => target.cTypeBitSize(.ulonglong),311 .@"unsigned long long" => target.cTypeBitSize(.ulonglong).?,
139312
140 .@"signed short" => target.cTypeBitSize(.short),313 .@"signed short" => target.cTypeBitSize(.short).?,
141 .@"signed int" => target.cTypeBitSize(.int),314 .@"signed int" => target.cTypeBitSize(.int).?,
142 .@"signed long" => target.cTypeBitSize(.long),315 .@"signed long" => target.cTypeBitSize(.long).?,
143 .@"signed long long" => target.cTypeBitSize(.longlong),316 .@"signed long long" => target.cTypeBitSize(.longlong).?,
144317
145 .uintptr_t, .intptr_t => target.ptrBitWidth(),318 .uintptr_t, .intptr_t => target.ptrBitWidth(),
146319
147 .uint8_t, .int8_t => 8,320 .uint8_t, .int8_t => 8,
148 .uint16_t, .int16_t => 16,321 .uint16_t, .int16_t => 16,
149 .uint24_t, .int24_t => 24,322 .uint24_t, .int24_t => 24,
150 .uint32_t, .int32_t => 32,323 .uint32_t, .int32_t => 32,
151 .uint48_t, .int48_t => 48,324 .uint48_t, .int48_t => 48,
152 .uint64_t, .int64_t => 64,325 .uint64_t, .int64_t => 64,
153 .zig_u128, .zig_i128 => 128,326 .zig_u128, .zig_i128 => 128,
154 // zig fmt: on327 // zig fmt: on
155 };328 };
156 }329 }
157 };330 };
...@@ -376,6 +549,7 @@ pub const CType = union(enum) {...@@ -376,6 +549,7 @@ pub const CType = union(enum) {
376 .ret_ty = ret_cty_buf,549 .ret_ty = ret_cty_buf,
377 .param_tys = param_cty_buf,550 .param_tys = param_cty_buf,
378 .varargs = func_type.is_var_args,551 .varargs = func_type.is_var_args,
552 .cc = .fromLang(func_type.cc, zcu.getTarget()),
379 } };553 } };
380 }554 }
381 try deps.addType(gpa, cur_ty, allow_incomplete);555 try deps.addType(gpa, cur_ty, allow_incomplete);
...@@ -763,6 +937,13 @@ pub const CType = union(enum) {...@@ -763,6 +937,13 @@ pub const CType = union(enum) {
763 try w.writeByte('(');937 try w.writeByte('(');
764 },938 },
765 }939 }
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 }
766 try w.writeByte('*');947 try w.writeByte('*');
767 },948 },
768949
...@@ -812,7 +993,7 @@ pub const CType = union(enum) {...@@ -812,7 +993,7 @@ pub const CType = union(enum) {
812 => {},993 => {},
813994
814 .pointer => |ptr| {995 .pointer => |ptr| {
815 // Match opening paren "(" write `writeTypePrefix`.996 // Match opening paren "(" in `writeTypePrefix`.
816 switch (ptr.elem_ty.kind()) {997 switch (ptr.elem_ty.kind()) {
817 .specifier, .pointer => {},998 .specifier, .pointer => {},
818 .postfix_op => try w.writeByte(')'),999 .postfix_op => try w.writeByte(')'),
src/codegen/c/type/render_defs.zig+143-155
...@@ -21,16 +21,21 @@ pub fn defineAligned(...@@ -21,16 +21,21 @@ pub fn defineAligned(
21 if (complete and alignment.compareStrict(.lt, ty.abiAlignment(zcu))) {21 if (complete and alignment.compareStrict(.lt, ty.abiAlignment(zcu))) {
22 try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?});22 try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?});
23 }23 }
24 try w.print("{f}{f}{f}; /* align({d}) {f} */\n", .{24 try w.print("{f}{f}{f};", .{
25 cty.fmtDeclaratorPrefix(zcu),25 cty.fmtDeclaratorPrefix(zcu),
26 name_cty.fmtTypeName(zcu),26 name_cty.fmtTypeName(zcu),
27 cty.fmtDeclaratorSuffix(zcu),27 cty.fmtDeclaratorSuffix(zcu),
28 });
29 if (!zcu.comp.config.root_strip) try w.print(" /* align({d}) {f} */", .{
28 alignment.toByteUnits().?,30 alignment.toByteUnits().?,
29 ty.fmt(pt),31 ty.fmt(pt),
30 });32 });
33 try w.writeByte('\n');
31}34}
32/// Renders the definition of a big-int `struct`.35/// Renders the definition of a big-int `struct`.
33pub fn defineBigInt(big: CType.BigInt, w: *Writer, zcu: *const Zcu) Writer.Error!void {36pub 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;
34 const name_cty: CType = .{ .bigint = .{39 const name_cty: CType = .{ .bigint = .{
35 .limb_size = big.limb_size,40 .limb_size = big.limb_size,
36 .limbs_len = big.limbs_len,41 .limbs_len = big.limbs_len,
...@@ -41,12 +46,20 @@ pub fn defineBigInt(big: CType.BigInt, w: *Writer, zcu: *const Zcu) Writer.Error...@@ -41,12 +46,20 @@ pub fn defineBigInt(big: CType.BigInt, w: *Writer, zcu: *const Zcu) Writer.Error
41 .elem_ty = &limb_cty,46 .elem_ty = &limb_cty,
42 .nonstring = limb_cty.isStringElem(),47 .nonstring = limb_cty.isStringElem(),
43 } };48 } };
44 try w.print("{f} {{ {f}limbs{f}; }}; /* {d} bits */\n", .{49 try w.print("{f} {{ {f}limbs{f}; }};", .{
45 name_cty.fmtTypeName(zcu),50 name_cty.fmtTypeName(zcu),
46 array_cty.fmtDeclaratorPrefix(zcu),51 array_cty.fmtDeclaratorPrefix(zcu),
47 array_cty.fmtDeclaratorSuffix(zcu),52 array_cty.fmtDeclaratorSuffix(zcu),
48 big.limb_size.bits() * @as(u17, big.limbs_len),
49 });53 });
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 );
50}63}
5164
52/// Renders a forward declaration of the `struct` which represents an error union whose payload type65/// Renders a forward declaration of the `struct` which represents an error union whose payload type
...@@ -81,27 +94,28 @@ pub fn errunionDefineComplete(...@@ -81,27 +94,28 @@ pub fn errunionDefineComplete(
81 if (payload_ty.hasRuntimeBits(zcu)) {94 if (payload_ty.hasRuntimeBits(zcu)) {
82 const payload_cty: CType = try .lower(payload_ty, deps, arena, zcu);95 const payload_cty: CType = try .lower(payload_ty, deps, arena, zcu);
83 try w.print(96 try w.print(
84 \\{f} {{ /* anyerror!{f} */97 \\{f} {{
85 \\ {f}payload{f};98 \\ {f}payload{f};
86 \\ {f}error{f};99 \\ {f}error{f};
87 \\}};100 \\}};
88 \\
89 , .{101 , .{
90 name_cty.fmtTypeName(zcu),102 name_cty.fmtTypeName(zcu),
91 payload_ty.fmt(pt),
92 payload_cty.fmtDeclaratorPrefix(zcu),103 payload_cty.fmtDeclaratorPrefix(zcu),
93 payload_cty.fmtDeclaratorSuffix(zcu),104 payload_cty.fmtDeclaratorSuffix(zcu),
94 error_cty.fmtDeclaratorPrefix(zcu),105 error_cty.fmtDeclaratorPrefix(zcu),
95 error_cty.fmtDeclaratorSuffix(zcu),106 error_cty.fmtDeclaratorSuffix(zcu),
96 });107 });
97 } else {108 } else {
98 try w.print("{f} {{ {f}error{f}; }}; /* anyerror!{f} */\n", .{109 try w.print("{f} {{ {f}error{f}; }};", .{
99 name_cty.fmtTypeName(zcu),110 name_cty.fmtTypeName(zcu),
100 error_cty.fmtDeclaratorPrefix(zcu),111 error_cty.fmtDeclaratorPrefix(zcu),
101 error_cty.fmtDeclaratorSuffix(zcu),112 error_cty.fmtDeclaratorSuffix(zcu),
102 payload_ty.fmt(pt),
103 });113 });
104 }114 }
115 if (!zcu.comp.config.root_strip) try w.print(" /* anyerror!{f} */", .{
116 payload_ty.fmt(pt),
117 });
118 try w.writeByte('\n');
105}119}
106120
107/// If the Zig type `ty` lowers to a `struct` or `union` type, renders a forward declaration of that121/// 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...@@ -141,10 +155,13 @@ pub fn defineIncomplete(ty: Type, w: *Writer, pt: Zcu.PerThread) Writer.Error!vo
141 },155 },
142 else => return,156 else => return,
143 };157 };
144 try w.print("typedef void {f}; /* {f} */\n", .{158 try w.print("typedef void {f};", .{
145 name_cty.fmtTypeName(zcu),159 name_cty.fmtTypeName(zcu),
160 });
161 if (!zcu.comp.config.root_strip) try w.print(" /* {f} */", .{
146 ty.fmt(pt),162 ty.fmt(pt),
147 });163 });
164 try w.writeByte('\n');
148}165}
149166
150/// If the Zig type `ty` lowers to a `struct` or `union` type, or to a `typedef`, renders the167/// 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(...@@ -163,13 +180,13 @@ pub fn defineComplete(
163180
164 ty.assertHasLayout(zcu);181 ty.assertHasLayout(zcu);
165182
166 switch (ty.zigTypeTag(zcu)) {183 const check_cty = check_cty: switch (ty.zigTypeTag(zcu)) {
167 .@"fn" => if (!ty.fnHasRuntimeBits(zcu)) {184 .@"fn" => if (!ty.fnHasRuntimeBits(zcu)) {
168 const name_cty: CType = .{ .@"fn" = ty };185 const name_cty: CType = .{ .@"fn" = ty };
169 try w.print("typedef void {f}; /* {f} */\n", .{186 try w.print("typedef void {f};", .{
170 name_cty.fmtTypeName(zcu),187 name_cty.fmtTypeName(zcu),
171 ty.fmt(pt),
172 });188 });
189 break :check_cty null;
173 } else {190 } else {
174 const ip = &zcu.intern_pool;191 const ip = &zcu.intern_pool;
175 const func_type = ip.indexToKey(ty.toIntern()).func_type;192 const func_type = ip.indexToKey(ty.toIntern()).func_type;
...@@ -186,10 +203,12 @@ pub fn defineComplete(...@@ -186,10 +203,12 @@ pub fn defineComplete(
186 const name_cty: CType = .{ .@"fn" = ty };203 const name_cty: CType = .{ .@"fn" = ty };
187 const ret_cty: CType = try .lower(effective_ret_ty, deps, arena, zcu);204 const ret_cty: CType = try .lower(effective_ret_ty, deps, arena, zcu);
188205
189 try w.print("typedef {f}{f}(", .{206 try w.print("typedef {f}", .{ret_cty.fmtDeclaratorPrefix(zcu)});
190 ret_cty.fmtDeclaratorPrefix(zcu),207 switch (CType.CallingConvention.fromLang(func_type.cc, zcu.getTarget())) {
191 name_cty.fmtTypeName(zcu),208 .c => {},
192 });209 else => |cc| try w.print("zig_callconv({t}) ", .{cc}),
210 }
211 try w.print("{f}(", .{name_cty.fmtTypeName(zcu)});
193 var any_params = false;212 var any_params = false;
194 for (func_type.param_types.get(ip)) |param_ty_ip| {213 for (func_type.param_types.get(ip)) |param_ty_ip| {
195 const param_ty: Type = .fromInterned(param_ty_ip);214 const param_ty: Type = .fromInterned(param_ty_ip);
...@@ -205,88 +224,85 @@ pub fn defineComplete(...@@ -205,88 +224,85 @@ pub fn defineComplete(
205 } else if (!any_params) {224 } else if (!any_params) {
206 try w.writeAll("void");225 try w.writeAll("void");
207 }226 }
208 try w.print("){f}; /* {f} */\n", .{227 try w.print("){f};", .{ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu)});
209 ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu),228 break :check_cty null;
210 ty.fmt(pt),
211 });
212 },229 },
213 .@"enum" => {230 .@"enum" => {
214 const name_cty: CType = .{ .@"enum" = ty };231 const name_cty: CType = .{ .@"enum" = ty };
215 const cty: CType = try .lower(ty.backingIntType(zcu), deps, arena, zcu);232 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};", .{
217 cty.fmtDeclaratorPrefix(zcu),234 cty.fmtDeclaratorPrefix(zcu),
218 name_cty.fmtTypeName(zcu),235 name_cty.fmtTypeName(zcu),
219 cty.fmtDeclaratorSuffix(zcu),236 cty.fmtDeclaratorSuffix(zcu),
220 ty.fmt(pt),
221 });237 });
238 break :check_cty null;
222 },239 },
223 .@"struct" => if (ty.isTuple(zcu)) {240 .@"struct" => if (ty.isTuple(zcu))
224 try defineTuple(ty, deps, arena, w, pt);241 if (ty.hasRuntimeBits(zcu)) try defineTuple(ty, deps, arena, w, pt) else return
225 } else switch (ty.containerLayout(zcu)) {242 else switch (ty.containerLayout(zcu)) {
226 .auto, .@"extern" => try defineStruct(ty, deps, arena, w, pt),243 .auto, .@"extern" => if (ty.hasRuntimeBits(zcu)) try defineStruct(ty, deps, arena, w, pt) else return,
227 .@"packed" => try defineBitpack(ty, deps, arena, w, pt),244 .@"packed" => try defineBitpack(ty, deps, arena, w, pt),
228 },245 },
229 .@"union" => switch (ty.containerLayout(zcu)) {246 .@"union" => switch (ty.containerLayout(zcu)) {
230 .auto => try defineUnionAuto(ty, deps, arena, w, pt),247 .auto => if (ty.hasRuntimeBits(zcu)) try defineUnionAuto(ty, deps, arena, w, pt) else return,
231 .@"extern" => try defineUnionExtern(ty, deps, arena, w, pt),248 .@"extern" => if (ty.hasRuntimeBits(zcu)) try defineUnionExtern(ty, deps, arena, w, pt) else return,
232 .@"packed" => try defineBitpack(ty, deps, arena, w, pt),249 .@"packed" => try defineBitpack(ty, deps, arena, w, pt),
233 },250 },
234 .pointer => if (ty.isSlice(zcu)) {251 .pointer => if (ty.isSlice(zcu)) {
235 const name_cty: CType = .{ .slice = ty };252 const name_cty: CType = .{ .slice = ty };
236 const ptr_cty: CType = try .lower(ty.slicePtrFieldType(zcu), deps, arena, zcu);253 const ptr_cty: CType = try .lower(ty.slicePtrFieldType(zcu), deps, arena, zcu);
237 try w.print(254 try w.print(
238 \\{f} {{ /* {f} */255 \\{f} {{
239 \\ {f}ptr{f};256 \\ {f}ptr{f};
240 \\ size_t len;257 \\ uintptr_t len;
241 \\}};258 \\}};
242 \\
243 , .{259 , .{
244 name_cty.fmtTypeName(zcu),260 name_cty.fmtTypeName(zcu),
245 ty.fmt(pt),
246 ptr_cty.fmtDeclaratorPrefix(zcu),261 ptr_cty.fmtDeclaratorPrefix(zcu),
247 ptr_cty.fmtDeclaratorSuffix(zcu),262 ptr_cty.fmtDeclaratorSuffix(zcu),
248 });263 });
249 // Don't bother with `writeStaticAssertLayout`---there's not really any way we could mess264 break :check_cty switch (ty.toIntern()) {
250 // slices up, and they're all obviously the same layout.265 .slice_const_u8_sentinel_0_type => name_cty,
251 },266 else => null,
267 };
268 } else return,
252 .optional => switch (CType.classifyOptional(ty, zcu)) {269 .optional => switch (CType.classifyOptional(ty, zcu)) {
253 .error_set,270 .error_set,
254 .ptr_like,271 .ptr_like,
255 .slice_like,272 .slice_like,
256 .npv_payload,273 .npv_payload,
257 => {},274 => return,
258275
259 .opv_payload => {276 .opv_payload => {
260 const name_cty: CType = .{ .opt = ty };277 const name_cty: CType = .{ .opt = ty };
261 try w.print("{f} {{ bool is_null; }}; /* {f} */\n", .{278 try w.print("{f} {{ bool is_null; }};", .{
262 name_cty.fmtTypeName(zcu),279 name_cty.fmtTypeName(zcu),
263 ty.fmt(pt),
264 });280 });
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 };
266 },285 },
267286
268 .@"struct" => {287 .@"struct" => {
269 const name_cty: CType = .{ .opt = ty };288 const name_cty: CType = .{ .opt = ty };
270 const payload_cty: CType = try .lower(ty.optionalChild(zcu), deps, arena, zcu);289 const payload_cty: CType = try .lower(ty.optionalChild(zcu), deps, arena, zcu);
271 try w.print(290 try w.print(
272 \\{f} {{ /* {f} */291 \\{f} {{
273 \\ {f}payload{f};292 \\ {f}payload{f};
274 \\ bool is_null;293 \\ bool is_null;
275 \\}};294 \\}};
276 \\
277 , .{295 , .{
278 name_cty.fmtTypeName(zcu),296 name_cty.fmtTypeName(zcu),
279 ty.fmt(pt),
280 payload_cty.fmtDeclaratorPrefix(zcu),297 payload_cty.fmtDeclaratorPrefix(zcu),
281 payload_cty.fmtDeclaratorSuffix(zcu),298 payload_cty.fmtDeclaratorSuffix(zcu),
282 });299 });
283 try writeStaticAssertLayout(ty, name_cty, w, zcu);300 break :check_cty name_cty;
284 },301 },
285 },302 },
286 .array => if (ty.hasRuntimeBits(zcu)) {303 .array => if (ty.hasRuntimeBits(zcu)) {
287 const elem_ty = ty.childType(zcu);
288 const name_cty: CType = .{ .arr = ty };304 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);
290 const array_cty: CType = .{ .array = .{306 const array_cty: CType = .{ .array = .{
291 .len = ty.arrayLenIncludingSentinel(zcu),307 .len = ty.arrayLenIncludingSentinel(zcu),
292 .elem_ty = &elem_cty,308 .elem_ty = &elem_cty,
...@@ -296,43 +312,35 @@ pub fn defineComplete(...@@ -296,43 +312,35 @@ pub fn defineComplete(
296 break :nonstring Value.compareHetero(s, .neq, .zero_comptime_int, zcu);312 break :nonstring Value.compareHetero(s, .neq, .zero_comptime_int, zcu);
297 },313 },
298 } };314 } };
299 if (elem_ty.defaultStructFieldAlignment(.auto, zcu) == elem_ty.abiAlignment(zcu)) {315 try w.print("{f} {{ {f}array{f}; }};", .{
300 try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{316 name_cty.fmtTypeName(zcu),
301 name_cty.fmtTypeName(zcu),317 array_cty.fmtDeclaratorPrefix(zcu),
302 array_cty.fmtDeclaratorPrefix(zcu),318 array_cty.fmtDeclaratorSuffix(zcu),
303 array_cty.fmtDeclaratorSuffix(zcu),319 });
304 ty.fmt(pt),320 break :check_cty name_cty;
305 });321 } else return,
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 },
317 .vector => if (ty.hasRuntimeBits(zcu)) {322 .vector => if (ty.hasRuntimeBits(zcu)) {
318 const elem_ty = ty.childType(zcu);
319 const name_cty: CType = .{ .vec = ty };323 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);
321 const array_cty: CType = .{ .array = .{325 const array_cty: CType = .{ .array = .{
322 .len = ty.arrayLenIncludingSentinel(zcu),326 .len = ty.arrayLenIncludingSentinel(zcu),
323 .elem_ty = &elem_cty,327 .elem_ty = &elem_cty,
324 .nonstring = elem_cty.isStringElem(),328 .nonstring = elem_cty.isStringElem(),
325 } };329 } };
326 try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{330 try w.print("{f} {{ {f}array{f}; }};", .{
327 name_cty.fmtTypeName(zcu),331 name_cty.fmtTypeName(zcu),
328 array_cty.fmtDeclaratorPrefix(zcu),332 array_cty.fmtDeclaratorPrefix(zcu),
329 array_cty.fmtDeclaratorSuffix(zcu),333 array_cty.fmtDeclaratorSuffix(zcu),
330 ty.fmt(pt),
331 });334 });
332 try writeStaticAssertLayout(ty, name_cty, w, zcu);335 break :check_cty name_cty;
333 },336 } else return,
334 else => {},337 else => return,
335 }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);
336}344}
337fn defineBitpack(345fn defineBitpack(
338 ty: Type,346 ty: Type,
...@@ -340,16 +348,16 @@ fn defineBitpack(...@@ -340,16 +348,16 @@ fn defineBitpack(
340 arena: Allocator,348 arena: Allocator,
341 w: *Writer,349 w: *Writer,
342 pt: Zcu.PerThread,350 pt: Zcu.PerThread,
343) (Allocator.Error || Writer.Error)!void {351) (Allocator.Error || Writer.Error)!?CType {
344 const zcu = pt.zcu;352 const zcu = pt.zcu;
345 const name_cty: CType = .{ .bitpack = ty };353 const name_cty: CType = .{ .bitpack = ty };
346 const cty: CType = try .lower(ty.backingIntType(zcu), deps, arena, zcu);354 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};", .{
348 cty.fmtDeclaratorPrefix(zcu),356 cty.fmtDeclaratorPrefix(zcu),
349 name_cty.fmtTypeName(zcu),357 name_cty.fmtTypeName(zcu),
350 cty.fmtDeclaratorSuffix(zcu),358 cty.fmtDeclaratorSuffix(zcu),
351 ty.fmt(pt),
352 });359 });
360 return null;
353}361}
354fn defineTuple(362fn defineTuple(
355 ty: Type,363 ty: Type,
...@@ -357,72 +365,54 @@ fn defineTuple(...@@ -357,72 +365,54 @@ fn defineTuple(
357 arena: Allocator,365 arena: Allocator,
358 w: *Writer,366 w: *Writer,
359 pt: Zcu.PerThread,367 pt: Zcu.PerThread,
360) (Allocator.Error || Writer.Error)!void {368) (Allocator.Error || Writer.Error)!CType {
361 const zcu = pt.zcu;369 const zcu = pt.zcu;
362 if (!ty.hasRuntimeBits(zcu)) return;
363 const ip = &zcu.intern_pool;370 const ip = &zcu.intern_pool;
364 const tuple = ip.indexToKey(ty.toIntern()).tuple_type;371 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.376 const tuple_align = ty.abiAlignment(zcu);
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 };
384377
385 // If the alignment of other fields would not give the tuple sufficient alignment, we378 // If the alignment of other fields would not give the tuple sufficient alignment, we
386 // need to align the first field (which does not affect its offset, because 0 is always379 // need to align the first field (which does not affect its offset, because 0 is always
387 // well-aligned) to indirectly specify the tuple alignment.380 // well-aligned) to indirectly specify the tuple alignment.
388 const overalign: bool = switch (pack) {381 const overalign: bool = for (tuple.types.get(ip)) |field_ty_ip| {
389 true => tuple_align.compareStrict(.gt, .@"1"),382 const field_ty: Type = .fromInterned(field_ty_ip);
390 false => for (tuple.types.get(ip)) |field_ty_ip| {383 if (!field_ty.hasRuntimeBits(zcu)) continue;
391 const field_ty: Type = .fromInterned(field_ty_ip);384 const natural_align = field_ty.abiAlignment(zcu);
392 if (!field_ty.hasRuntimeBits(zcu)) continue;385 if (natural_align.compareStrict(.gte, tuple_align)) break false;
393 const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu);386 } else true;
394 if (natural_align.compareStrict(.gte, tuple_align)) break false;
395 } else true,
396 };
397387
398 if (pack) try w.writeAll("zig_packed(");
399 const name_cty: CType = .{ .@"struct" = ty };388 const name_cty: CType = .{ .@"struct" = ty };
400 try w.print("{f} {{ /* {f} */\n", .{389 try w.print("{f} {{\n", .{
401 name_cty.fmtTypeName(zcu),390 name_cty.fmtTypeName(zcu),
402 ty.fmt(pt),
403 });391 });
404 var zig_offset: u64 = 0;392 var zig_offset: u64 = 0;
405 var c_offset: u64 = 0;393 var c_offset: u64 = 0;
406 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty_ip, field_val_ip, field_index| {394 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty_ip, field_val_ip, field_index| {
407 if (field_val_ip != .none) continue; // `comptime` field395 if (field_val_ip != .none) continue; // `comptime` field
408 const field_ty: Type = .fromInterned(field_ty_ip);396 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);
410 if (!field_ty.hasRuntimeBits(zcu)) continue;399 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);
412 try w.writeByte(' ');401 try w.writeByte(' ');
413 if (zig_offset == 0 and overalign) {402 if (zig_offset == 0 and overalign) {
414 // This is the first field; specify its alignment to align the tuple.403 // This is the first field; specify its alignment to align the tuple.
415 try writeFieldAlign(field_ty, tuple_align, w, zcu);404 try writeFieldAlign(field_ty, tuple_align, w, zcu);
416 } else if (zig_offset > c_offset) {405 } else switch (zig_offset - c_offset) {
417 // This field needs to be underaligned or overaligned compared to what its406 0 => {},
418 // offset would otherwise be.407 else => |need_bytes| {
419 const need_align: Alignment = .minStrict(408 // This field needs to be overaligned compared to what its offset would otherwise be.
420 tuple_align, // don't make the tuple more aligned than it should be409 const need_align: Alignment = .fromLog2Units(std.math.log2_int(u64, need_bytes) + 1);
421 .fromLog2Units(@ctz(zig_offset)),410 assert(need_align.compareStrict(.lte, tuple_align));
422 );411 try writeFieldAlign(field_ty, need_align, w, zcu);
423 try writeFieldAlign(field_ty, need_align, w, zcu);412 c_offset = need_align.forward(c_offset);
424 c_offset = need_align.forward(c_offset);413 },
425 }414 }
415 assert(c_offset == zig_offset);
426 const field_cty: CType = try .lower(field_ty, deps, arena, zcu);416 const field_cty: CType = try .lower(field_ty, deps, arena, zcu);
427 try w.print("{f}f{d}{f};\n", .{417 try w.print("{f}f{d}{f};\n", .{
428 field_cty.fmtDeclaratorPrefix(zcu),418 field_cty.fmtDeclaratorPrefix(zcu),
...@@ -433,11 +423,8 @@ fn defineTuple(...@@ -433,11 +423,8 @@ fn defineTuple(
433 zig_offset += field_size;423 zig_offset += field_size;
434 c_offset += field_size;424 c_offset += field_size;
435 }425 }
436 try w.writeByte('}');426 try w.writeAll("};");
437 if (pack) try w.writeByte(')');427 return name_cty;
438 try w.writeAll(";\n");
439
440 try writeStaticAssertLayout(ty, name_cty, w, zcu);
441}428}
442fn defineStruct(429fn defineStruct(
443 ty: Type,430 ty: Type,
...@@ -445,9 +432,8 @@ fn defineStruct(...@@ -445,9 +432,8 @@ fn defineStruct(
445 arena: Allocator,432 arena: Allocator,
446 w: *Writer,433 w: *Writer,
447 pt: Zcu.PerThread,434 pt: Zcu.PerThread,
448) (Allocator.Error || Writer.Error)!void {435) (Allocator.Error || Writer.Error)!CType {
449 const zcu = pt.zcu;436 const zcu = pt.zcu;
450 if (!ty.hasRuntimeBits(zcu)) return;
451 const ip = &zcu.intern_pool;437 const ip = &zcu.intern_pool;
452438
453 const struct_type = ip.loadStructType(ty.toIntern());439 const struct_type = ip.loadStructType(ty.toIntern());
...@@ -459,7 +445,7 @@ fn defineStruct(...@@ -459,7 +445,7 @@ fn defineStruct(
459 while (it.next()) |field_index| {445 while (it.next()) |field_index| {
460 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]);446 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]);
461 if (!field_ty.hasRuntimeBits(zcu)) continue;447 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);
463 const natural_offset = natural_align.forward(offset);449 const natural_offset = natural_align.forward(offset);
464 const actual_offset = struct_type.field_offsets.get(ip)[field_index];450 const actual_offset = struct_type.field_offsets.get(ip)[field_index];
465 if (actual_offset < natural_offset) break :pack true;451 if (actual_offset < natural_offset) break :pack true;
...@@ -480,7 +466,7 @@ fn defineStruct(...@@ -480,7 +466,7 @@ fn defineStruct(
480 while (it.next()) |field_index| {466 while (it.next()) |field_index| {
481 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]);467 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]);
482 if (!field_ty.hasRuntimeBits(zcu)) continue;468 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);
484 if (natural_align.compareStrict(.gte, struct_type.alignment)) break :overalign false;470 if (natural_align.compareStrict(.gte, struct_type.alignment)) break :overalign false;
485 }471 }
486 break :overalign true;472 break :overalign true;
...@@ -489,16 +475,15 @@ fn defineStruct(...@@ -489,16 +475,15 @@ fn defineStruct(
489475
490 if (pack) try w.writeAll("zig_packed(");476 if (pack) try w.writeAll("zig_packed(");
491 const name_cty: CType = .{ .@"struct" = ty };477 const name_cty: CType = .{ .@"struct" = ty };
492 try w.print("{f} {{ /* {f} */\n", .{478 try w.print("{f} {{\n", .{
493 name_cty.fmtTypeName(zcu),479 name_cty.fmtTypeName(zcu),
494 ty.fmt(pt),
495 });480 });
496 var it = struct_type.iterateRuntimeOrder(ip);481 var it = struct_type.iterateRuntimeOrder(ip);
497 var offset: u64 = 0;482 var offset: u64 = 0;
498 while (it.next()) |field_index| {483 while (it.next()) |field_index| {
499 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]);484 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]);
500 if (!field_ty.hasRuntimeBits(zcu)) continue;485 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);
502 const natural_offset = switch (pack) {487 const natural_offset = switch (pack) {
503 true => offset,488 true => offset,
504 false => natural_align.forward(offset),489 false => natural_align.forward(offset),
...@@ -529,9 +514,8 @@ fn defineStruct(...@@ -529,9 +514,8 @@ fn defineStruct(
529 assert(struct_type.alignment.forward(offset) == struct_type.size);514 assert(struct_type.alignment.forward(offset) == struct_type.size);
530 try w.writeByte('}');515 try w.writeByte('}');
531 if (pack) try w.writeByte(')');516 if (pack) try w.writeByte(')');
532 try w.writeAll(";\n");517 try w.writeByte(';');
533518 return name_cty;
534 try writeStaticAssertLayout(ty, name_cty, w, zcu);
535}519}
536fn defineUnionAuto(520fn defineUnionAuto(
537 ty: Type,521 ty: Type,
...@@ -539,9 +523,8 @@ fn defineUnionAuto(...@@ -539,9 +523,8 @@ fn defineUnionAuto(
539 arena: Allocator,523 arena: Allocator,
540 w: *Writer,524 w: *Writer,
541 pt: Zcu.PerThread,525 pt: Zcu.PerThread,
542) (Allocator.Error || Writer.Error)!void {526) (Allocator.Error || Writer.Error)!CType {
543 const zcu = pt.zcu;527 const zcu = pt.zcu;
544 if (!ty.hasRuntimeBits(zcu)) return;
545 const ip = &zcu.intern_pool;528 const ip = &zcu.intern_pool;
546529
547 const union_type = ip.loadUnionType(ty.toIntern());530 const union_type = ip.loadUnionType(ty.toIntern());
...@@ -553,7 +536,7 @@ fn defineUnionAuto(...@@ -553,7 +536,7 @@ fn defineUnionAuto(
553 const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| {536 const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| {
554 const field_ty: Type = .fromInterned(field_ty_ip);537 const field_ty: Type = .fromInterned(field_ty_ip);
555 if (!field_ty.hasRuntimeBits(zcu)) continue;538 if (!field_ty.hasRuntimeBits(zcu)) continue;
556 const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu);539 const natural_align = field_ty.abiAlignment(zcu);
557 if (natural_align.compareStrict(.gt, union_type.alignment)) break true;540 if (natural_align.compareStrict(.gt, union_type.alignment)) break true;
558 // The tag will immediately follow the payload. This layout may put the tag in what would541 // The tag will immediately follow the payload. This layout may put the tag in what would
559 // otherwise be padding on the payload union, because if the most-aligned union field is not542 // otherwise be padding on the payload union, because if the most-aligned union field is not
...@@ -571,7 +554,7 @@ fn defineUnionAuto(...@@ -571,7 +554,7 @@ fn defineUnionAuto(
571 false => for (union_type.field_types.get(ip)) |field_ty_ip| {554 false => for (union_type.field_types.get(ip)) |field_ty_ip| {
572 const field_ty: Type = .fromInterned(field_ty_ip);555 const field_ty: Type = .fromInterned(field_ty_ip);
573 if (!field_ty.hasRuntimeBits(zcu)) continue;556 if (!field_ty.hasRuntimeBits(zcu)) continue;
574 const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu);557 const natural_align = field_ty.abiAlignment(zcu);
575 if (natural_align.compareStrict(.gte, union_type.alignment)) break false;558 if (natural_align.compareStrict(.gte, union_type.alignment)) break false;
576 } else overalign: {559 } else overalign: {
577 if (union_type.has_runtime_tag) {560 if (union_type.has_runtime_tag) {
...@@ -585,9 +568,8 @@ fn defineUnionAuto(...@@ -585,9 +568,8 @@ fn defineUnionAuto(
585 const payload_has_bits = !union_type.has_runtime_tag or union_type.size > enum_tag_ty.abiSize(zcu);568 const payload_has_bits = !union_type.has_runtime_tag or union_type.size > enum_tag_ty.abiSize(zcu);
586569
587 const name_cty: CType = .{ .union_auto = ty };570 const name_cty: CType = .{ .union_auto = ty };
588 try w.print("{f} {{ /* {f} */\n", .{571 try w.print("{f} {{\n", .{
589 name_cty.fmtTypeName(zcu),572 name_cty.fmtTypeName(zcu),
590 ty.fmt(pt),
591 });573 });
592 if (payload_has_bits) {574 if (payload_has_bits) {
593 try w.writeByte(' ');575 try w.writeByte(' ');
...@@ -619,9 +601,8 @@ fn defineUnionAuto(...@@ -619,9 +601,8 @@ fn defineUnionAuto(
619 tag_cty.fmtDeclaratorSuffix(zcu),601 tag_cty.fmtDeclaratorSuffix(zcu),
620 });602 });
621 }603 }
622 try w.writeAll("};\n");604 try w.writeAll("};");
623605 return name_cty;
624 try writeStaticAssertLayout(ty, name_cty, w, zcu);
625}606}
626fn defineUnionExtern(607fn defineUnionExtern(
627 ty: Type,608 ty: Type,
...@@ -629,9 +610,8 @@ fn defineUnionExtern(...@@ -629,9 +610,8 @@ fn defineUnionExtern(
629 arena: Allocator,610 arena: Allocator,
630 w: *Writer,611 w: *Writer,
631 pt: Zcu.PerThread,612 pt: Zcu.PerThread,
632) (Allocator.Error || Writer.Error)!void {613) (Allocator.Error || Writer.Error)!CType {
633 const zcu = pt.zcu;614 const zcu = pt.zcu;
634 if (!ty.hasRuntimeBits(zcu)) return;
635 const ip = &zcu.intern_pool;615 const ip = &zcu.intern_pool;
636616
637 const union_type = ip.loadUnionType(ty.toIntern());617 const union_type = ip.loadUnionType(ty.toIntern());
...@@ -642,7 +622,7 @@ fn defineUnionExtern(...@@ -642,7 +622,7 @@ fn defineUnionExtern(
642 const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| {622 const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| {
643 const field_ty: Type = .fromInterned(field_ty_ip);623 const field_ty: Type = .fromInterned(field_ty_ip);
644 if (!field_ty.hasRuntimeBits(zcu)) continue;624 if (!field_ty.hasRuntimeBits(zcu)) continue;
645 const natural_align = field_ty.defaultStructFieldAlignment(.@"extern", zcu);625 const natural_align = field_ty.abiAlignment(zcu);
646 if (natural_align.compareStrict(.gt, union_type.alignment)) break true;626 if (natural_align.compareStrict(.gt, union_type.alignment)) break true;
647 } else false;627 } else false;
648628
...@@ -654,7 +634,7 @@ fn defineUnionExtern(...@@ -654,7 +634,7 @@ fn defineUnionExtern(
654 false => for (union_type.field_types.get(ip)) |field_ty_ip| {634 false => for (union_type.field_types.get(ip)) |field_ty_ip| {
655 const field_ty: Type = .fromInterned(field_ty_ip);635 const field_ty: Type = .fromInterned(field_ty_ip);
656 if (!field_ty.hasRuntimeBits(zcu)) continue;636 if (!field_ty.hasRuntimeBits(zcu)) continue;
657 const natural_align = field_ty.defaultStructFieldAlignment(.@"extern", zcu);637 const natural_align = field_ty.abiAlignment(zcu);
658 if (natural_align.compareStrict(.gte, union_type.alignment)) break false;638 if (natural_align.compareStrict(.gte, union_type.alignment)) break false;
659 } else overalign: {639 } else overalign: {
660 if (union_type.has_runtime_tag) {640 if (union_type.has_runtime_tag) {
...@@ -668,9 +648,8 @@ fn defineUnionExtern(...@@ -668,9 +648,8 @@ fn defineUnionExtern(
668 if (pack) try w.writeAll("zig_packed(");648 if (pack) try w.writeAll("zig_packed(");
669649
670 const name_cty: CType = .{ .union_extern = ty };650 const name_cty: CType = .{ .union_extern = ty };
671 try w.print("{f} {{ /* {f} */\n", .{651 try w.print("{f} {{\n", .{
672 name_cty.fmtTypeName(zcu),652 name_cty.fmtTypeName(zcu),
673 ty.fmt(pt),
674 });653 });
675654
676 for (0..enum_tag_ty.enumFieldCount(zcu)) |field_index| {655 for (0..enum_tag_ty.enumFieldCount(zcu)) |field_index| {
...@@ -691,9 +670,8 @@ fn defineUnionExtern(...@@ -691,9 +670,8 @@ fn defineUnionExtern(
691 }670 }
692 try w.writeByte('}');671 try w.writeByte('}');
693 if (pack) try w.writeByte(')');672 if (pack) try w.writeByte(')');
694 try w.writeAll(";\n");673 try w.writeByte(';');
695674 return name_cty;
696 try writeStaticAssertLayout(ty, name_cty, w, zcu);
697}675}
698676
699/// Writes an annotation which, placed before a struct/union field declaration with field type `ty`,677/// Writes an annotation which, placed before a struct/union field declaration with field type `ty`,
...@@ -704,7 +682,7 @@ fn writeFieldAlign(...@@ -704,7 +682,7 @@ fn writeFieldAlign(
704 w: *Writer,682 w: *Writer,
705 zcu: *const Zcu,683 zcu: *const Zcu,
706) Writer.Error!void {684) Writer.Error!void {
707 if (alignment.compareStrict(.lt, ty.defaultStructFieldAlignment(.auto, zcu))) {685 if (alignment.compareStrict(.lt, ty.abiAlignment(zcu))) {
708 try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?});686 try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?});
709 } else {687 } else {
710 try w.print("zig_align({d}) ", .{alignment.toByteUnits().?});688 try w.print("zig_align({d}) ", .{alignment.toByteUnits().?});
...@@ -712,19 +690,29 @@ fn writeFieldAlign(...@@ -712,19 +690,29 @@ fn writeFieldAlign(
712}690}
713691
714/// Emits static assertions that the size and alignment of `cty` match those of the Zig type `ty`.692/// Emits static assertions that the size and alignment of `cty` match those of the Zig type `ty`.
715fn writeStaticAssertLayout(693pub fn writeStaticAssertTypeLayout(
716 ty: Type,694 ty: Type,
717 cty: CType,695 cty: CType,
718 w: *Writer,696 w: *Writer,
719 zcu: *const Zcu,697 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,
720) Writer.Error!void {709) Writer.Error!void {
721 try w.print(710 try w.print(
722 \\zig_static_assert(sizeof ({f}) == {d}, "incorrect size");711 \\zig_static_assert(sizeof({f}) == {d} && zig_alignOf({f}) == {d}, "abi mismatch");
723 \\zig_static_assert(_Alignof ({f}) == {d}, "incorrect alignment");
724 \\712 \\
725 , .{713 , .{
726 cty.fmtTypeName(zcu), ty.abiSize(zcu),714 cty.fmtTypeName(zcu), expected_size,
727 cty.fmtTypeName(zcu), ty.abiAlignment(zcu).toByteUnits().?,715 cty.fmtTypeName(zcu), expected_alignment.toByteUnits().?,
728 });716 });
729}717}
730718
src/codegen/llvm.zig+722-544
...@@ -263,7 +263,7 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8...@@ -263,7 +263,7 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8
263 => {},263 => {},
264 .semver => |ver| if (target.os.tag == .wasi and ver.min.major == 0) {264 .semver => |ver| if (target.os.tag == .wasi and ver.min.major == 0) {
265 try llvm_triple.print("p{d}", .{ver.min.minor});265 try llvm_triple.print("p{d}", .{ver.min.minor});
266 } else {266 } else if (target.os.tag != .amdhsa) {
267 try llvm_triple.print("{d}.{d}.{d}", .{267 try llvm_triple.print("{d}.{d}.{d}", .{
268 ver.min.major,268 ver.min.major,
269 ver.min.minor,269 ver.min.minor,
...@@ -345,160 +345,6 @@ pub fn supportsTailCall(target: *const std.Target) bool {...@@ -345,160 +345,6 @@ pub fn supportsTailCall(target: *const std.Target) bool {
345 };345 };
346}346}
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
502// Avoid depending on `bindings.CodeModel` in the bitcode-only case.348// Avoid depending on `bindings.CodeModel` in the bitcode-only case.
503const CodeModel = enum {349const CodeModel = enum {
504 default,350 default,
...@@ -573,6 +419,8 @@ pub const Object = struct {...@@ -573,6 +419,8 @@ pub const Object = struct {
573 val: InternPool.Index,419 val: InternPool.Index,
574 @"addrspace": std.lang.AddressSpace,420 @"addrspace": std.lang.AddressSpace,
575 }, Builder.Variable.Index),421 }, 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),
576 /// Maps enum types to their corresponding LLVM functions for implementing the `tag_name` instruction.424 /// Maps enum types to their corresponding LLVM functions for implementing the `tag_name` instruction.
577 enum_tag_name_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Function.Index),425 enum_tag_name_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Function.Index),
578 /// Serves the same purpose as `enum_tag_name_map` but for the `is_named_enum_value` instruction.426 /// 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 {...@@ -616,8 +464,6 @@ pub const Object = struct {
616 });464 });
617 errdefer builder.deinit();465 errdefer builder.deinit();
618466
619 builder.data_layout = try builder.string(dataLayout(target));
620
621 const debug_compile_unit, const debug_enums_fwd_ref, const debug_globals_fwd_ref =467 const debug_compile_unit, const debug_enums_fwd_ref, const debug_globals_fwd_ref =
622 if (!builder.strip) debug_info: {468 if (!builder.strip) debug_info: {
623 // We fully resolve all paths at this point to avoid lack of469 // We fully resolve all paths at this point to avoid lack of
...@@ -653,7 +499,7 @@ pub const Object = struct {...@@ -653,7 +499,7 @@ pub const Object = struct {
653 }),499 }),
654 debug_enums_fwd_ref,500 debug_enums_fwd_ref,
655 debug_globals_fwd_ref,501 debug_globals_fwd_ref,
656 .{ .optimized = comp.root_mod.optimize_mode != .Debug },502 .{ .optimized = comp.root_mod.optimize_mode != .debug },
657 );503 );
658504
659 try builder.addNamedMetadata(try builder.string("llvm.dbg.cu"), &.{debug_compile_unit});505 try builder.addNamedMetadata(try builder.string("llvm.dbg.cu"), &.{debug_compile_unit});
...@@ -693,6 +539,7 @@ pub const Object = struct {...@@ -693,6 +539,7 @@ pub const Object = struct {
693 .zcu = zcu,539 .zcu = zcu,
694 .nav_map = .empty,540 .nav_map = .empty,
695 .uav_map = .empty,541 .uav_map = .empty,
542 .const_map = .empty,
696 .enum_tag_name_map = .empty,543 .enum_tag_name_map = .empty,
697 .named_enum_map = .empty,544 .named_enum_map = .empty,
698 .type_map = .empty,545 .type_map = .empty,
...@@ -703,21 +550,22 @@ pub const Object = struct {...@@ -703,21 +550,22 @@ pub const Object = struct {
703 return obj;550 return obj;
704 }551 }
705552
706 pub fn deinit(self: *Object) void {553 pub fn deinit(o: *Object) void {
707 const gpa = self.gpa;554 const gpa = o.gpa;
708 self.type_pool.deinit(gpa);555 o.type_pool.deinit(gpa);
709 self.lazy_abi_aligns.deinit(gpa);556 o.lazy_abi_aligns.deinit(gpa);
710 self.debug_enums.deinit(gpa);557 o.debug_enums.deinit(gpa);
711 self.debug_globals.deinit(gpa);558 o.debug_globals.deinit(gpa);
712 self.debug_file_map.deinit(gpa);559 o.debug_file_map.deinit(gpa);
713 self.debug_types.deinit(gpa);560 o.debug_types.deinit(gpa);
714 self.nav_map.deinit(gpa);561 o.nav_map.deinit(gpa);
715 self.uav_map.deinit(gpa);562 o.uav_map.deinit(gpa);
716 self.enum_tag_name_map.deinit(gpa);563 o.const_map.deinit(gpa);
717 self.named_enum_map.deinit(gpa);564 o.enum_tag_name_map.deinit(gpa);
718 self.type_map.deinit(gpa);565 o.named_enum_map.deinit(gpa);
719 self.builder.deinit();566 o.type_map.deinit(gpa);
720 self.* = undefined;567 o.builder.deinit();
568 o.* = undefined;
721 }569 }
722570
723 fn genErrorNameTable(o: *Object) Allocator.Error!void {571 fn genErrorNameTable(o: *Object) Allocator.Error!void {
...@@ -741,16 +589,16 @@ pub const Object = struct {...@@ -741,16 +589,16 @@ pub const Object = struct {
741 for (llvm_errors[1..], error_name_list) |*llvm_error, name| {589 for (llvm_errors[1..], error_name_list) |*llvm_error, name| {
742 const name_string = try o.builder.stringNull(name.toSlice(ip));590 const name_string = try o.builder.stringNull(name.toSlice(ip));
743 const name_init = try o.builder.stringConst(name_string);591 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);592 const name_llvm_variable = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
745 try name_variable_index.setInitializer(name_init, &o.builder);593 try name_llvm_variable.setInitializer(name_init, &o.builder);
746 name_variable_index.setMutability(.constant, &o.builder);594 name_llvm_variable.setMutability(.constant, &o.builder);
747 name_variable_index.setAlignment(comptime .fromByteUnits(1), &o.builder);595 name_llvm_variable.setAlignment(comptime .fromByteUnits(1), &o.builder);
748 const global_index = name_variable_index.ptrConst(&o.builder).global;596 const llvm_global = name_llvm_variable.ptrConst(&o.builder).global;
749 global_index.setLinkage(.private, &o.builder);597 llvm_global.setLinkage(.private, &o.builder);
750 global_index.setUnnamedAddr(.unnamed_addr, &o.builder);598 llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder);
751599
752 llvm_error.* = try o.builder.structConst(llvm_slice_ty, &.{600 llvm_error.* = try o.builder.structConst(llvm_slice_ty, &.{
753 name_variable_index.toConst(&o.builder),601 name_llvm_variable.toConst(&o.builder),
754 try o.builder.intConst(llvm_usize_ty, name_string.slice(&o.builder).?.len - 1),602 try o.builder.intConst(llvm_usize_ty, name_string.slice(&o.builder).?.len - 1),
755 });603 });
756 }604 }
...@@ -770,7 +618,7 @@ pub const Object = struct {...@@ -770,7 +618,7 @@ pub const Object = struct {
770 b.module_asm.appendSliceAssumeCapacity(assembly);618 b.module_asm.appendSliceAssumeCapacity(assembly);
771 b.module_asm.appendAssumeCapacity('\n');619 b.module_asm.appendAssumeCapacity('\n');
772 }620 }
773 if (b.module_asm.getLast()) |last| {621 if (b.module_asm.last()) |last| {
774 if (last != '\n') try b.module_asm.append(gpa, '\n');622 if (last != '\n') try b.module_asm.append(gpa, '\n');
775 }623 }
776 }624 }
...@@ -1028,7 +876,7 @@ pub const Object = struct {...@@ -1028,7 +876,7 @@ pub const Object = struct {
1028876
1029 const optimize_mode = comp.root_mod.optimize_mode;877 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)
1032 .None880 .None
1033 else881 else
1034 .Aggressive;882 .Aggressive;
...@@ -1199,19 +1047,33 @@ pub const Object = struct {...@@ -1199,19 +1047,33 @@ pub const Object = struct {
1199 global.dll_storage_class = .default;1047 global.dll_storage_class = .default;
1200 global.unnamed_addr = .unnamed_addr;1048 global.unnamed_addr = .unnamed_addr;
1201 }1049 }
1202 llvm_function.setAlignment(switch (nav.resolved.?.@"align") {1050 llvm_function.setAlignment(nav.resolved.?.@"align".toLlvm(), &o.builder);
1203 .none => fn_ty.abiAlignment(zcu).toLlvm(),
1204 else => |a| a.toLlvm(),
1205 }, &o.builder);
1206 llvm_function.setSection(s: {1051 llvm_function.setSection(s: {
1207 const section = nav.resolved.?.@"linksection".toSlice(ip) orelse break :s .none;1052 const section = nav.resolved.?.@"linksection".toSlice(ip) orelse break :s .none;
1208 break :s try o.builder.string(section);1053 break :s try o.builder.string(section);
1209 }, &o.builder);1054 }, &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 = .{};
1213 defer attributes.deinit(&o.builder);1057 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
1215 const func_analysis = func.analysisUnordered(ip);1077 const func_analysis = func.analysisUnordered(ip);
1216 if (func_analysis.is_noinline) {1078 if (func_analysis.is_noinline) {
1217 try attributes.addFnAttr(.@"noinline", &o.builder);1079 try attributes.addFnAttr(.@"noinline", &o.builder);
...@@ -1299,7 +1161,7 @@ pub const Object = struct {...@@ -1299,7 +1161,7 @@ pub const Object = struct {
1299 .NoReturn = fn_info.return_type == .noreturn_type,1161 .NoReturn = fn_info.return_type == .noreturn_type,
1300 },1162 },
1301 .sp_flags = .{1163 .sp_flags = .{
1302 .Optimized = owner_mod.optimize_mode != .Debug,1164 .Optimized = owner_mod.optimize_mode != .debug,
1303 .Definition = true,1165 .Definition = true,
1304 .LocalToUnit = is_internal_linkage,1166 .LocalToUnit = is_internal_linkage,
1305 },1167 },
...@@ -1324,7 +1186,7 @@ pub const Object = struct {...@@ -1324,7 +1186,7 @@ pub const Object = struct {
1324 const counters_variable = try o.builder.addVariable(anon_name, .void, .default);1186 const counters_variable = try o.builder.addVariable(anon_name, .void, .default);
1325 try o.used.append(gpa, counters_variable.toConst(&o.builder));1187 try o.used.append(gpa, counters_variable.toConst(&o.builder));
1326 counters_variable.ptrConst(&o.builder).global.setLinkage(.private, &o.builder);1188 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
1329 if (target.ofmt == .macho) {1191 if (target.ofmt == .macho) {
1330 counters_variable.setSection(try o.builder.string("__DATA,__sancov_cntrs"), &o.builder);1192 counters_variable.setSection(try o.builder.string("__DATA,__sancov_cntrs"), &o.builder);
...@@ -1507,10 +1369,6 @@ pub const Object = struct {...@@ -1507,10 +1369,6 @@ pub const Object = struct {
1507 llvm_global.ptr(&o.builder).unnamed_addr = .unnamed_addr;1369 llvm_global.ptr(&o.builder).unnamed_addr = .unnamed_addr;
1508 }1370 }
15091371
1510 const llvm_align = switch (resolved.@"align") {
1511 .none => nav_ty.abiAlignment(zcu).toLlvm(),
1512 else => |a| a.toLlvm(),
1513 };
1514 const llvm_section: Builder.String = if (resolved.@"linksection".toSlice(ip)) |section| s: {1372 const llvm_section: Builder.String = if (resolved.@"linksection".toSlice(ip)) |section| s: {
1515 break :s try o.builder.string(section);1373 break :s try o.builder.string(section);
1516 } else .none;1374 } else .none;
...@@ -1519,13 +1377,20 @@ pub const Object = struct {...@@ -1519,13 +1377,20 @@ pub const Object = struct {
1519 // can see are extern functions or other comptime function body values (e.g. undefined). Of1377 // can see are extern functions or other comptime function body values (e.g. undefined). Of
1520 // these, only extern functions need to be lowered to LLVM functions.1378 // these, only extern functions need to be lowered to LLVM functions.
1521 if (opt_extern != null and nav_ty.zigTypeTag(zcu) == .@"fn" and nav_ty.fnHasRuntimeBits(zcu)) {1379 if (opt_extern != null and nav_ty.zigTypeTag(zcu) == .@"fn" and nav_ty.fnHasRuntimeBits(zcu)) {
1380 const fn_info = zcu.typeToFunc(nav_ty).?;
1522 const llvm_function: Builder.Function.Index = switch (llvm_global.ptrConst(&o.builder).kind) {1381 const llvm_function: Builder.Function.Index = switch (llvm_global.ptrConst(&o.builder).kind) {
1523 .function => |function| function, // re-use existing `Builder.Function`1382 .function => |function| function, // re-use existing `Builder.Function`
1524 .replaced, .alias, .variable => try llvm_global.toNewFunction(&o.builder),1383 .replaced, .alias, .variable => try llvm_global.toNewFunction(&o.builder),
1525 };1384 };
1526 llvm_function.setAlignment(llvm_align, &o.builder);1385 llvm_function.setAlignment(resolved.@"align".toLlvm(), &o.builder);
1527 llvm_function.setSection(llvm_section, &o.builder);1386 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);
1529 } else {1394 } else {
1530 const file_scope = nav.srcInst(ip).resolveFile(ip);1395 const file_scope = nav.srcInst(ip).resolveFile(ip);
1531 const mod = zcu.fileByIndex(file_scope).mod.?;1396 const mod = zcu.fileByIndex(file_scope).mod.?;
...@@ -1534,7 +1399,10 @@ pub const Object = struct {...@@ -1534,7 +1399,10 @@ pub const Object = struct {
1534 .variable => |variable| variable, // re-use existing `Builder.Variable`1399 .variable => |variable| variable, // re-use existing `Builder.Variable`
1535 .replaced, .alias, .function => try llvm_global.toNewVariable(&o.builder),1400 .replaced, .alias, .function => try llvm_global.toNewVariable(&o.builder),
1536 };1401 };
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);
1538 llvm_variable.setSection(llvm_section, &o.builder);1406 llvm_variable.setSection(llvm_section, &o.builder);
1539 llvm_variable.setMutability(if (resolved.@"const") .constant else .global, &o.builder);1407 llvm_variable.setMutability(if (resolved.@"const") .constant else .global, &o.builder);
1540 try llvm_variable.setInitializer(if (opt_extern != null) .no_init else try o.lowerValue(resolved.value, .in_memory), &o.builder);1408 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 {...@@ -1585,7 +1453,7 @@ pub const Object = struct {
1585 const uav_ty = Value.fromInterned(uav).typeOf(zcu);1453 const uav_ty = Value.fromInterned(uav).typeOf(zcu);
1586 const uav_ref = try o.lowerUavRef(1454 const uav_ref = try o.lowerUavRef(
1587 uav,1455 uav,
1588 uav_ty.abiAlignment(zcu),1456 uav_ty.abiAlignment(zcu).toLlvm(),
1589 target_util.defaultAddressSpace(zcu.getTarget(), .global_constant),1457 target_util.defaultAddressSpace(zcu.getTarget(), .global_constant),
1590 );1458 );
1591 break :exp .{ uav_ty, uav_ref };1459 break :exp .{ uav_ty, uav_ref };
...@@ -1599,7 +1467,7 @@ pub const Object = struct {...@@ -1599,7 +1467,7 @@ pub const Object = struct {
15991467
1600 fn updateExportedGlobal(1468 fn updateExportedGlobal(
1601 o: *Object,1469 o: *Object,
1602 global_index: Builder.Global.Index,1470 llvm_global: Builder.Global.Index,
1603 ty: Type,1471 ty: Type,
1604 export_indices: []const Zcu.Export.Index,1472 export_indices: []const Zcu.Export.Index,
1605 ) link.Error!void {1473 ) link.Error!void {
...@@ -1634,18 +1502,21 @@ pub const Object = struct {...@@ -1634,18 +1502,21 @@ pub const Object = struct {
1634 // make much sense: the linksection should be associated with the declaration itself rather1502 // make much sense: the linksection should be associated with the declaration itself rather
1635 // than some particular symbol it is exported as!1503 // than some particular symbol it is exported as!
1636 if (export_indices[0].ptr(zcu).opts.section.toSlice(ip)) |section_slice| {1504 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;
1638 variable.setSection(try o.builder.string(section_slice), &o.builder);1506 variable.setSection(try o.builder.string(section_slice), &o.builder);
1639 }1507 }
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
1643 // All exports are represented as aliases to the original global.1514 // All exports are represented as aliases to the original global.
16441515
1645 // TODO: we currently do not delete old exports. To do that we'll need to track which1516 // TODO: we currently do not delete old exports. To do that we'll need to track which
1646 // globals actually *are* exports.1517 // globals actually *are* exports.
16471518
1648 for (export_indices) |export_idx| {1519 for (export_indices, 0..) |export_idx, export_i| {
1649 const exp = export_idx.ptr(zcu);1520 const exp = export_idx.ptr(zcu);
1650 const exp_name = try o.builder.strtabString(exp.opts.name.toSlice(ip));1521 const exp_name = try o.builder.strtabString(exp.opts.name.toSlice(ip));
16511522
...@@ -1656,13 +1527,23 @@ pub const Object = struct {...@@ -1656,13 +1527,23 @@ pub const Object = struct {
1656 // The name, aliasee, and type will be set within this block. Other properties of the1527 // The name, aliasee, and type will be set within this block. Other properties of the
1657 // alias will be set below.1528 // alias will be set below.
1658 const alias_global: Builder.Global.Index = global: {1529 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
1659 const existing_global = o.builder.getGlobal(exp_name) orelse {1540 const existing_global = o.builder.getGlobal(exp_name) orelse {
1660 // There is no existing global with this name, so make a new alias.1541 // There is no existing global with this name, so make a new alias.
1661 const alias = try o.builder.addAlias(1542 const alias = try o.builder.addAlias(
1662 exp_name,1543 exp_name,
1663 llvm_global_ty,1544 llvm_global_ty,
1664 .default,1545 llvm_global.ptrConst(&o.builder).addr_space,
1665 global_index.toConst(),1546 llvm_global.toConst(),
1666 );1547 );
1667 break :global alias.ptrConst(&o.builder).global;1548 break :global alias.ptrConst(&o.builder).global;
1668 };1549 };
...@@ -1671,8 +1552,9 @@ pub const Object = struct {...@@ -1671,8 +1552,9 @@ pub const Object = struct {
1671 switch (existing_global.ptrConst(&o.builder).kind) {1552 switch (existing_global.ptrConst(&o.builder).kind) {
1672 .alias => |alias| {1553 .alias => |alias| {
1673 // We can just repurpose the existing alias.1554 // We can just repurpose the existing alias.
1674 alias.setAliasee(global_index.toConst(), &o.builder);1555 alias.setAliasee(llvm_global.toConst(), &o.builder);
1675 alias.ptrConst(&o.builder).global.ptr(&o.builder).type = global_index.typeOf(&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;
1676 break :global existing_global;1558 break :global existing_global;
1677 },1559 },
1678 .variable, .function => {1560 .variable, .function => {
...@@ -1682,13 +1564,13 @@ pub const Object = struct {...@@ -1682,13 +1564,13 @@ pub const Object = struct {
1682 // We need to make a new global which is an alias. Replace this existing one1564 // We need to make a new global which is an alias. Replace this existing one
1683 // with the target global, making the name available and fixing references1565 // with the target global, making the name available and fixing references
1684 // to this global to point to the target.1566 // 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);
1686 // The name is now free, so create an alias.1568 // The name is now free, so create an alias.
1687 const alias = try o.builder.addAlias(1569 const alias = try o.builder.addAlias(
1688 exp_name,1570 exp_name,
1689 llvm_global_ty,1571 llvm_global_ty,
1690 .default,1572 llvm_global.ptrConst(&o.builder).addr_space,
1691 global_index.toConst(),1573 llvm_global.toConst(),
1692 );1574 );
1693 break :global alias.ptrConst(&o.builder).global;1575 break :global alias.ptrConst(&o.builder).global;
1694 },1576 },
...@@ -1721,11 +1603,11 @@ pub const Object = struct {...@@ -1721,11 +1603,11 @@ pub const Object = struct {
1721 pub fn updateContainerType(o: *Object, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Allocator.Error!void {1603 pub fn updateContainerType(o: *Object, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Allocator.Error!void {
1722 _ = o.type_map.remove(ty);1604 _ = o.type_map.remove(ty);
1723 try o.type_pool.updateContainerType(pt, .{ .llvm = o }, ty, success);1605 try o.type_pool.updateContainerType(pt, .{ .llvm = o }, ty, success);
1724 if (o.named_enum_map.get(ty)) |function_index| {1606 if (o.named_enum_map.get(ty)) |llvm_function| {
1725 try o.updateIsNamedEnumValueFunction(.fromInterned(ty), function_index);1607 try o.updateIsNamedEnumValueFunction(.fromInterned(ty), llvm_function);
1726 }1608 }
1727 if (o.enum_tag_name_map.get(ty)) |function_index| {1609 if (o.enum_tag_name_map.get(ty)) |llvm_function| {
1728 try o.updateEnumTagNameFunction(.fromInterned(ty), function_index);1610 try o.updateEnumTagNameFunction(.fromInterned(ty), llvm_function);
1729 }1611 }
1730 }1612 }
17311613
...@@ -2098,7 +1980,7 @@ pub const Object = struct {...@@ -2098,7 +1980,7 @@ pub const Object = struct {
2098 payload_offset * 8,1980 payload_offset * 8,
2099 );1981 );
21001982
2101 return try o.builder.debugStructType(1983 return o.builder.debugStructType(
2102 name,1984 name,
2103 null, // File1985 null, // File
2104 o.debug_compile_unit.unwrap().?, // Scope1986 o.debug_compile_unit.unwrap().?, // Scope
...@@ -2136,7 +2018,7 @@ pub const Object = struct {...@@ -2136,7 +2018,7 @@ pub const Object = struct {
2136 defer debug_param_types.deinit(gpa);2018 defer debug_param_types.deinit(gpa);
21372019
2138 // Return type goes first.2020 // 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) {
2140 // Actual return type is void, then first arg is the sret pointer.2022 // Actual return type is void, then first arg is the sret pointer.
2141 const ptr_ty = try pt.singleMutPtrType(.fromInterned(fn_info.return_type));2023 const ptr_ty = try pt.singleMutPtrType(.fromInterned(fn_info.return_type));
2142 debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, .void));2024 debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, .void));
...@@ -2571,53 +2453,117 @@ pub const Object = struct {...@@ -2571,53 +2453,117 @@ pub const Object = struct {
2571 fn namespaceToDebugScope(o: *Object, pt: Zcu.PerThread, namespace_index: InternPool.NamespaceIndex) !Builder.Metadata {2453 fn namespaceToDebugScope(o: *Object, pt: Zcu.PerThread, namespace_index: InternPool.NamespaceIndex) !Builder.Metadata {
2572 const zcu = o.zcu;2454 const zcu = o.zcu;
2573 const namespace = zcu.namespacePtr(namespace_index);2455 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);
2575 return o.getDebugType(pt, .fromInterned(namespace.owner_type));2457 return o.getDebugType(pt, .fromInterned(namespace.owner_type));
2576 }2458 }
25772459
2578 /// Sets the attributes and callconv of the given `Builder.Function`, which corresponds to the2460 fn addCommonFnAttributes(
2579 /// given `Nav` (which is a function).2461 o: *Object,
2580 fn addLlvmFunctionAttributes(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(
2581 o: *Object,2531 o: *Object,
2582 pt: Zcu.PerThread,2532 pt: Zcu.PerThread,
2583 nav_id: InternPool.Nav.Index,2533 llvm_function: Builder.Function.Index,
2584 function_index: 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,
2585 ) Allocator.Error!void {2540 ) Allocator.Error!void {
2586 const zcu = o.zcu;2541 const zcu = o.zcu;
2587 const ip = &zcu.intern_pool;2542 const target = zcu.getTarget();
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;
25942543
2595 var attributes: Builder.FunctionAttributes.Wip = .{};2544 if (fn_info.cc == .async) {
2596 defer attributes.deinit(&o.builder);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"| {
2599 try attributes.addFnAttr(.{ .string = .{2549 try attributes.addFnAttr(.{ .string = .{
2600 .kind = try o.builder.string("wasm-import-name"),2550 .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),
2602 } }, &o.builder);2552 } }, &o.builder);
2603 if (@"extern".lib_name.toSlice(ip)) |lib_name_slice| {2553 if (@"extern".lib_name) |lib_name| {
2604 if (!std.mem.eql(u8, lib_name_slice, "c")) try attributes.addFnAttr(.{ .string = .{2554 if (!std.mem.eql(u8, lib_name, "c")) try attributes.addFnAttr(.{ .string = .{
2605 .kind = try o.builder.string("wasm-import-module"),2555 .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),
2607 } }, &o.builder);2557 } }, &o.builder);
2608 }2558 }
2609 };2559 };
26102560
2611 if (fn_info.cc == .async) {
2612 @panic("TODO: LLVM backend lower async function");
2613 }
2614
2615 const cc_info = toLlvmCallConv(fn_info.cc, target).?;2561 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
2619 if (cc_info.align_stack) {2565 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);
2621 }2567 }
26222568
2623 if (cc_info.naked) {2569 if (cc_info.naked) {
...@@ -2668,29 +2614,16 @@ pub const Object = struct {...@@ -2668,29 +2614,16 @@ pub const Object = struct {
2668 else => {},2614 else => {},
2669 }2615 }
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
2684 if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder);2617 if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder);
26852618
2686 var it = iterateParamTypes(o, fn_info);2619 var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types);
2687 if (try fnReturnStrat(o, fn_info) == .sret) {2620 if (try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type)) == .sret) {
2688 // Sret pointers must not be address 02621 try o.addSRetFnAttributes(
2689 try attributes.addParamAttr(it.llvm_index, .nonnull, &o.builder);2622 attributes,
2690 try attributes.addParamAttr(it.llvm_index, .@"noalias", &o.builder);2623 try o.lowerType(.fromInterned(fn_info.return_type), .in_memory),
26912624 Type.fromInterned(fn_info.return_type).abiAlignment(zcu).toLlvm(),
2692 const raw_llvm_ret_ty = try o.lowerType(.fromInterned(fn_info.return_type), .in_memory);2625 .declaration,
2693 try attributes.addParamAttr(it.llvm_index, .{ .sret = raw_llvm_ret_ty }, &o.builder);2626 );
2694 it.llvm_index += 1;2627 it.llvm_index += 1;
2695 } else if (ccAbiPromoteInt(fn_info.cc, zcu, Type.fromInterned(fn_info.return_type))) |s| switch (s) {2628 } else if (ccAbiPromoteInt(fn_info.cc, zcu, Type.fromInterned(fn_info.return_type))) |s| switch (s) {
2696 .signed => try attributes.addRetAttr(.signext, &o.builder),2629 .signed => try attributes.addRetAttr(.signext, &o.builder),
...@@ -2709,9 +2642,9 @@ pub const Object = struct {...@@ -2709,9 +2642,9 @@ pub const Object = struct {
2709 while (try it.next()) |lowering| switch (lowering) {2642 while (try it.next()) |lowering| switch (lowering) {
2710 .byval => {2643 .byval => {
2711 const param_index = it.zig_index - 1;2644 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]);
2713 if (!isByRef(param_ty, zcu)) {2646 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);
2715 }2648 }
27162649
2717 if (remaining_inreg_int > 0 and2650 if (remaining_inreg_int > 0 and
...@@ -2730,12 +2663,12 @@ pub const Object = struct {...@@ -2730,12 +2663,12 @@ pub const Object = struct {
2730 }2663 }
2731 },2664 },
2732 .byref => {2665 .byref => {
2733 const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);2666 const param_ty: Type = .fromInterned(fn_info.param_types[it.zig_index - 1]);
2734 try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, it.byval_attr, param_ty);2667 try o.addByRefParamAttrs(attributes, it.llvm_index - 1, it.byval_attr, param_ty);
2735 },2668 },
2736 .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder),2669 .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder),
2737 .slice => {2670 .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]);
2739 const ptr_info = param_ty.ptrInfo(zcu);2672 const ptr_info = param_ty.ptrInfo(zcu);
2740 const llvm_ptr_index = it.llvm_index - 2;2673 const llvm_ptr_index = it.llvm_index - 2;
2741 if (std.math.cast(u5, it.zig_index - 1)) |i| {2674 if (std.math.cast(u5, it.zig_index - 1)) |i| {
...@@ -2767,94 +2700,205 @@ pub const Object = struct {...@@ -2767,94 +2700,205 @@ pub const Object = struct {
2767 .i64_array,2700 .i64_array,
2768 => continue,2701 => continue,
2769 };2702 };
2770
2771 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
2772 }2703 }
27732704
2774 fn addCommonFnAttributes(2705 pub fn addSRetFnAttributes(
2775 o: *Object,2706 o: *Object,
2776 attributes: *Builder.FunctionAttributes.Wip,2707 attributes: *Builder.FunctionAttributes.Wip,
2777 owner_mod: *Module,2708 ret_ty: Builder.Type,
2778 omit_frame_pointer: bool,2709 ret_align: Builder.Alignment,
2710 location: enum { declaration, callsite },
2779 ) Allocator.Error!void {2711 ) Allocator.Error!void {
2780 if (!owner_mod.red_zone) {2712 try attributes.addParamAttr(0, .dead_on_unwind, &o.builder);
2781 try attributes.addFnAttr(.noredzone, &o.builder);2713 switch (location) {
2782 }2714 .declaration => try attributes.addParamAttr(0, .@"noalias", &o.builder),
2783 if (omit_frame_pointer) {2715 .callsite => {},
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);
2841 }2716 }
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);
2842 }2721 }
28432722
2844 pub const TypeRepr = enum {2723 pub const TypeRepr = enum {
2845 /// The representation of the type when it is being manipulated as a value in a function.2724 /// The representation of the type when it is being manipulated as a value in a function.
2846 /// e.g. Zig `u5` -> LLVM `i5`2725 /// e.g. Zig `u90` -> LLVM `i90`
2847 by_value,2726 as_value,
2848 /// The representation of the type when it is stored in memory.2727 /// The representation of the type when it is loaded from or stored to memory.
2849 /// e.g. Zig `u5` -> LLVM `i8`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]`
2850 in_memory,2732 in_memory,
2851 };2733 };
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
2853 pub fn errorIntType(o: *Object, repr: TypeRepr) Allocator.Error!Builder.Type {2755 pub fn errorIntType(o: *Object, repr: TypeRepr) Allocator.Error!Builder.Type {
2854 return o.builder.intType(switch (repr) {2756 return o.intType(o.zcu.errorSetBits(), repr);
2855 .by_value => o.zcu.errorSetBits(),2757 }
2856 .in_memory => @intCast(Type.anyerror.abiSize(o.zcu) * 8),2758
2857 });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;
2858 }2902 }
28592903
2860 pub fn lowerType(o: *Object, t: Type, repr: TypeRepr) Allocator.Error!Builder.Type {2904 pub fn lowerType(o: *Object, t: Type, repr: TypeRepr) Allocator.Error!Builder.Type {
...@@ -2862,42 +2906,31 @@ pub const Object = struct {...@@ -2862,42 +2906,31 @@ pub const Object = struct {
2862 const target = zcu.getTarget();2906 const target = zcu.getTarget();
2863 const ip = &zcu.intern_pool;2907 const ip = &zcu.intern_pool;
28642908
2865 if (repr == .by_value) {2909 switch (repr) {
2866 assert(!isByRef(t, zcu)); // by-ref types must only be manipulated in memory2910 .as_value => assert(!isByRef(t, zcu)), // by-ref types must only be manipulated in memory
2911 .memory_access, .in_memory => {},
2867 }2912 }
28682913
2869 return switch (t.toIntern()) {2914 return switch (t.toIntern()) {
2870 .u0_type => unreachable, // no runtime bits2915 .u0_type => unreachable, // no runtime bits
2871 inline .u1_type,2916 .u1_type, .bool_type => try o.intType(1, repr),
2872 .u8_type,2917 .u8_type, .i8_type => try o.intType(8, repr),
2873 .i8_type,2918 .u16_type, .i16_type => try o.intType(16, repr),
2874 .u16_type,2919 .u29_type => try o.intType(29, repr),
2875 .i16_type,2920 .u32_type, .i32_type => try o.intType(32, repr),
2876 .u29_type,2921 .u64_type, .i64_type => try o.intType(64, repr),
2877 .u32_type,2922 .u80_type => try o.intType(80, repr),
2878 .i32_type,2923 .u128_type, .i128_type => try o.intType(128, repr),
2879 .u64_type,2924 .usize_type, .isize_type => try o.intType(target.ptrBitWidth(), repr),
2880 .i64_type,2925 .c_char_type => try o.intType(target.cTypeBitSize(.char).?, repr),
2881 .u80_type,2926 .c_short_type => try o.intType(target.cTypeBitSize(.short).?, repr),
2882 .u128_type,2927 .c_ushort_type => try o.intType(target.cTypeBitSize(.ushort).?, repr),
2883 .i128_type,2928 .c_int_type => try o.intType(target.cTypeBitSize(.int).?, repr),
2884 => |tag| switch (repr) {2929 .c_uint_type => try o.intType(target.cTypeBitSize(.uint).?, repr),
2885 .by_value => @field(Builder.Type, "i" ++ @tagName(tag)[1 .. @tagName(tag).len - "_type".len]),2930 .c_long_type => try o.intType(target.cTypeBitSize(.long).?, repr),
2886 .in_memory => try o.builder.intType(@intCast(t.abiSize(zcu) * 8)),2931 .c_ulong_type => try o.intType(target.cTypeBitSize(.ulong).?, repr),
2887 },2932 .c_longlong_type => try o.intType(target.cTypeBitSize(.longlong).?, repr),
2888 .usize_type, .isize_type => try o.builder.intType(target.ptrBitWidth()),2933 .c_ulonglong_type => try o.intType(target.cTypeBitSize(.ulonglong).?, repr),
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 )),
2901 .c_longdouble_type,2934 .c_longdouble_type,
2902 .f16_type,2935 .f16_type,
2903 .f32_type,2936 .f32_type,
...@@ -2905,11 +2938,44 @@ pub const Object = struct {...@@ -2905,11 +2938,44 @@ pub const Object = struct {
2905 .f80_type,2938 .f80_type,
2906 .f128_type,2939 .f128_type,
2907 => switch (t.floatBits(target)) {2940 => switch (t.floatBits(target)) {
2908 16 => if (backendSupportsF16(target)) .half else .i16,2941 16 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) {
2909 32 => .float,2942 .hard => .half,
2910 64 => .double,2943 .soft => .i16,
2911 80 => if (backendSupportsF80(target)) .x86_fp80 else .i80,2944 },
2912 128 => .fp128,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 },
2913 else => unreachable,2979 else => unreachable,
2914 },2980 },
2915 .anyopaque_type => {2981 .anyopaque_type => {
...@@ -2918,7 +2984,6 @@ pub const Object = struct {...@@ -2918,7 +2984,6 @@ pub const Object = struct {
2918 // @foo = external global i82984 // @foo = external global i8
2919 return .i8;2985 return .i8;
2920 },2986 },
2921 .bool_type => .i1,
2922 .anyerror_type => try o.errorIntType(repr),2987 .anyerror_type => try o.errorIntType(repr),
2923 .void_type => unreachable, // no runtime bits2988 .void_type => unreachable, // no runtime bits
2924 .type_type => unreachable, // no runtime bits2989 .type_type => unreachable, // no runtime bits
...@@ -2968,10 +3033,7 @@ pub const Object = struct {...@@ -2968,10 +3033,7 @@ pub const Object = struct {
2968 .none,3033 .none,
2969 => unreachable,3034 => unreachable,
2970 else => switch (ip.indexToKey(t.toIntern())) {3035 else => switch (ip.indexToKey(t.toIntern())) {
2971 .int_type => |int_type| switch (repr) {3036 .int_type => |int_type| o.intType(int_type.bits, repr),
2972 .by_value => try o.builder.intType(int_type.bits),
2973 .in_memory => try o.builder.intType(@intCast(t.abiSize(zcu) * 8)),
2974 },
2975 .ptr_type => |ptr_type| type: {3037 .ptr_type => |ptr_type| type: {
2976 const ptr_ty = try o.builder.ptrType(3038 const ptr_ty = try o.builder.ptrType(
2977 toLlvmAddressSpace(ptr_type.flags.address_space, target),3039 toLlvmAddressSpace(ptr_type.flags.address_space, target),
...@@ -2988,11 +3050,13 @@ pub const Object = struct {...@@ -2988,11 +3050,13 @@ pub const Object = struct {
2988 array_type.lenIncludingSentinel(),3050 array_type.lenIncludingSentinel(),
2989 try o.lowerType(.fromInterned(array_type.child), repr),3051 try o.lowerType(.fromInterned(array_type.child), repr),
2990 ),3052 ),
2991 .vector_type => |vector_type| o.builder.vectorType(3053 .vector_type => |vector_type| if (isByRef(t, zcu)) {
2992 .normal,3054 const child_llvm_ty = try o.lowerType(.fromInterned(vector_type.child), repr);
2993 vector_type.len,3055 return o.builder.arrayType(vector_type.len, child_llvm_ty);
2994 try o.lowerType(.fromInterned(vector_type.child), .by_value),3056 } else {
2995 ),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 },
2996 .opt_type => |child_ty| {3060 .opt_type => |child_ty| {
2997 // Must stay in sync with `opt_payload` logic in `lowerPtr`.3061 // Must stay in sync with `opt_payload` logic in `lowerPtr`.
2998 switch (Type.fromInterned(child_ty).classify(zcu)) {3062 switch (Type.fromInterned(child_ty).classify(zcu)) {
...@@ -3252,8 +3316,11 @@ pub const Object = struct {...@@ -3252,8 +3316,11 @@ pub const Object = struct {
3252 return ty;3316 return ty;
3253 },3317 },
3254 .opaque_type, .spirv_type => unreachable, // no runtime bits3318 .opaque_type, .spirv_type => unreachable, // no runtime bits
3255 .enum_type => try o.lowerType(t.backingIntType(zcu), repr),3319 .enum_type => try o.intType(t.backingIntType(zcu).intInfo(zcu).bits, repr),
3256 .func_type => |func_type| try o.lowerFnType(t, func_type),3320 .func_type => |func_type| {
3321 assert(t.fnHasRuntimeBits(zcu));
3322 return o.lowerFnType(.fromIntern(func_type, ip));
3323 },
3257 .error_set_type, .inferred_error_set_type => try o.errorIntType(repr),3324 .error_set_type, .inferred_error_set_type => try o.errorIntType(repr),
3258 // values, not types3325 // values, not types
3259 .undef,3326 .undef,
...@@ -3279,14 +3346,28 @@ pub const Object = struct {...@@ -3279,14 +3346,28 @@ pub const Object = struct {
3279 };3346 };
3280 }3347 }
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 {
3283 const zcu = o.zcu;3367 const zcu = o.zcu;
3284 const ip = &zcu.intern_pool;
3285 const target = zcu.getTarget();3368 const target = zcu.getTarget();
32863369
3287 assert(fn_ty.fnHasRuntimeBits(zcu));3370 const ret_strat = try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type));
3288
3289 const ret_strat = try fnReturnStrat(o, fn_info);
32903371
3291 var llvm_params: std.ArrayList(Builder.Type) = .empty;3372 var llvm_params: std.ArrayList(Builder.Type) = .empty;
3292 defer llvm_params.deinit(o.gpa);3373 defer llvm_params.deinit(o.gpa);
...@@ -3301,35 +3382,35 @@ pub const Object = struct {...@@ -3301,35 +3382,35 @@ pub const Object = struct {
3301 try llvm_params.append(o.gpa, llvm_ptr_ty);3382 try llvm_params.append(o.gpa, llvm_ptr_ty);
3302 }3383 }
33033384
3304 var it = iterateParamTypes(o, fn_info);3385 var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types);
3305 while (try it.next()) |lowering| switch (lowering) {3386 while (try it.next()) |lowering| switch (lowering) {
3306 .no_bits => continue,3387 .no_bits => continue,
3307 .byval => {3388 .byval => {
3308 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);3389 const param_ty = Type.fromInterned(fn_info.param_types[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));3390 try llvm_params.append(o.gpa, try o.lowerType(param_ty, if (isByRef(param_ty, zcu)) .memory_access else .as_value));
3310 },3391 },
3311 .byref, .byref_mut => {3392 .byref, .byref_mut => {
3312 try llvm_params.append(o.gpa, .ptr);3393 try llvm_params.append(o.gpa, .ptr);
3313 },3394 },
3314 .abi_sized_int => {3395 .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]);
3316 try llvm_params.append(o.gpa, try o.builder.intType(3397 try llvm_params.append(o.gpa, try o.builder.intType(
3317 @intCast(param_ty.abiSize(zcu) * 8),3398 @intCast(param_ty.abiSize(zcu) * 8),
3318 ));3399 ));
3319 },3400 },
3320 .slice => {3401 .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]);
3322 try llvm_params.appendSlice(o.gpa, &.{3403 try llvm_params.appendSlice(o.gpa, &.{
3323 try o.builder.ptrType(toLlvmAddressSpace(param_ty.ptrAddressSpace(zcu), target)),3404 try o.builder.ptrType(toLlvmAddressSpace(param_ty.ptrAddressSpace(zcu), target)),
3324 try o.lowerType(.usize, .by_value),3405 try o.lowerType(.usize, .as_value),
3325 });3406 });
3326 },3407 },
3327 .multiple_llvm_types => {3408 .multiple_llvm_types => {
3328 try llvm_params.appendSlice(o.gpa, it.types_buffer[0..it.types_len]);3409 try llvm_params.appendSlice(o.gpa, it.types_buffer[0..it.types_len]);
3329 },3410 },
3330 .float_array => |count| {3411 .float_array => |count| {
3331 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);3412 const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]);
3332 const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, zcu).?, .in_memory);3413 const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, zcu).?, .memory_access);
3333 try llvm_params.append(o.gpa, try o.builder.arrayType(count, float_ty));3414 try llvm_params.append(o.gpa, try o.builder.arrayType(count, float_ty));
3334 },3415 },
3335 .i32_array, .i64_array => |arr_len| {3416 .i32_array, .i64_array => |arr_len| {
...@@ -3343,7 +3424,7 @@ pub const Object = struct {...@@ -3343,7 +3424,7 @@ pub const Object = struct {
33433424
3344 const llvm_ret_ty: Builder.Type = switch (ret_strat) {3425 const llvm_ret_ty: Builder.Type = switch (ret_strat) {
3345 .void, .sret => .void,3426 .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),
3347 .mem_cast => |llvm_ret_ty| llvm_ret_ty,3428 .mem_cast => |llvm_ret_ty| llvm_ret_ty,
3348 };3429 };
3349 const llvm_fn_kind: Builder.Type.Function.Kind = switch (fn_info.is_var_args) {3430 const llvm_fn_kind: Builder.Type.Function.Kind = switch (fn_info.is_var_args) {
...@@ -3391,8 +3472,14 @@ pub const Object = struct {...@@ -3391,8 +3472,14 @@ pub const Object = struct {
3391 .null => unreachable, // non-runtime value3472 .null => unreachable, // non-runtime value
3392 .@"unreachable" => unreachable, // non-runtime value3473 .@"unreachable" => unreachable, // non-runtime value
33933474
3394 .false => .false,3475 .false => switch (repr) {
3395 .true => .true,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 },
3396 },3483 },
3397 .enum_literal => unreachable, // non-runtime value3484 .enum_literal => unreachable, // non-runtime value
3398 .@"extern" => unreachable, // non-runtime value3485 .@"extern" => unreachable, // non-runtime value
...@@ -3401,7 +3488,12 @@ pub const Object = struct {...@@ -3401,7 +3488,12 @@ pub const Object = struct {
3401 var bigint_space: Value.BigIntSpace = undefined;3488 var bigint_space: Value.BigIntSpace = undefined;
3402 const bigint = val.toBigInt(&bigint_space, zcu);3489 const bigint = val.toBigInt(&bigint_space, zcu);
3403 const llvm_int_ty = try o.lowerType(ty, repr);3490 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));
3405 },3497 },
3406 .err => |err| {3498 .err => |err| {
3407 const int = zcu.intern_pool.getErrorValueIfExists(err.name).?;3499 const int = zcu.intern_pool.getErrorValueIfExists(err.name).?;
...@@ -3456,18 +3548,12 @@ pub const Object = struct {...@@ -3456,18 +3548,12 @@ pub const Object = struct {
3456 },3548 },
3457 .enum_tag => |enum_tag| o.lowerValue(enum_tag.int, repr),3549 .enum_tag => |enum_tag| o.lowerValue(enum_tag.int, repr),
3458 .float => switch (ty.floatBits(target)) {3550 .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)),
3470 else => unreachable,3551 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)),
3471 },3557 },
3472 .ptr => try o.lowerPtr(arg_val, 0),3558 .ptr => try o.lowerPtr(arg_val, 0),
3473 .slice => |slice| return o.builder.structConst(try o.lowerType(ty, repr), &.{3559 .slice => |slice| return o.builder.structConst(try o.lowerType(ty, repr), &.{
...@@ -3586,12 +3672,13 @@ pub const Object = struct {...@@ -3586,12 +3672,13 @@ pub const Object = struct {
3586 },3672 },
3587 .vector_type => |vector_type| {3673 .vector_type => |vector_type| {
3588 const vector_ty = try o.lowerType(ty, repr);3674 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);
3589 switch (aggregate.storage) {3680 switch (aggregate.storage) {
3590 .bytes, .elems => {3681 .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();
3595 const vals = try allocator.alloc(Builder.Constant, vector_type.len);3682 const vals = try allocator.alloc(Builder.Constant, vector_type.len);
3596 defer allocator.free(vals);3683 defer allocator.free(vals);
35973684
...@@ -3600,16 +3687,21 @@ pub const Object = struct {...@@ -3600,16 +3687,21 @@ pub const Object = struct {
3600 result_val.* = try o.builder.intConst(.i8, byte);3687 result_val.* = try o.builder.intConst(.i8, byte);
3601 },3688 },
3602 .elems => |elems| for (vals, elems) |*result_val, elem| {3689 .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);
3604 },3691 },
3605 .repeated_elem => unreachable,3692 .repeated_elem => unreachable,
3606 }3693 }
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);
3608 },3698 },
3609 .repeated_elem => |elem| return o.builder.splatConst(3699 .repeated_elem => |elem| if (is_by_ref) {
3610 vector_ty,3700 const vals = try allocator.alloc(Builder.Constant, vector_type.len);
3611 try o.lowerValue(elem, .by_value),3701 defer allocator.free(vals);
3612 ),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)),
3613 }3705 }
3614 },3706 },
3615 .tuple_type => |tuple| {3707 .tuple_type => |tuple| {
...@@ -3837,6 +3929,117 @@ pub const Object = struct {...@@ -3837,6 +3929,117 @@ pub const Object = struct {
3837 };3929 };
3838 }3930 }
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
3840 fn lowerPtr(4043 fn lowerPtr(
3841 o: *Object,4044 o: *Object,
3842 ptr_val: InternPool.Index,4045 ptr_val: InternPool.Index,
...@@ -3856,7 +4059,7 @@ pub const Object = struct {...@@ -3856,7 +4059,7 @@ pub const Object = struct {
3856 const orig_ptr_ty: Type = .fromInterned(uav.orig_ty);4059 const orig_ptr_ty: Type = .fromInterned(uav.orig_ty);
3857 const base_ptr = try o.lowerUavRef(4060 const base_ptr = try o.lowerUavRef(
3858 uav.val,4061 uav.val,
3859 orig_ptr_ty.ptrAlignment(zcu),4062 orig_ptr_ty.ptrAlignment(zcu).toLlvm(),
3860 orig_ptr_ty.ptrAddressSpace(zcu),4063 orig_ptr_ty.ptrAddressSpace(zcu),
3861 );4064 );
3862 return o.builder.gepConst(.inbounds, .i8, base_ptr, null, &.{4065 return o.builder.gepConst(.inbounds, .i8, base_ptr, null, &.{
...@@ -3865,8 +4068,8 @@ pub const Object = struct {...@@ -3865,8 +4068,8 @@ pub const Object = struct {
3865 },4068 },
3866 .int => try o.builder.castConst(4069 .int => try o.builder.castConst(
3867 .inttoptr,4070 .inttoptr,
3868 try o.builder.intConst(try o.lowerType(.usize, .by_value), offset),4071 try o.builder.intConst(try o.lowerType(.usize, .as_value), offset),
3869 try o.lowerType(.fromInterned(ptr.ty), .by_value),4072 try o.lowerType(.fromInterned(ptr.ty), .as_value),
3870 ),4073 ),
3871 .eu_payload => |eu_ptr| try o.lowerPtr(4074 .eu_payload => |eu_ptr| try o.lowerPtr(
3872 eu_ptr,4075 eu_ptr,
...@@ -3908,12 +4111,12 @@ pub const Object = struct {...@@ -3908,12 +4111,12 @@ pub const Object = struct {
39084111
3909 pub fn lowerPtrToVoid(4112 pub fn lowerPtrToVoid(
3910 o: *Object,4113 o: *Object,
3911 /// Must not be `.none`.4114 /// Must not be `.default`.
3912 @"align": InternPool.Alignment,4115 @"align": Builder.Alignment,
3913 @"addrspace": std.lang.AddressSpace,4116 @"addrspace": std.lang.AddressSpace,
3914 ) Allocator.Error!Builder.Constant {4117 ) Allocator.Error!Builder.Constant {
3915 const addr: u64 = @"align".toByteUnits().?;4118 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);
3917 const llvm_addr = try o.builder.intConst(llvm_usize, addr);4120 const llvm_addr = try o.builder.intConst(llvm_usize, addr);
3918 const llvm_ptr_ty = try o.builder.ptrType(toLlvmAddressSpace(@"addrspace", o.zcu.getTarget()));4121 const llvm_ptr_ty = try o.builder.ptrType(toLlvmAddressSpace(@"addrspace", o.zcu.getTarget()));
3919 return o.builder.castConst(.inttoptr, llvm_addr, llvm_ptr_ty);4122 return o.builder.castConst(.inttoptr, llvm_addr, llvm_ptr_ty);
...@@ -3922,11 +4125,11 @@ pub const Object = struct {...@@ -3922,11 +4125,11 @@ pub const Object = struct {
3922 pub fn lowerUavRef(4125 pub fn lowerUavRef(
3923 o: *Object,4126 o: *Object,
3924 uav_val: InternPool.Index,4127 uav_val: InternPool.Index,
3925 /// Must not be `.none`.4128 /// Must not be `.default`.
3926 @"align": InternPool.Alignment,4129 @"align": Builder.Alignment,
3927 @"addrspace": std.lang.AddressSpace,4130 @"addrspace": std.lang.AddressSpace,
3928 ) Allocator.Error!Builder.Constant {4131 ) Allocator.Error!Builder.Constant {
3929 assert(@"align" != .none);4132 assert(@"align" != .default);
39304133
3931 const zcu = o.zcu;4134 const zcu = o.zcu;
3932 const ip = &zcu.intern_pool;4135 const ip = &zcu.intern_pool;
...@@ -3951,19 +4154,18 @@ pub const Object = struct {...@@ -3951,19 +4154,18 @@ pub const Object = struct {
3951 // Keep the greater of the two alignments.4154 // Keep the greater of the two alignments.
3952 const llvm_variable = gop.value_ptr.*;4155 const llvm_variable = gop.value_ptr.*;
3953 const llvm_old_align = llvm_variable.getAlignment(&o.builder);4156 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");
3955 llvm_variable.setAlignment(llvm_new_align, &o.builder);4158 llvm_variable.setAlignment(llvm_new_align, &o.builder);
3956 return llvm_variable.ptrConst(&o.builder).global.toConst();4159 return llvm_variable.ptrConst(&o.builder).global.toConst();
3957 }4160 }
3958 errdefer assert(o.uav_map.remove(.{ .val = uav_val, .@"addrspace" = @"addrspace" }));4161 errdefer assert(o.uav_map.remove(.{ .val = uav_val, .@"addrspace" = @"addrspace" }));
39594162
3960 const llvm_ty = try o.lowerType(uav_ty, .in_memory);
3961 const llvm_name = try o.builder.strtabStringFmt("__anon_{d}", .{@backingInt(uav_val)});4163 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);
3963 gop.value_ptr.* = llvm_variable;4165 gop.value_ptr.* = llvm_variable;
3964 try llvm_variable.setInitializer(try o.lowerValue(uav_val, .in_memory), &o.builder);4166 try llvm_variable.setInitializer(try o.lowerValue(uav_val, .in_memory), &o.builder);
3965 llvm_variable.setMutability(.constant, &o.builder);4167 llvm_variable.setMutability(.constant, &o.builder);
3966 llvm_variable.setAlignment(@"align".toLlvm(), &o.builder);4168 llvm_variable.setAlignment(@"align", &o.builder);
3967 const llvm_global = llvm_variable.ptrConst(&o.builder).global;4169 const llvm_global = llvm_variable.ptrConst(&o.builder).global;
3968 llvm_global.setLinkage(if (o.builder.strip) .private else .internal, &o.builder);4170 llvm_global.setLinkage(if (o.builder.strip) .private else .internal, &o.builder);
3969 llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder);4171 llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder);
...@@ -3982,7 +4184,7 @@ pub const Object = struct {...@@ -3982,7 +4184,7 @@ pub const Object = struct {
3982 .none => nav_ty.abiAlignment(zcu),4184 .none => nav_ty.abiAlignment(zcu),
3983 else => |a| a,4185 else => |a| a,
3984 };4186 };
3985 return o.lowerPtrToVoid(nav_align, nav.resolved.?.@"addrspace");4187 return o.lowerPtrToVoid(nav_align.toLlvm(), nav.resolved.?.@"addrspace");
3986 }4188 }
39874189
3988 const gop = try o.nav_map.getOrPut(gpa, nav_id);4190 const gop = try o.nav_map.getOrPut(gpa, nav_id);
...@@ -4011,7 +4213,7 @@ pub const Object = struct {...@@ -4011,7 +4213,7 @@ pub const Object = struct {
4011 attributes: *Builder.FunctionAttributes.Wip,4213 attributes: *Builder.FunctionAttributes.Wip,
4012 param_ty: Type,4214 param_ty: Type,
4013 param_index: u32,4215 param_index: u32,
4014 fn_info: InternPool.Key.FuncType,4216 fn_info: FuncInfo,
4015 llvm_arg_i: u32,4217 llvm_arg_i: u32,
4016 ) Allocator.Error!void {4218 ) Allocator.Error!void {
4017 const zcu = o.zcu;4219 const zcu = o.zcu;
...@@ -4051,19 +4253,26 @@ pub const Object = struct {...@@ -4051,19 +4253,26 @@ pub const Object = struct {
4051 };4253 };
4052 }4254 }
40534255
4256 pub const Byval = struct { alignment: InternPool.Alignment = .none };
4054 pub fn addByRefParamAttrs(4257 pub fn addByRefParamAttrs(
4055 o: *Object,4258 o: *Object,
4056 attributes: *Builder.FunctionAttributes.Wip,4259 attributes: *Builder.FunctionAttributes.Wip,
4057 llvm_arg_i: u32,4260 llvm_arg_i: u32,
4058 byval: bool,4261 maybe_byval: ?Byval,
4059 param_ty: Type,4262 param_ty: Type,
4060 ) Allocator.Error!void {4263 ) Allocator.Error!void {
4061 const llvm_param_ty = try o.lowerType(param_ty, .in_memory);4264 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);
4064 try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);4265 try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);
4065 try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = .wrap(alignment) }, &o.builder);4266 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
4066 if (byval) try attributes.addParamAttr(llvm_arg_i, .{ .byval = llvm_param_ty }, &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);
4067 }4276 }
40684277
4069 pub fn getErrorNameTable(o: *Object) Allocator.Error!Builder.Variable.Index {4278 pub fn getErrorNameTable(o: *Object) Allocator.Error!Builder.Variable.Index {
...@@ -4071,18 +4280,18 @@ pub const Object = struct {...@@ -4071,18 +4280,18 @@ pub const Object = struct {
40714280
4072 const name = try o.builder.strtabString("__zig_error_name_table");4281 const name = try o.builder.strtabString("__zig_error_name_table");
4073 // TODO: Address space4282 // TODO: Address space
4074 const variable_index = try o.builder.addVariable(name, .ptr, .default);4283 const llvm_variable = try o.builder.addVariable(name, .ptr, .default);
4075 variable_index.setMutability(.constant, &o.builder);4284 llvm_variable.setMutability(.constant, &o.builder);
4076 variable_index.setAlignment(4285 llvm_variable.setAlignment(
4077 Type.slice_const_u8_sentinel_0.abiAlignment(o.zcu).toLlvm(),4286 Type.slice_const_u8_sentinel_0.abiAlignment(o.zcu).toLlvm(),
4078 &o.builder,4287 &o.builder,
4079 );4288 );
4080 const global_index = variable_index.ptrConst(&o.builder).global;4289 const llvm_global = llvm_variable.ptrConst(&o.builder).global;
4081 global_index.setLinkage(.private, &o.builder);4290 llvm_global.setLinkage(.private, &o.builder);
4082 global_index.setUnnamedAddr(.unnamed_addr, &o.builder);4291 llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder);
40834292
4084 o.error_name_table = variable_index;4293 o.error_name_table = llvm_variable;
4085 return variable_index;4294 return llvm_variable;
4086 }4295 }
40874296
4088 pub fn getErrorsLen(o: *Object) Allocator.Error!Builder.Variable.Index {4297 pub fn getErrorsLen(o: *Object) Allocator.Error!Builder.Variable.Index {
...@@ -4090,13 +4299,13 @@ pub const Object = struct {...@@ -4090,13 +4299,13 @@ pub const Object = struct {
4090 if (o.errors_len_variable == .none) {4299 if (o.errors_len_variable == .none) {
4091 const llvm_err_int_ty = try o.errorIntType(.in_memory);4300 const llvm_err_int_ty = try o.errorIntType(.in_memory);
4092 const name = try builder.strtabString("__zig_errors_len");4301 const name = try builder.strtabString("__zig_errors_len");
4093 const variable_index = try builder.addVariable(name, llvm_err_int_ty, .default);4302 const llvm_variable = try builder.addVariable(name, llvm_err_int_ty, .default);
4094 variable_index.setMutability(.constant, builder);4303 llvm_variable.setMutability(.constant, builder);
4095 variable_index.setAlignment(Type.errorAbiAlignment(o.zcu).toLlvm(), builder);4304 llvm_variable.setAlignment(Type.errorAbiAlignment(o.zcu).toLlvm(), builder);
4096 const global_index = variable_index.ptrConst(&o.builder).global;4305 const llvm_global = llvm_variable.ptrConst(&o.builder).global;
4097 global_index.setLinkage(.private, builder);4306 llvm_global.setLinkage(.private, builder);
4098 global_index.setUnnamedAddr(.unnamed_addr, builder);4307 llvm_global.setUnnamedAddr(.unnamed_addr, builder);
4099 o.errors_len_variable = variable_index;4308 o.errors_len_variable = llvm_variable;
4100 }4309 }
4101 return o.errors_len_variable;4310 return o.errors_len_variable;
4102 }4311 }
...@@ -4108,43 +4317,43 @@ pub const Object = struct {...@@ -4108,43 +4317,43 @@ pub const Object = struct {
4108 const gop = try o.enum_tag_name_map.getOrPut(o.gpa, enum_ty.toIntern());4317 const gop = try o.enum_tag_name_map.getOrPut(o.gpa, enum_ty.toIntern());
4109 if (gop.found_existing) return gop.value_ptr.*;4318 if (gop.found_existing) return gop.value_ptr.*;
4110 errdefer assert(o.enum_tag_name_map.remove(enum_ty.toIntern()));4319 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(
4112 // Dummy function type; `updateEnumTagNameFunction` will replace it with the correct type.4321 // Dummy function type; `updateEnumTagNameFunction` will replace it with the correct type.
4113 // TODO: change the builder API so we don't need to do this.4322 // TODO: change the builder API so we don't need to do this.
4114 try o.builder.fnType(.void, &.{}, .normal),4323 try o.builder.fnType(.void, &.{}, .normal),
4115 try o.builder.strtabStringFmt("__zig_tag_name_{f}", .{enum_ty.containerTypeName(ip).fmt(ip)}),4324 try o.builder.strtabStringFmt("__zig_tag_name_{f}", .{enum_ty.containerTypeName(ip).fmt(ip)}),
4116 toLlvmAddressSpace(.generic, zcu.getTarget()),4325 toLlvmAddressSpace(.generic, zcu.getTarget()),
4117 );4326 );
4118 gop.value_ptr.* = function_index;4327 gop.value_ptr.* = llvm_function;
4119 try o.updateEnumTagNameFunction(enum_ty, function_index);4328 try o.updateEnumTagNameFunction(enum_ty, llvm_function);
4120 return function_index;4329 return llvm_function;
4121 }4330 }
4122 fn updateEnumTagNameFunction(4331 fn updateEnumTagNameFunction(
4123 o: *Object,4332 o: *Object,
4124 enum_ty: Type,4333 enum_ty: Type,
4125 function_index: Builder.Function.Index,4334 llvm_function: Builder.Function.Index,
4126 ) Allocator.Error!void {4335 ) Allocator.Error!void {
4127 const zcu = o.zcu;4336 const zcu = o.zcu;
4128 const ip = &zcu.intern_pool;4337 const ip = &zcu.intern_pool;
4129 const loaded_enum = ip.loadEnumType(enum_ty.toIntern());4338 const loaded_enum = ip.loadEnumType(enum_ty.toIntern());
41304339
4131 const llvm_usize_ty = try o.lowerType(.usize, .by_value);4340 const llvm_usize_ty = try o.lowerType(.usize, .as_value);
4132 const llvm_ret_ty = try o.lowerType(.slice_const_u8_sentinel_0, .by_value);4341 const llvm_ret_ty = try o.lowerType(.slice_const_u8_sentinel_0, .as_value);
4133 const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .by_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 =
4136 try o.builder.fnType(llvm_ret_ty, &.{llvm_int_ty}, .normal);4345 try o.builder.fnType(llvm_ret_ty, &.{llvm_int_ty}, .normal);
41374346
4138 var attributes: Builder.FunctionAttributes.Wip = .{};4347 var attributes: Builder.FunctionAttributes.Wip = .{};
4139 defer attributes.deinit(&o.builder);4348 defer attributes.deinit(&o.builder);
4140 try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer);4349 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);4351 llvm_function.setLinkage(if (o.builder.strip) .private else .internal, &o.builder);
4143 function_index.setCallConv(.fastcc, &o.builder);4352 llvm_function.setCallConv(.fastcc, &o.builder);
4144 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);4353 llvm_function.setAttributes(try attributes.finish(&o.builder), &o.builder);
41454354
4146 var wip = try Builder.WipFunction.init(&o.builder, .{4355 var wip = try Builder.WipFunction.init(&o.builder, .{
4147 .function = function_index,4356 .function = llvm_function,
4148 .strip = true,4357 .strip = true,
4149 });4358 });
4150 defer wip.deinit();4359 defer wip.deinit();
...@@ -4163,23 +4372,23 @@ pub const Object = struct {...@@ -4163,23 +4372,23 @@ pub const Object = struct {
4163 for (0..loaded_enum.field_names.len) |field_index| {4372 for (0..loaded_enum.field_names.len) |field_index| {
4164 const name = try o.builder.stringNull(loaded_enum.field_names.get(ip)[field_index].toSlice(ip));4373 const name = try o.builder.stringNull(loaded_enum.field_names.get(ip)[field_index].toSlice(ip));
4165 const name_init = try o.builder.stringConst(name);4374 const name_init = try o.builder.stringConst(name);
4166 const name_variable_index = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);4375 const name_llvm_variable = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
4167 try name_variable_index.setInitializer(name_init, &o.builder);4376 try name_llvm_variable.setInitializer(name_init, &o.builder);
4168 name_variable_index.setMutability(.constant, &o.builder);4377 name_llvm_variable.setMutability(.constant, &o.builder);
4169 name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder);4378 name_llvm_variable.setAlignment(comptime .fromByteUnits(1), &o.builder);
4170 const name_global_index = name_variable_index.ptrConst(&o.builder).global;4379 const name_llvm_global = name_llvm_variable.ptrConst(&o.builder).global;
4171 name_global_index.setLinkage(.private, &o.builder);4380 name_llvm_global.setLinkage(.private, &o.builder);
4172 name_global_index.setUnnamedAddr(.unnamed_addr, &o.builder);4381 name_llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder);
41734382
4174 const name_val = try o.builder.structValue(llvm_ret_ty, &.{4383 const name_val = try o.builder.structValue(llvm_ret_ty, &.{
4175 name_global_index.toConst(),4384 name_llvm_global.toConst(),
4176 try o.builder.intConst(llvm_usize_ty, name.slice(&o.builder).?.len - 1),4385 try o.builder.intConst(llvm_usize_ty, name.slice(&o.builder).?.len - 1),
4177 });4386 });
41784387
4179 const return_block = try wip.block(1, "Name");4388 const return_block = try wip.block(1, "Name");
4180 const llvm_tag_val = switch (loaded_enum.field_values.getOrNone(ip, field_index)) {4389 const llvm_tag_val = switch (loaded_enum.field_values.getOrNone(ip, field_index)) {
4181 .none => try o.builder.intConst(llvm_int_ty, field_index), // auto-numbered4390 .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),
4183 };4392 };
4184 try wip_switch.addCase(llvm_tag_val, return_block, &wip);4393 try wip_switch.addCase(llvm_tag_val, return_block, &wip);
41854394
...@@ -4205,40 +4414,40 @@ pub const Object = struct {...@@ -4205,40 +4414,40 @@ pub const Object = struct {
4205 const gop = try o.named_enum_map.getOrPut(o.gpa, enum_ty.toIntern());4414 const gop = try o.named_enum_map.getOrPut(o.gpa, enum_ty.toIntern());
4206 if (gop.found_existing) return gop.value_ptr.*;4415 if (gop.found_existing) return gop.value_ptr.*;
4207 errdefer assert(o.named_enum_map.remove(enum_ty.toIntern()));4416 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(
4209 // Dummy function type; `updateIsNamedEnumValue` will replace it with the correct type.4418 // Dummy function type; `updateIsNamedEnumValue` will replace it with the correct type.
4210 // TODO: change the builder API so we don't need to do this.4419 // TODO: change the builder API so we don't need to do this.
4211 try o.builder.fnType(.void, &.{}, .normal),4420 try o.builder.fnType(.void, &.{}, .normal),
4212 try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_ty.containerTypeName(ip).fmt(ip)}),4421 try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_ty.containerTypeName(ip).fmt(ip)}),
4213 toLlvmAddressSpace(.generic, zcu.getTarget()),4422 toLlvmAddressSpace(.generic, zcu.getTarget()),
4214 );4423 );
4215 gop.value_ptr.* = function_index;4424 gop.value_ptr.* = llvm_function;
4216 try o.updateIsNamedEnumValueFunction(enum_ty, function_index);4425 try o.updateIsNamedEnumValueFunction(enum_ty, llvm_function);
4217 return function_index;4426 return llvm_function;
4218 }4427 }
4219 fn updateIsNamedEnumValueFunction(4428 fn updateIsNamedEnumValueFunction(
4220 o: *Object,4429 o: *Object,
4221 enum_ty: Type,4430 enum_ty: Type,
4222 function_index: Builder.Function.Index,4431 llvm_function: Builder.Function.Index,
4223 ) Allocator.Error!void {4432 ) Allocator.Error!void {
4224 const zcu = o.zcu;4433 const zcu = o.zcu;
4225 const ip = &zcu.intern_pool;4434 const ip = &zcu.intern_pool;
4226 const loaded_enum = ip.loadEnumType(enum_ty.toIntern());4435 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);4437 const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .as_value);
4229 function_index.ptrConst(&o.builder).global.ptr(&o.builder).type =4438 llvm_function.ptrConst(&o.builder).global.ptr(&o.builder).type =
4230 try o.builder.fnType(.i1, &.{llvm_int_ty}, .normal);4439 try o.builder.fnType(.i1, &.{llvm_int_ty}, .normal);
42314440
4232 var attributes: Builder.FunctionAttributes.Wip = .{};4441 var attributes: Builder.FunctionAttributes.Wip = .{};
4233 defer attributes.deinit(&o.builder);4442 defer attributes.deinit(&o.builder);
4234 try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer);4443 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);4445 llvm_function.setLinkage(if (o.builder.strip) .private else .internal, &o.builder);
4237 function_index.setCallConv(.fastcc, &o.builder);4446 llvm_function.setCallConv(.fastcc, &o.builder);
4238 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);4447 llvm_function.setAttributes(try attributes.finish(&o.builder), &o.builder);
42394448
4240 var wip: Builder.WipFunction = try .init(&o.builder, .{4449 var wip: Builder.WipFunction = try .init(&o.builder, .{
4241 .function = function_index,4450 .function = llvm_function,
4242 .strip = true,4451 .strip = true,
4243 });4452 });
4244 defer wip.deinit();4453 defer wip.deinit();
...@@ -4252,7 +4461,7 @@ pub const Object = struct {...@@ -4252,7 +4461,7 @@ pub const Object = struct {
42524461
4253 if (loaded_enum.field_values.len > 0) {4462 if (loaded_enum.field_values.len > 0) {
4254 for (loaded_enum.field_values.get(ip)) |tag_val_ip| {4463 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);
4256 try wip_switch.addCase(llvm_tag_val, named_block, &wip);4465 try wip_switch.addCase(llvm_tag_val, named_block, &wip);
4257 }4466 }
4258 } else {4467 } else {
...@@ -4274,20 +4483,27 @@ pub const Object = struct {...@@ -4274,20 +4483,27 @@ pub const Object = struct {
42744483
4275 pub fn getLibcFunction(4484 pub fn getLibcFunction(
4276 o: *Object,4485 o: *Object,
4486 pt: Zcu.PerThread,
4277 fn_name: Builder.StrtabString,4487 fn_name: Builder.StrtabString,
4278 param_types: []const Builder.Type,4488 fn_info: FuncInfo,
4279 return_type: Builder.Type,
4280 ) Allocator.Error!Builder.Function.Index {4489 ) Allocator.Error!Builder.Function.Index {
4281 if (o.builder.getGlobal(fn_name)) |global| return switch (global.ptrConst(&o.builder).kind) {4490 if (o.builder.getGlobal(fn_name)) |global| return switch (global.ptrConst(&o.builder).kind) {
4282 .alias => |alias| alias.getAliasee(&o.builder).ptrConst(&o.builder).kind.function,4491 .alias => |alias| alias.getAliasee(&o.builder).ptrConst(&o.builder).kind.function,
4283 .function => |function| function,4492 .function => |function| function,
4284 .variable, .replaced => unreachable,4493 .variable, .replaced => unreachable,
4285 };4494 };
4286 return o.builder.addFunction(4495 const llvm_function = try o.builder.addFunction(
4287 try o.builder.fnType(return_type, param_types, .normal),4496 try o.lowerFnType(fn_info),
4288 fn_name,4497 fn_name,
4289 toLlvmAddressSpace(.generic, o.zcu.getTarget()),4498 toLlvmAddressSpace(.generic, o.zcu.getTarget()),
4290 );4499 );
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;
4291 }4507 }
4292};4508};
42934509
...@@ -4324,7 +4540,7 @@ pub fn toLlvmCallConv(cc: std.lang.CallingConvention, target: *const std.Target)...@@ -4324,7 +4540,7 @@ pub fn toLlvmCallConv(cc: std.lang.CallingConvention, target: *const std.Target)
4324 std.lang.CallingConvention.SpirvFragmentOptions,4540 std.lang.CallingConvention.SpirvFragmentOptions,
4325 std.lang.CallingConvention.SpirvMeshOptions,4541 std.lang.CallingConvention.SpirvMeshOptions,
4326 => .{ null, 0, 0 },4542 => .{ null, 0, 0 },
4327 else => @compileError("TODO: toLlvmCallConv" ++ @tagName(pl)),4543 else => @compileError("TODO: toLlvmCallConv(." ++ @tagName(pl) ++ ")"),
4328 },4544 },
4329 };4545 };
4330 return .{4546 return .{
...@@ -4360,6 +4576,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const...@@ -4360,6 +4576,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const
4360 null,4576 null,
4361 .x86_64_vectorcall => .x86_vectorcallcc,4577 .x86_64_vectorcall => .x86_vectorcallcc,
4362 .x86_64_interrupt => .x86_intrcc,4578 .x86_64_interrupt => .x86_intrcc,
4579 .x86_64_preserve_none => .preserve_nonecc,
4363 .x86_stdcall => .x86_stdcallcc,4580 .x86_stdcall => .x86_stdcallcc,
4364 .x86_fastcall => .x86_fastcallcc,4581 .x86_fastcall => .x86_fastcallcc,
4365 .x86_thiscall => .x86_thiscallcc,4582 .x86_thiscall => .x86_thiscallcc,
...@@ -4375,6 +4592,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const...@@ -4375,6 +4592,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const
4375 .x86_interrupt => .x86_intrcc,4592 .x86_interrupt => .x86_intrcc,
4376 .aarch64_vfabi => .aarch64_vector_pcs,4593 .aarch64_vfabi => .aarch64_vector_pcs,
4377 .aarch64_vfabi_sve => .aarch64_sve_vector_pcs,4594 .aarch64_vfabi_sve => .aarch64_sve_vector_pcs,
4595 .aarch64_preserve_none => .preserve_nonecc,
4378 .arm_aapcs => .arm_aapcscc,4596 .arm_aapcs => .arm_aapcscc,
4379 .arm_aapcs_vfp => .arm_aapcs_vfpcc,4597 .arm_aapcs_vfp => .arm_aapcs_vfpcc,
4380 .riscv64_lp64_v => .riscv_vectorcallcc,4598 .riscv64_lp64_v => .riscv_vectorcallcc,
...@@ -4407,6 +4625,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const...@@ -4407,6 +4625,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const
4407 .x86_16_interrupt,4625 .x86_16_interrupt,
4408 .x86_sysv,4626 .x86_sysv,
4409 .x86_win,4627 .x86_win,
4628 .x86_mingw,
4410 .x86_thiscall_mingw,4629 .x86_thiscall_mingw,
4411 .x86_64_x32,4630 .x86_64_x32,
4412 .aarch64_aapcs,4631 .aarch64_aapcs,
...@@ -4581,47 +4800,6 @@ fn toLlvmGlobalAddressSpace(wanted_address_space: std.lang.AddressSpace, target:...@@ -4581,47 +4800,6 @@ fn toLlvmGlobalAddressSpace(wanted_address_space: std.lang.AddressSpace, target:
4581 };4800 };
4582}4801}
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
4625/// We need to insert extra padding if LLVM's isn't enough.4803/// We need to insert extra padding if LLVM's isn't enough.
4626/// However we don't want to ever call LLVMABIAlignmentOfType or4804/// However we don't want to ever call LLVMABIAlignmentOfType or
4627/// LLVMABISizeOfType because these functions will trip assertions4805/// 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 {...@@ -164,12 +164,12 @@ fn resolveValue(self: *FuncGen, val: Value) Allocator.Error!Builder.Constant {
164 const zcu = o.zcu;164 const zcu = o.zcu;
165 const ty = val.typeOf(zcu);165 const ty = val.typeOf(zcu);
166 if (!isByRef(ty, zcu)) {166 if (!isByRef(ty, zcu)) {
167 return o.lowerValue(val.toIntern(), .by_value);167 return o.lowerValue(val.toIntern(), .as_value);
168 } else {168 } else {
169 // We need a pointer to a global constant, i.e. a UAV.169 // We need a pointer to a global constant, i.e. a UAV.
170 return o.lowerUavRef(170 return o.lowerUavRef(
171 val.toIntern(),171 val.toIntern(),
172 ty.abiAlignment(zcu),172 ty.abiAlignment(zcu).toLlvm(),
173 target_util.defaultAddressSpace(zcu.getTarget(), .global_constant),173 target_util.defaultAddressSpace(zcu.getTarget(), .global_constant),
174 );174 );
175 }175 }
...@@ -190,10 +190,10 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {...@@ -190,10 +190,10 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {
190 const fn_info = zcu.typeToFunc(fn_ty).?;190 const fn_info = zcu.typeToFunc(fn_ty).?;
191 const param_types = fn_info.param_types.get(ip);191 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
195 // Populate `fg.ret_ptr`...195 // 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))) {
197 .sret => rp: {197 .sret => rp: {
198 defer it.llvm_index += 1;198 defer it.llvm_index += 1;
199 break :rp fg.wip.arg(it.llvm_index);199 break :rp fg.wip.arg(it.llvm_index);
...@@ -218,7 +218,7 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {...@@ -218,7 +218,7 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {
218 switch (lowering) {218 switch (lowering) {
219 .no_bits => continue,219 .no_bits => continue,
220 .byval => {220 .byval => {
221 assert(!it.byval_attr);221 assert(it.byval_attr == null);
222 const param_index = it.zig_index - 1;222 const param_index = it.zig_index - 1;
223 const param_ty: Type = .fromInterned(param_types[param_index]);223 const param_ty: Type = .fromInterned(param_types[param_index]);
224 const param = fg.wip.arg(it.llvm_index - 1);224 const param = fg.wip.arg(it.llvm_index - 1);
...@@ -237,15 +237,16 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {...@@ -237,15 +237,16 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {
237 .byref, .byref_mut => {237 .byref, .byref_mut => {
238 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);238 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
239 const param = fg.wip.arg(it.llvm_index - 1);239 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)) {
242 args.appendAssumeCapacity(param);243 args.appendAssumeCapacity(param);
243 } else {244 } else {
244 args.appendAssumeCapacity(try fg.load(param, .none, param_ty, .normal));245 args.appendAssumeCapacity(try fg.load(param, alignment, param_ty, .normal));
245 }246 }
246 },247 },
247 .abi_sized_int => {248 .abi_sized_int => {
248 assert(!it.byval_attr);249 assert(it.byval_attr == null);
249 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);250 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
250 const param = fg.wip.arg(it.llvm_index - 1);251 const param = fg.wip.arg(it.llvm_index - 1);
251252
...@@ -260,18 +261,18 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {...@@ -260,18 +261,18 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {
260 }261 }
261 },262 },
262 .slice => {263 .slice => {
263 assert(!it.byval_attr);264 assert(it.byval_attr == null);
264 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);265 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
265 assert(!isByRef(param_ty, zcu));266 assert(!isByRef(param_ty, zcu));
266 const slice_val = try fg.wip.buildAggregate(267 const slice_val = try fg.wip.buildAggregate(
267 try o.lowerType(param_ty, .by_value),268 try o.lowerType(param_ty, .as_value),
268 &.{ fg.wip.arg(it.llvm_index - 2), fg.wip.arg(it.llvm_index - 1) },269 &.{ fg.wip.arg(it.llvm_index - 2), fg.wip.arg(it.llvm_index - 1) },
269 "",270 "",
270 );271 );
271 args.appendAssumeCapacity(slice_val);272 args.appendAssumeCapacity(slice_val);
272 },273 },
273 .multiple_llvm_types => {274 .multiple_llvm_types => {
274 assert(!it.byval_attr);275 assert(it.byval_attr == null);
275 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);276 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
276 const param_alignment = param_ty.abiAlignment(zcu);277 const param_alignment = param_ty.abiAlignment(zcu);
277 const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8);278 const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8);
...@@ -696,7 +697,7 @@ fn genBodyDebugScope(...@@ -696,7 +697,7 @@ fn genBodyDebugScope(
696 .{697 .{
697 .di_flags = .{ .StaticMember = true },698 .di_flags = .{ .StaticMember = true },
698 .sp_flags = .{699 .sp_flags = .{
699 .Optimized = mod.optimize_mode != .Debug,700 .Optimized = mod.optimize_mode != .debug,
700 .Definition = true,701 .Definition = true,
701 .LocalToUnit = true, // inline functions cannot be exported702 .LocalToUnit = true, // inline functions cannot be exported
702 },703 },
...@@ -721,29 +722,19 @@ fn genBodyDebugScope(...@@ -721,29 +722,19 @@ fn genBodyDebugScope(
721 try self.genBody(body, coverage_point);722 try self.genBody(body, coverage_point);
722}723}
723724
724const CallAttr = enum {725fn airCall(fg: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier) Allocator.Error!Builder.Value {
725 Auto,726 const o = fg.object;
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;
737 const zcu = o.zcu;727 const zcu = o.zcu;
728 const air_call = fg.air.unwrapCall(inst);
729 const args = air_call.args;
738 const ip = &zcu.intern_pool;730 const ip = &zcu.intern_pool;
739 const callee_ty = self.typeOf(air_call.callee);731 const callee_ty = fg.typeOf(air_call.callee);
740 const zig_fn_ty = switch (callee_ty.zigTypeTag(zcu)) {732 const zig_fn_ty = switch (callee_ty.zigTypeTag(zcu)) {
741 .@"fn" => callee_ty,733 .@"fn" => callee_ty,
742 .pointer => callee_ty.childType(zcu),734 .pointer => callee_ty.childType(zcu),
743 else => unreachable,735 else => unreachable,
744 };736 };
745 const fn_info = zcu.typeToFunc(zig_fn_ty).?;737 const fn_info = zcu.typeToFunc(zig_fn_ty).?;
746 const return_type: Type = .fromInterned(fn_info.return_type);
747 const llvm_fn = llvm_fn: {738 const llvm_fn = llvm_fn: {
748 // If the callee is a function *body*, we need to use a pointer to the global.739 // If the callee is a function *body*, we need to use a pointer to the global.
749 if (air_call.callee.toInterned()) |ip_index| switch (ip.indexToKey(ip_index)) {740 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...@@ -752,22 +743,54 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
752 else => {},743 else => {},
753 };744 };
754 // Otherwise, the operand is already a function pointer (possibly runtime-known).745 // 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);
756 };747 };
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);
757 const target = zcu.getTarget();780 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);783 var llvm_args: std.ArrayList(Builder.Value) = .empty;
761 defer llvm_args.deinit();784 defer llvm_args.deinit(fg.gpa);
762785
763 var attributes: Builder.FunctionAttributes.Wip = .{};786 var attributes: Builder.FunctionAttributes.Wip = .{};
764 defer attributes.deinit(&o.builder);787 defer attributes.deinit(&o.builder);
765788
766 if (self.disable_intrinsics) {789 if (fg.disable_intrinsics) {
767 try attributes.addFnAttr(.nobuiltin, &o.builder);790 try attributes.addFnAttr(.nobuiltin, &o.builder);
768 }791 }
769792
770 switch (modifier) {793 switch (opts.modifier) {
771 .auto, .always_tail => {},794 .auto, .always_tail => {},
772 .never_tail, .never_inline => try attributes.addFnAttr(.@"noinline", &o.builder),795 .never_tail, .never_inline => try attributes.addFnAttr(.@"noinline", &o.builder),
773 .no_suspend, .always_inline, .compile_time => unreachable,796 .no_suspend, .always_inline, .compile_time => unreachable,
...@@ -775,10 +798,11 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier...@@ -775,10 +798,11 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
775798
776 const sret_alloc: ?Builder.Value = switch (ret_strat) {799 const sret_alloc: ?Builder.Value = switch (ret_strat) {
777 .sret => sret_alloc: {800 .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);804 const ptr = try fg.buildZigAlloca(return_type, .none);
781 try llvm_args.append(ptr);805 try llvm_args.append(fg.gpa, ptr);
782 break :sret_alloc ptr;806 break :sret_alloc ptr;
783 },807 },
784 else => sret_alloc: {808 else => sret_alloc: {
...@@ -792,132 +816,111 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier...@@ -792,132 +816,111 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
792816
793 const err_return_tracing = fn_info.cc == .auto and zcu.comp.config.any_error_tracing;817 const err_return_tracing = fn_info.cc == .auto and zcu.comp.config.any_error_tracing;
794 if (err_return_tracing) {818 if (err_return_tracing) {
795 assert(self.err_ret_trace != .none);819 assert(fg.err_ret_trace != .none);
796 try llvm_args.append(self.err_ret_trace);820 try llvm_args.append(fg.gpa, fg.err_ret_trace);
797 }821 }
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);
894822
895 const loaded = try self.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), "");823 var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types);
896 try llvm_args.append(loaded);824 while (try it.nextCall(arg_types)) |lowering| {
897 },825 const arg_ty: Type = .fromInterned(arg_types[it.zig_index - 1]);
898 .i32_array, .i64_array => |arr_len| {826 const arg_val = arg_values[it.zig_index - 1];
899 const elem_size: u8 = if (lowering == .i32_array) 32 else 64;827 switch (lowering) {
900 const arg = args[it.zig_index - 1];828 .no_bits => continue,
901 const arg_ty = self.typeOf(arg);829 .byval => {
902 const arg_val = try self.resolveInst(arg);830 if (isByRef(arg_ty, zcu)) {
903831 const alignment = arg_ty.abiAlignment(zcu).toLlvm();
904 const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: {832 // We don't need to handle non-ABI-sized integer types in memory here since they are
905 const ptr = try self.buildZigAlloca(arg_ty, .none);833 // never by-ref.
906 try self.store(ptr, .none, arg_val, arg_ty, .normal);834 const llvm_arg_ty = try o.lowerType(arg_ty, .memory_access);
907 break :ptr ptr;835 const loaded = try fg.wip.load(.normal, llvm_arg_ty, arg_val, alignment, "");
908 } else arg_val;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)));858 if (isByRef(arg_ty, zcu)) {
911 const loaded = try self.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), "");859 const alignment = arg_ty.abiAlignment(zcu).toLlvm();
912 try llvm_args.append(loaded);860 const loaded = try fg.wip.load(.normal, int_llvm_ty, arg_val, alignment, "");
913 },861 try llvm_args.append(fg.gpa, loaded);
914 };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
916 const cc_info = llvm.toLlvmCallConv(fn_info.cc, target).?;919 const cc_info = llvm.toLlvmCallConv(fn_info.cc, target).?;
917920
918 {921 {
919 // Add argument attributes.922 // Add argument attributes.
920 it = iterateParamTypes(o, fn_info);923 it = iterateParamTypes(o, fn_info.cc, fn_info.param_types);
921 it.llvm_index += @intFromBool(ret_strat == .sret);924 it.llvm_index += @intFromBool(ret_strat == .sret);
922 it.llvm_index += @intFromBool(err_return_tracing);925 it.llvm_index += @intFromBool(err_return_tracing);
923 var remaining_inreg_int = cc_info.inreg_int_params;926 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...@@ -925,7 +928,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
925 while (try it.next()) |lowering| switch (lowering) {928 while (try it.next()) |lowering| switch (lowering) {
926 .byval => {929 .byval => {
927 const param_index = it.zig_index - 1;930 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]);
929 if (!isByRef(param_ty, zcu)) {932 if (!isByRef(param_ty, zcu)) {
930 try o.addByValParamAttrs(pt, &attributes, param_ty, param_index, fn_info, it.llvm_index - 1);933 try o.addByValParamAttrs(pt, &attributes, param_ty, param_index, fn_info, it.llvm_index - 1);
931 }934 }
...@@ -947,7 +950,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier...@@ -947,7 +950,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
947 },950 },
948 .byref => {951 .byref => {
949 const param_index = it.zig_index - 1;952 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]);
951 try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, it.byval_attr, param_ty);954 try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, it.byval_attr, param_ty);
952 },955 },
953 .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder),956 .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...@@ -961,8 +964,8 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
961 => continue,964 => continue,
962965
963 .slice => {966 .slice => {
964 assert(!it.byval_attr);967 assert(it.byval_attr == null);
965 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);968 const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]);
966 const ptr_info = param_ty.ptrInfo(zcu);969 const ptr_info = param_ty.ptrInfo(zcu);
967 const llvm_arg_i = it.llvm_index - 2;970 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...@@ -989,8 +992,8 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
989 };992 };
990 }993 }
991994
992 const call = try self.wip.call(995 const call = try fg.wip.call(
993 switch (modifier) {996 switch (opts.modifier) {
994 .auto, .never_inline => .normal,997 .auto, .never_inline => .normal,
995 .never_tail => .notail,998 .never_tail => .notail,
996 .always_tail => .musttail,999 .always_tail => .musttail,
...@@ -998,19 +1001,14 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier...@@ -998,19 +1001,14 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
998 },1001 },
999 cc_info.llvm_cc,1002 cc_info.llvm_cc,
1000 try attributes.finish(&o.builder),1003 try attributes.finish(&o.builder),
1001 try o.lowerType(zig_fn_ty, .by_value),1004 llvm_fn_ty,
1002 llvm_fn,1005 llvm_fn,
1003 llvm_args.items,1006 llvm_args.items,
1004 "",1007 "",
1005 );1008 );
10061009
1007 if (fn_info.return_type == .noreturn_type and modifier != .always_tail) {1010 if (opts.is_unused) return .none;
1008 return .none;1011 if (fn_info.return_type == .noreturn_type and opts.modifier != .always_tail) return .none;
1009 }
1010
1011 if (self.liveness.isUnused(inst)) {
1012 return .none;
1013 }
10141012
1015 // We exit this `switch` if we have a pointer to the return value.1013 // We exit this `switch` if we have a pointer to the return value.
1016 const ret_val_ptr: Builder.Value = switch (ret_strat) {1014 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...@@ -1020,15 +1018,15 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
1020 .sret => sret_alloc.?,1018 .sret => sret_alloc.?,
1021 .mem_cast => |llvm_ret_ty| ret_val_ptr: {1019 .mem_cast => |llvm_ret_ty| ret_val_ptr: {
1022 const alignment = return_type.abiAlignment(zcu).toLlvm();1020 const alignment = return_type.abiAlignment(zcu).toLlvm();
1023 const ptr = try self.buildAlloca(llvm_ret_ty, alignment);1021 const ptr = try fg.buildAlloca(llvm_ret_ty, alignment);
1024 _ = try self.wip.store(.normal, call, ptr, alignment);1022 _ = try fg.wip.store(.normal, call, ptr, alignment);
1025 break :ret_val_ptr ptr;1023 break :ret_val_ptr ptr;
1026 },1024 },
1027 };1025 };
1028 if (isByRef(return_type, zcu)) {1026 if (isByRef(return_type, zcu)) {
1029 return ret_val_ptr;1027 return ret_val_ptr;
1030 } else {1028 } else {
1031 return self.load(ret_val_ptr, .none, return_type, .normal);1029 return fg.load(ret_val_ptr, .none, return_type, .normal);
1032 }1030 }
1033}1031}
10341032
...@@ -1038,7 +1036,7 @@ fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.SimplePanicId) Allocator.Error!v...@@ -1038,7 +1036,7 @@ fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.SimplePanicId) Allocator.Error!v
1038 const target = zcu.getTarget();1036 const target = zcu.getTarget();
1039 const panic_func = zcu.funcInfo(zcu.std_lang_decl_values.get(panic_id.toStdLangDecl()));1037 const panic_func = zcu.funcInfo(zcu.std_lang_decl_values.get(panic_id.toStdLangDecl()));
1040 const fn_info = zcu.typeToFunc(.fromInterned(panic_func.ty)).?;1038 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
1043 const llvm_panic_fn_ref = try o.lowerNavRef(panic_func.owner_nav);1041 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...@@ -1067,7 +1065,7 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!vo
10671065
1068 const fn_info = zcu.typeToFunc(Type.fromInterned(ip.getNav(self.nav_index).resolved.?.type)).?;1066 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));
1071 const val_is_undef = if (un_op.toInterned()) |i| Value.fromInterned(i).isUndef(zcu) else false;1069 const val_is_undef = if (un_op.toInterned()) |i| Value.fromInterned(i).isUndef(zcu) else false;
1072 const ret_ty_align = ret_ty.abiAlignment(zcu);1070 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...@@ -1076,7 +1074,7 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!vo
1076 .none => try self.buildZigAlloca(ret_ty, .none),1074 .none => try self.buildZigAlloca(ret_ty, .none),
1077 else => |rp| rp,1075 else => |rp| rp,
1078 };1076 };
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));
1080 _ = try self.wip.callMemSet(1078 _ = try self.wip.callMemSet(
1081 rp,1079 rp,
1082 ret_ty_align.toLlvm(),1080 ret_ty_align.toLlvm(),
...@@ -1141,7 +1139,7 @@ fn airRetLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!void {...@@ -1141,7 +1139,7 @@ fn airRetLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!void {
1141 const ret_ty = ptr_ty.childType(zcu);1139 const ret_ty = ptr_ty.childType(zcu);
1142 const fn_info = zcu.typeToFunc(.fromInterned(ip.getNav(self.nav_index).resolved.?.type)).?;1140 const fn_info = zcu.typeToFunc(.fromInterned(ip.getNav(self.nav_index).resolved.?.type)).?;
1143 const ptr = try self.resolveInst(un_op);1141 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))) {
1145 .void => _ = try self.wip.retVoid(),1143 .void => _ = try self.wip.retVoid(),
1146 .sret => {1144 .sret => {
1147 assert(self.ret_ptr != .none);1145 assert(self.ret_ptr != .none);
...@@ -1165,7 +1163,7 @@ fn airCVaArg(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value...@@ -1165,7 +1163,7 @@ fn airCVaArg(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
1165 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;1163 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
1166 const list = try self.resolveInst(ty_op.operand);1164 const list = try self.resolveInst(ty_op.operand);
1167 const arg_ty = ty_op.ty.toType();1165 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
1170 return self.wip.vaArg(list, llvm_arg_ty, "");1168 return self.wip.vaArg(list, llvm_arg_ty, "");
1171}1169}
...@@ -1378,7 +1376,7 @@ fn lowerBlock(...@@ -1378,7 +1376,7 @@ fn lowerBlock(
1378 if (have_block_result) {1376 if (have_block_result) {
1379 const llvm_ty: Builder.Type = switch (isByRef(inst_ty, zcu)) {1377 const llvm_ty: Builder.Type = switch (isByRef(inst_ty, zcu)) {
1380 true => .ptr,1378 true => .ptr,
1381 false => try o.lowerType(inst_ty, .by_value),1379 false => try o.lowerType(inst_ty, .as_value),
1382 };1380 };
1383 parent_bb.ptr(&self.wip).incoming = @intCast(breaks.list.len);1381 parent_bb.ptr(&self.wip).incoming = @intCast(breaks.list.len);
1384 const phi = try self.wip.phi(llvm_ty, "");1382 const phi = try self.wip.phi(llvm_ty, "");
...@@ -1485,7 +1483,7 @@ fn lowerSwitchDispatch(...@@ -1485,7 +1483,7 @@ fn lowerSwitchDispatch(
1485 const table_index = try self.wip.conv(1483 const table_index = try self.wip.conv(
1486 .unsigned,1484 .unsigned,
1487 try self.wip.bin(.@"sub nuw", cond, jmp_table.min.toValue(), ""),1485 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),
1489 "",1487 "",
1490 );1488 );
1491 const target_ptr_ptr = try self.ptraddScaled(1489 const target_ptr_ptr = try self.ptraddScaled(
...@@ -1510,7 +1508,7 @@ fn lowerSwitchDispatch(...@@ -1510,7 +1508,7 @@ fn lowerSwitchDispatch(
1510 // The switch prongs will correspond to our scalar cases. Ranges will1508 // The switch prongs will correspond to our scalar cases. Ranges will
1511 // be handled by conditional branches in the `else` prong.1509 // 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);
1514 const cond_int = if (cond_ty.zigTypeTag(zcu) == .pointer)1512 const cond_int = if (cond_ty.zigTypeTag(zcu) == .pointer)
1515 try self.wip.cast(.ptrtoint, cond, llvm_usize, "")1513 try self.wip.cast(.ptrtoint, cond, llvm_usize, "")
1516 else1514 else
...@@ -1725,7 +1723,7 @@ fn lowerTry(...@@ -1725,7 +1723,7 @@ fn lowerTry(
1725 if (err_union_ty.isVolatilePtr(zcu)) .@"volatile" else .normal,1723 if (err_union_ty.isVolatilePtr(zcu)) .@"volatile" else .normal,
1726 );1724 );
1727 };1725 };
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);
1729 const is_err = try fg.wip.icmp(.ne, loaded, zero, "");1727 const is_err = try fg.wip.icmp(.ne, loaded, zero, "");
17301728
1731 const return_block = try fg.wip.block(1, "TryRet");1729 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...@@ -1862,8 +1860,8 @@ fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Tod
1862 const table_includes_else = item_count != table_len;1860 const table_includes_else = item_count != table_len;
18631861
1864 break :jmp_table .{1862 break :jmp_table .{
1865 .min = try o.lowerValue(min.toIntern(), .by_value),1863 .min = try o.lowerValue(min.toIntern(), .as_value),
1866 .max = try o.lowerValue(max.toIntern(), .by_value),1864 .max = try o.lowerValue(max.toIntern(), .as_value),
1867 .in_bounds_hint = if (table_includes_else) .none else switch (switch_br.getElseHint()) {1865 .in_bounds_hint = if (table_includes_else) .none else switch (switch_br.getElseHint()) {
1868 .none, .cold => .none,1866 .none, .cold => .none,
1869 .unpredictable => .unpredictable,1867 .unpredictable => .unpredictable,
...@@ -2021,142 +2019,102 @@ fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder...@@ -2021,142 +2019,102 @@ fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder
2021 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;2019 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
2022 const operand_ty = self.typeOf(ty_op.operand);2020 const operand_ty = self.typeOf(ty_op.operand);
2023 const array_ty = operand_ty.childType(zcu);2021 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);
2025 const len = try o.builder.intValue(llvm_usize, array_ty.arrayLen(zcu));2023 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);
2027 const operand = try self.resolveInst(ty_op.operand);2025 const operand = try self.resolveInst(ty_op.operand);
2028 return self.wip.buildAggregate(slice_llvm_ty, &.{ operand, len }, "");2026 return self.wip.buildAggregate(slice_llvm_ty, &.{ operand, len }, "");
2029}2027}
20302028
2031fn airFloatFromInt(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {2029fn airFloatFromInt(fg: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
2032 const o = self.object;2030 const o = fg.object;
2033 const zcu = o.zcu;2031 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);2034 const operand = try fg.resolveInst(ty_op.operand);
2037 const operand_ty = self.typeOf(ty_op.operand);2035 const operand_ty = fg.typeOf(ty_op.operand);
2038 const operand_scalar_ty = operand_ty.scalarType(zcu);2036 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);
2042 const dest_scalar_ty = dest_ty.scalarType(zcu);2040 const dest_scalar_ty = dest_ty.scalarType(zcu);
2043 const dest_llvm_ty = try o.lowerType(dest_ty, .by_value);
2044 const target = zcu.getTarget();2041 const target = zcu.getTarget();
20452042
2046 if (intrinsicsAllowed(dest_scalar_ty, target)) return self.wip.conv(2043 if (intrinsicsAllowed(.compiler_rt, dest_scalar_ty, target))
2047 if (is_signed_int) .signed else .unsigned,2044 return fg.wip.conv(.fromStdLang(operand_scalar_info.signedness), operand, try o.lowerType(dest_ty, .as_value), "");
2048 operand,
2049 dest_llvm_ty,
2050 "",
2051 );
20522045
2053 const rt_int_bits = compilerRtIntBits(@intCast(operand_scalar_ty.bitSize(zcu))) orelse {2046 const rt_int_ty = compilerRtPromoteInt(operand_scalar_info) orelse {
2054 return self.todo("float_from_int on {d} bit integer", .{operand_scalar_ty.bitSize(zcu)});2047 return fg.todo("float_from_int on {d} bit integer", .{operand_scalar_info.bits});
2055 };2048 };
2056 const rt_int_ty = try o.builder.intType(rt_int_bits);2049 const vector_len = if (operand_ty.isVector(zcu)) operand_ty.vectorLen(zcu) else null;
2057 var extended = try self.wip.conv(2050 const rt_llvm_int_ty = try o.lowerType(rt_int_ty, .as_value);
2058 if (is_signed_int) .signed else .unsigned,2051 const extended = try fg.wip.conv(
2052 .fromStdLang(operand_scalar_info.signedness),
2059 operand,2053 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,
2061 "",2058 "",
2062 );2059 );
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";
2067 const fn_name = try o.builder.strtabStringFmt("__float{s}{s}i{s}f", .{2060 const fn_name = try o.builder.strtabStringFmt("__float{s}{s}i{s}f", .{
2068 sign_prefix,2061 switch (operand_scalar_info.signedness) {
2069 compiler_rt_operand_abbrev,2062 .signed => "",
2070 compiler_rt_dest_abbrev,2063 .unsigned => "un",
2064 },
2065 compilerRtIntAbbrev(rt_int_ty.intInfo(zcu).bits),
2066 compilerRtFloatAbbrev(target, dest_scalar_ty.floatBits(target)),
2071 });2067 });
20722068 return fg.buildElementwiseCall(fn_name, .{
2073 var param_type = rt_int_ty;2069 .cc = target.cCallingConvention().?,
2074 if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) {2070 .param_types = &.{rt_int_ty.toIntern()},
2075 // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard2071 .return_type = dest_scalar_ty.toIntern(),
2076 // i128 calling convention to adhere to the ABI that LLVM expects compiler-rt to have.2072 }, &.{extended}, vector_len);
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 );
2091}2073}
20922074
2093fn airIntFromFloat(2075fn airIntFromFloat(
2094 self: *FuncGen,2076 fg: *FuncGen,
2095 inst: Air.Inst.Index,2077 inst: Air.Inst.Index,
2096 fast: Builder.FastMathKind,2078 fast: Builder.FastMathKind,
2097) TodoError!Builder.Value {2079) TodoError!Builder.Value {
2098 _ = fast;2080 _ = fast;
20992081
2100 const o = self.object;2082 const o = fg.object;
2101 const zcu = o.zcu;2083 const zcu = o.zcu;
2102 const target = zcu.getTarget();2084 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);2087 const operand = try fg.resolveInst(ty_op.operand);
2106 const operand_ty = self.typeOf(ty_op.operand);2088 const operand_ty = fg.typeOf(ty_op.operand);
2107 const operand_scalar_ty = operand_ty.scalarType(zcu);2089 const operand_scalar_ty = operand_ty.scalarType(zcu);
21082090
2109 const dest_ty = self.typeOfIndex(inst);2091 const dest_ty = fg.typeOfIndex(inst);
2110 const dest_scalar_ty = dest_ty.scalarType(zcu);2092 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)) {
2114 // TODO set fast math flag2097 // TODO set fast math flag
2115 return self.wip.conv(2098 return fg.wip.conv(.fromStdLang(dest_scalar_info.signedness), operand, dest_llvm_ty, "");
2116 if (dest_scalar_ty.isSignedInt(zcu)) .signed else .unsigned,
2117 operand,
2118 dest_llvm_ty,
2119 "",
2120 );
2121 }2099 }
21222100
2123 const rt_int_bits = compilerRtIntBits(@intCast(dest_scalar_ty.bitSize(zcu))) orelse {2101 const rt_int_ty = compilerRtPromoteInt(dest_scalar_info) orelse {
2124 return self.todo("int_from_float to {d} bit integer", .{dest_scalar_ty.bitSize(zcu)});2102 return fg.todo("int_from_float to {d} bit integer", .{dest_scalar_info.bits});
2125 };2103 };
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
2139 const fn_name = try o.builder.strtabStringFmt("__fix{s}{s}f{s}i", .{2104 const fn_name = try o.builder.strtabStringFmt("__fix{s}{s}f{s}i", .{
2140 sign_prefix,2105 switch (dest_scalar_info.signedness) {
2141 compiler_rt_operand_abbrev,2106 .signed => "",
2142 compiler_rt_dest_abbrev,2107 .unsigned => "uns",
2108 },
2109 compilerRtFloatAbbrev(target, operand_scalar_ty.floatBits(target)),
2110 compilerRtIntAbbrev(rt_int_ty.intInfo(zcu).bits),
2143 });2111 });
21442112 const result = try fg.buildElementwiseCall(fn_name, .{
2145 const operand_llvm_ty = try o.lowerType(operand_ty, .by_value);2113 .cc = target.cCallingConvention().?,
2146 const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, libc_ret_ty);2114 .param_types = &.{operand_scalar_ty.toIntern()},
2147 var result = try self.wip.call(2115 .return_type = rt_int_ty.toIntern(),
2148 .normal,2116 }, &.{operand}, if (operand_ty.isVector(zcu)) operand_ty.vectorLen(zcu) else null);
2149 .ccc,2117 return fg.wip.cast(.trunc, result, try o.lowerType(dest_ty, .as_value), "");
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;
2160}2118}
21612119
2162fn sliceOrArrayPtr(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!Builder.Value {2120fn 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...@@ -2167,7 +2125,7 @@ fn sliceOrArrayPtr(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!B
2167fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!Builder.Value {2125fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!Builder.Value {
2168 const o = fg.object;2126 const o = fg.object;
2169 const zcu = o.zcu;2127 const zcu = o.zcu;
2170 const llvm_usize = try o.lowerType(.usize, .by_value);2128 const llvm_usize = try o.lowerType(.usize, .as_value);
2171 switch (ty.ptrSize(zcu)) {2129 switch (ty.ptrSize(zcu)) {
2172 .slice => {2130 .slice => {
2173 const len = try fg.wip.extractValue(ptr, &.{1}, "");2131 const len = try fg.wip.extractValue(ptr, &.{1}, "");
...@@ -2365,7 +2323,7 @@ fn airAggFieldVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder....@@ -2365,7 +2323,7 @@ fn airAggFieldVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.
2365 },2323 },
2366 .float => {2324 .float => {
2367 // bitcast int->float2325 // 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), "");
2369 },2327 },
2370 }2328 }
2371 }2329 }
...@@ -2395,8 +2353,8 @@ fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build...@@ -2395,8 +2353,8 @@ fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build
2395 const field_offset = parent_ty.structFieldOffset(extra.field_index, zcu);2353 const field_offset = parent_ty.structFieldOffset(extra.field_index, zcu);
2396 if (field_offset == 0) return field_ptr;2354 if (field_offset == 0) return field_ptr;
23972355
2398 const res_ty = try o.lowerType(ty_pl.ty.toType(), .by_value);2356 const res_ty = try o.lowerType(ty_pl.ty.toType(), .as_value);
2399 const llvm_usize = try o.lowerType(.usize, .by_value);2357 const llvm_usize = try o.lowerType(.usize, .as_value);
24002358
2401 const field_ptr_int = try self.wip.cast(.ptrtoint, field_ptr, llvm_usize, "");2359 const field_ptr_int = try self.wip.cast(.ptrtoint, field_ptr, llvm_usize, "");
2402 const base_ptr_int = try self.wip.bin(2360 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...@@ -2516,7 +2474,7 @@ fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index, is_arg: bool) Allocator.Er
2516 },2474 },
2517 "",2475 "",
2518 );2476 );
2519 } else if (owner_mod.optimize_mode == .Debug and !self.is_naked) {2477 } else if (owner_mod.optimize_mode == .debug and !self.is_naked) {
2520 // We avoid taking this path for naked functions because there's no guarantee that such2478 // We avoid taking this path for naked functions because there's no guarantee that such
2521 // functions even have a valid stack pointer, making the `alloca` + `store` unsafe.2479 // 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 {...@@ -2612,7 +2570,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
2612 const output_inst = try self.resolveInst(output.operand);2570 const output_inst = try self.resolveInst(output.operand);
2613 const output_ty = self.typeOf(output.operand);2571 const output_ty = self.typeOf(output.operand);
2614 assert(output_ty.zigTypeTag(zcu) == .pointer);2572 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
2617 switch (constraint[0]) {2575 switch (constraint[0]) {
2618 '=' => {},2576 '=' => {},
...@@ -2650,7 +2608,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {...@@ -2650,7 +2608,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
2650 llvm_ret_indirect[output.index] = false;2608 llvm_ret_indirect[output.index] = false;
26512609
2652 const ret_ty = self.typeOfIndex(inst);2610 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);
2654 llvm_ret_i += 1;2612 llvm_ret_i += 1;
2655 }2613 }
26562614
...@@ -2689,7 +2647,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {...@@ -2689,7 +2647,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
2689 llvm_param_types[llvm_param_i] = arg_llvm_value.typeOfWip(&self.wip);2647 llvm_param_types[llvm_param_i] = arg_llvm_value.typeOfWip(&self.wip);
2690 } else {2648 } else {
2691 const alignment = arg_ty.abiAlignment(zcu).toLlvm();2649 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);
2693 const load_inst = try self.wip.load(.normal, arg_llvm_ty, arg_llvm_value, alignment, "");2651 const load_inst = try self.wip.load(.normal, arg_llvm_ty, arg_llvm_value, alignment, "");
2694 llvm_param_values[llvm_param_i] = load_inst;2652 llvm_param_values[llvm_param_i] = load_inst;
2695 llvm_param_types[llvm_param_i] = arg_llvm_ty;2653 llvm_param_types[llvm_param_i] = arg_llvm_ty;
...@@ -2729,7 +2687,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {...@@ -2729,7 +2687,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
2729 llvm_param_attrs[llvm_param_i] = if (constraint[0] == '*') blk: {2687 llvm_param_attrs[llvm_param_i] = if (constraint[0] == '*') blk: {
2730 if (!is_by_ref) self.maybeMarkAllowZeroAccess(arg_ty.ptrInfo(zcu));2688 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);
2733 } else .none;2691 } else .none;
27342692
2735 llvm_param_i += 1;2693 llvm_param_i += 1;
...@@ -2743,7 +2701,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {...@@ -2743,7 +2701,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
2743 if (constraint[0] != '+') continue;2701 if (constraint[0] != '+') continue;
27442702
2745 const rw_ty = self.typeOf(output.operand);2703 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);
2747 if (llvm_ret_indirect[output.index]) {2705 if (llvm_ret_indirect[output.index]) {
2748 llvm_param_values[llvm_param_i] = llvm_rw_vals[output.index];2706 llvm_param_values[llvm_param_i] = llvm_rw_vals[output.index];
2749 llvm_param_types[llvm_param_i] = llvm_rw_vals[output.index].typeOfWip(&self.wip);2707 llvm_param_types[llvm_param_i] = llvm_rw_vals[output.index].typeOfWip(&self.wip);
...@@ -2957,7 +2915,7 @@ fn airIsNonNull(...@@ -2957,7 +2915,7 @@ fn airIsNonNull(
2957 ));2915 ));
2958 return self.wip.icmp(cond, slice_ptr, try o.builder.nullValue(ptr_ty), "");2916 return self.wip.icmp(cond, slice_ptr, try o.builder.nullValue(ptr_ty), "");
2959 }2917 }
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)), "");
2961 }2919 }
29622920
2963 comptime assert(optional_layout_version == 3);2921 comptime assert(optional_layout_version == 3);
...@@ -2986,18 +2944,17 @@ fn airIsErr(...@@ -2986,18 +2944,17 @@ fn airIsErr(
2986 const operand_ty = self.typeOf(un_op);2944 const operand_ty = self.typeOf(un_op);
2987 const err_union_ty = if (operand_is_ptr) operand_ty.childType(zcu) else operand_ty;2945 const err_union_ty = if (operand_is_ptr) operand_ty.childType(zcu) else operand_ty;
2988 const payload_ty = err_union_ty.errorUnionPayload(zcu);2946 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
2991 const access_kind: Builder.MemoryAccessKind =2949 const access_kind: Builder.MemoryAccessKind =
2992 if (operand_is_ptr and operand_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;2950 if (operand_is_ptr and operand_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
29932951
2994 if (err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) {2952 if (err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) {
2995 const val: Builder.Constant = switch (cond) {2953 return switch (cond) {
2996 .eq => .true, // 0 == 02954 .eq => .true, // 0 == 0
2997 .ne => .false, // 0 != 02955 .ne => .false, // 0 != 0
2998 else => unreachable,2956 else => unreachable,
2999 };2957 };
3000 return val.toValue();
3001 }2958 }
30022959
3003 if (operand_is_ptr) self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu));2960 if (operand_is_ptr) self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu));
...@@ -3156,7 +3113,7 @@ fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) Allocator.Erro...@@ -3156,7 +3113,7 @@ fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) Allocator.Erro
3156 const err_union_ptr_align = err_union_ptr_ty.ptrAlignment(zcu);3113 const err_union_ptr_align = err_union_ptr_ty.ptrAlignment(zcu);
31573114
3158 const payload_ty = err_union_ty.errorUnionPayload(zcu);3115 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
3161 const access_kind: Builder.MemoryAccessKind =3118 const access_kind: Builder.MemoryAccessKind =
3162 if (err_union_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;3119 if (err_union_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
...@@ -3234,7 +3191,7 @@ fn airWrapErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!...@@ -3234,7 +3191,7 @@ fn airWrapErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!
3234 const payload_ty = self.typeOf(ty_op.operand);3191 const payload_ty = self.typeOf(ty_op.operand);
3235 assert(payload_ty.hasRuntimeBits(zcu));3192 assert(payload_ty.hasRuntimeBits(zcu));
3236 assert(isByRef(err_un_ty, zcu)); // error unions with runtime bits are always by-ref3193 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
3239 const result_ptr = try self.buildZigAlloca(err_un_ty, .none);3196 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...@@ -3273,7 +3230,7 @@ fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build
3273 const o = self.object;3230 const o = self.object;
3274 const pl_op = self.air.instructions.items(.data)[@backingInt(inst)].pl_op;3231 const pl_op = self.air.instructions.items(.data)[@backingInt(inst)].pl_op;
3275 const index = pl_op.payload;3232 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);
3277 return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.size", &.{llvm_usize}, &.{3234 return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.size", &.{llvm_usize}, &.{
3278 try o.builder.intValue(.i32, index),3235 try o.builder.intValue(.i32, index),
3279 }, "");3236 }, "");
...@@ -3283,7 +3240,7 @@ fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build...@@ -3283,7 +3240,7 @@ fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build
3283 const o = self.object;3240 const o = self.object;
3284 const pl_op = self.air.instructions.items(.data)[@backingInt(inst)].pl_op;3241 const pl_op = self.air.instructions.items(.data)[@backingInt(inst)].pl_op;
3285 const index = pl_op.payload;3242 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);
3287 return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.grow", &.{llvm_isize}, &.{3244 return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.grow", &.{llvm_isize}, &.{
3288 try o.builder.intValue(.i32, index), try self.resolveInst(pl_op.operand),3245 try o.builder.intValue(.i32, index), try self.resolveInst(pl_op.operand),
3289 }, "");3246 }, "");
...@@ -3310,7 +3267,7 @@ fn airMin(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {...@@ -3310,7 +3267,7 @@ fn airMin(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
3310 .normal,3267 .normal,
3311 .none,3268 .none,
3312 if (scalar_ty.isSignedInt(zcu)) .smin else .umin,3269 if (scalar_ty.isSignedInt(zcu)) .smin else .umin,
3313 &.{try o.lowerType(inst_ty, .by_value)},3270 &.{try o.lowerType(inst_ty, .as_value)},
3314 &.{ lhs, rhs },3271 &.{ lhs, rhs },
3315 "",3272 "",
3316 );3273 );
...@@ -3330,7 +3287,7 @@ fn airMax(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {...@@ -3330,7 +3287,7 @@ fn airMax(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
3330 .normal,3287 .normal,
3331 .none,3288 .none,
3332 if (scalar_ty.isSignedInt(zcu)) .smax else .umax,3289 if (scalar_ty.isSignedInt(zcu)) .smax else .umax,
3333 &.{try o.lowerType(inst_ty, .by_value)},3290 &.{try o.lowerType(inst_ty, .as_value)},
3334 &.{ lhs, rhs },3291 &.{ lhs, rhs },
3335 "",3292 "",
3336 );3293 );
...@@ -3342,7 +3299,7 @@ fn airSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value...@@ -3342,7 +3299,7 @@ fn airSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
3342 const ptr = try self.resolveInst(bin_op.lhs);3299 const ptr = try self.resolveInst(bin_op.lhs);
3343 const len = try self.resolveInst(bin_op.rhs);3300 const len = try self.resolveInst(bin_op.rhs);
3344 const inst_ty = self.typeOfIndex(inst);3301 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 }, "");
3346}3303}
33473304
3348fn airAdd(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value {3305fn airAdd(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value {
...@@ -3373,7 +3330,7 @@ fn airSafeArithmetic(...@@ -3373,7 +3330,7 @@ fn airSafeArithmetic(
3373 const scalar_ty = inst_ty.scalarType(zcu);3330 const scalar_ty = inst_ty.scalarType(zcu);
33743331
3375 const intrinsic = if (scalar_ty.isSignedInt(zcu)) signed_intrinsic else unsigned_intrinsic;3332 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);
3377 const results =3334 const results =
3378 try fg.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_inst_ty}, &.{ lhs, rhs }, "");3335 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...@@ -3423,7 +3380,7 @@ fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
3423 .normal,3380 .normal,
3424 .none,3381 .none,
3425 if (scalar_ty.isSignedInt(zcu)) .@"sadd.sat" else .@"uadd.sat",3382 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)},
3427 &.{ lhs, rhs },3384 &.{ lhs, rhs },
3428 "",3385 "",
3429 );3386 );
...@@ -3462,7 +3419,7 @@ fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value...@@ -3462,7 +3419,7 @@ fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
3462 .normal,3419 .normal,
3463 .none,3420 .none,
3464 if (scalar_ty.isSignedInt(zcu)) .@"ssub.sat" else .@"usub.sat",3421 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)},
3466 &.{ lhs, rhs },3423 &.{ lhs, rhs },
3467 "",3424 "",
3468 );3425 );
...@@ -3501,7 +3458,7 @@ fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value...@@ -3501,7 +3458,7 @@ fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
3501 .normal,3458 .normal,
3502 .none,3459 .none,
3503 if (scalar_ty.isSignedInt(zcu)) .@"smul.fix.sat" else .@"umul.fix.sat",3460 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)},
3505 &.{ lhs, rhs, .@"0" },3462 &.{ lhs, rhs, .@"0" },
3506 "",3463 "",
3507 );3464 );
...@@ -3545,8 +3502,8 @@ fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind)...@@ -3545,8 +3502,8 @@ fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind)
3545 return self.buildFloatOp(.floor, fast, inst_ty, 1, .{result});3502 return self.buildFloatOp(.floor, fast, inst_ty, 1, .{result});
3546 }3503 }
3547 if (scalar_ty.isSignedInt(zcu)) {3504 if (scalar_ty.isSignedInt(zcu)) {
3548 const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value);3505 const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value);
3549 const inst_llvm_ty = try o.lowerType(inst_ty, .by_value);3506 const inst_llvm_ty = try o.lowerType(inst_ty, .as_value);
35503507
3551 const ExpectedContents = [std.math.big.int.calcTwosCompLimbCount(256)]std.math.big.Limb;3508 const ExpectedContents = [std.math.big.int.calcTwosCompLimbCount(256)]std.math.big.Limb;
3552 var bfa_buf: ExpectedContents = undefined;3509 var bfa_buf: ExpectedContents = undefined;
...@@ -3594,8 +3551,8 @@ fn airDivCeil(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind)...@@ -3594,8 +3551,8 @@ fn airDivCeil(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind)
3594 return self.buildFloatOp(.ceil, fast, inst_ty, 1, .{result});3551 return self.buildFloatOp(.ceil, fast, inst_ty, 1, .{result});
3595 }3552 }
3596 if (scalar_ty.isSignedInt(zcu)) {3553 if (scalar_ty.isSignedInt(zcu)) {
3597 const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value);3554 const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value);
3598 const inst_llvm_ty = try o.lowerType(inst_ty, .by_value);3555 const inst_llvm_ty = try o.lowerType(inst_ty, .as_value);
35993556
3600 const ExpectedContents = [std.math.big.int.calcTwosCompLimbCount(256)]std.math.big.Limb;3557 const ExpectedContents = [std.math.big.int.calcTwosCompLimbCount(256)]std.math.big.Limb;
3601 var bfa_buf: ExpectedContents = undefined;3558 var bfa_buf: ExpectedContents = undefined;
...@@ -3634,8 +3591,8 @@ fn airDivCeil(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind)...@@ -3634,8 +3591,8 @@ fn airDivCeil(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind)
3634 const correction = try self.wip.cast(.zext, need_correction, inst_llvm_ty, "divCeil.correction");3591 const correction = try self.wip.cast(.zext, need_correction, inst_llvm_ty, "divCeil.correction");
3635 return self.wip.bin(.@"add nsw", div, correction, "divCeil");3592 return self.wip.bin(.@"add nsw", div, correction, "divCeil");
3636 } else {3593 } else {
3637 const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value);3594 const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value);
3638 const inst_llvm_ty = try o.lowerType(inst_ty, .by_value);3595 const inst_llvm_ty = try o.lowerType(inst_ty, .as_value);
36393596
3640 const zero = try o.builder.splatValue(3597 const zero = try o.builder.splatValue(
3641 inst_llvm_ty,3598 inst_llvm_ty,
...@@ -3692,15 +3649,17 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo...@@ -3692,15 +3649,17 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo
3692 const lhs = try self.resolveInst(bin_op.lhs);3649 const lhs = try self.resolveInst(bin_op.lhs);
3693 const rhs = try self.resolveInst(bin_op.rhs);3650 const rhs = try self.resolveInst(bin_op.rhs);
3694 const inst_ty = self.typeOfIndex(inst);3651 const inst_ty = self.typeOfIndex(inst);
3695 const inst_llvm_ty = try o.lowerType(inst_ty, .by_value);
3696 const scalar_ty = inst_ty.scalarType(zcu);3652 const scalar_ty = inst_ty.scalarType(zcu);
36973653
3698 if (scalar_ty.isRuntimeFloat()) {3654 if (scalar_ty.isRuntimeFloat()) {
3699 const a = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ lhs, rhs });3655 const a = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ lhs, rhs });
3700 const b = try self.buildFloatOp(.add, fast, inst_ty, 2, .{ a, rhs });3656 const b = try self.buildFloatOp(.add, fast, inst_ty, 2, .{ a, rhs });
3701 const c = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ b, rhs });3657 const c = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ b, rhs });
3702 const zero = try o.builder.zeroInitValue(inst_llvm_ty);3658 const zero = if (isByRef(inst_ty, zcu)) zero: {
3703 const ltz = try self.buildFloatCmp(fast, .lt, inst_ty, .{ lhs, 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() });
3704 return self.wip.select(fast, ltz, c, a, "");3663 return self.wip.select(fast, ltz, c, a, "");
3705 }3664 }
3706 if (scalar_ty.isSignedInt(zcu)) {3665 if (scalar_ty.isSignedInt(zcu)) {
...@@ -3709,6 +3668,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo...@@ -3709,6 +3668,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo
3709 var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), self.gpa);3668 var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), self.gpa);
3710 const allocator = bfa.allocator();3669 const allocator = bfa.allocator();
37113670
3671 const inst_llvm_ty = try o.lowerType(inst_ty, .as_value);
3712 const scalar_bits = scalar_ty.intInfo(zcu).bits;3672 const scalar_bits = scalar_ty.intInfo(zcu).bits;
3713 var smin_big_int: std.math.big.int.Mutable = .{3673 var smin_big_int: std.math.big.int.Mutable = .{
3714 .limbs = try allocator.alloc(3674 .limbs = try allocator.alloc(
...@@ -3721,7 +3681,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo...@@ -3721,7 +3681,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo
3721 defer allocator.free(smin_big_int.limbs);3681 defer allocator.free(smin_big_int.limbs);
3722 smin_big_int.setTwosCompIntLimit(.min, .signed, scalar_bits);3682 smin_big_int.setTwosCompIntLimit(.min, .signed, scalar_bits);
3723 const smin = try o.builder.splatValue(inst_llvm_ty, try o.builder.bigIntConst(3683 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),
3725 smin_big_int.toConst(),3685 smin_big_int.toConst(),
3726 ));3686 ));
37273687
...@@ -3757,7 +3717,7 @@ fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value...@@ -3757,7 +3717,7 @@ fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
3757 const ty_pl = self.air.instructions.items(.data)[@backingInt(inst)].ty_pl;3717 const ty_pl = self.air.instructions.items(.data)[@backingInt(inst)].ty_pl;
3758 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;3718 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
3759 const ptr_or_slice = try self.resolveInst(bin_op.lhs);3719 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);
3761 const ptr_ty = self.typeOf(bin_op.lhs);3721 const ptr_ty = self.typeOf(bin_op.lhs);
3762 const elem_ty = ptr_ty.indexableElem(zcu);3722 const elem_ty = ptr_ty.indexableElem(zcu);
3763 const ptr = switch (ptr_ty.ptrSize(zcu)) {3723 const ptr = switch (ptr_ty.ptrSize(zcu)) {
...@@ -3790,7 +3750,7 @@ fn airOverflow(...@@ -3790,7 +3750,7 @@ fn airOverflow(
3790 assert(isByRef(inst_ty, zcu)); // auto structs are by-ref3750 assert(isByRef(inst_ty, zcu)); // auto structs are by-ref
37913751
3792 const intrinsic = if (scalar_ty.isSignedInt(zcu)) signed_intrinsic else unsigned_intrinsic;3752 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);
3794 const results =3754 const results =
3795 try self.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_lhs_ty}, &.{ lhs, rhs }, "");3755 try self.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_lhs_ty}, &.{ lhs, rhs }, "");
37963756
...@@ -3818,34 +3778,97 @@ fn airOverflow(...@@ -3818,34 +3778,97 @@ fn airOverflow(
3818}3778}
38193779
3820fn buildElementwiseCall(3780fn buildElementwiseCall(
3821 self: *FuncGen,3781 fg: *FuncGen,
3822 llvm_fn: Builder.Function.Index,3782 fn_name: Builder.StrtabString,
3823 args_vectors: []const Builder.Value,3783 fn_info: Object.FuncInfo,
3824 result_vector: Builder.Value,3784 arg_values: []const Builder.Value,
3825 vector_len: usize,3785 vector_len: ?u32,
3826) Allocator.Error!Builder.Value {3786) Allocator.Error!Builder.Value {
3827 const o = self.object;3787 const o = fg.object;
3828 assert(args_vectors.len <= 3);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;3812 fg.wip.cursor = .{ .block = loop_block };
3831 var result = result_vector;3813 const index = try fg.wip.phi(.i32, "elementwise.index");
3832 while (i < vector_len) : (i += 1) {
3833 const index_i32 = try o.builder.intValue(.i32, i);
38343814
3835 var args: [3]Builder.Value = undefined;3815 var arg_elems_buf: [3]Builder.Value = undefined;
3836 for (args[0..args_vectors.len], args_vectors) |*arg_elem, arg_vector| {3816 const arg_elems = arg_elems_buf[0..arg_values.len];
3837 arg_elem.* = try self.wip.extractElement(arg_vector, index_i32, "");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);
3838 }3820 }
3839 const result_elem = try self.wip.call(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);
3840 .normal,3822 if (fn_info.return_type == .void_type) {
3841 .ccc,3823 assert(result_elem == .none);
3842 .none,3824 } else if (result_elem != .none) {
3843 llvm_fn.typeOf(&o.builder),3825 const result_elem_ptr = try fg.ptraddScaled(result_ptr, index.toValue(), ret_ty.abiSize(zcu));
3844 llvm_fn.toValue(&o.builder),3826 try fg.store(result_elem_ptr, .none, result_elem, ret_ty, .normal);
3845 args[0..args_vectors.len],3827 }
3846 "",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(),
3847 );3843 );
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 }
3849 }3872 }
3850 return result;3873 return result;
3851}3874}
...@@ -3853,19 +3876,18 @@ fn buildElementwiseCall(...@@ -3853,19 +3876,18 @@ fn buildElementwiseCall(
3853/// Creates a floating point comparison by lowering to the appropriate3876/// Creates a floating point comparison by lowering to the appropriate
3854/// hardware instruction or softfloat routine for the target3877/// hardware instruction or softfloat routine for the target
3855fn buildFloatCmp(3878fn buildFloatCmp(
3856 self: *FuncGen,3879 fg: *FuncGen,
3857 fast: Builder.FastMathKind,3880 fast: Builder.FastMathKind,
3858 pred: math.CompareOperator,3881 pred: math.CompareOperator,
3859 ty: Type,3882 ty: Type,
3860 params: [2]Builder.Value,3883 params: [2]Builder.Value,
3861) Allocator.Error!Builder.Value {3884) Allocator.Error!Builder.Value {
3862 const o = self.object;3885 const o = fg.object;
3863 const zcu = o.zcu;3886 const zcu = o.zcu;
3864 const target = zcu.getTarget();3887 const target = zcu.getTarget();
3865 const scalar_ty = ty.scalarType(zcu);3888 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)) {
3869 const cond: Builder.FloatCondition = switch (pred) {3891 const cond: Builder.FloatCondition = switch (pred) {
3870 .eq => .oeq,3892 .eq => .oeq,
3871 .neq => .une,3893 .neq => .une,
...@@ -3874,53 +3896,33 @@ fn buildFloatCmp(...@@ -3874,53 +3896,33 @@ fn buildFloatCmp(
3874 .gt => .ogt,3896 .gt => .ogt,
3875 .gte => .oge,3897 .gte => .oge,
3876 };3898 };
3877 return self.wip.fcmp(fast, cond, params[0], params[1], "");3899 return fg.wip.fcmp(fast, cond, params[0], params[1], "");
3878 }3900 }
38793901
3880 const float_bits = scalar_ty.floatBits(target);3902 const fn_name = try o.builder.strtabStringFmt("__{s}{s}f2", .{
3881 const compiler_rt_float_abbrev = compilerRtFloatAbbrev(float_bits);3903 switch (pred) {
3882 const fn_base_name = switch (pred) {3904 .neq => "ne",
3883 .neq => "ne",3905 .eq => "eq",
3884 .eq => "eq",3906 .lt => "lt",
3885 .lt => "lt",3907 .lte => "le",
3886 .lte => "le",3908 .gt => "gt",
3887 .gt => "gt",3909 .gte => "ge",
3888 .gte => "ge",3910 },
3889 };3911 compilerRtFloatAbbrev(target, scalar_ty.floatBits(target)),
3890 const fn_name = try o.builder.strtabStringFmt("__{s}{s}f2", .{ fn_base_name, compiler_rt_float_abbrev });3912 });
38913913 const result = try fg.buildElementwiseCall(fn_name, .{
3892 const libc_fn = try o.getLibcFunction(fn_name, &.{ scalar_llvm_ty, scalar_llvm_ty }, .i32);3914 .cc = target.cCallingConvention().?,
38933915 .param_types = &.{ scalar_ty.toIntern(), scalar_ty.toIntern() },
3894 const int_cond: Builder.IntegerCondition = switch (pred) {3916 .return_type = .i32_type,
3917 }, &params, if (ty.isVector(zcu)) ty.vectorLen(zcu) else null);
3918 return fg.wip.icmp(switch (pred) {
3895 .eq => .eq,3919 .eq => .eq,
3896 .neq => .ne,3920 .neq => .ne,
3897 .lt => .slt,3921 .lt => .slt,
3898 .lte => .sle,3922 .lte => .sle,
3899 .gt => .sgt,3923 .gt => .sgt,
3900 .gte => .sge,3924 .gte => .sge,
3901 };3925 }, result, try o.builder.splatValue(result.typeOfWip(&fg.wip), .@"0"), "");
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", "");
3924}3926}
39253927
3926const FloatOp = enum {3928const FloatOp = enum {
...@@ -3949,32 +3951,30 @@ const FloatOp = enum {...@@ -3949,32 +3951,30 @@ const FloatOp = enum {
3949 trunc,3951 trunc,
3950};3952};
39513953
3952const FloatOpStrat = union(enum) {
3953 intrinsic: []const u8,
3954 libc: Builder.String,
3955};
3956
3957/// Creates a floating point operation (add, sub, fma, sqrt, exp, etc.)3954/// Creates a floating point operation (add, sub, fma, sqrt, exp, etc.)
3958/// by lowering to the appropriate hardware instruction or softfloat3955/// by lowering to the appropriate hardware instruction or softfloat
3959/// routine for the target3956/// routine for the target
3960fn buildFloatOp(3957fn buildFloatOp(
3961 self: *FuncGen,3958 fg: *FuncGen,
3962 comptime op: FloatOp,3959 comptime op: FloatOp,
3963 fast: Builder.FastMathKind,3960 fast: Builder.FastMathKind,
3964 ty: Type,3961 ty: Type,
3965 comptime params_len: usize,3962 comptime params_len: usize,
3966 params: [params_len]Builder.Value,3963 params: [params_len]Builder.Value,
3967) Allocator.Error!Builder.Value {3964) Allocator.Error!Builder.Value {
3968 const o = self.object;3965 const o = fg.object;
3969 const zcu = o.zcu;3966 const zcu = o.zcu;
3970 const target = zcu.getTarget();3967 const target = zcu.getTarget();
3971 const scalar_ty = ty.scalarType(zcu);3968 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) {
3975 // Some operations are dedicated LLVM instructions, not available as intrinsics3971 // Some operations are dedicated LLVM instructions, not available as intrinsics
3976 .neg => return self.wip.un(.fneg, params[0], ""),3972 .neg => if (intrinsicsAllowed(.compiler_rt, scalar_ty, target)) return fg.wip.un(.fneg, params[0], ""),
3977 .add, .sub, .mul, .div, .fmod => return self.wip.bin(switch (fast) {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) {
3978 .normal => switch (op) {3978 .normal => switch (op) {
3979 .add => .fadd,3979 .add => .fadd,
3980 .sub => .fsub,3980 .sub => .fsub,
...@@ -3992,6 +3992,7 @@ fn buildFloatOp(...@@ -3992,6 +3992,7 @@ fn buildFloatOp(
3992 else => unreachable,3992 else => unreachable,
3993 },3993 },
3994 }, params[0], params[1], ""),3994 }, params[0], params[1], ""),
3995 .fma,
3995 .fmax,3996 .fmax,
3996 .fmin,3997 .fmin,
3997 .ceil,3998 .ceil,
...@@ -4006,9 +4007,10 @@ fn buildFloatOp(...@@ -4006,9 +4007,10 @@ fn buildFloatOp(
4006 .round,4007 .round,
4007 .sin,4008 .sin,
4008 .sqrt,4009 .sqrt,
4010 .tan,
4009 .trunc,4011 .trunc,
4010 .fma,4012 => if (intrinsicsAllowed(.libc, scalar_ty, target)) return fg.wip.callIntrinsic(fast, .none, switch (op) {
4011 => return self.wip.callIntrinsic(fast, .none, switch (op) {4013 .fma => .fma,
4012 .fmax => .maxnum,4014 .fmax => .maxnum,
4013 .fmin => .minnum,4015 .fmin => .minnum,
4014 .ceil => .ceil,4016 .ceil => .ceil,
...@@ -4023,39 +4025,154 @@ fn buildFloatOp(...@@ -4023,39 +4025,154 @@ fn buildFloatOp(
4023 .round => .round,4025 .round => .round,
4024 .sin => .sin,4026 .sin => .sin,
4025 .sqrt => .sqrt,4027 .sqrt => .sqrt,
4028 .tan => .tan,
4026 .trunc => .trunc,4029 .trunc => .trunc,
4027 .fma => .fma,
4028 else => unreachable,4030 else => unreachable,
4029 }, &.{llvm_ty}, &params, ""),4031 }, &.{try o.lowerType(ty, .as_value)}, &params, ""),
4030 .tan => unreachable,4032 }
4031 };
40324033
4033 const float_bits = scalar_ty.floatBits(target);4034 const float_bits = scalar_ty.floatBits(target);
4034 const fn_name = switch (op) {4035 const fn_name = switch (op) {
4035 .neg => {4036 // In these cases we can generate a softfloat operation by modifying the sign bit using a bitwise operation.
4036 // In this case we can generate a softfloat negation by XORing the4037 .neg, .fabs => if (isByRef(scalar_ty, zcu)) {
4037 // bits with a constant.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 {
4038 const int_ty = try o.builder.intType(@intCast(float_bits));4149 const int_ty = try o.builder.intType(@intCast(float_bits));
4039 const cast_ty = switch (ty.zigTypeTag(zcu)) {4150 const cast_ty = switch (ty.zigTypeTag(zcu)) {
4040 .vector => try o.builder.vectorType(.normal, ty.vectorLen(zcu), int_ty),4151 .vector => try o.builder.vectorType(.normal, ty.vectorLen(zcu), int_ty),
4041 else => int_ty,4152 else => int_ty,
4042 };4153 };
4043 const sign_mask = try o.builder.splatValue(4154 const sign_bit = @as(u128, 1) << @intCast(float_bits - 1);
4044 cast_ty,4155 const bitwise_rhs = try o.builder.splatValue(cast_ty, try o.builder.intConst(int_ty, switch (op) {
4045 try o.builder.intConst(int_ty, @as(u128, 1) << @intCast(float_bits - 1)),4156 else => unreachable,
4046 );4157 .neg => sign_bit,
4047 const bitcasted_operand = try self.wip.cast(.bitcast, params[0], cast_ty, "");4158 .fabs => sign_bit - 1,
4048 const result = try self.wip.bin(.xor, bitcasted_operand, sign_mask, "");4159 }));
4049 return self.wip.cast(.bitcast, result, llvm_ty, "");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, "");
4050 },4168 },
4051 .add, .sub, .div, .mul => try o.builder.strtabStringFmt("__{s}{s}f3", .{4169 .add, .sub, .div, .mul => try o.builder.strtabStringFmt("__{s}{s}f3", .{
4052 @tagName(op), compilerRtFloatAbbrev(float_bits),4170 @tagName(op), compilerRtFloatAbbrev(target, float_bits),
4053 }),4171 }),
4054 .ceil,4172 .ceil,
4055 .cos,4173 .cos,
4056 .exp,4174 .exp,
4057 .exp2,4175 .exp2,
4058 .fabs,
4059 .floor,4176 .floor,
4060 .fma,4177 .fma,
4061 .fmax,4178 .fmax,
...@@ -4073,27 +4190,27 @@ fn buildFloatOp(...@@ -4073,27 +4190,27 @@ fn buildFloatOp(
4073 libcFloatPrefix(float_bits), @tagName(op), libcFloatSuffix(float_bits),4190 libcFloatPrefix(float_bits), @tagName(op), libcFloatSuffix(float_bits),
4074 }),4191 }),
4075 };4192 };
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);4200/// Creates a floating point cast operation by lowering to the specified softfloat routine.
4078 const libc_fn = try o.getLibcFunction(4201fn buildFloatCastCall(
4079 fn_name,4202 fg: *FuncGen,
4080 @as([3]Builder.Type, @splat(scalar_llvm_ty))[0..params.len],4203 dest_ty: Type,
4081 scalar_llvm_ty,4204 fn_name: Builder.StrtabString,
4082 );4205 operand_ty: Type,
4083 if (ty.zigTypeTag(zcu) == .vector) {4206 operand: Builder.Value,
4084 const result = try o.builder.poisonValue(llvm_ty);4207) Allocator.Error!Builder.Value {
4085 return self.buildElementwiseCall(libc_fn, &params, result, ty.vectorLen(zcu));4208 const zcu = fg.object.zcu;
4086 }4209 return fg.buildElementwiseCall(fn_name, .{
40874210 .cc = zcu.getTarget().cCallingConvention().?,
4088 return self.wip.call(4211 .param_types = &.{operand_ty.scalarType(zcu).toIntern()},
4089 fast.toCallKind(),4212 .return_type = dest_ty.scalarType(zcu).toIntern(),
4090 .ccc,4213 }, &.{operand}, if (operand_ty.isVector(zcu)) operand_ty.vectorLen(zcu) else null);
4091 .none,
4092 libc_fn.typeOf(&o.builder),
4093 libc_fn.toValue(&o.builder),
4094 &params,
4095 "",
4096 );
4097}4214}
40984215
4099fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {4216fn 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...@@ -4129,7 +4246,7 @@ fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Buil
4129 const dest_ty = self.typeOfIndex(inst);4246 const dest_ty = self.typeOfIndex(inst);
4130 assert(isByRef(dest_ty, zcu)); // auto structs are by-ref4247 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
4134 const result = try self.wip.bin(.shl, lhs, casted_rhs, "");4251 const result = try self.wip.bin(.shl, lhs, casted_rhs, "");
4135 const reconstructed = try self.wip.bin(if (lhs_scalar_ty.isSignedInt(zcu))4252 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...@@ -4196,7 +4313,7 @@ fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
4196 }4313 }
4197 const lhs_scalar_ty = lhs_ty.scalarType(zcu);4314 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), "");
4200 return self.wip.bin(if (lhs_scalar_ty.isSignedInt(zcu))4317 return self.wip.bin(if (lhs_scalar_ty.isSignedInt(zcu))
4201 .@"shl nsw"4318 .@"shl nsw"
4202 else4319 else
...@@ -4217,7 +4334,7 @@ fn airShl(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {...@@ -4217,7 +4334,7 @@ fn airShl(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
4217 // features which we do not use. Therefore this branch is currently impossible.4334 // features which we do not use. Therefore this branch is currently impossible.
4218 unreachable;4335 unreachable;
4219 }4336 }
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), "");
4221 return self.wip.bin(.shl, lhs, casted_rhs, "");4338 return self.wip.bin(.shl, lhs, casted_rhs, "");
4222}4339}
42234340
...@@ -4231,8 +4348,8 @@ fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value...@@ -4231,8 +4348,8 @@ fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
42314348
4232 const lhs_ty = self.typeOf(bin_op.lhs);4349 const lhs_ty = self.typeOf(bin_op.lhs);
4233 const lhs_info = lhs_ty.intInfo(zcu);4350 const lhs_info = lhs_ty.intInfo(zcu);
4234 const llvm_lhs_ty = try o.lowerType(lhs_ty, .by_value);4351 const llvm_lhs_ty = try o.lowerType(lhs_ty, .as_value);
4235 const llvm_lhs_scalar_ty = try o.lowerType(lhs_ty.scalarType(zcu), .by_value);4352 const llvm_lhs_scalar_ty = try o.lowerType(lhs_ty.scalarType(zcu), .as_value);
42364353
4237 const rhs_ty = self.typeOf(bin_op.rhs);4354 const rhs_ty = self.typeOf(bin_op.rhs);
4238 if (lhs_ty.isVector(zcu) and !rhs_ty.isVector(zcu)) {4355 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...@@ -4242,8 +4359,8 @@ fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
4242 }4359 }
4243 const rhs_info = rhs_ty.intInfo(zcu);4360 const rhs_info = rhs_ty.intInfo(zcu);
4244 assert(rhs_info.signedness == .unsigned);4361 assert(rhs_info.signedness == .unsigned);
4245 const llvm_rhs_ty = try o.lowerType(rhs_ty, .by_value);4362 const llvm_rhs_ty = try o.lowerType(rhs_ty, .as_value);
4246 const llvm_rhs_scalar_ty = try o.lowerType(rhs_ty.scalarType(zcu), .by_value);4363 const llvm_rhs_scalar_ty = try o.lowerType(rhs_ty.scalarType(zcu), .as_value);
42474364
4248 const result = try self.wip.callIntrinsic(4365 const result = try self.wip.callIntrinsic(
4249 .normal,4366 .normal,
...@@ -4319,7 +4436,7 @@ fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) Allocator.Error!...@@ -4319,7 +4436,7 @@ fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) Allocator.Error!
4319 }4436 }
4320 const lhs_scalar_ty = lhs_ty.scalarType(zcu);4437 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), "");
4323 const is_signed_int = lhs_scalar_ty.isSignedInt(zcu);4440 const is_signed_int = lhs_scalar_ty.isSignedInt(zcu);
43244441
4325 return self.wip.bin(if (is_exact)4442 return self.wip.bin(if (is_exact)
...@@ -4340,7 +4457,7 @@ fn airAbs(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {...@@ -4340,7 +4457,7 @@ fn airAbs(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
4340 .normal,4457 .normal,
4341 .none,4458 .none,
4342 .abs,4459 .abs,
4343 &.{try o.lowerType(operand_ty, .by_value)},4460 &.{try o.lowerType(operand_ty, .as_value)},
4344 &.{ operand, .false },4461 &.{ operand, .false },
4345 "",4462 "",
4346 ),4463 ),
...@@ -4354,7 +4471,7 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!...@@ -4354,7 +4471,7 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!
4354 const zcu = o.zcu;4471 const zcu = o.zcu;
4355 const ty_op = fg.air.instructions.items(.data)[@backingInt(inst)].ty_op;4472 const ty_op = fg.air.instructions.items(.data)[@backingInt(inst)].ty_op;
4356 const dest_ty = fg.typeOfIndex(inst);4473 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);
4358 const operand = try fg.resolveInst(ty_op.operand);4475 const operand = try fg.resolveInst(ty_op.operand);
4359 const operand_ty = fg.typeOf(ty_op.operand);4476 const operand_ty = fg.typeOf(ty_op.operand);
4360 const operand_info = operand_ty.intInfo(zcu);4477 const operand_info = operand_ty.intInfo(zcu);
...@@ -4382,8 +4499,8 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!...@@ -4382,8 +4499,8 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!
43824499
4383 if (!have_min_check and !have_max_check) break :bounds_check;4500 if (!have_min_check and !have_max_check) break :bounds_check;
43844501
4385 const operand_llvm_ty = try o.lowerType(operand_ty, .by_value);4502 const operand_llvm_ty = try o.lowerType(operand_ty, .as_value);
4386 const operand_scalar_llvm_ty = try o.lowerType(operand_scalar, .by_value);4503 const operand_scalar_llvm_ty = try o.lowerType(operand_scalar, .as_value);
43874504
4388 const is_vector = operand_ty.zigTypeTag(zcu) == .vector;4505 const is_vector = operand_ty.zigTypeTag(zcu) == .vector;
4389 assert(is_vector == (dest_ty.zigTypeTag(zcu) == .vector));4506 assert(is_vector == (dest_ty.zigTypeTag(zcu) == .vector));
...@@ -4461,7 +4578,7 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!...@@ -4461,7 +4578,7 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!
4461fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {4578fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
4462 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;4579 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
4463 const operand = try self.resolveInst(ty_op.operand);4580 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);
4465 return self.wip.cast(.trunc, operand, dest_llvm_ty, "");4582 return self.wip.cast(.trunc, operand, dest_llvm_ty, "");
4466}4583}
44674584
...@@ -4471,32 +4588,20 @@ fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu...@@ -4471,32 +4588,20 @@ fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu
4471 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;4588 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
4472 const operand = try self.resolveInst(ty_op.operand);4589 const operand = try self.resolveInst(ty_op.operand);
4473 const operand_ty = self.typeOf(ty_op.operand);4590 const operand_ty = self.typeOf(ty_op.operand);
4591 const operand_scalar_ty = operand_ty.scalarType(zcu);
4474 const dest_ty = self.typeOfIndex(inst);4592 const dest_ty = self.typeOfIndex(inst);
4593 const dest_scalar_ty = dest_ty.scalarType(zcu);
4475 const target = zcu.getTarget();4594 const target = zcu.getTarget();
44764595
4477 if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) {4596 if (intrinsicsAllowed(.compiler_rt, dest_scalar_ty, target) and
4478 return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty, .by_value), "");4597 intrinsicsAllowed(.compiler_rt, operand_scalar_ty, target))
4479 } else {4598 return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty, .as_value), "");
4480 const operand_llvm_ty = try o.lowerType(operand_ty, .by_value);4599 const dest_bits = dest_scalar_ty.floatBits(target);
4481 const dest_llvm_ty = try o.lowerType(dest_ty, .by_value);4600 const src_bits = operand_scalar_ty.floatBits(target);
44824601 const fn_name = try o.builder.strtabStringFmt("__trunc{s}f{s}f2", .{
4483 const dest_bits = dest_ty.floatBits(target);4602 compilerRtFloatAbbrev(target, src_bits), compilerRtFloatAbbrev(target, dest_bits),
4484 const src_bits = operand_ty.floatBits(target);4603 });
4485 const fn_name = try o.builder.strtabStringFmt("__trunc{s}f{s}f2", .{4604 return self.buildFloatCastCall(dest_ty, fn_name, operand_ty, operand);
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 }
4500}4605}
45014606
4502fn airFpext(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {4607fn 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...@@ -4505,38 +4610,20 @@ fn airFpext(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
4505 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;4610 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
4506 const operand = try self.resolveInst(ty_op.operand);4611 const operand = try self.resolveInst(ty_op.operand);
4507 const operand_ty = self.typeOf(ty_op.operand);4612 const operand_ty = self.typeOf(ty_op.operand);
4613 const operand_scalar_ty = operand_ty.scalarType(zcu);
4508 const dest_ty = self.typeOfIndex(inst);4614 const dest_ty = self.typeOfIndex(inst);
4615 const dest_scalar_ty = dest_ty.scalarType(zcu);
4509 const target = zcu.getTarget();4616 const target = zcu.getTarget();
45104617
4511 if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) {4618 if (intrinsicsAllowed(.compiler_rt, dest_scalar_ty, target) and
4512 return self.wip.cast(.fpext, operand, try o.lowerType(dest_ty, .by_value), "");4619 intrinsicsAllowed(.compiler_rt, operand_scalar_ty, target))
4513 } else {4620 return self.wip.cast(.fpext, operand, try o.lowerType(dest_ty, .as_value), "");
4514 const operand_llvm_ty = try o.lowerType(operand_ty, .by_value);4621 const dest_bits = dest_scalar_ty.floatBits(target);
4515 const dest_llvm_ty = try o.lowerType(dest_ty, .by_value);4622 const src_bits = operand_scalar_ty.floatBits(target);
45164623 const fn_name = try o.builder.strtabStringFmt("__extend{s}f{s}f2", .{
4517 const dest_bits = dest_ty.scalarType(zcu).floatBits(target);4624 compilerRtFloatAbbrev(target, src_bits), compilerRtFloatAbbrev(target, dest_bits),
4518 const src_bits = operand_ty.scalarType(zcu).floatBits(target);4625 });
4519 const fn_name = try o.builder.strtabStringFmt("__extend{s}f{s}f2", .{4626 return self.buildFloatCastCall(dest_ty, fn_name, operand_ty, operand);
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 }
4540}4627}
45414628
4542fn airBitCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Builder.Value {4629fn 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!...@@ -4558,28 +4645,161 @@ fn airBitCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!
4558 // * bool/int/float <-> bool/int/float4645 // * bool/int/float <-> bool/int/float
4559 // * `@Vector(n, A)` <-> `@Vector(n, B)`4646 // * `@Vector(n, A)` <-> `@Vector(n, B)`
4560 //4647 //
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));4651 if (isByRef(operand_ty, zcu)) {
4564 assert(!isByRef(dest_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);4662 const len = if (operand_ty.toIntern() != operand_scalar_ty.toIntern())
4567 const result = try fg.wip.cast(.bitcast, operand, llvm_dest_ty, "");4663 operand_ty.vectorLen(zcu)
4568 if (safety and dest_ty.zigTypeTag(zcu) == .@"enum" and !dest_ty.isNonexhaustiveEnum(zcu)) {4664 else
4569 const llvm_fn = try o.getIsNamedEnumValueFunction(dest_ty);4665 null;
4570 const is_valid_enum_val = try fg.wip.call(4666 const operand_scalar_size = operand_scalar_ty.abiSize(zcu);
4571 .normal,4667 var result = if (len) |_|
4572 .fastcc,4668 try o.builder.poisonValue(try o.lowerType(dest_ty, .as_value))
4573 .none,4669 else
4574 llvm_fn.typeOf(&o.builder),4670 undefined;
4575 llvm_fn.toValue(&o.builder),4671 for (0..len orelse 1) |index| {
4576 &.{result},4672 const result_elem = result_elem: switch (bits) {
4577 "",4673 else => unreachable,
4578 );4674 80 => {
4579 const fail_block = try fg.wip.block(1, "ValidEnumFail");4675 const f80_layout = o.softF80Layout(.{}) catch unreachable;
4580 const ok_block = try fg.wip.block(1, "ValidEnumOk");4676 const mantissa = try fg.load(
4581 _ = try fg.wip.brCond(is_valid_enum_val, ok_block, fail_block, .none);4677 try fg.ptraddConst(operand, operand_scalar_size * index + f80_layout.mantissa_offset),
4582 fg.wip.cursor = .{ .block = fail_block };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 };
4583 try fg.buildSimplePanic(.invalid_enum_value);4803 try fg.buildSimplePanic(.invalid_enum_value);
4584 fg.wip.cursor = .{ .block = ok_block };4804 fg.wip.cursor = .{ .block = ok_block };
4585 }4805 }
...@@ -4606,7 +4826,7 @@ fn airPtrFromInt(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val...@@ -4606,7 +4826,7 @@ fn airPtrFromInt(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
4606 assert(dest_ty.scalarType(zcu).isPtrAtRuntime(zcu));4826 assert(dest_ty.scalarType(zcu).isPtrAtRuntime(zcu));
46074827
4608 const operand = try fg.resolveInst(ty_op.operand);4828 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);
4610 return fg.wip.cast(.inttoptr, operand, llvm_dest_ty, "");4830 return fg.wip.cast(.inttoptr, operand, llvm_dest_ty, "");
4611}4831}
46124832
...@@ -4620,7 +4840,7 @@ fn airIntFromPtr(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val...@@ -4620,7 +4840,7 @@ fn airIntFromPtr(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
4620 assert(dest_ty.scalarType(zcu).toIntern() == .usize_type);4840 assert(dest_ty.scalarType(zcu).toIntern() == .usize_type);
46214841
4622 const operand = try fg.resolveInst(ty_op.operand);4842 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);
4624 return fg.wip.cast(.ptrtoint, operand, llvm_dest_ty, "");4844 return fg.wip.cast(.ptrtoint, operand, llvm_dest_ty, "");
4625}4845}
46264846
...@@ -4689,7 +4909,7 @@ fn airArg(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {...@@ -4689,7 +4909,7 @@ fn airArg(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
4689 },4909 },
4690 "",4910 "",
4691 );4911 );
4692 } else if (mod.optimize_mode == .Debug) {4912 } else if (mod.optimize_mode == .debug) {
4693 const alloca = try self.buildZigAlloca(inst_ty, .none);4913 const alloca = try self.buildZigAlloca(inst_ty, .none);
4694 try self.store(alloca, .none, arg_val, inst_ty, .normal);4914 try self.store(alloca, .none, arg_val, inst_ty, .normal);
4695 _ = try self.wip.callIntrinsic(4915 _ = try self.wip.callIntrinsic(
...@@ -4730,7 +4950,7 @@ fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value...@@ -4730,7 +4950,7 @@ fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
4730 const ptr_align = ptr_ty.ptrAlignment(zcu);4950 const ptr_align = ptr_ty.ptrAlignment(zcu);
4731 const elem_ty = ptr_ty.childType(zcu);4951 const elem_ty = ptr_ty.childType(zcu);
4732 if (!elem_ty.hasRuntimeBits(zcu)) {4952 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();
4734 }4954 }
4735 return self.buildZigAlloca(elem_ty, ptr_align);4955 return self.buildZigAlloca(elem_ty, ptr_align);
4736}4956}
...@@ -4743,7 +4963,7 @@ fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value...@@ -4743,7 +4963,7 @@ fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
4743 const ptr_align = ptr_ty.ptrAlignment(zcu);4963 const ptr_align = ptr_ty.ptrAlignment(zcu);
4744 const elem_ty = ptr_ty.childType(zcu);4964 const elem_ty = ptr_ty.childType(zcu);
4745 if (!elem_ty.hasRuntimeBits(zcu)) {4965 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();
4747 }4967 }
4748 return self.buildZigAlloca(elem_ty, ptr_align);4968 return self.buildZigAlloca(elem_ty, ptr_align);
4749}4969}
...@@ -4754,10 +4974,7 @@ fn buildZigAlloca(fg: *FuncGen, ty: Type, @"align": InternPool.Alignment) Alloca...@@ -4754,10 +4974,7 @@ fn buildZigAlloca(fg: *FuncGen, ty: Type, @"align": InternPool.Alignment) Alloca
4754 .none => ty.abiAlignment(o.zcu),4974 .none => ty.abiAlignment(o.zcu),
4755 else => |a| a,4975 else => |a| a,
4756 };4976 };
4757 return fg.buildAlloca(4977 return fg.buildAlloca(try o.lowerType(ty, .in_memory), resolved_align.toLlvm());
4758 try o.lowerType(ty, .in_memory),
4759 resolved_align.toLlvm(),
4760 );
4761}4978}
47624979
4763/// Unlike `WipFunction.alloca`, this puts the alloca instruction at the top of the function.4980/// 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...@@ -4820,7 +5037,7 @@ fn airStore(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Bu
4820 // unexpected call in the user's code. This is problematic if the code in question is5037 // unexpected call in the user's code. This is problematic if the code in question is
4821 // not ready to correctly make calls yet, such as in our early PIE startup code, or in5038 // not ready to correctly make calls yet, such as in our early PIE startup code, or in
4822 // the early stages of a dynamic linker, etc.5039 // 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) {
4824 return .none;5041 return .none;
4825 }5042 }
48265043
...@@ -4832,7 +5049,7 @@ fn airStore(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Bu...@@ -4832,7 +5049,7 @@ fn airStore(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Bu
4832 return .none;5049 return .none;
4833 }5050 }
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));
4836 _ = try fg.wip.callMemSet(5053 _ = try fg.wip.callMemSet(
4837 ptr,5054 ptr,
4838 ptr_alignment.toLlvm(),5055 ptr_alignment.toLlvm(),
...@@ -4850,24 +5067,31 @@ fn airStore(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Bu...@@ -4850,24 +5067,31 @@ fn airStore(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Bu
4850 const elem = try fg.resolveInst(bin_op.rhs);5067 const elem = try fg.resolveInst(bin_op.rhs);
48515068
4852 if (ptr_info.flags.vector_index != .none) {5069 if (ptr_info.flags.vector_index != .none) {
4853 // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.5070 if (isByRef(elem_ty, zcu)) {
4854 const vec_ty = try fg.pt.vectorType(.{5071 const offset = @backingInt(ptr_info.flags.vector_index) * elem_ty.abiSize(zcu);
4855 .len = ptr_info.packed_offset.host_size,5072 const elem_ptr = try fg.ptraddConst(ptr, offset);
4856 .child = elem_ty.toIntern(),5073 try fg.store(elem_ptr, ptr_alignment.offset(offset), elem, elem_ty, access_kind);
4857 });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);5085 try fg.store(ptr, ptr_alignment, modified_vector, vec_ty, access_kind);
4860 const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index);5086 }
4861 const modified_vector = try fg.wip.insertElement(loaded_vector, elem, index_val, "");
48625087
4863 try fg.store(ptr, ptr_alignment, modified_vector, vec_ty, access_kind);
4864 return .none;5088 return .none;
4865 }5089 }
48665090
4867 if (ptr_info.packed_offset.host_size != 0) {5091 if (ptr_info.packed_offset.host_size != 0) {
4868 // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.5092 // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.
4869 const backing_int_ty = try fg.pt.intType(.unsigned, @intCast(ptr_info.packed_offset.host_size * 8));5093 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
4872 const backing_int_val = try fg.load(ptr, ptr_alignment, backing_int_ty, access_kind);5096 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 {...@@ -4927,32 +5151,98 @@ fn airLoad(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
4927 if (ptr_info.flags.is_volatile) .@"volatile" else .normal;5151 if (ptr_info.flags.is_volatile) .@"volatile" else .normal;
49285152
4929 if (ptr_info.flags.vector_index != .none) {5153 if (ptr_info.flags.vector_index != .none) {
4930 // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.5154 if (isByRef(elem_ty, zcu)) {
4931 const vec_ty = try fg.pt.vectorType(.{5155 const elem_size = elem_ty.abiSize(zcu);
4932 .len = ptr_info.packed_offset.host_size,5156 const offset = @backingInt(ptr_info.flags.vector_index) * elem_size;
4933 .child = elem_ty.toIntern(),5157 const elem_ptr = try fg.ptraddConst(ptr, offset);
4934 });5158 return fg.load(elem_ptr, ptr_align.offset(offset), elem_ty, access_kind);
4935 const vector_val = try fg.load(ptr, ptr_align, vec_ty, access_kind);5159 } else {
4936 const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index);5160 // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.
4937 return fg.wip.extractElement(vector_val, index_val, "");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 }
4938 }5169 }
49395170
4940 if (ptr_info.packed_offset.host_size == 0) {5171 if (ptr_info.packed_offset.host_size == 0) {
4941 return fg.load(ptr, ptr_align, elem_ty, access_kind);5172 return fg.load(ptr, ptr_align, elem_ty, access_kind);
4942 }5173 }
49435174
4944 assert(!isByRef(elem_ty, zcu)); // all packable types are by-val
4945
4946 // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.5175 // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.
4947 const backing_int_ty = try fg.pt.intType(.unsigned, @intCast(ptr_info.packed_offset.host_size * 8));5176 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
4950 const backing_int_val = try fg.load(ptr, ptr_align, backing_int_ty, .normal);5179 const backing_int_val = try fg.load(ptr, ptr_align, backing_int_ty, .normal);
49515180
4952 const elem_bits = ptr_ty.childType(zcu).bitSize(zcu);5181 const elem_bits = ptr_ty.childType(zcu).bitSize(zcu);
4953 const shift_amt = try o.builder.intValue(llvm_backing_int_ty, ptr_info.packed_offset.bit_offset);5182 const shift_amt = try o.builder.intValue(llvm_backing_int_ty, ptr_info.packed_offset.bit_offset);
4954 const shifted_value = try fg.wip.bin(.lshr, backing_int_val, shift_amt, "");5183 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
4957 if (elem_ty.zigTypeTag(zcu) == .float or elem_ty.zigTypeTag(zcu) == .vector) {5247 if (elem_ty.zigTypeTag(zcu) == .float or elem_ty.zigTypeTag(zcu) == .vector) {
4958 const same_size_int = try o.builder.intType(@intCast(elem_bits));5248 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...@@ -5002,7 +5292,7 @@ fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.V
5002fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {5292fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
5003 _ = inst;5293 _ = inst;
5004 const o = self.object;5294 const o = self.object;
5005 const llvm_usize = try o.lowerType(.usize, .by_value);5295 const llvm_usize = try o.lowerType(.usize, .as_value);
5006 if (!target_util.supportsReturnAddress(self.object.zcu.getTarget(), self.ownerModule().optimize_mode)) {5296 if (!target_util.supportsReturnAddress(self.object.zcu.getTarget(), self.ownerModule().optimize_mode)) {
5007 // https://github.com/ziglang/zig/issues/119465297 // https://github.com/ziglang/zig/issues/11946
5008 return o.builder.intValue(llvm_usize, 0);5298 return o.builder.intValue(llvm_usize, 0);
...@@ -5014,7 +5304,7 @@ fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu...@@ -5014,7 +5304,7 @@ fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu
5014fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {5304fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
5015 _ = inst;5305 _ = inst;
5016 const result = try self.wip.callIntrinsic(.normal, .none, .frameaddress, &.{.ptr}, &.{.@"0"}, "");5306 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), "");
5018}5308}
50195309
5020fn airCmpxchg(5310fn airCmpxchg(
...@@ -5031,7 +5321,7 @@ fn airCmpxchg(...@@ -5031,7 +5321,7 @@ fn airCmpxchg(
5031 var expected_value = try self.resolveInst(extra.expected_value);5321 var expected_value = try self.resolveInst(extra.expected_value);
5032 var new_value = try self.resolveInst(extra.new_value);5322 var new_value = try self.resolveInst(extra.new_value);
5033 const operand_ty = ptr_ty.childType(zcu);5323 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);
5035 const llvm_abi_ty = try self.getAtomicAbiType(operand_ty, false);5325 const llvm_abi_ty = try self.getAtomicAbiType(operand_ty, false);
5036 if (llvm_abi_ty != .none) {5326 if (llvm_abi_ty != .none) {
5037 // operand needs widening and truncating5327 // operand needs widening and truncating
...@@ -5101,7 +5391,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va...@@ -5101,7 +5391,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va
5101 const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float);5391 const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float);
5102 const ordering = toLlvmAtomicOrdering(extra.ordering());5392 const ordering = toLlvmAtomicOrdering(extra.ordering());
5103 const llvm_abi_ty = try self.getAtomicAbiType(operand_ty, op == .xchg);5393 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
5106 const access_kind: Builder.MemoryAccessKind =5396 const access_kind: Builder.MemoryAccessKind =
5107 if (ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;5397 if (ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
...@@ -5130,7 +5420,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va...@@ -5130,7 +5420,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va
51305420
5131 // If we are storing a pointer we need to convert to and from a plain old integer.5421 // If we are storing a pointer we need to convert to and from a plain old integer.
5132 const non_ptr_operand = switch (operand_ty.zigTypeTag(zcu)) {5422 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), ""),
5134 else => operand,5424 else => operand,
5135 };5425 };
51365426
...@@ -5169,7 +5459,7 @@ fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.V...@@ -5169,7 +5459,7 @@ fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.V
5169 Type.fromInterned(info.child).abiAlignment(zcu)).toLlvm();5459 Type.fromInterned(info.child).abiAlignment(zcu)).toLlvm();
5170 const access_kind: Builder.MemoryAccessKind =5460 const access_kind: Builder.MemoryAccessKind =
5171 if (info.flags.is_volatile) .@"volatile" else .normal;5461 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
5174 self.maybeMarkAllowZeroAccess(info);5464 self.maybeMarkAllowZeroAccess(info);
51755465
...@@ -5503,11 +5793,11 @@ fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic)...@@ -5503,11 +5793,11 @@ fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic)
5503 .normal,5793 .normal,
5504 .none,5794 .none,
5505 intrinsic,5795 intrinsic,
5506 &.{try o.lowerType(operand_ty, .by_value)},5796 &.{try o.lowerType(operand_ty, .as_value)},
5507 &.{ operand, .false },5797 &.{ operand, .false },
5508 "",5798 "",
5509 );5799 );
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), "");
5511}5801}
55125802
5513fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) Allocator.Error!Builder.Value {5803fn 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)...@@ -5521,11 +5811,11 @@ fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic)
5521 .normal,5811 .normal,
5522 .none,5812 .none,
5523 intrinsic,5813 intrinsic,
5524 &.{try o.lowerType(operand_ty, .by_value)},5814 &.{try o.lowerType(operand_ty, .as_value)},
5525 &.{operand},5815 &.{operand},
5526 "",5816 "",
5527 );5817 );
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), "");
5529}5819}
55305820
5531fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {5821fn 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...@@ -5538,7 +5828,7 @@ fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
55385828
5539 const inst_ty = self.typeOfIndex(inst);5829 const inst_ty = self.typeOfIndex(inst);
5540 var operand = try self.resolveInst(ty_op.operand);5830 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
5543 if (bits % 16 == 8) {5833 if (bits % 16 == 8) {
5544 // If not an even byte-multiple, we need zero-extend + shift-left 1 byte5834 // 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...@@ -5559,7 +5849,7 @@ fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
55595849
5560 const result =5850 const result =
5561 try self.wip.callIntrinsic(.normal, .none, .bswap, &.{llvm_operand_ty}, &.{operand}, "");5851 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), "");
5563}5853}
55645854
5565fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {5855fn 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...@@ -5579,7 +5869,7 @@ fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Bui
55795869
5580 for (0..names.len) |name_index| {5870 for (0..names.len) |name_index| {
5581 const err_int = ip.getErrorValueIfExists(names.get(ip)[name_index]).?;5871 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);
5583 try wip_switch.addCase(this_tag_int_value, valid_block, &self.wip);5873 try wip_switch.addCase(this_tag_int_value, valid_block, &self.wip);
5584 }5874 }
5585 self.wip.cursor = .{ .block = valid_block };5875 self.wip.cursor = .{ .block = valid_block };
...@@ -5638,7 +5928,7 @@ fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va...@@ -5638,7 +5928,7 @@ fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va
5638 const slice_ty = self.typeOfIndex(inst);5928 const slice_ty = self.typeOfIndex(inst);
56395929
5640 // If operand is small (e.g. `u8`), then signedness becomes a problem -- GEP always treats the index as signed.5930 // 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
5643 const error_name_table_ptr = try o.getErrorNameTable();5933 const error_name_table_ptr = try o.getErrorNameTable();
5644 const error_name_ptr = try self.ptraddScaled(error_name_table_ptr.toValue(&o.builder), operand_usize, slice_ty.abiSize(zcu));5934 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...@@ -5649,7 +5939,7 @@ fn airSplat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
5649 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;5939 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
5650 const scalar = try self.resolveInst(ty_op.operand);5940 const scalar = try self.resolveInst(ty_op.operand);
5651 const vector_ty = self.typeOfIndex(inst);5941 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, "");
5653}5943}
56545944
5655fn airSelect(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {5945fn 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...@@ -5672,9 +5962,9 @@ fn airShuffleOne(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
5672 const operand = try fg.resolveInst(unwrapped.operand);5962 const operand = try fg.resolveInst(unwrapped.operand);
5673 const mask = unwrapped.mask;5963 const mask = unwrapped.mask;
5674 const operand_ty = fg.typeOf(unwrapped.operand);5964 const operand_ty = fg.typeOf(unwrapped.operand);
5675 const llvm_operand_ty = try o.lowerType(operand_ty, .by_value);5965 const llvm_operand_ty = try o.lowerType(operand_ty, .as_value);
5676 const llvm_result_ty = try o.lowerType(unwrapped.result_ty, .by_value);5966 const llvm_result_ty = try o.lowerType(unwrapped.result_ty, .as_value);
5677 const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .by_value);5967 const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .as_value);
5678 const llvm_poison_elem = try o.builder.poisonConst(llvm_elem_ty);5968 const llvm_poison_elem = try o.builder.poisonConst(llvm_elem_ty);
5679 const llvm_poison_mask_elem = try o.builder.poisonConst(.i32);5969 const llvm_poison_mask_elem = try o.builder.poisonConst(.i32);
5680 const llvm_mask_ty = try o.builder.vectorType(.normal, @intCast(mask.len), .i32);5970 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...@@ -5704,7 +5994,7 @@ fn airShuffleOne(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
5704 .elem => llvm_poison_elem,5994 .elem => llvm_poison_elem,
5705 .value => |val| if (!Value.fromInterned(val).isUndef(zcu)) elem: {5995 .value => |val| if (!Value.fromInterned(val).isUndef(zcu)) elem: {
5706 any_defined_comptime_value = true;5996 any_defined_comptime_value = true;
5707 break :elem try o.lowerValue(val, .by_value);5997 break :elem try o.lowerValue(val, .as_value);
5708 } else llvm_poison_elem,5998 } else llvm_poison_elem,
5709 };5999 };
5710 }6000 }
...@@ -5776,7 +6066,7 @@ fn airShuffleTwo(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val...@@ -5776,7 +6066,7 @@ fn airShuffleTwo(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
5776 const unwrapped = fg.air.unwrapShuffleTwo(zcu, inst);6066 const unwrapped = fg.air.unwrapShuffleTwo(zcu, inst);
57776067
5778 const mask = unwrapped.mask;6068 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);
5780 const llvm_mask_ty = try o.builder.vectorType(.normal, @intCast(mask.len), .i32);6070 const llvm_mask_ty = try o.builder.vectorType(.normal, @intCast(mask.len), .i32);
5781 const llvm_poison_mask_elem = try o.builder.poisonConst(.i32);6071 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...@@ -5848,95 +6138,25 @@ fn airShuffleTwo(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
5848 );6138 );
5849}6139}
58506140
5851/// Reduce a vector by repeatedly applying `llvm_fn` to produce an accumulated result.6141fn airReduce(fg: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value {
5852///6142 const o = fg.object;
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;
5921 const zcu = o.zcu;6143 const zcu = o.zcu;
5922 const target = zcu.getTarget();6144 const target = zcu.getTarget();
59236145
5924 const reduce = self.air.instructions.items(.data)[@backingInt(inst)].reduce;6146 const reduce = fg.air.instructions.items(.data)[@backingInt(inst)].reduce;
5925 const operand = try self.resolveInst(reduce.operand);6147 const operand = try fg.resolveInst(reduce.operand);
5926 const operand_ty = self.typeOf(reduce.operand);6148 const operand_ty = fg.typeOf(reduce.operand);
5927 const llvm_operand_ty = try o.lowerType(operand_ty, .by_value);6149 const scalar_ty = fg.typeOfIndex(inst);
5928 const scalar_ty = self.typeOfIndex(inst);
5929 const llvm_scalar_ty = try o.lowerType(scalar_ty, .by_value);
59306150
5931 switch (reduce.operation) {6151 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) {
5933 .And => .@"vector.reduce.and",6153 .And => .@"vector.reduce.and",
5934 .Or => .@"vector.reduce.or",6154 .Or => .@"vector.reduce.or",
5935 .Xor => .@"vector.reduce.xor",6155 .Xor => .@"vector.reduce.xor",
5936 else => unreachable,6156 else => unreachable,
5937 }, &.{llvm_operand_ty}, &.{operand}, ""),6157 }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""),
5938 .Min, .Max => switch (scalar_ty.zigTypeTag(zcu)) {6158 .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) {
5940 .Min => if (scalar_ty.isSignedInt(zcu))6160 .Min => if (scalar_ty.isSignedInt(zcu))
5941 .@"vector.reduce.smin"6161 .@"vector.reduce.smin"
5942 else6162 else
...@@ -5946,29 +6166,29 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) A...@@ -5946,29 +6166,29 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) A
5946 else6166 else
5947 .@"vector.reduce.umax",6167 .@"vector.reduce.umax",
5948 else => unreachable,6168 else => unreachable,
5949 }, &.{llvm_operand_ty}, &.{operand}, ""),6169 }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""),
5950 .float => if (intrinsicsAllowed(scalar_ty, target))6170 .float => if (intrinsicsAllowed(.libc, scalar_ty, target))
5951 return self.wip.callIntrinsic(fast, .none, switch (reduce.operation) {6171 return fg.wip.callIntrinsic(fast, .none, switch (reduce.operation) {
5952 .Min => .@"vector.reduce.fmin",6172 .Min => .@"vector.reduce.fmin",
5953 .Max => .@"vector.reduce.fmax",6173 .Max => .@"vector.reduce.fmax",
5954 else => unreachable,6174 else => unreachable,
5955 }, &.{llvm_operand_ty}, &.{operand}, ""),6175 }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""),
5956 else => unreachable,6176 else => unreachable,
5957 },6177 },
5958 .Add, .Mul => switch (scalar_ty.zigTypeTag(zcu)) {6178 .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) {
5960 .Add => .@"vector.reduce.add",6180 .Add => .@"vector.reduce.add",
5961 .Mul => .@"vector.reduce.mul",6181 .Mul => .@"vector.reduce.mul",
5962 else => unreachable,6182 else => unreachable,
5963 }, &.{llvm_operand_ty}, &.{operand}, ""),6183 }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""),
5964 .float => if (intrinsicsAllowed(scalar_ty, target))6184 .float => if (intrinsicsAllowed(.compiler_rt, scalar_ty, target))
5965 return self.wip.callIntrinsic(fast, .none, switch (reduce.operation) {6185 return fg.wip.callIntrinsic(fast, .none, switch (reduce.operation) {
5966 .Add => .@"vector.reduce.fadd",6186 .Add => .@"vector.reduce.fadd",
5967 .Mul => .@"vector.reduce.fmul",6187 .Mul => .@"vector.reduce.fmul",
5968 else => unreachable,6188 else => unreachable,
5969 }, &.{llvm_operand_ty}, &.{ switch (reduce.operation) {6189 }, &.{try o.lowerType(operand_ty, .as_value)}, &.{ switch (reduce.operation) {
5970 .Add => try o.builder.fpValue(llvm_scalar_ty, -0.0),6190 .Add => try o.builder.fpValue(try o.lowerType(scalar_ty, .as_value), -0.0),
5971 .Mul => try o.builder.fpValue(llvm_scalar_ty, 1.0),6191 .Mul => try o.builder.fpValue(try o.lowerType(scalar_ty, .as_value), 1.0),
5972 else => unreachable,6192 else => unreachable,
5973 }, operand }, ""),6193 }, operand }, ""),
5974 else => unreachable,6194 else => unreachable,
...@@ -5986,62 +6206,119 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) A...@@ -5986,62 +6206,119 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) A
5986 libcFloatPrefix(float_bits), libcFloatSuffix(float_bits),6206 libcFloatPrefix(float_bits), libcFloatSuffix(float_bits),
5987 }),6207 }),
5988 .Add => try o.builder.strtabStringFmt("__add{s}f3", .{6208 .Add => try o.builder.strtabStringFmt("__add{s}f3", .{
5989 compilerRtFloatAbbrev(float_bits),6209 compilerRtFloatAbbrev(target, float_bits),
5990 }),6210 }),
5991 .Mul => try o.builder.strtabStringFmt("__mul{s}f3", .{6211 .Mul => try o.builder.strtabStringFmt("__mul{s}f3", .{
5992 compilerRtFloatAbbrev(float_bits),6212 compilerRtFloatAbbrev(target, float_bits),
5993 }),6213 }),
5994 else => unreachable,6214 else => unreachable,
5995 };6215 };
59966216 const fn_info: Object.FuncInfo = .{
5997 const libc_fn = try o.getLibcFunction(fn_name, &.{ llvm_scalar_ty, llvm_scalar_ty }, llvm_scalar_ty);6217 .cc = target.cCallingConvention().?,
5998 const init_val = switch (llvm_scalar_ty) {6218 .param_types = &.{ scalar_ty.toIntern(), scalar_ty.toIntern() },
5999 .i16 => try o.builder.intValue(.i16, @as(i16, @bitCast(6219 .return_type = scalar_ty.toIntern(),
6000 @as(f16, switch (reduce.operation) {6220 };
6001 .Min, .Max => std.math.nan(f16),6221 const llvm_fn = try fg.object.getLibcFunction(fg.pt, fn_name, fn_info);
6002 .Add => -0.0,6222 const init = switch (float_bits) {
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 ))),
6023 else => unreachable,6223 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 }),
6024 };6254 };
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;
6026}6293}
60276294
6028fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {6295fn airAggregateInit(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
6029 const o = self.object;6296 const o = fg.object;
6030 const zcu = o.zcu;6297 const zcu = o.zcu;
6031 const ip = &zcu.intern_pool;6298 const ip = &zcu.intern_pool;
6032 const ty_pl = self.air.instructions.items(.data)[@backingInt(inst)].ty_pl;6299 const ty_pl = fg.air.instructions.items(.data)[@backingInt(inst)].ty_pl;
6033 const result_ty = self.typeOfIndex(inst);6300 const result_ty = fg.typeOfIndex(inst);
6034 const len: usize = @intCast(result_ty.arrayLen(zcu));6301 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
6037 switch (result_ty.zigTypeTag(zcu)) {6304 switch (result_ty.zigTypeTag(zcu)) {
6038 .vector => {6305 .vector => if (isByRef(result_ty, zcu)) {
6039 const llvm_result_ty = try o.lowerType(result_ty, .by_value);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);
6040 var vector = try o.builder.poisonValue(llvm_result_ty);6317 var vector = try o.builder.poisonValue(llvm_result_ty);
6041 for (elements, 0..) |elem, i| {6318 for (elements, 0..) |elem, elem_index| {
6042 const index_u32 = try o.builder.intValue(.i32, i);6319 const elem_index_val = try o.builder.intValue(.i32, elem_index);
6043 const llvm_elem = try self.resolveInst(elem);6320 const llvm_elem = try fg.resolveInst(elem);
6044 vector = try self.wip.insertElement(vector, llvm_elem, index_u32, "");6321 vector = try fg.wip.insertElement(vector, llvm_elem, elem_index_val, "");
6045 }6322 }
6046 return vector;6323 return vector;
6047 },6324 },
...@@ -6057,18 +6334,18 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde...@@ -6057,18 +6334,18 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde
6057 for (elements, struct_type.field_types.get(ip)) |elem, field_ty| {6334 for (elements, struct_type.field_types.get(ip)) |elem, field_ty| {
6058 if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue;6335 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);
6061 const ty_bit_size: u16 = @intCast(Type.fromInterned(field_ty).bitSize(zcu));6338 const ty_bit_size: u16 = @intCast(Type.fromInterned(field_ty).bitSize(zcu));
6062 const small_int_ty = try o.builder.intType(ty_bit_size);6339 const small_int_ty = try o.builder.intType(ty_bit_size);
6063 const small_int_val = if (Type.fromInterned(field_ty).isPtrAtRuntime(zcu))6340 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, "")
6065 else6342 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, "");
6067 const shift_rhs = try o.builder.intValue(int_ty, running_bits);6344 const shift_rhs = try o.builder.intValue(int_ty, running_bits);
6068 const extended_int_val =6345 const extended_int_val =
6069 try self.wip.conv(.unsigned, small_int_val, int_ty, "");6346 try fg.wip.conv(.unsigned, small_int_val, int_ty, "");
6070 const shifted = try self.wip.bin(.shl, extended_int_val, shift_rhs, "");6347 const shifted = try fg.wip.bin(.shl, extended_int_val, shift_rhs, "");
6071 running_int = try self.wip.bin(.@"or", running_int, shifted, "");6348 running_int = try fg.wip.bin(.@"or", running_int, shifted, "");
6072 running_bits += ty_bit_size;6349 running_bits += ty_bit_size;
6073 }6350 }
6074 return running_int;6351 return running_int;
...@@ -6078,19 +6355,19 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde...@@ -6078,19 +6355,19 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde
6078 // TODO in debug builds init to undef so that the padding will be 0xaa6355 // TODO in debug builds init to undef so that the padding will be 0xaa
6079 // even if we fully populate the fields.6356 // even if we fully populate the fields.
6080 const struct_align = result_ty.abiAlignment(zcu);6357 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
6083 for (elements, 0..) |elem, field_index| {6360 for (elements, 0..) |elem, field_index| {
6084 if (result_ty.structFieldIsComptime(field_index, zcu)) continue;6361 if (result_ty.structFieldIsComptime(field_index, zcu)) continue;
6085 const field_ty = result_ty.fieldType(field_index, zcu);6362 const field_ty = result_ty.fieldType(field_index, zcu);
6086 if (!field_ty.hasRuntimeBits(zcu)) continue;6363 if (!field_ty.hasRuntimeBits(zcu)) continue;
6087 const offset = result_ty.structFieldOffset(field_index, zcu);6364 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);
6089 const field_ptr_align = struct_align.offset(offset);6366 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);
6094 }6371 }
60956372
6096 return alloca_inst;6373 return alloca_inst;
...@@ -6099,21 +6376,21 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde...@@ -6099,21 +6376,21 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde
6099 .array => {6376 .array => {
6100 assert(isByRef(result_ty, zcu));6377 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
6104 const array_info = result_ty.arrayInfo(zcu);6381 const array_info = result_ty.arrayInfo(zcu);
61056382
6106 const elem_size = array_info.elem_type.abiSize(zcu);6383 const elem_size = array_info.elem_type.abiSize(zcu);
61076384
6108 for (elements, 0..) |elem, i| {6385 for (elements, 0..) |elem, i| {
6109 const elem_ptr = try self.ptraddConst(alloca_inst, elem_size * i);6386 const elem_ptr = try fg.ptraddConst(alloca_inst, elem_size * i);
6110 const llvm_elem = try self.resolveInst(elem);6387 const llvm_elem = try fg.resolveInst(elem);
6111 try self.store(elem_ptr, .none, llvm_elem, array_info.elem_type, .normal);6388 try fg.store(elem_ptr, .none, llvm_elem, array_info.elem_type, .normal);
6112 }6389 }
6113 if (array_info.sentinel) |sent_val| {6390 if (array_info.sentinel) |sent_val| {
6114 const elem_ptr = try self.ptraddConst(alloca_inst, elem_size * array_info.len);6391 const elem_ptr = try fg.ptraddConst(alloca_inst, elem_size * array_info.len);
6115 const llvm_elem = try self.resolveValue(sent_val);6392 const llvm_elem = try fg.resolveValue(sent_val);
6116 try self.store(elem_ptr, .none, llvm_elem.toValue(), array_info.elem_type, .normal);6393 try fg.store(elem_ptr, .none, llvm_elem.toValue(), array_info.elem_type, .normal);
6117 }6394 }
61186395
6119 return alloca_inst;6396 return alloca_inst;
...@@ -6153,10 +6430,10 @@ fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va...@@ -6153,10 +6430,10 @@ fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va
6153 const loaded_enum = ip.loadEnumType(tag_ty.toIntern());6430 const loaded_enum = ip.loadEnumType(tag_ty.toIntern());
6154 const llvm_tag_val = switch (loaded_enum.field_values.getOrNone(ip, extra.field_index)) {6431 const llvm_tag_val = switch (loaded_enum.field_values.getOrNone(ip, extra.field_index)) {
6155 .none => try o.builder.intConst(6432 .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),
6157 extra.field_index, // auto-numbered6434 extra.field_index, // auto-numbered
6158 ),6435 ),
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),
6160 };6437 };
6161 const tag_ptr = try self.ptraddConst(result_ptr, layout.tagOffset());6438 const tag_ptr = try self.ptraddConst(result_ptr, layout.tagOffset());
6162 try self.store(tag_ptr, layout.tag_align, llvm_tag_val.toValue(), tag_ty, .normal);6439 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...@@ -6218,7 +6495,7 @@ fn airAddrSpaceCast(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde
6218 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;6495 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
6219 const inst_ty = self.typeOfIndex(inst);6496 const inst_ty = self.typeOfIndex(inst);
6220 const operand = try self.resolveInst(ty_op.operand);6497 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), "");
6222}6499}
62236500
6224fn workIntrinsic(6501fn workIntrinsic(
...@@ -6370,7 +6647,7 @@ fn load(...@@ -6370,7 +6647,7 @@ fn load(
6370 };6647 };
63716648
6372 if (isByRef(load_ty, zcu)) {6649 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);
6374 const result_ptr = try fg.buildZigAlloca(load_ty, .none);6651 const result_ptr = try fg.buildZigAlloca(load_ty, .none);
6375 _ = try fg.wip.callMemCpy(6652 _ = try fg.wip.callMemCpy(
6376 result_ptr,6653 result_ptr,
...@@ -6384,11 +6661,14 @@ fn load(...@@ -6384,11 +6661,14 @@ fn load(
6384 return result_ptr;6661 return result_ptr;
6385 }6662 }
63866663
6387 const llvm_memory_ty = try o.lowerType(load_ty, .in_memory);6664 const llvm_access_ty = try o.lowerType(load_ty, .memory_access);
6388 const llvm_value_ty = try o.lowerType(load_ty, .by_value);6665 const llvm_value_ty = try o.lowerType(load_ty, .as_value);
63896666
6390 if (llvm_memory_ty != llvm_value_ty) {6667 if (llvm_access_ty != llvm_value_ty) {
6391 assert(load_ty.isAbiInt(zcu));6668 const signedness: std.lang.Signedness = switch (load_ty.toIntern()) {
6669 .bool_type => .unsigned,
6670 else => load_ty.intInfo(zcu).signedness,
6671 };
6392 // `load_ty` is an integer type with padding bits. In theory, we shouldn't need any special6672 // `load_ty` is an integer type with padding bits. In theory, we shouldn't need any special
6393 // handling for these, as LLVM's documented semantics are a valid implementation of Zig's6673 // handling for these, as LLVM's documented semantics are a valid implementation of Zig's
6394 // semantics. However:6674 // semantics. However:
...@@ -6401,13 +6681,13 @@ fn load(...@@ -6401,13 +6681,13 @@ fn load(
6401 //6681 //
6402 // Therefore, we handle these memory accesses specially: in this case we will actually load6682 // Therefore, we handle these memory accesses specially: in this case we will actually load
6403 // the next-largest "natural" integer type and then truncate to `load_ty`.6683 // 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, "");
6405 // For packed structs, current Zig semantics don't really allow us to make the padding bits6685 // For packed structs, current Zig semantics don't really allow us to make the padding bits
6406 // well-defined. This should be solved once https://github.com/ziglang/zig/issues/24061 is6686 // well-defined. This should be solved once https://github.com/ziglang/zig/issues/24061 is
6407 // implemented, but until then, do a normal trunc for packed types.6687 // implemented, but until then, do a normal trunc for packed types.
6408 return fg.wip.cast(switch (load_ty.zigTypeTag(zcu)) {6688 return fg.wip.cast(switch (load_ty.zigTypeTag(zcu)) {
6409 .@"struct", .@"union" => .trunc,6689 .@"struct", .@"union" => .trunc,
6410 else => switch (load_ty.intInfo(zcu).signedness) {6690 else => switch (signedness) {
6411 .unsigned => .@"trunc nuw",6691 .unsigned => .@"trunc nuw",
6412 .signed => .@"trunc nsw",6692 .signed => .@"trunc nsw",
6413 },6693 },
...@@ -6443,7 +6723,7 @@ fn store(...@@ -6443,7 +6723,7 @@ fn store(
6443 };6723 };
64446724
6445 if (isByRef(elem_ty, zcu)) {6725 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);
6447 _ = try fg.wip.callMemCpy(6727 _ = try fg.wip.callMemCpy(
6448 ptr,6728 ptr,
6449 llvm_ptr_align,6729 llvm_ptr_align,
...@@ -6456,45 +6736,34 @@ fn store(...@@ -6456,45 +6736,34 @@ fn store(
6456 return;6736 return;
6457 }6737 }
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);6741 const llvm_access_ty = try o.lowerType(elem_ty, .memory_access);
6462 const llvm_value_ty = try o.lowerType(elem_ty, .by_value);6742 const llvm_value_ty = try o.lowerType(elem_ty, .as_value);
64636743
6464 if (llvm_memory_ty != llvm_value_ty) {6744 if (llvm_access_ty != llvm_value_ty) {
6465 assert(elem_ty.isAbiInt(zcu));6745 const signedness: std.lang.Signedness = switch (elem_ty.toIntern()) {
6746 .bool_type => .unsigned,
6747 else => elem_ty.intInfo(zcu).signedness,
6748 };
6466 // `elem_ty` is an integer type with padding bits, so we need to handle it specially---see6749 // `elem_ty` is an integer type with padding bits, so we need to handle it specially---see
6467 // the corresponding comment in `FuncGen.load` for more details.6750 // 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) {
6469 .unsigned => .zext,6752 .unsigned => .zext,
6470 .signed => .sext,6753 .signed => .sext,
6471 }, elem, llvm_memory_ty, "");6754 }, elem, llvm_access_ty, "");
6472 _ = try fg.wip.storeAtomic(6755 _ = try fg.wip.store(access_kind, extended, ptr, llvm_ptr_align);
6473 access_kind,
6474 extended,
6475 ptr,
6476 fg.sync_scope,
6477 .none,
6478 llvm_ptr_align,
6479 );
6480 return;6756 return;
6481 }6757 }
64826758
6483 // `elem_ty` is a simple by-val type which requires no special handling.6759 // `elem_ty` is a simple by-val type which requires no special handling.
6484 _ = try fg.wip.storeAtomic(6760 _ = try fg.wip.store(access_kind, elem, ptr, llvm_ptr_align);
6485 access_kind,
6486 elem,
6487 ptr,
6488 fg.sync_scope,
6489 .none,
6490 llvm_ptr_align,
6491 );
6492}6761}
64936762
6494fn valgrindMarkUndef(fg: *FuncGen, ptr: Builder.Value, len: Builder.Value) Allocator.Error!void {6763fn valgrindMarkUndef(fg: *FuncGen, ptr: Builder.Value, len: Builder.Value) Allocator.Error!void {
6495 const VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545;6764 const VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545;
6496 const o = fg.object;6765 const o = fg.object;
6497 const usize_ty = try o.lowerType(.usize, .by_value);6766 const usize_ty = try o.lowerType(.usize, .as_value);
6498 const zero = try o.builder.intValue(usize_ty, 0);6767 const zero = try o.builder.intValue(usize_ty, 0);
6499 const req = try o.builder.intValue(usize_ty, VG_USERREQ__MAKE_MEM_UNDEFINED);6768 const req = try o.builder.intValue(usize_ty, VG_USERREQ__MAKE_MEM_UNDEFINED);
6500 const ptr_as_usize = try fg.wip.cast(.ptrtoint, ptr, usize_ty, "");6769 const ptr_as_usize = try fg.wip.cast(.ptrtoint, ptr, usize_ty, "");
...@@ -6516,7 +6785,7 @@ fn valgrindClientRequest(...@@ -6516,7 +6785,7 @@ fn valgrindClientRequest(
6516 const target = zcu.getTarget();6785 const target = zcu.getTarget();
6517 if (!target_util.hasValgrindSupport(target, .stage2_llvm)) return default_value;6786 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);
6520 const usize_align = Type.usize.abiAlignment(zcu).toLlvm();6789 const usize_align = Type.usize.abiAlignment(zcu).toLlvm();
65216790
6522 const array_llvm_ty = try o.builder.arrayType(6, llvm_usize);6791 const array_llvm_ty = try o.builder.arrayType(6, llvm_usize);
...@@ -6650,13 +6919,14 @@ fn typeOfIndex(fg: *FuncGen, inst: Air.Inst.Index) Type {...@@ -6650,13 +6919,14 @@ fn typeOfIndex(fg: *FuncGen, inst: Air.Inst.Index) Type {
66506919
6651const ParamTypeIterator = struct {6920const ParamTypeIterator = struct {
6652 object: *Object,6921 object: *Object,
6653 fn_info: InternPool.Key.FuncType,6922 cc: std.lang.CallingConvention,
6923 param_types: []const InternPool.Index,
6654 zig_index: u32,6924 zig_index: u32,
6655 llvm_index: u32,6925 llvm_index: u32,
6656 types_len: u32,6926 types_len: u32,
6657 types_buffer: [8]Builder.Type,6927 types_buffer: [8]Builder.Type,
6658 offsets_buffer: [9]u64,6928 offsets_buffer: [9]u64,
6659 byval_attr: bool,6929 byval_attr: ?Object.Byval,
66606930
6661 const Lowering = union(enum) {6931 const Lowering = union(enum) {
6662 no_bits,6932 no_bits,
...@@ -6672,88 +6942,78 @@ const ParamTypeIterator = struct {...@@ -6672,88 +6942,78 @@ const ParamTypeIterator = struct {
6672 };6942 };
66736943
6674 pub fn next(it: *ParamTypeIterator) Allocator.Error!?Lowering {6944 pub fn next(it: *ParamTypeIterator) Allocator.Error!?Lowering {
6675 if (it.zig_index >= it.fn_info.param_types.len) return null;6945 if (it.zig_index >= it.param_types.len) return null;
6676 const ip = &it.object.zcu.intern_pool;6946 const ty = it.param_types[it.zig_index];
6677 const ty = it.fn_info.param_types.get(ip)[it.zig_index];6947 it.byval_attr = null;
6678 it.byval_attr = false;
6679 return nextInner(it, Type.fromInterned(ty));6948 return nextInner(it, Type.fromInterned(ty));
6680 }6949 }
66816950
6682 /// `airCall` uses this instead of `next` so that it can take into account variadic functions.6951 /// `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 {6952 fn nextCall(it: *ParamTypeIterator, arg_types: []const InternPool.Index) Allocator.Error!?Lowering {
6684 const ip = &it.object.zcu.intern_pool;6953 if (it.zig_index >= it.param_types.len) {
6685 if (it.zig_index >= it.fn_info.param_types.len) {6954 if (it.zig_index >= arg_types.len) {
6686 if (it.zig_index >= args.len) {
6687 return null;6955 return null;
6688 } else {6956 } else {
6689 return nextInner(it, fg.typeOf(args[it.zig_index]));6957 return nextInner(it, .fromInterned(arg_types[it.zig_index]));
6690 }6958 }
6691 } else {6959 } 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]));
6693 }6961 }
6694 }6962 }
66956963
6696 fn nextInner(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering {6964 fn nextInner(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering {
6697 const zcu = it.object.zcu;6965 const zcu = it.object.zcu;
6698 const target = zcu.getTarget();6966 ty.assertHasLayout(zcu);
6699
6700 if (!ty.hasRuntimeBits(zcu)) {6967 if (!ty.hasRuntimeBits(zcu)) {
6701 it.zig_index += 1;6968 it.zig_index += 1;
6702 return .no_bits;6969 return .no_bits;
6703 }6970 }
6704 switch (it.fn_info.cc) {6971 switch (it.cc) {
6705 .@"inline" => unreachable,6972 .@"inline" => unreachable,
6706 .auto => {6973 .auto => {
6707 it.zig_index += 1;6974 it.zig_index += 1;
6708 it.llvm_index += 1;6975 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
6709 if (ty.isSlice(zcu) or6991 if (ty.isSlice(zcu) or
6710 (ty.zigTypeTag(zcu) == .optional and ty.optionalChild(zcu).isSlice(zcu) and !ty.ptrAllowsZero(zcu)))6992 (ty.zigTypeTag(zcu) == .optional and ty.optionalChild(zcu).isSlice(zcu) and !ty.ptrAllowsZero(zcu)))
6711 {6993 {
6712 it.llvm_index += 1;6994 it.llvm_index += 1;
6713 return .slice;6995 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;
6725 }6996 }
6997 if (isByRef(ty, zcu)) return .byref;
6998 return .byval;
6726 },6999 },
6727 .async => {7000 .async => {
6728 @panic("TODO implement async function lowering in the LLVM backend");7001 @panic("TODO implement async function lowering in the LLVM backend");
6729 },7002 },
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 },
6743 .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => {7003 .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => {
6744 it.zig_index += 1;7004 it.zig_index += 1;
6745 it.llvm_index += 1;7005 it.llvm_index += 1;
6746 switch (aarch64_c_abi.classifyType(ty, zcu)) {7006 switch (aarch64_c_abi.classifyType(ty, zcu)) {
6747 .memory => return .byref_mut,7007 .memory => return .byref_mut,
6748 .float_array => |len| return Lowering{ .float_array = len },7008 .float_array => |len| return .{ .float_array = len },
6749 .byval => return .byval,7009 .byval => return .byval,
6750 .integer => {7010 .integer => {
6751 it.types_len = 1;
6752 it.types_buffer[0..1].* = .{.i64};7011 it.types_buffer[0..1].* = .{.i64};
6753 it.offsets_buffer[0..2].* = .{ 0, 8 };7012 it.offsets_buffer[0..2].* = .{ 0, 8 };
7013 it.types_len = 1;
6754 return .multiple_llvm_types;7014 return .multiple_llvm_types;
6755 },7015 },
6756 .double_integer => return Lowering{ .i64_array = 2 },7016 .double_integer => return .{ .i64_array = 2 },
6757 }7017 }
6758 },7018 },
6759 .arm_aapcs, .arm_aapcs_vfp => {7019 .arm_aapcs, .arm_aapcs_vfp => {
...@@ -6761,26 +7021,101 @@ const ParamTypeIterator = struct {...@@ -6761,26 +7021,101 @@ const ParamTypeIterator = struct {
6761 it.llvm_index += 1;7021 it.llvm_index += 1;
6762 switch (arm_c_abi.classifyType(ty, zcu, .arg)) {7022 switch (arm_c_abi.classifyType(ty, zcu, .arg)) {
6763 .memory => {7023 .memory => {
6764 it.byval_attr = true;7024 it.byval_attr = .{};
6765 return .byref;7025 return .byref;
6766 },7026 },
6767 .byval => return .byval,7027 .byval => return .byval,
6768 .i32_array => |size| return Lowering{ .i32_array = size },7028 .i32_array => |size| return .{ .i32_array = size },
6769 .i64_array => |size| return Lowering{ .i64_array = size },7029 .i64_array => |size| return .{ .i64_array = size },
6770 }7030 }
6771 },7031 },
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 },
6772 .mips_o32 => {7097 .mips_o32 => {
6773 it.zig_index += 1;7098 it.zig_index += 1;
6774 it.llvm_index += 1;7099 it.llvm_index += 1;
6775 switch (mips_c_abi.classifyType(ty, zcu, .arg)) {7100 switch (mips_c_abi.classifyType(ty, zcu, .arg)) {
6776 .memory => {7101 .memory => {
6777 it.byval_attr = true;7102 it.byval_attr = .{};
6778 return .byref;7103 return .byref;
6779 },7104 },
6780 .byval => return .byval,7105 .byval => return .byval,
6781 .i32_array => |size| return Lowering{ .i32_array = size },7106 .i32_array => |size| return .{ .i32_array = size },
6782 }7107 }
6783 },7108 },
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 },
6784 .riscv64_lp64, .riscv32_ilp32 => {7119 .riscv64_lp64, .riscv32_ilp32 => {
6785 it.zig_index += 1;7120 it.zig_index += 1;
6786 it.llvm_index += 1;7121 it.llvm_index += 1;
...@@ -6788,7 +7123,7 @@ const ParamTypeIterator = struct {...@@ -6788,7 +7123,7 @@ const ParamTypeIterator = struct {
6788 .memory => return .byref_mut,7123 .memory => return .byref_mut,
6789 .byval => return .byval,7124 .byval => return .byval,
6790 .integer => return .abi_sized_int,7125 .integer => return .abi_sized_int,
6791 .double_integer => return Lowering{ .i64_array = 2 },7126 .double_integer => return .{ .i64_array = 2 },
6792 .fields => {7127 .fields => {
6793 it.types_len = 0;7128 it.types_len = 0;
6794 var field_it: InternPool.LoadedStructType.RuntimeOrderIterator = if (zcu.typeToStruct(ty)) |loaded_struct|7129 var field_it: InternPool.LoadedStructType.RuntimeOrderIterator = if (zcu.typeToStruct(ty)) |loaded_struct|
...@@ -6798,7 +7133,7 @@ const ParamTypeIterator = struct {...@@ -6798,7 +7133,7 @@ const ParamTypeIterator = struct {
6798 while (field_it.next()) |field_index| {7133 while (field_it.next()) |field_index| {
6799 const field_ty = ty.fieldType(field_index, zcu);7134 const field_ty = ty.fieldType(field_index, zcu);
6800 if (!field_ty.hasRuntimeBits(zcu)) continue;7135 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);
6802 it.offsets_buffer[it.types_len] = ty.structFieldOffset(field_index, zcu);7137 it.offsets_buffer[it.types_len] = ty.structFieldOffset(field_index, zcu);
6803 it.types_len += 1;7138 it.types_len += 1;
6804 }7139 }
...@@ -6808,28 +7143,105 @@ const ParamTypeIterator = struct {...@@ -6808,28 +7143,105 @@ const ParamTypeIterator = struct {
6808 },7143 },
6809 }7144 }
6810 },7145 },
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)) {
6812 .direct => |scalar_ty| {7165 .direct => |scalar_ty| {
6813 if (isScalar(zcu, ty)) {7166 if (isScalar(zcu, ty)) {
6814 it.zig_index += 1;7167 it.zig_index += 1;
6815 it.llvm_index += 1;7168 it.llvm_index += 1;
6816 return .byval;7169 return .byval;
6817 } else {7170 } 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)};
6819 it.offsets_buffer[0..2].* = .{ 0, scalar_ty.abiSize(zcu) };7172 it.offsets_buffer[0..2].* = .{ 0, scalar_ty.abiSize(zcu) };
6820 it.types_len = 1;7173 it.types_len = 1;
6821 it.llvm_index += 1;
6822 it.zig_index += 1;7174 it.zig_index += 1;
7175 it.llvm_index += 1;
6823 return .multiple_llvm_types;7176 return .multiple_llvm_types;
6824 }7177 }
6825 },7178 },
6826 .indirect => {7179 .indirect => {
6827 it.zig_index += 1;7180 it.zig_index += 1;
6828 it.llvm_index += 1;7181 it.llvm_index += 1;
6829 it.byval_attr = true;7182 it.byval_attr = .{};
6830 return .byref;7183 return .byref;
6831 },7184 },
6832 },7185 },
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),
6833 // TODO investigate other callconvs7245 // TODO investigate other callconvs
6834 else => {7246 else => {
6835 it.zig_index += 1;7247 it.zig_index += 1;
...@@ -6839,7 +7251,7 @@ const ParamTypeIterator = struct {...@@ -6839,7 +7251,7 @@ const ParamTypeIterator = struct {
6839 }7251 }
6840 }7252 }
68417253
6842 fn nextWin64(it: *ParamTypeIterator, ty: Type) ?Lowering {7254 fn next_x86_64_win(it: *ParamTypeIterator, ty: Type) Lowering {
6843 const zcu = it.object.zcu;7255 const zcu = it.object.zcu;
6844 switch (x86_64_abi.classifyWindows(ty, zcu, zcu.getTarget(), .arg)) {7256 switch (x86_64_abi.classifyWindows(ty, zcu, zcu.getTarget(), .arg)) {
6845 .integer => {7257 .integer => {
...@@ -6880,119 +7292,114 @@ const ParamTypeIterator = struct {...@@ -6880,119 +7292,114 @@ const ParamTypeIterator = struct {
6880 }7292 }
6881 }7293 }
68827294
6883 fn nextSystemV(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering {7295 fn next_x86_64_sysv(it: *ParamTypeIterator, ty: Type) Allocator.Error!Lowering {
6884 const zcu = it.object.zcu;7296 const o = it.object;
6885 const ip = &zcu.intern_pool;7297 const zcu = o.zcu;
6886 ty.assertHasLayout(zcu);7298 const target = zcu.getTarget();
6887 const classes = x86_64_abi.classifySystemV(ty, zcu, zcu.getTarget(), .arg);7299 const classes = x86_64_abi.classifySystemV(ty, zcu, target, .arg);
6888 if (classes[0] == .memory) {7300 var types_len: u32 = 0;
6889 it.zig_index += 1;7301 const classes_len = for (classes, 0..) |class, class_index| switch (class) {
6890 it.llvm_index += 1;7302 .integer => {
6891 it.byval_attr = true;7303 it.types_buffer[types_len] = try o.builder.intType(@min(8 * ty.abiSize(zcu) - 64 * class_index, 64));
6892 return .byref;7304 it.offsets_buffer[types_len] = 8 * class_index;
6893 }7305 types_len += 1;
6894 if (isScalar(zcu, ty)) {7306 },
6895 it.zig_index += 1;7307 .sse => {
6896 it.llvm_index += 1;7308 it.types_buffer[types_len] = .double;
6897 return .byval;7309 it.offsets_buffer[types_len] = 8 * class_index;
6898 }7310 types_len += 1;
6899 var types_index: u32 = 0;7311 },
6900 var offset: u64 = 0;7312 .sseup => {
6901 for (classes) |class| {7313 if (it.types_buffer[types_len - 1] == .double) {
6902 switch (class) {7314 if (ty.isVector(zcu)) {
6903 .integer => {7315 it.zig_index += 1;
6904 it.types_buffer[types_index] = .i64;7316 it.llvm_index += 1;
6905 it.offsets_buffer[types_index] = offset;7317 return .byval;
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;
6920 }7318 }
6921 },7319 it.types_buffer[types_len - 1] = .fp128;
6922 .float => {7320 } else {
6923 it.types_buffer[types_index] = .float;7321 it.types_buffer[types_len] = .double;
6924 it.offsets_buffer[types_index] = offset;7322 it.offsets_buffer[types_len] = 8 * class_index;
6925 types_index += 1;7323 types_len += 1;
6926 },7324 }
6927 .float_combine => {7325 },
6928 it.types_buffer[types_index] = try it.object.builder.vectorType(.normal, 2, .float);7326 .float => {
6929 it.offsets_buffer[types_index] = offset;7327 it.types_buffer[types_len] = .float;
6930 types_index += 1;7328 it.offsets_buffer[types_len] = 8 * class_index;
6931 },7329 types_len += 1;
6932 .x87 => {7330 },
6933 it.zig_index += 1;7331 .float_combine => {
6934 it.llvm_index += 1;7332 it.types_buffer[types_len] = try it.object.builder.vectorType(.normal, 2, .float);
6935 it.byval_attr = true;7333 it.offsets_buffer[types_len] = 8 * class_index;
6936 return .byref;7334 types_len += 1;
6937 },7335 },
6938 .x87up => unreachable,7336 .x87 => {
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) {
6957 it.zig_index += 1;7337 it.zig_index += 1;
6958 it.llvm_index += 1;7338 it.llvm_index += 1;
6959 return .abi_sized_int;7339 it.byval_attr = .{};
6960 }7340 return .byref;
6961 if (it.llvm_index + types_index > 6) {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) {
6962 it.zig_index += 1;7366 it.zig_index += 1;
6963 it.llvm_index += 1;7367 it.llvm_index += 1;
6964 it.byval_attr = true;7368 it.byval_attr = .{};
6965 return .byref;7369 return .byref;
6966 }7370 }
6967 switch (ip.indexToKey(ty.toIntern())) {7371 } else if (!isByRef(ty, zcu)) {
6968 .struct_type => {7372 const llvm_ty = try o.lowerType(ty, .as_value);
6969 const size = ty.abiSize(zcu);7373 if (it.types_buffer[0] == llvm_ty or
6970 assert(@divCeil(size, 8) == types_index);7374 (it.types_buffer[0] == .i64 and llvm_ty.isPointer(&o.builder)))
6971 if (size % 8 > 0) {7375 {
6972 it.types_buffer[types_index - 1] =7376 it.zig_index += 1;
6973 try it.object.builder.intType(@intCast(size % 8 * 8));7377 it.llvm_index += 1;
6974 }7378 return .byval;
6975 },
6976 else => {},
6977 }7379 }
6978 }7380 }
6979 it.offsets_buffer[types_index] = offset;7381 it.offsets_buffer[types_len] = 8 * classes_len;
6980 it.types_len = types_index;7382 it.types_len = types_len;
6981 it.llvm_index += types_index;7383 it.llvm_index += types_len;
6982 it.zig_index += 1;7384 it.zig_index += 1;
6983 return .multiple_llvm_types;7385 return .multiple_llvm_types;
6984 }7386 }
6985};7387};
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 {
6987 return .{7393 return .{
6988 .object = object,7394 .object = object,
6989 .fn_info = fn_info,7395 .cc = cc,
7396 .param_types = param_types,
6990 .zig_index = 0,7397 .zig_index = 0,
6991 .llvm_index = 0,7398 .llvm_index = 0,
6992 .types_len = undefined,7399 .types_len = undefined,
6993 .types_buffer = undefined,7400 .types_buffer = undefined,
6994 .offsets_buffer = undefined,7401 .offsets_buffer = undefined,
6995 .byval_attr = false,7402 .byval_attr = null,
6996 };7403 };
6997}7404}
69987405
...@@ -7017,54 +7424,68 @@ pub const FnReturnStrat = union(enum) {...@@ -7017,54 +7424,68 @@ pub const FnReturnStrat = union(enum) {
7017/// In order to support the C calling convention, some return types need to be lowered7424/// In order to support the C calling convention, some return types need to be lowered
7018/// completely differently in the function prototype to honor the C ABI, and then7425/// completely differently in the function prototype to honor the C ABI, and then
7019/// be effectively bitcasted to the actual return type.7426/// 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 {
7021 const zcu = o.zcu;7428 const zcu = o.zcu;
7022 const ret_ty: Type = .fromInterned(fn_info.return_type);
7023 ret_ty.assertHasLayout(zcu);7429 ret_ty.assertHasLayout(zcu);
7024 if (!ret_ty.hasRuntimeBits(zcu)) return .void;7430 if (!ret_ty.hasRuntimeBits(zcu)) return .void;
7025 switch (fn_info.cc) {7431 return switch (cc) {
7026 .@"inline" => unreachable,7432 .@"inline" => unreachable,
7027 .auto => {7433 .auto => {
7028 if (isByRef(ret_ty, zcu)) return .sret;7434 // Match the c calling convention in some cases to avoid llvm bugs.
7029
7030 const target = zcu.getTarget();7435 const target = zcu.getTarget();
7031 if (target.cpu.arch.isX86() and7436 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)) {
7032 !target.cpu.has(.x86, .avx512f) and7437 0 => .void,
7033 ret_ty.totalVectorBits(zcu) >= 512)7438 1...8 => .{ .mem_cast = .i8 },
7034 {7439 9...16 => .{ .mem_cast = .i16 },
7035 // As of LLVM 18, passing a vector byval with fastcc that is 512 bits or more returns7440 17...32 => .{ .mem_cast = .i32 },
7036 // "512-bit vector arguments require 'avx512f' for AVX512"7441 33...64 => .{ .mem_cast = .double },
7037 return .sret;7442 else => .by_val,
7038 }7443 };
70397444 return if (isByRef(ret_ty, zcu)) .sret else .by_val;
7040 return .by_val;
7041 },7445 },
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,
7050 .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => switch (aarch64_c_abi.classifyType(ret_ty, zcu)) {7446 .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => switch (aarch64_c_abi.classifyType(ret_ty, zcu)) {
7051 .memory => return .sret,7447 .memory => .sret,
7052 .float_array, .byval => return .forceByVal(o, ret_ty),7448 .float_array, .byval => .forceByVal(o, ret_ty),
7053 .integer => return .{ .mem_cast = .i64 },7449 .integer => .{ .mem_cast = .i64 },
7054 .double_integer => return .{ .mem_cast = try o.builder.arrayType(2, .i64) },7450 .double_integer => .{ .mem_cast = try o.builder.arrayType(2, .i64) },
7055 },7451 },
7056 .arm_aapcs, .arm_aapcs_vfp => switch (arm_c_abi.classifyType(ret_ty, zcu, .ret)) {7452 .arm_aapcs, .arm_aapcs_vfp => switch (arm_c_abi.classifyType(ret_ty, zcu, .ret)) {
7057 .memory, .i64_array => return .sret,7453 .memory, .i64_array => .sret,
7058 .i32_array => |len| return if (len == 1) .{ .mem_cast = .i32 } else .sret,7454 .i32_array => |len| if (len == 1) .{ .mem_cast = .i32 } else .sret,
7059 .byval => return .forceByVal(o, ret_ty),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,
7060 },7476 },
7061 .mips_o32 => switch (mips_c_abi.classifyType(ret_ty, zcu, .ret)) {7477 .mips_o32 => switch (mips_c_abi.classifyType(ret_ty, zcu, .ret)) {
7062 .memory, .i32_array => return .sret,7478 .memory, .i32_array => .sret,
7063 .byval => return .forceByVal(o, ret_ty),7479 .byval => .forceByVal(o, ret_ty),
7064 },7480 },
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
7065 .riscv64_lp64, .riscv32_ilp32 => switch (riscv_c_abi.classifyType(ret_ty, zcu)) {7486 .riscv64_lp64, .riscv32_ilp32 => switch (riscv_c_abi.classifyType(ret_ty, zcu)) {
7066 .memory => return .sret,7487 .memory => .sret,
7067 .integer => return .{ .mem_cast = try o.builder.intType(@intCast(ret_ty.abiSize(zcu) * 8)) },7488 .integer => .{ .mem_cast = try o.builder.intType(@intCast(ret_ty.abiSize(zcu) * 8)) },
7068 .double_integer => {7489 .double_integer => {
7069 const integer: Builder.Type = switch (zcu.getTarget().cpu.arch) {7490 const integer: Builder.Type = switch (zcu.getTarget().cpu.arch) {
7070 .riscv64, .riscv64be => .i64,7491 .riscv64, .riscv64be => .i64,
...@@ -7073,34 +7494,78 @@ pub fn fnReturnStrat(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Err...@@ -7073,34 +7494,78 @@ pub fn fnReturnStrat(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Err
7073 };7494 };
7074 return .{ .mem_cast = try o.builder.structType(.normal, &.{ integer, integer }) };7495 return .{ .mem_cast = try o.builder.structType(.normal, &.{ integer, integer }) };
7075 },7496 },
7076 .byval => return .forceByVal(o, ret_ty),7497 .byval => .forceByVal(o, ret_ty),
7077 .fields => {7498 .fields => {
7078 var types_len: usize = 0;7499 var types_len: usize = 0;
7079 var types: [8]Builder.Type = undefined;7500 var types: [8]Builder.Type = undefined;
7080 for (0..ret_ty.structFieldCount(zcu)) |field_index| {7501 for (0..ret_ty.structFieldCount(zcu)) |field_index| {
7081 const field_ty = ret_ty.fieldType(field_index, zcu);7502 const field_ty = ret_ty.fieldType(field_index, zcu);
7082 if (!field_ty.hasRuntimeBits(zcu)) continue;7503 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);
7084 types_len += 1;7505 types_len += 1;
7085 }7506 }
7086 return .{ .mem_cast = try o.builder.structType(.normal, types[0..types_len]) };7507 return .{ .mem_cast = try o.builder.structType(.normal, types[0..types_len]) };
7087 },7508 },
7088 },7509 },
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)) {
7090 .direct => |scalar_ty| if (scalar_ty.toIntern() == ret_ty.toIntern()) {7517 .direct => |scalar_ty| if (scalar_ty.toIntern() == ret_ty.toIntern()) {
7091 assert(!isByRef(ret_ty, zcu));7518 assert(!isByRef(ret_ty, zcu));
7092 return .by_val;7519 return .by_val;
7093 } else {7520 } else .{ .mem_cast = try o.lowerType(scalar_ty, .as_value) },
7094 return .{ .mem_cast = try o.lowerType(scalar_ty, .by_value) };7521 .indirect => .sret,
7095 },
7096 .indirect => return .sret,
7097 },7522 },
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),
7098 // TODO investigate other callconvs7563 // TODO investigate other callconvs
7099 else => return .forceByVal(o, ret_ty),7564 else => .forceByVal(o, ret_ty),
7100 }7565 };
7101}7566}
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 {
7104 if (isScalar(zcu, ty)) {7569 if (isScalar(zcu, ty)) {
7105 assert(!isByRef(ty, zcu));7570 assert(!isByRef(ty, zcu));
7106 return .by_val;7571 return .by_val;
...@@ -7115,9 +7580,8 @@ fn lowerX86FastcallFnRetTy(o: *Object, zcu: *Zcu, ty: Type) Allocator.Error!FnRe...@@ -7115,9 +7580,8 @@ fn lowerX86FastcallFnRetTy(o: *Object, zcu: *Zcu, ty: Type) Allocator.Error!FnRe
7115 return .sret;7580 return .sret;
7116}7581}
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 {
7119 const zcu = o.zcu;7584 const zcu = o.zcu;
7120 const ret_ty = Type.fromInterned(fn_info.return_type);
7121 switch (x86_64_abi.classifyWindows(ret_ty, zcu, zcu.getTarget(), .ret)) {7585 switch (x86_64_abi.classifyWindows(ret_ty, zcu, zcu.getTarget(), .ret)) {
7122 .integer => if (isScalar(zcu, ret_ty)) {7586 .integer => if (isScalar(zcu, ret_ty)) {
7123 assert(!isByRef(ret_ty, zcu));7587 assert(!isByRef(ret_ty, zcu));
...@@ -7150,78 +7614,65 @@ fn lowerWin64FnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Err...@@ -7150,78 +7614,65 @@ fn lowerWin64FnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Err
7150 }7614 }
7151}7615}
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 {
7154 const zcu = o.zcu;7618 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 }
7161 const classes = x86_64_abi.classifySystemV(ret_ty, zcu, zcu.getTarget(), .ret);7619 const classes = x86_64_abi.classifySystemV(ret_ty, zcu, zcu.getTarget(), .ret);
7162 var types_index: u32 = 0;
7163 var types_buffer: [8]Builder.Type = undefined;7620 var types_buffer: [8]Builder.Type = undefined;
7164 for (classes) |class| {7621 var types_len: u32 = 0;
7165 switch (class) {7622 for (classes, 0..) |class, class_index| switch (class) {
7166 .integer => {7623 .integer => {
7167 types_buffer[types_index] = .i64;7624 types_buffer[types_len] = try o.builder.intType(@min(8 * ret_ty.abiSize(zcu) - 64 * class_index, 64));
7168 types_index += 1;7625 types_len += 1;
7169 },7626 },
7170 .sse => {7627 .sse => {
7171 types_buffer[types_index] = .double;7628 types_buffer[types_len] = .double;
7172 types_index += 1;7629 types_len += 1;
7173 },7630 },
7174 .sseup => {7631 .sseup => {
7175 if (types_buffer[types_index - 1] == .double) {7632 if (types_buffer[types_len - 1] == .double) {
7176 types_buffer[types_index - 1] = .fp128;7633 if (ret_ty.isVector(zcu)) return .by_val;
7177 } else {7634 types_buffer[types_len - 1] = .fp128;
7178 types_buffer[types_index] = .double;7635 } else {
7179 types_index += 1;7636 types_buffer[types_len] = .double;
7180 }7637 types_len += 1;
7181 },7638 }
7182 .float => {7639 },
7183 types_buffer[types_index] = .float;7640 .float => {
7184 types_index += 1;7641 types_buffer[types_len] = .float;
7185 },7642 types_len += 1;
7186 .float_combine => {7643 },
7187 types_buffer[types_index] = try o.builder.vectorType(.normal, 2, .float);7644 .float_combine => {
7188 types_index += 1;7645 types_buffer[types_len] = try o.builder.vectorType(.normal, 2, .float);
7189 },7646 types_len += 1;
7190 .x87 => {7647 },
7191 if (types_index != 0 or classes[2] != .none) return .sret;7648 .x87 => {
7192 types_buffer[types_index] = .x86_fp80;7649 if (types_len > 0 or classes[2] != .none) return .sret;
7193 types_index += 1;7650 types_buffer[types_len] = .x86_fp80;
7194 },7651 types_len += 1;
7195 .x87up => continue,7652 },
7196 .none => break,7653 .x87up => continue,
7197 .memory => return .sret,7654 .none => break,
7198 .win_i128 => unreachable, // windows only7655 .memory => return if (ret_ty.isVector(zcu)) .by_val else .sret,
7199 .bool_vector_mask,7656 .win_i128 => unreachable, // windows only
7200 .integer_per_element,7657 .bool_vector_mask,
7201 .sse_per_element,7658 .integer_per_element,
7202 .sse_sse_x87_per_qword,7659 .sse_per_element,
7203 .sse_per_xword,7660 .sse_sse_x87_per_qword,
7204 .sse_per_yword,7661 .sse_per_xword,
7205 .sse_per_zword,7662 .sse_per_yword,
7206 => unreachable, // vectors already handled by `isScalar` above7663 .sse_per_zword,
7207 }7664 => return .by_val,
7208 }7665 };
7209 const first_non_integer = std.mem.indexOfNone(x86_64_abi.Class, &classes, &.{.integer});7666 if (types_len > 1) return .{ .mem_cast = try o.builder.structType(.normal, types_buffer[0..types_len]) };
7210 if (first_non_integer == null or classes[first_non_integer.?] == .none) {7667 if (!isByRef(ret_ty, zcu)) {
7211 assert(first_non_integer orelse classes.len == types_index);7668 const llvm_ty = try o.lowerType(ret_ty, .as_value);
7212 switch (ip.indexToKey(ret_ty.toIntern())) {7669 if (types_buffer[0] == llvm_ty) return .by_val;
7213 .struct_type => {7670 if (types_buffer[0] == .i64 and llvm_ty.isPointer(&o.builder)) return .by_val;
7214 const size = ret_ty.abiSize(zcu);7671 if (types_buffer[0] == .double and llvm_ty.isVector(&o.builder) and
7215 assert(@divCeil(size, 8) == types_index);7672 llvm_ty.vectorLen(&o.builder) == 1 and
7216 if (size % 8 > 0) {7673 llvm_ty.scalarType(&o.builder) == .double) return .by_val;
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] };
7223 }7674 }
7224 return .{ .mem_cast = try o.builder.structType(.normal, types_buffer[0..types_index]) };7675 return .{ .mem_cast = types_buffer[0] };
7225}7676}
72267677
7227/// This function deliberately does not handle `_BitInt` because it typically7678/// 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...@@ -7234,15 +7685,22 @@ pub fn ccAbiPromoteInt(cc: std.lang.CallingConvention, zcu: *Zcu, ty: Type) ?std
7234 else => {},7685 else => {},
7235 }7686 }
72367687
7237 const ty_tag = ty.zigTypeTag(zcu);7688 const target = zcu.getTarget();
7238 const int_info = switch (ty_tag) {7689 const int_info: std.lang.Type.Int = if (ty.toIntern() == .bool_type)
7239 .bool => Type.u1.intInfo(zcu),7690 .{ .signedness = .unsigned, .bits = 1 }
7240 else => if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else return null,7691 else if (ty.isAbiInt(zcu))
7241 };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();
7246 return switch (target.cpu.arch) {7704 return switch (target.cpu.arch) {
7247 .aarch64,7705 .aarch64,
7248 .aarch64_be,7706 .aarch64_be,
...@@ -7338,15 +7796,26 @@ pub fn isByRef(ty: Type, zcu: *const Zcu) bool {...@@ -7338,15 +7796,26 @@ pub fn isByRef(ty: Type, zcu: *const Zcu) bool {
7338 .void,7796 .void,
7339 .bool,7797 .bool,
7340 .int,7798 .int,
7341 .float,
7342 .pointer,7799 .pointer,
7343 .error_set,7800 .error_set,
7344 .@"fn",7801 .@"fn",
7345 .@"enum",7802 .@"enum",
7346 .vector,
7347 .@"anyframe",7803 .@"anyframe",
7348 => false,7804 => 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
7350 .array,7819 .array,
7351 .frame,7820 .frame,
7352 => ty.hasRuntimeBits(zcu),7821 => ty.hasRuntimeBits(zcu),
...@@ -7392,7 +7861,7 @@ fn getAtomicAbiType(fg: *const FuncGen, ty: Type, is_rmw_xchg: bool) Allocator.E...@@ -7392,7 +7861,7 @@ fn getAtomicAbiType(fg: *const FuncGen, ty: Type, is_rmw_xchg: bool) Allocator.E
7392fn ptraddConst(fg: *FuncGen, ptr: Builder.Value, offset: u64) Allocator.Error!Builder.Value {7861fn ptraddConst(fg: *FuncGen, ptr: Builder.Value, offset: u64) Allocator.Error!Builder.Value {
7393 if (offset == 0) return ptr;7862 if (offset == 0) return ptr;
7394 const o = fg.object;7863 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);
7396 const offset_val = try o.builder.intValue(llvm_usize_ty, offset);7865 const offset_val = try o.builder.intValue(llvm_usize_ty, offset);
7397 return fg.wip.gep(.inbounds, .i8, ptr, &.{offset_val}, "");7866 return fg.wip.gep(.inbounds, .i8, ptr, &.{offset_val}, "");
7398}7867}
...@@ -7407,12 +7876,19 @@ fn ptraddScaled(fg: *FuncGen, ptr: Builder.Value, index: Builder.Value, scale: u...@@ -7407,12 +7876,19 @@ fn ptraddScaled(fg: *FuncGen, ptr: Builder.Value, index: Builder.Value, scale: u
7407 return fg.wip.gep(.inbounds, llvm_scale_ty, ptr, &.{index}, "");7876 return fg.wip.gep(.inbounds, llvm_scale_ty, ptr, &.{index}, "");
7408}7877}
74097878
7410fn compilerRtIntBits(bits: u16) ?u16 {7879fn compilerRtPromoteInt(int_info: InternPool.Key.IntType) ?Type {
7411 inline for (.{ 32, 64, 128 }) |b| {7880 if (int_info.bits <= 32) return switch (int_info.signedness) {
7412 if (bits <= b) {7881 .signed => .i32,
7413 return b;7882 .unsigned => .u32,
7414 }7883 };
7415 }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 };
7416 return null;7892 return null;
7417}7893}
74187894
...@@ -7471,13 +7947,21 @@ fn appendConstraints(...@@ -7471,13 +7947,21 @@ fn appendConstraints(
7471}7947}
74727948
7473/// LLVM does not support all relevant intrinsics for all targets, so we7949/// LLVM does not support all relevant intrinsics for all targets, so we
7474/// may need to manually generate a compiler-rt call.7950/// may need to manually generate a compiler-rt call using a soft type.
7475fn intrinsicsAllowed(scalar_ty: Type, target: *const std.Target) bool {7951fn intrinsicsAllowed(kind: enum { compiler_rt, libc }, scalar_ty: Type, target: *const std.Target) bool {
7476 return switch (scalar_ty.toIntern()) {7952 if (!scalar_ty.isRuntimeFloat()) return true;
7477 .f16_type => llvm.backendSupportsF16(target),7953 const bits = scalar_ty.floatBits(target);
7478 .f80_type => (target.cTypeBitSize(.longdouble) == 80) and llvm.backendSupportsF80(target),7954 // Since upstream musl/msvc do not actually define the *f128 functions, llvm decides
7479 .f128_type => (target.cTypeBitSize(.longdouble) == 128) and llvm.backendSupportsF128(target),7955 // that it is a much better idea to just emit a call to the entirely wrong function as
7480 else => true,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,
7481 };7965 };
7482}7966}
74837967
...@@ -7823,12 +8307,14 @@ const Builder = std.zig.llvm.Builder;...@@ -7823,12 +8307,14 @@ const Builder = std.zig.llvm.Builder;
7823const assert = std.debug.assert;8307const assert = std.debug.assert;
7824const math = std.math;8308const math = std.math;
78258309
7826const x86_64_abi = @import("../x86_64/abi.zig");
7827const wasm_c_abi = @import("../wasm/abi.zig");
7828const aarch64_c_abi = @import("../aarch64/abi.zig");8310const aarch64_c_abi = @import("../aarch64/abi.zig");
7829const arm_c_abi = @import("../arm/abi.zig");8311const arm_c_abi = @import("../arm/abi.zig");
7830const riscv_c_abi = @import("../riscv64/abi.zig");8312const loongarch_c_abi = @import("../loongarch/abi.zig");
7831const mips_c_abi = @import("../mips/abi.zig");8313const 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
7833const Zcu = @import("../../Zcu.zig");8319const Zcu = @import("../../Zcu.zig");
7834const Air = @import("../../Air.zig");8320const Air = @import("../../Air.zig");
src/codegen/llvm/bindings.zig+2
...@@ -331,6 +331,8 @@ extern fn ZigLLVMWriteArchive(...@@ -331,6 +331,8 @@ extern fn ZigLLVMWriteArchive(
331 file_names_ptr: [*]const [*:0]const u8,331 file_names_ptr: [*]const [*:0]const u8,
332 file_names_len: usize,332 file_names_len: usize,
333 archive_kind: ArchiveKind,333 archive_kind: ArchiveKind,
334 err_file_index_out: *usize,
335 err_msg_out: *[*:0]u8,
334) bool;336) bool;
335337
336pub const ParseCommandLineOptions = ZigLLVMParseCommandLineOptions;338pub 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 {...@@ -38,7 +38,14 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
38 return .byval;38 return .byval;
39 },39 },
40 .bool => return .byval,40 .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 },
42 .int, .@"enum", .error_set => {49 .int, .@"enum", .error_set => {
43 return .byval;50 return .byval;
44 },51 },
src/codegen/riscv64/CodeGen.zig+8-8
...@@ -5036,7 +5036,7 @@ fn airRet(func: *Func, inst: Air.Inst.Index, safety: bool) !void {...@@ -5036,7 +5036,7 @@ fn airRet(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
5036 .register_pair,5036 .register_pair,
5037 => {5037 => {
5038 if (ret_ty.isVector(zcu)) {5038 if (ret_ty.isVector(zcu)) {
5039 const bit_size = ret_ty.totalVectorBits(zcu);5039 const bit_size = ret_ty.bitSize(zcu);
50405040
5041 // set the vtype to hold the entire vector's contents in a single element5041 // set the vtype to hold the entire vector's contents in a single element
5042 try func.setVl(.zero, 0, .{5042 try func.setVl(.zero, 0, .{
...@@ -6235,8 +6235,8 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void {...@@ -6235,8 +6235,8 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void {
6235 next_op: for (&ops) |*op| {6235 next_op: for (&ops) |*op| {
6236 const op_str = while (!last_op) {6236 const op_str = while (!last_op) {
6237 const full_str = op_it.next() orelse break :next_op;6237 const full_str = op_it.next() orelse break :next_op;
6238 const code_str = if (mem.indexOfScalar(u8, full_str, '#') orelse6238 const code_str = if (mem.findScalar(u8, full_str, '#') orelse
6239 mem.indexOf(u8, full_str, "//")) |comment|6239 mem.find(u8, full_str, "//")) |comment|
6240 code: {6240 code: {
6241 last_op = true;6241 last_op = true;
6242 break :code full_str[0..comment];6242 break :code full_str[0..comment];
...@@ -6250,7 +6250,7 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void {...@@ -6250,7 +6250,7 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void {
6250 } else if (std.fmt.parseInt(i12, op_str, 10)) |int| {6250 } else if (std.fmt.parseInt(i12, op_str, 10)) |int| {
6251 op.* = .{ .imm = Immediate.s(int) };6251 op.* = .{ .imm = Immediate.s(int) };
6252 } else |_| if (mem.startsWith(u8, op_str, "%[")) {6252 } 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, "]@");
6254 const modifier = if (mod_index) |index|6254 const modifier = if (mod_index) |index|
6255 op_str[index + "]@".len ..]6255 op_str[index + "]@".len ..]
6256 else6256 else
...@@ -6871,7 +6871,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -6871,7 +6871,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
6871 // size to the total size of the vector, and vmv.x.s will work then6871 // size to the total size of the vector, and vmv.x.s will work then
6872 if (src_reg.class() == .vector) {6872 if (src_reg.class() == .vector) {
6873 try func.setVl(.zero, 0, .{6873 try func.setVl(.zero, 0, .{
6874 .vsew = switch (ty.totalVectorBits(zcu)) {6874 .vsew = switch (ty.bitSize(zcu)) {
6875 8 => .@"8",6875 8 => .@"8",
6876 16 => .@"16",6876 16 => .@"16",
6877 32 => .@"32",6877 32 => .@"32",
...@@ -8339,9 +8339,9 @@ fn resolveCallingConventionValues(...@@ -8339,9 +8339,9 @@ fn resolveCallingConventionValues(
8339fn wantSafety(func: *Func) bool {8339fn wantSafety(func: *Func) bool {
8340 return switch (func.mod.optimize_mode) {8340 return switch (func.mod.optimize_mode) {
8341 .Debug => true,8341 .Debug => true,
8342 .ReleaseSafe => true,8342 .safe => true,
8343 .ReleaseFast => false,8343 .fast => false,
8344 .ReleaseSmall => false,8344 .small => false,
8345 };8345 };
8346}8346}
83478347
src/codegen/riscv64/abi.zig+10-2
...@@ -56,12 +56,20 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class {...@@ -56,12 +56,20 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class {
56 return .integer;56 return .integer;
57 },57 },
58 .bool => return .integer,58 .bool => return .integer,
59 .float => return .byval,
60 .int, .@"enum", .error_set => {59 .int, .@"enum", .error_set => {
61 const bit_size = ty.bitSize(zcu);60 const bit_size = ty.bitSize(zcu);
62 if (bit_size > max_byval_size) return .memory;61 if (bit_size > max_byval_size) return .memory;
63 return .byval;62 return .byval;
64 },63 },
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 },
65 .vector => {73 .vector => {
66 const bit_size = ty.bitSize(zcu);74 const bit_size = ty.bitSize(zcu);
67 if (bit_size > max_byval_size) return .memory;75 if (bit_size > max_byval_size) return .memory;
...@@ -190,7 +198,7 @@ pub fn classifySystem(ty: Type, zcu: *Zcu) [8]SystemClass {...@@ -190,7 +198,7 @@ pub fn classifySystem(ty: Type, zcu: *Zcu) [8]SystemClass {
190 },198 },
191 .vector => {199 .vector => {
192 // we pass vectors through integer registers if they are small enough to fit.200 // 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);
194 if (vec_bits <= 64) {202 if (vec_bits <= 64) {
195 result[0] = .integer;203 result[0] = .integer;
196 return result;204 return result;
src/codegen/riscv64/encoding.zig+1-1
...@@ -498,7 +498,7 @@ pub const Instruction = union(Lir.Format) {...@@ -498,7 +498,7 @@ pub const Instruction = union(Lir.Format) {
498 extra: u32,498 extra: u32,
499499
500 comptime {500 comptime {
501 for (std.meta.fieldTypes(Instruction)) |field_type| {501 for (@typeInfo(Instruction).@"union".field_types) |field_type| {
502 assert(@bitSizeOf(field_type) == 32);502 assert(@bitSizeOf(field_type) == 32);
503 }503 }
504 }504 }
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(...@@ -4764,9 +4764,9 @@ fn truncRegister(
4764fn wantSafety(self: *Self) bool {4764fn wantSafety(self: *Self) bool {
4765 return switch (self.bin_file.comp.root_mod.optimize_mode) {4765 return switch (self.bin_file.comp.root_mod.optimize_mode) {
4766 .Debug => true,4766 .Debug => true,
4767 .ReleaseSafe => true,4767 .safe => true,
4768 .ReleaseFast => false,4768 .fast => false,
4769 .ReleaseSmall => false,4769 .small => false,
4770 };4770 };
4771}4771}
47724772
src/codegen/spirv/Assembler.zig+39-38
...@@ -24,8 +24,9 @@ inst: struct {...@@ -24,8 +24,9 @@ inst: struct {
24 opcode: Opcode = undefined,24 opcode: Opcode = undefined,
25 operands: std.ArrayList(Operand) = .empty,25 operands: std.ArrayList(Operand) = .empty,
26 string_bytes: std.ArrayList(u8) = .empty,26 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 {
29 for (ass.operands.items[0..@min(ass.operands.items.len, 2)]) |op| {30 for (ass.operands.items[0..@min(ass.operands.items.len, 2)]) |op| {
30 switch (op) {31 switch (op) {
31 .result_id => |index| return index,32 .result_id => |index| return index,
...@@ -35,7 +36,7 @@ inst: struct {...@@ -35,7 +36,7 @@ inst: struct {
35 return null;36 return null;
36 }37 }
37} = .{},38} = .{},
38value_map: std.array_hash_map.String(AsmValue) = .{},39value_map: std.array_hash_map.String(AsmValue) = .empty,
39inst_map: std.array_hash_map.String(void) = .empty,40inst_map: std.array_hash_map.String(void) = .empty,
4041
41const Operand = union(enum) {42const Operand = union(enum) {
...@@ -82,7 +83,7 @@ pub fn assemble(ass: *Assembler, src: []const u8) Error!void {...@@ -82,7 +83,7 @@ pub fn assemble(ass: *Assembler, src: []const u8) Error!void {
82 if (ass.inst_map.count() == 0) {83 if (ass.inst_map.count() == 0) {
83 const instructions = spec.InstructionSet.core.instructions();84 const instructions = spec.InstructionSet.core.instructions();
84 try ass.inst_map.ensureUnusedCapacity(gpa, @intCast(instructions.len));85 try ass.inst_map.ensureUnusedCapacity(gpa, @intCast(instructions.len));
85 for (spec.InstructionSet.core.instructions(), 0..) |inst, i| {86 for (instructions, 0..) |inst, i| {
86 const entry = try ass.inst_map.getOrPut(gpa, inst.name);87 const entry = try ass.inst_map.getOrPut(gpa, inst.name);
87 assert(entry.index == i);88 assert(entry.index == i);
88 }89 }
...@@ -114,12 +115,13 @@ fn addError(ass: *Assembler, offset: u32, comptime fmt: []const u8, args: anytyp...@@ -114,12 +115,13 @@ fn addError(ass: *Assembler, offset: u32, comptime fmt: []const u8, args: anytyp
114}115}
115116
116fn fail(ass: *Assembler, offset: u32, comptime fmt: []const u8, args: anytype) Error {117fn fail(ass: *Assembler, offset: u32, comptime fmt: []const u8, args: anytype) Error {
118 @branchHint(.cold);
117 try ass.addError(offset, fmt, args);119 try ass.addError(offset, fmt, args);
118 return error.AssembleFail;120 return error.AssembleFail;
119}121}
120122
121fn todo(ass: *Assembler, comptime fmt: []const u8, args: anytype) Error {123fn 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);
123}125}
124126
125const AsmValue = union(enum) {127const AsmValue = union(enum) {
...@@ -177,19 +179,19 @@ fn processInstruction(ass: *Assembler) !void {...@@ -177,19 +179,19 @@ fn processInstruction(ass: *Assembler) !void {
177 const cg = ass.cg;179 const cg = ass.cg;
178 const result: AsmValue = switch (ass.inst.opcode) {180 const result: AsmValue = switch (ass.inst.opcode) {
179 .OpEntryPoint => {181 .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", .{});
181 },183 },
182 .OpExecutionMode, .OpExecutionModeId => {184 .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", .{});
184 },186 },
185 .OpCapability, .OpExtension => {187 .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", .{});
187 },189 },
188 .OpExtInstImport => blk: {190 .OpExtInstImport => blk: {
189 const set_name_offset = ass.inst.operands.items[1].string;191 const set_name_offset = ass.inst.operands.items[1].string;
190 const set_name = std.mem.sliceTo(ass.inst.string_bytes.items[set_name_offset..], 0);192 const set_name = std.mem.sliceTo(ass.inst.string_bytes.items[set_name_offset..], 0);
191 const set_tag = std.meta.stringToEnum(spec.InstructionSet, set_name) orelse {193 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});
193 };195 };
194 break :blk .{ .value = try cg.importInstructionSet(set_tag) };196 break :blk .{ .value = try cg.importInstructionSet(set_tag) };
195 },197 },
...@@ -209,9 +211,8 @@ fn processInstruction(ass: *Assembler) !void {...@@ -209,9 +211,8 @@ fn processInstruction(ass: *Assembler) !void {
209 switch (ass.value_map.values()[result_ref]) {211 switch (ass.value_map.values()[result_ref]) {
210 .just_declared => ass.value_map.values()[result_ref] = result,212 .just_declared => ass.value_map.values()[result_ref] = result,
211 else => {213 else => {
212 // TODO: Improve source location.
213 const name = ass.value_map.keys()[result_ref];214 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});
215 },216 },
216 }217 }
217}218}
...@@ -229,12 +230,11 @@ fn processTypeInstruction(ass: *Assembler) !AsmValue {...@@ -229,12 +230,11 @@ fn processTypeInstruction(ass: *Assembler) !AsmValue {
229 0 => .unsigned,230 0 => .unsigned,
230 1 => .signed,231 1 => .signed,
231 else => {232 else => {
232 // TODO: Improve source location.233 return ass.fail(ass.inst.inst_offset, "{} is not a valid signedness (expected 0 or 1)", .{operands[2].literal32});
233 return ass.fail(0, "{} is not a valid signedness (expected 0 or 1)", .{operands[2].literal32});
234 },234 },
235 };235 };
236 const width = std.math.cast(u16, operands[1].literal32) orelse {236 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});
238 };238 };
239 break :blk try cg.intType(signedness, width);239 break :blk try cg.intType(signedness, width);
240 },240 },
...@@ -243,7 +243,7 @@ fn processTypeInstruction(ass: *Assembler) !AsmValue {...@@ -243,7 +243,7 @@ fn processTypeInstruction(ass: *Assembler) !AsmValue {
243 switch (bits) {243 switch (bits) {
244 16, 32, 64 => {},244 16, 32, 64 => {},
245 else => {245 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});
247 },247 },
248 }248 }
249 break :blk try cg.floatType(@intCast(bits));249 break :blk try cg.floatType(@intCast(bits));
...@@ -366,38 +366,40 @@ fn processGenericInstruction(ass: *Assembler) !?AsmValue {...@@ -366,38 +366,40 @@ fn processGenericInstruction(ass: *Assembler) !?AsmValue {
366366
367 var maybe_result_id: ?Id = null;367 var maybe_result_id: ?Id = null;
368 const first_word = section.instructions.items.len;368 const first_word = section.instructions.items.len;
369 // At this point we're not quite sure how many operands this instruction is369
370 // going to have, so insert 0 and patch up the actual opcode word later.370 // Pre-calculate exact instruction size to avoid per-operand capacity checks.
371 try section.ensureUnusedCapacity(cg.gpa, 1);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);
372 section.writeWord(0);384 section.writeWord(0);
373385
374 for (operands) |operand| {386 for (operands) |operand| {
375 switch (operand) {387 switch (operand) {
376 .value, .literal32 => |word| {388 .value, .literal32 => |word| section.writeWord(word),
377 try section.ensureUnusedCapacity(cg.gpa, 1);389 .literal64 => |dword| section.writeDoubleWord(dword),
378 section.writeWord(word);
379 },
380 .literal64 => |dword| {
381 try section.ensureUnusedCapacity(cg.gpa, 2);
382 section.writeDoubleWord(dword);
383 },
384 .result_id => {390 .result_id => {
385 maybe_result_id = if (maybe_spv_decl_index) |spv_decl_index|391 maybe_result_id = if (maybe_spv_decl_index) |spv_decl_index|
386 cg.declPtr(spv_decl_index).result_id392 cg.declPtr(spv_decl_index).result_id
387 else393 else
388 cg.allocId();394 cg.allocId();
389 try section.ensureUnusedCapacity(cg.gpa, 1);
390 section.writeOperand(Id, maybe_result_id.?);395 section.writeOperand(Id, maybe_result_id.?);
391 },396 },
392 .ref_id => |index| {397 .ref_id => |index| {
393 const result = try ass.resolveRef(index);398 const result = try ass.resolveRef(index);
394 try section.ensureUnusedCapacity(cg.gpa, 1);
395 section.writeOperand(spec.Id, result.resultId());399 section.writeOperand(spec.Id, result.resultId());
396 },400 },
397 .string => |offset| {401 .string => |offset| {
398 const text = std.mem.sliceTo(ass.inst.string_bytes.items[offset..], 0);402 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);
401 section.writeOperand(spec.LiteralString, text);403 section.writeOperand(spec.LiteralString, text);
402 },404 },
403 }405 }
...@@ -445,11 +447,11 @@ fn processSpecConstVector(ass: *Assembler) !?AsmValue {...@@ -445,11 +447,11 @@ fn processSpecConstVector(ass: *Assembler) !?AsmValue {
445 const gpa = cg.gpa;447 const gpa = cg.gpa;
446 const ty_ref = switch (ass.inst.operands.items[0]) {448 const ty_ref = switch (ass.inst.operands.items[0]) {
447 .ref_id => |i| i,449 .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", .{}),
449 };451 };
450 const composite_ty_id = switch (try ass.resolveRef(ty_ref)) {452 const composite_ty_id = switch (try ass.resolveRef(ty_ref)) {
451 .ty => |id| id,453 .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", .{}),
453 };455 };
454456
455 const globals = &cg.sections.globals;457 const globals = &cg.sections.globals;
...@@ -483,7 +485,7 @@ fn processSpecConstVector(ass: *Assembler) !?AsmValue {...@@ -483,7 +485,7 @@ fn processSpecConstVector(ass: *Assembler) !?AsmValue {
483 }485 }
484486
485 const spec_id_word = std.math.cast(u32, spec_id_base + i) orelse {487 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});
487 };489 };
488 try annotations.emitRaw(gpa, .OpDecorate, 3);490 try annotations.emitRaw(gpa, .OpDecorate, 3);
489 annotations.writeOperand(Id, elem_id);491 annotations.writeOperand(Id, elem_id);
...@@ -505,8 +507,7 @@ fn resolveMaybeForwardRef(ass: *Assembler, ref: AsmValue.Ref) !AsmValue {...@@ -505,8 +507,7 @@ fn resolveMaybeForwardRef(ass: *Assembler, ref: AsmValue.Ref) !AsmValue {
505 switch (value) {507 switch (value) {
506 .just_declared => {508 .just_declared => {
507 const name = ass.value_map.keys()[ref];509 const name = ass.value_map.keys()[ref];
508 // TODO: Improve source location.510 return ass.fail(ass.inst.inst_offset, "self-referential parameter %{s}", .{name});
509 return ass.fail(0, "ass-referential parameter %{s}", .{name});
510 },511 },
511 else => return value,512 else => return value,
512 }513 }
...@@ -518,8 +519,7 @@ fn resolveRef(ass: *Assembler, ref: AsmValue.Ref) !AsmValue {...@@ -518,8 +519,7 @@ fn resolveRef(ass: *Assembler, ref: AsmValue.Ref) !AsmValue {
518 .just_declared => unreachable,519 .just_declared => unreachable,
519 .unresolved_forward_reference => {520 .unresolved_forward_reference => {
520 const name = ass.value_map.keys()[ref];521 const name = ass.value_map.keys()[ref];
521 // TODO: Improve source location.522 return ass.fail(ass.inst.inst_offset, "reference to undeclared result-id %{s}", .{name});
522 return ass.fail(0, "reference to undeclared result-id %{s}", .{name});
523 },523 },
524 else => return value,524 else => return value,
525 }525 }
...@@ -536,6 +536,7 @@ fn parseInstruction(ass: *Assembler) !void {...@@ -536,6 +536,7 @@ fn parseInstruction(ass: *Assembler) !void {
536 ass.inst.opcode = undefined;536 ass.inst.opcode = undefined;
537 ass.inst.operands.clearRetainingCapacity();537 ass.inst.operands.clearRetainingCapacity();
538 ass.inst.string_bytes.clearRetainingCapacity();538 ass.inst.string_bytes.clearRetainingCapacity();
539 ass.inst.inst_offset = ass.currentToken().start;
539540
540 const lhs_result_tok = ass.currentToken();541 const lhs_result_tok = ass.currentToken();
541 const maybe_lhs_result: ?AsmValue.Ref = if (ass.eatToken(.result_id_assign)) blk: {542 const maybe_lhs_result: ?AsmValue.Ref = if (ass.eatToken(.result_id_assign)) blk: {
...@@ -589,8 +590,8 @@ fn parseInstruction(ass: *Assembler) !void {...@@ -589,8 +590,8 @@ fn parseInstruction(ass: *Assembler) !void {
589 .required => if (ass.isAtInstructionBoundary()) {590 .required => if (ass.isAtInstructionBoundary()) {
590 return ass.fail(591 return ass.fail(
591 ass.currentToken().start,592 ass.currentToken().start,
592 "missing required operand", // TODO: Operand name?593 "missing required operand '{s}'",
593 .{},594 .{@tagName(operand.kind)},
594 );595 );
595 } else {596 } else {
596 try ass.parseOperand(operand.kind);597 try ass.parseOperand(operand.kind);
src/codegen/spirv/CodeGen.zig+2-2
...@@ -7280,7 +7280,7 @@ fn structuredBreak(cg: *CodeGen, target_block: Id) !void {...@@ -7280,7 +7280,7 @@ fn structuredBreak(cg: *CodeGen, target_block: Id) !void {
7280 if (cg.block_terminated) return;7280 if (cg.block_terminated) return;
72817281
7282 const gpa = cg.gpa;7282 const gpa = cg.gpa;
7283 const sblock = cg.block_stack.getLast().?;7283 const sblock = cg.block_stack.last().?;
7284 const merge_block = switch (sblock.*) {7284 const merge_block = switch (sblock.*) {
7285 .selection => |*merge| blk: {7285 .selection => |*merge| blk: {
7286 const merge_label = cg.allocId();7286 const merge_label = cg.allocId();
...@@ -7447,7 +7447,7 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index)...@@ -7447,7 +7447,7 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index)
7447 .operand_2 = this_block,7447 .operand_2 = this_block,
7448 });7448 });
74497449
7450 const sblock = cg.block_stack.getLast().?;7450 const sblock = cg.block_stack.last().?;
74517451
7452 if (ty.isNoReturn(zcu)) {7452 if (ty.isNoReturn(zcu)) {
7453 // If this block is noreturn, this instruction is the last of a block,7453 // 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(...@@ -49,8 +49,9 @@ pub fn emitRaw(
49 operand_words: usize,49 operand_words: usize,
50) !void {50) !void {
51 const word_count = 1 + operand_words;51 const word_count = 1 + operand_words;
52 if (word_count > std.math.maxInt(u16)) return error.OutOfMemory;
52 try section.instructions.ensureUnusedCapacity(allocator, word_count);53 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));
54}55}
5556
56/// Write an entire instruction, including all operands57/// Write an entire instruction, including all operands
...@@ -70,7 +71,8 @@ pub fn emitAssumeCapacity(...@@ -70,7 +71,8 @@ pub fn emitAssumeCapacity(
70 operands: opcode.Operands(),71 operands: opcode.Operands(),
71) !void {72) !void {
72 const word_count = instructionSize(opcode, operands);73 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));
74 section.writeOperands(opcode.Operands(), operands);76 section.writeOperands(opcode.Operands(), operands);
75}77}
7678
...@@ -81,8 +83,9 @@ pub fn emit(...@@ -81,8 +83,9 @@ pub fn emit(
81 operands: opcode.Operands(),83 operands: opcode.Operands(),
82) !void {84) !void {
83 const word_count = instructionSize(opcode, operands);85 const word_count = instructionSize(opcode, operands);
86 if (word_count > std.math.maxInt(u16)) return error.OutOfMemory;
84 try section.instructions.ensureUnusedCapacity(allocator, word_count);87 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));
86 section.writeOperands(opcode.Operands(), operands);89 section.writeOperands(opcode.Operands(), operands);
87}90}
8891
src/codegen/wasm/CodeGen.zig+111-65
...@@ -24,12 +24,6 @@ const Alignment = InternPool.Alignment;...@@ -24,12 +24,6 @@ const Alignment = InternPool.Alignment;
24const errUnionPayloadOffset = codegen.errUnionPayloadOffset;24const errUnionPayloadOffset = codegen.errUnionPayloadOffset;
25const errUnionErrorOffset = codegen.errUnionErrorOffset;25const 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
33pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {27pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
34 return comptime &.initMany(&.{28 return comptime &.initMany(&.{
35 .expand_bit_cast_safe,29 .expand_bit_cast_safe,
...@@ -573,7 +567,7 @@ fn addCallIntrinsic(cg: *CodeGen, intrinsic: Mir.Intrinsic) error{OutOfMemory}!v...@@ -573,7 +567,7 @@ fn addCallIntrinsic(cg: *CodeGen, intrinsic: Mir.Intrinsic) error{OutOfMemory}!v
573/// Appends entries to `mir_extra` based on the type of `extra`.567/// Appends entries to `mir_extra` based on the type of `extra`.
574/// Returns the index into `mir_extra`568/// Returns the index into `mir_extra`
575fn addExtra(cg: *CodeGen, extra: anytype) error{OutOfMemory}!u32 {569fn 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;
577 try cg.mir_extra.ensureUnusedCapacity(cg.gpa, field_count);571 try cg.mir_extra.ensureUnusedCapacity(cg.gpa, field_count);
578 return cg.addExtraAssumeCapacity(extra);572 return cg.addExtraAssumeCapacity(extra);
579}573}
...@@ -933,21 +927,26 @@ fn resolveCallingConventionValues(...@@ -933,21 +927,26 @@ fn resolveCallingConventionValues(
933 },927 },
934 .wasm_mvp => {928 .wasm_mvp => {
935 for (fn_info.param_types.get(ip)) |ty| {929 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)) {
937 continue;932 continue;
938 }933 }
939 switch (abi.classifyType(.fromInterned(ty), zcu)) {934
940 .direct => |scalar_ty| if (!abi.lowerAsDoubleI64(scalar_ty, zcu)) {935 switch (abi.classifyType(param_ty, zcu, target)) {
936 .direct, .indirect => {
941 try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } });937 try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } });
942 result.local_index += 1;938 result.local_index += 1;
943 } else {939 },
940 .double_i64 => {
944 try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } });941 try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } });
945 try args.append(.{ .local = .{ .value = result.local_index + 1, .references = 1 } });942 try args.append(.{ .local = .{ .value = result.local_index + 1, .references = 1 } });
946 result.local_index += 2;943 result.local_index += 2;
947 },944 },
948 .indirect => {945 .unrolled => |vector| {
949 try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } });946 for (0..vector.len) |_| {
950 result.local_index += 1;947 try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } });
948 result.local_index += 1;
949 }
951 },950 },
952 }951 }
953 }952 }
...@@ -974,9 +973,10 @@ pub fn firstParamSRet(...@@ -974,9 +973,10 @@ pub fn firstParamSRet(
974 switch (cc) {973 switch (cc) {
975 .@"inline" => unreachable,974 .@"inline" => unreachable,
976 .auto => return isByRef(return_type, zcu, target),975 .auto => return isByRef(return_type, zcu, target),
977 .wasm_mvp => switch (abi.classifyType(return_type, zcu)) {976 .wasm_mvp => switch (abi.classifyType(return_type, zcu, target)) {
978 .direct => |scalar_ty| return abi.lowerAsDoubleI64(scalar_ty, zcu),977 .direct => return false,
979 .indirect => return true,978 .double_i64, .indirect => return true,
979 .unrolled => |vector| return vector.len > 1,
980 },980 },
981 else => return false,981 else => return false,
982 }982 }
...@@ -991,18 +991,15 @@ fn lowerArg(cg: *CodeGen, cc: std.lang.CallingConvention, ty: Type, value: WValu...@@ -991,18 +991,15 @@ fn lowerArg(cg: *CodeGen, cc: std.lang.CallingConvention, ty: Type, value: WValu
991991
992 const zcu = cg.pt.zcu;992 const zcu = cg.pt.zcu;
993993
994 switch (abi.classifyType(ty, zcu)) {994 switch (abi.classifyType(ty, zcu, cg.target)) {
995 .direct => |scalar_type| if (!abi.lowerAsDoubleI64(scalar_type, zcu)) {995 .direct => |scalar_ty| {
996 if (!isByRef(ty, zcu, cg.target)) {996 if (!isByRef(ty, zcu, cg.target)) {
997 return cg.lowerToStack(value);997 return cg.lowerToStack(value);
998 } else {998 } else {
999 switch (value) {999 _ = try cg.load(value, scalar_ty, 0);
1000 .nav_ref, .stack_offset => _ = try cg.load(value, scalar_type, 0),
1001 .dead => unreachable,
1002 else => try cg.emitWValue(value),
1003 }
1004 }1000 }
1005 } else {1001 },
1002 .double_i64 => {
1006 assert(ty.abiSize(zcu) == 16);1003 assert(ty.abiSize(zcu) == 16);
1007 // in this case we have an integer or float that must be lowered as 2 i64's.1004 // in this case we have an integer or float that must be lowered as 2 i64's.
1008 try cg.emitWValue(value);1005 try cg.emitWValue(value);
...@@ -1010,7 +1007,17 @@ fn lowerArg(cg: *CodeGen, cc: std.lang.CallingConvention, ty: Type, value: WValu...@@ -1010,7 +1007,17 @@ fn lowerArg(cg: *CodeGen, cc: std.lang.CallingConvention, ty: Type, value: WValu
1010 try cg.emitWValue(value);1007 try cg.emitWValue(value);
1011 try cg.addMemArg(.i64_load, .{ .offset = value.offset() + 8, .alignment = 8 });1008 try cg.addMemArg(.i64_load, .{ .offset = value.offset() + 8, .alignment = 8 });
1012 },1009 },
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 },
1014 }1021 }
1015}1022}
10161023
...@@ -1953,16 +1960,19 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -1953,16 +1960,19 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
1953 if (cg.return_value != .none) {1960 if (cg.return_value != .none) {
1954 try cg.store(cg.return_value, operand, ret_ty, 0);1961 try cg.store(cg.return_value, operand, ret_ty, 0);
1955 } else if (fn_info.cc == .wasm_mvp and ret_ty.hasRuntimeBits(zcu)) {1962 } 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)) {
1957 .direct => |scalar_type| {1964 .direct => |scalar_type| {
1958 assert(!abi.lowerAsDoubleI64(scalar_type, zcu));
1959 if (!isByRef(ret_ty, zcu, cg.target)) {1965 if (!isByRef(ret_ty, zcu, cg.target)) {
1960 try cg.emitWValue(operand);1966 try cg.emitWValue(operand);
1961 } else {1967 } else {
1962 _ = try cg.load(operand, scalar_type, 0);1968 _ = try cg.load(operand, scalar_type, 0);
1963 }1969 }
1964 },1970 },
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 },
1966 }1976 }
1967 } else {1977 } else {
1968 if (!ret_ty.hasRuntimeBits(zcu) and ret_ty.isError(zcu)) {1978 if (!ret_ty.hasRuntimeBits(zcu) and ret_ty.isError(zcu)) {
...@@ -2009,8 +2019,18 @@ fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2009,8 +2019,18 @@ fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2009 try cg.addImm32(0);2019 try cg.addImm32(0);
2010 }2020 }
2011 } else if (!firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), zcu, cg.target)) {2021 } else if (!firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), zcu, cg.target)) {
2012 // leave on the stack2022 if (fn_info.cc == .wasm_mvp) {
2013 _ = try cg.load(operand, ret_ty, 0);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 }
2014 }2034 }
20152035
2016 try cg.restoreStackPointer();2036 try cg.restoreStackPointer();
...@@ -2138,22 +2158,30 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier)...@@ -2138,22 +2158,30 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier)
2138 } else if (first_param_sret) {2158 } else if (first_param_sret) {
2139 break :result_value sret;2159 break :result_value sret;
2140 } else if (zcu.typeToFunc(fn_ty).?.cc == .wasm_mvp) {2160 } 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)) {
2142 .direct => |scalar_type| {2162 .direct => |scalar_type| {
2143 assert(!abi.lowerAsDoubleI64(scalar_type, zcu));
2144 if (!isByRef(ret_ty, zcu, cg.target)) {2163 if (!isByRef(ret_ty, zcu, cg.target)) {
2145 const result_local = try cg.allocLocal(ret_ty);2164 const result_local = try cg.allocLocal(ret_ty);
2146 try cg.addLocal(.local_set, result_local.local.value);2165 try cg.addLocal(.local_set, result_local.local.value);
2147 break :result_value result_local;2166 break :result_value result_local;
2148 } else {2167 } else {
2149 const result_local = try cg.allocLocal(ret_ty);2168 const result_local = try cg.allocLocal(scalar_type);
2150 try cg.addLocal(.local_set, result_local.local.value);2169 try cg.addLocal(.local_set, result_local.local.value);
2151 const result = try cg.allocStack(ret_ty);2170 const result = try cg.allocStack(ret_ty);
2152 try cg.store(result, result_local, scalar_type, 0);2171 try cg.store(result, result_local, scalar_type, 0);
2153 break :result_value result;2172 break :result_value result;
2154 }2173 }
2155 },2174 },
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 },
2157 }2185 }
2158 } else {2186 } else {
2159 const result_local = try cg.allocLocal(ret_ty);2187 const result_local = try cg.allocLocal(ret_ty);
...@@ -2456,17 +2484,32 @@ fn airArg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2456,17 +2484,32 @@ fn airArg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2456 const cc = zcu.typeToFunc(zcu.navValue(cg.owner_nav).typeOf(zcu)).?.cc;2484 const cc = zcu.typeToFunc(zcu.navValue(cg.owner_nav).typeOf(zcu)).?.cc;
2457 const arg_ty = cg.typeOfIndex(inst);2485 const arg_ty = cg.typeOfIndex(inst);
2458 if (cc == .wasm_mvp) {2486 if (cc == .wasm_mvp) {
2459 switch (abi.classifyType(arg_ty, zcu)) {2487 switch (abi.classifyType(arg_ty, zcu, cg.target)) {
2460 .direct => |scalar_ty| if (!abi.lowerAsDoubleI64(scalar_ty, zcu)) {2488 .direct => |scalar_type| {
2461 cg.arg_index += 1;2489 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 => {
2463 cg.arg_index += 2;2498 cg.arg_index += 2;
2464 const result = try cg.allocStack(arg_ty);2499 const result = try cg.allocStack(arg_ty);
2465 try cg.store(result, arg, Type.u64, 0);2500 try cg.store(result, arg, Type.u64, 0);
2466 try cg.store(result, cg.args[arg_index + 1], Type.u64, 8);2501 try cg.store(result, cg.args[arg_index + 1], Type.u64, 8);
2467 return cg.finishAir(inst, result, &.{});2502 return cg.finishAir(inst, result, &.{});
2468 },2503 },
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 },
2470 }2513 }
2471 } else {2514 } else {
2472 cg.arg_index += 1;2515 cg.arg_index += 1;
...@@ -2515,15 +2558,15 @@ const IntType = struct {...@@ -2515,15 +2558,15 @@ const IntType = struct {
2515 .anyerror, .adhoc_inferred_error_set => .{ .is_signed = false, .bits = zcu.errorSetBits() },2558 .anyerror, .adhoc_inferred_error_set => .{ .is_signed = false, .bits = zcu.errorSetBits() },
2516 .isize => .{ .is_signed = true, .bits = cg.target.ptrBitWidth() },2559 .isize => .{ .is_signed = true, .bits = cg.target.ptrBitWidth() },
2517 .usize => .{ .is_signed = false, .bits = cg.target.ptrBitWidth() },2560 .usize => .{ .is_signed = false, .bits = cg.target.ptrBitWidth() },
2518 .c_char => .{ .is_signed = cg.target.cCharSignedness() == .signed, .bits = cg.target.cTypeBitSize(.char) },2561 .c_char => .{ .is_signed = cg.target.cCharSignedness().? == .signed, .bits = cg.target.cTypeBitSize(.char).? },
2519 .c_short => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.short) },2562 .c_short => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.short).? },
2520 .c_ushort => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.short) },2563 .c_ushort => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.short).? },
2521 .c_int => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.int) },2564 .c_int => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.int).? },
2522 .c_uint => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.int) },2565 .c_uint => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.int).? },
2523 .c_long => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.long) },2566 .c_long => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.long).? },
2524 .c_ulong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.long) },2567 .c_ulong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.long).? },
2525 .c_longlong => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.longlong) },2568 .c_longlong => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.longlong).? },
2526 .c_ulonglong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.longlong) },2569 .c_ulonglong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.longlong).? },
2527 .f16, .f32, .f64, .f80, .f128, .c_longdouble => unreachable,2570 .f16, .f32, .f64, .f80, .f128, .c_longdouble => unreachable,
2528 .anyopaque, .void, .type, .comptime_int, .comptime_float, .noreturn, .null, .undefined, .enum_literal, .generic_poison => unreachable,2571 .anyopaque, .void, .type, .comptime_int, .comptime_float, .noreturn, .null, .undefined, .enum_literal, .generic_poison => unreachable,
2529 },2572 },
...@@ -4340,7 +4383,7 @@ fn floatRem(cg: *CodeGen, ty: FloatType, lhs: WValue, rhs: WValue) InnerError!WV...@@ -4340,7 +4383,7 @@ fn floatRem(cg: *CodeGen, ty: FloatType, lhs: WValue, rhs: WValue) InnerError!WV
4340 .f32 => return cg.callIntrinsic(.fmodf, &.{ .f32_type, .f32_type }, Type.f32, &.{ lhs, rhs }),4383 .f32 => return cg.callIntrinsic(.fmodf, &.{ .f32_type, .f32_type }, Type.f32, &.{ lhs, rhs }),
4341 .f64 => return cg.callIntrinsic(.fmod, &.{ .f64_type, .f64_type }, Type.f64, &.{ lhs, rhs }),4384 .f64 => return cg.callIntrinsic(.fmod, &.{ .f64_type, .f64_type }, Type.f64, &.{ lhs, rhs }),
4342 .f80 => return cg.callIntrinsic(.__fmodx, &.{ .f80_type, .f80_type }, Type.f80, &.{ lhs, rhs }),4385 .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 }),
4344 }4387 }
4345}4388}
43464389
...@@ -4376,7 +4419,7 @@ fn floatMax(cg: *CodeGen, ty: FloatType, lhs: WValue, rhs: WValue) InnerError!WV...@@ -4376,7 +4419,7 @@ fn floatMax(cg: *CodeGen, ty: FloatType, lhs: WValue, rhs: WValue) InnerError!WV
4376 .f32 => return cg.callIntrinsic(.fmaxf, &.{ .f32_type, .f32_type }, Type.f32, &.{ lhs, rhs }),4419 .f32 => return cg.callIntrinsic(.fmaxf, &.{ .f32_type, .f32_type }, Type.f32, &.{ lhs, rhs }),
4377 .f64 => return cg.callIntrinsic(.fmax, &.{ .f64_type, .f64_type }, Type.f64, &.{ lhs, rhs }),4420 .f64 => return cg.callIntrinsic(.fmax, &.{ .f64_type, .f64_type }, Type.f64, &.{ lhs, rhs }),
4378 .f80 => return cg.callIntrinsic(.__fmaxx, &.{ .f80_type, .f80_type }, Type.f80, &.{ lhs, rhs }),4421 .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 }),
4380 }4423 }
4381}4424}
43824425
...@@ -4387,7 +4430,7 @@ fn floatMin(cg: *CodeGen, ty: FloatType, lhs: WValue, rhs: WValue) InnerError!WV...@@ -4387,7 +4430,7 @@ fn floatMin(cg: *CodeGen, ty: FloatType, lhs: WValue, rhs: WValue) InnerError!WV
4387 .f32 => return cg.callIntrinsic(.fminf, &.{ .f32_type, .f32_type }, Type.f32, &.{ lhs, rhs }),4430 .f32 => return cg.callIntrinsic(.fminf, &.{ .f32_type, .f32_type }, Type.f32, &.{ lhs, rhs }),
4388 .f64 => return cg.callIntrinsic(.fmin, &.{ .f64_type, .f64_type }, Type.f64, &.{ lhs, rhs }),4431 .f64 => return cg.callIntrinsic(.fmin, &.{ .f64_type, .f64_type }, Type.f64, &.{ lhs, rhs }),
4389 .f80 => return cg.callIntrinsic(.__fminx, &.{ .f80_type, .f80_type }, Type.f80, &.{ lhs, rhs }),4432 .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 }),
4391 }4434 }
4392}4435}
43934436
...@@ -4405,7 +4448,7 @@ fn floatSqrt(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {...@@ -4405,7 +4448,7 @@ fn floatSqrt(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
4405 return .stack;4448 return .stack;
4406 },4449 },
4407 .f80 => return cg.callIntrinsic(.__sqrtx, &.{.f80_type}, Type.f80, &.{arg}),4450 .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}),
4409 }4452 }
4410}4453}
44114454
...@@ -4415,7 +4458,7 @@ fn floatSin(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {...@@ -4415,7 +4458,7 @@ fn floatSin(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
4415 .f32 => return cg.callIntrinsic(.sinf, &.{.f32_type}, Type.f32, &.{arg}),4458 .f32 => return cg.callIntrinsic(.sinf, &.{.f32_type}, Type.f32, &.{arg}),
4416 .f64 => return cg.callIntrinsic(.sin, &.{.f64_type}, Type.f64, &.{arg}),4459 .f64 => return cg.callIntrinsic(.sin, &.{.f64_type}, Type.f64, &.{arg}),
4417 .f80 => return cg.callIntrinsic(.__sinx, &.{.f80_type}, Type.f80, &.{arg}),4460 .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}),
4419 }4462 }
4420}4463}
44214464
...@@ -4425,7 +4468,7 @@ fn floatCos(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {...@@ -4425,7 +4468,7 @@ fn floatCos(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
4425 .f32 => return cg.callIntrinsic(.cosf, &.{.f32_type}, Type.f32, &.{arg}),4468 .f32 => return cg.callIntrinsic(.cosf, &.{.f32_type}, Type.f32, &.{arg}),
4426 .f64 => return cg.callIntrinsic(.cos, &.{.f64_type}, Type.f64, &.{arg}),4469 .f64 => return cg.callIntrinsic(.cos, &.{.f64_type}, Type.f64, &.{arg}),
4427 .f80 => return cg.callIntrinsic(.__cosx, &.{.f80_type}, Type.f80, &.{arg}),4470 .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}),
4429 }4472 }
4430}4473}
44314474
...@@ -4435,7 +4478,7 @@ fn floatTan(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {...@@ -4435,7 +4478,7 @@ fn floatTan(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
4435 .f32 => return cg.callIntrinsic(.tanf, &.{.f32_type}, Type.f32, &.{arg}),4478 .f32 => return cg.callIntrinsic(.tanf, &.{.f32_type}, Type.f32, &.{arg}),
4436 .f64 => return cg.callIntrinsic(.tan, &.{.f64_type}, Type.f64, &.{arg}),4479 .f64 => return cg.callIntrinsic(.tan, &.{.f64_type}, Type.f64, &.{arg}),
4437 .f80 => return cg.callIntrinsic(.__tanx, &.{.f80_type}, Type.f80, &.{arg}),4480 .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}),
4439 }4482 }
4440}4483}
44414484
...@@ -4445,7 +4488,7 @@ fn floatExp(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {...@@ -4445,7 +4488,7 @@ fn floatExp(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
4445 .f32 => return cg.callIntrinsic(.expf, &.{.f32_type}, Type.f32, &.{arg}),4488 .f32 => return cg.callIntrinsic(.expf, &.{.f32_type}, Type.f32, &.{arg}),
4446 .f64 => return cg.callIntrinsic(.exp, &.{.f64_type}, Type.f64, &.{arg}),4489 .f64 => return cg.callIntrinsic(.exp, &.{.f64_type}, Type.f64, &.{arg}),
4447 .f80 => return cg.callIntrinsic(.__expx, &.{.f80_type}, Type.f80, &.{arg}),4490 .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}),
4449 }4492 }
4450}4493}
44514494
...@@ -4455,7 +4498,7 @@ fn floatExp2(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {...@@ -4455,7 +4498,7 @@ fn floatExp2(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
4455 .f32 => return cg.callIntrinsic(.exp2f, &.{.f32_type}, Type.f32, &.{arg}),4498 .f32 => return cg.callIntrinsic(.exp2f, &.{.f32_type}, Type.f32, &.{arg}),
4456 .f64 => return cg.callIntrinsic(.exp2, &.{.f64_type}, Type.f64, &.{arg}),4499 .f64 => return cg.callIntrinsic(.exp2, &.{.f64_type}, Type.f64, &.{arg}),
4457 .f80 => return cg.callIntrinsic(.__exp2x, &.{.f80_type}, Type.f80, &.{arg}),4500 .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}),
4459 }4502 }
4460}4503}
44614504
...@@ -4465,7 +4508,7 @@ fn floatLog(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {...@@ -4465,7 +4508,7 @@ fn floatLog(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
4465 .f32 => return cg.callIntrinsic(.logf, &.{.f32_type}, Type.f32, &.{arg}),4508 .f32 => return cg.callIntrinsic(.logf, &.{.f32_type}, Type.f32, &.{arg}),
4466 .f64 => return cg.callIntrinsic(.log, &.{.f64_type}, Type.f64, &.{arg}),4509 .f64 => return cg.callIntrinsic(.log, &.{.f64_type}, Type.f64, &.{arg}),
4467 .f80 => return cg.callIntrinsic(.__logx, &.{.f80_type}, Type.f80, &.{arg}),4510 .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}),
4469 }4512 }
4470}4513}
44714514
...@@ -4475,7 +4518,7 @@ fn floatLog2(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {...@@ -4475,7 +4518,7 @@ fn floatLog2(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
4475 .f32 => return cg.callIntrinsic(.log2f, &.{.f32_type}, Type.f32, &.{arg}),4518 .f32 => return cg.callIntrinsic(.log2f, &.{.f32_type}, Type.f32, &.{arg}),
4476 .f64 => return cg.callIntrinsic(.log2, &.{.f64_type}, Type.f64, &.{arg}),4519 .f64 => return cg.callIntrinsic(.log2, &.{.f64_type}, Type.f64, &.{arg}),
4477 .f80 => return cg.callIntrinsic(.__log2x, &.{.f80_type}, Type.f80, &.{arg}),4520 .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}),
4479 }4522 }
4480}4523}
44814524
...@@ -4485,7 +4528,7 @@ fn floatLog10(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {...@@ -4485,7 +4528,7 @@ fn floatLog10(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
4485 .f32 => return cg.callIntrinsic(.log10f, &.{.f32_type}, Type.f32, &.{arg}),4528 .f32 => return cg.callIntrinsic(.log10f, &.{.f32_type}, Type.f32, &.{arg}),
4486 .f64 => return cg.callIntrinsic(.log10, &.{.f64_type}, Type.f64, &.{arg}),4529 .f64 => return cg.callIntrinsic(.log10, &.{.f64_type}, Type.f64, &.{arg}),
4487 .f80 => return cg.callIntrinsic(.__log10x, &.{.f80_type}, Type.f80, &.{arg}),4530 .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}),
4489 }4532 }
4490}4533}
44914534
...@@ -4503,7 +4546,7 @@ fn floatFloor(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {...@@ -4503,7 +4546,7 @@ fn floatFloor(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
4503 return .stack;4546 return .stack;
4504 },4547 },
4505 .f80 => return cg.callIntrinsic(.__floorx, &.{.f80_type}, Type.f80, &.{arg}),4548 .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}),
4507 }4550 }
4508}4551}
45094552
...@@ -4521,7 +4564,7 @@ fn floatCeil(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {...@@ -4521,7 +4564,7 @@ fn floatCeil(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
4521 return .stack;4564 return .stack;
4522 },4565 },
4523 .f80 => return cg.callIntrinsic(.__ceilx, &.{.f80_type}, Type.f80, &.{arg}),4566 .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}),
4525 }4568 }
4526}4569}
45274570
...@@ -4539,7 +4582,7 @@ fn floatRound(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {...@@ -4539,7 +4582,7 @@ fn floatRound(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
4539 return .stack;4582 return .stack;
4540 },4583 },
4541 .f80 => return cg.callIntrinsic(.__roundx, &.{.f80_type}, Type.f80, &.{arg}),4584 .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}),
4543 }4586 }
4544}4587}
45454588
...@@ -4557,7 +4600,7 @@ fn floatTrunc(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {...@@ -4557,7 +4600,7 @@ fn floatTrunc(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
4557 return .stack;4600 return .stack;
4558 },4601 },
4559 .f80 => return cg.callIntrinsic(.__truncx, &.{.f80_type}, Type.f80, &.{arg}),4602 .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}),
4561 }4604 }
4562}4605}
45634606
...@@ -4929,7 +4972,8 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro...@@ -4929,7 +4972,8 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro
4929 const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr;4972 const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr;
4930 const offset: u64 = prev_offset + ptr.byte_offset;4973 const offset: u64 = prev_offset + ptr.byte_offset;
4931 return switch (ptr.base_addr) {4974 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))
4933 .{ .nav_ref = .{ .nav_index = nav, .offset = @intCast(offset) } }4977 .{ .nav_ref = .{ .nav_index = nav, .offset = @intCast(offset) } }
4934 else4978 else
4935 .{ .imm32 = @intCast(zcu.navAlignment(nav).forward(@as(u32, 0xaaaaaaaa))) },4979 .{ .imm32 = @intCast(zcu.navAlignment(nav).forward(@as(u32, 0xaaaaaaaa))) },
...@@ -5613,6 +5657,8 @@ fn bitcastClass(cg: *CodeGen, ty: Type) BitcastClass {...@@ -5613,6 +5657,8 @@ fn bitcastClass(cg: *CodeGen, ty: Type) BitcastClass {
5613}5657}
56145658
5615fn bitcast(cg: *CodeGen, dest_ty: Type, src_ty: Type, operand: WValue) InnerError!?WValue {5659fn bitcast(cg: *CodeGen, dest_ty: Type, src_ty: Type, operand: WValue) InnerError!?WValue {
5660 if (dest_ty.eql(src_ty)) return null;
5661
5616 const zcu = cg.pt.zcu;5662 const zcu = cg.pt.zcu;
5617 const src_class = cg.bitcastClass(src_ty);5663 const src_class = cg.bitcastClass(src_ty);
5618 const dest_class = cg.bitcastClass(dest_ty);5664 const dest_class = cg.bitcastClass(dest_ty);
src/codegen/wasm/Emit.zig+125-49
...@@ -21,7 +21,7 @@ pub const Error = error{...@@ -21,7 +21,7 @@ pub const Error = error{
21 OutOfMemory,21 OutOfMemory,
22};22};
2323
24pub fn lowerToCode(emit: *Emit) Error!void {24pub fn lower(emit: *Emit) Error!void {
25 const mir = &emit.mir;25 const mir = &emit.mir;
26 const code = emit.code;26 const code = emit.code;
27 const wasm = emit.wasm;27 const wasm = emit.wasm;
...@@ -31,6 +31,47 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -31,6 +31,47 @@ pub fn lowerToCode(emit: *Emit) Error!void {
31 const target = &comp.root_mod.resolved_target.result;31 const target = &comp.root_mod.resolved_target.result;
32 const is_wasm32 = target.cpu.arch == .wasm32;32 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
34 const tags = mir.instructions.items(.tag);75 const tags = mir.instructions.items(.tag);
35 const datas = mir.instructions.items(.data);76 const datas = mir.instructions.items(.data);
36 var inst: u32 = 0;77 var inst: u32 = 0;
...@@ -78,14 +119,21 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -78,14 +119,21 @@ pub fn lowerToCode(emit: *Emit) Error!void {
78 continue :loop tags[inst];119 continue :loop tags[inst];
79 },120 },
80 .func_ref => {121 .func_ref => {
81 const indirect_func_idx: Wasm.ZcuIndirectFunctionSetIndex = @fromBackingInt(@intCast(122 try code.ensureUnusedCapacity(gpa, 11);
82 wasm.zcu_indirect_function_set.getIndex(datas[inst].nav_index).?,123 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;
83 ));124 code.appendAssumeCapacity(@backingInt(opcode));
84 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.i32_const));
85 if (is_obj) {125 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);
87 } else {133 } 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);
89 }137 }
90 inst += 1;138 inst += 1;
91 continue :loop tags[inst];139 continue :loop tags[inst];
...@@ -105,18 +153,17 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -105,18 +153,17 @@ pub fn lowerToCode(emit: *Emit) Error!void {
105 continue :loop tags[inst];153 continue :loop tags[inst];
106 },154 },
107 .error_name_table_ref => {155 .error_name_table_ref => {
108 wasm.error_name_table_ref_count += 1;
109 try code.ensureUnusedCapacity(gpa, 11);156 try code.ensureUnusedCapacity(gpa, 11);
110 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;157 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;
111 code.appendAssumeCapacity(@backingInt(opcode));158 code.appendAssumeCapacity(@backingInt(opcode));
112 if (is_obj) {159 if (is_obj) {
113 try wasm.out_relocs.append(gpa, .{160 try wasm.zcu_relocations.append(gpa, .{
114 .offset = @intCast(code.items.len),161 .offset = @intCast(code.items.len),
115 .pointee = .{ .symbol_index = try wasm.errorNameTableSymbolIndex() },162 .pointee = .{ .data_resolution = .__zig_error_name_table },
116 .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64,163 .tag = if (is_wasm32) .memory_addr_sleb else .memory_addr_sleb64,
117 .addend = 0,164 .addend = 0,
118 });165 });
119 code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10);166 appendSlebRelocPlaceholder(code, is_wasm32);
120167
121 inst += 1;168 inst += 1;
122 continue :loop tags[inst];169 continue :loop tags[inst];
...@@ -164,13 +211,13 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -164,13 +211,13 @@ pub fn lowerToCode(emit: *Emit) Error!void {
164 try code.ensureUnusedCapacity(gpa, 6);211 try code.ensureUnusedCapacity(gpa, 6);
165 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call));212 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call));
166 if (is_obj) {213 if (is_obj) {
167 try wasm.out_relocs.append(gpa, .{214 try wasm.zcu_relocations.append(gpa, .{
168 .offset = @intCast(code.items.len),215 .offset = @intCast(code.items.len),
169 .pointee = .{ .symbol_index = try wasm.navSymbolIndex(datas[inst].nav_index) },216 .pointee = .{ .function_nav = datas[inst].nav_index },
170 .tag = .function_index_leb,217 .tag = .function_index_leb,
171 .addend = 0,218 .addend = 0,
172 });219 });
173 code.appendNTimesAssumeCapacity(0, 5);220 appendUlebRelocPlaceholder(code);
174 } else {221 } else {
175 appendOutputFunctionIndex(code, .fromIpNav(wasm, datas[inst].nav_index));222 appendOutputFunctionIndex(code, .fromIpNav(wasm, datas[inst].nav_index));
176 }223 }
...@@ -191,13 +238,13 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -191,13 +238,13 @@ pub fn lowerToCode(emit: *Emit) Error!void {
191 ).?;238 ).?;
192 if (is_obj) {239 if (is_obj) {
193 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call_indirect));240 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call_indirect));
194 try wasm.out_relocs.append(gpa, .{241 try wasm.zcu_relocations.append(gpa, .{
195 .offset = @intCast(code.items.len),242 .offset = @intCast(code.items.len),
196 .pointee = .{ .type_index = func_ty_index },243 .pointee = .{ .type_index = func_ty_index },
197 .tag = .type_index_leb,244 .tag = .type_index_leb,
198 .addend = 0,245 .addend = 0,
199 });246 });
200 code.appendNTimesAssumeCapacity(0, 5);247 appendUlebRelocPlaceholder(code);
201 } else {248 } else {
202 const index: Wasm.Flush.FuncTypeIndex = @fromBackingInt(@intCast(wasm.flush_buffer.func_types.getIndex(func_ty_index) orelse {249 const index: Wasm.Flush.FuncTypeIndex = @fromBackingInt(@intCast(wasm.flush_buffer.func_types.getIndex(func_ty_index) orelse {
203 // In this case we tried to call a function pointer for250 // In this case we tried to call a function pointer for
...@@ -224,13 +271,13 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -224,13 +271,13 @@ pub fn lowerToCode(emit: *Emit) Error!void {
224 try code.ensureUnusedCapacity(gpa, 6);271 try code.ensureUnusedCapacity(gpa, 6);
225 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call));272 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call));
226 if (is_obj) {273 if (is_obj) {
227 try wasm.out_relocs.append(gpa, .{274 try wasm.zcu_relocations.append(gpa, .{
228 .offset = @intCast(code.items.len),275 .offset = @intCast(code.items.len),
229 .pointee = .{ .symbol_index = try wasm.tagTableIndexSymbolIndex(datas[inst].ip_index) },276 .pointee = .{ .tag_function = datas[inst].ip_index },
230 .tag = .function_index_leb,277 .tag = .function_index_leb,
231 .addend = 0,278 .addend = 0,
232 });279 });
233 code.appendNTimesAssumeCapacity(0, 5);280 appendUlebRelocPlaceholder(code);
234 } else {281 } else {
235 appendOutputFunctionIndex(code, .fromTagIndexType(wasm, datas[inst].ip_index));282 appendOutputFunctionIndex(code, .fromTagIndexType(wasm, datas[inst].ip_index));
236 }283 }
...@@ -244,14 +291,20 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -244,14 +291,20 @@ pub fn lowerToCode(emit: *Emit) Error!void {
244 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;291 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;
245 code.appendAssumeCapacity(@backingInt(opcode));292 code.appendAssumeCapacity(@backingInt(opcode));
246 if (is_obj) {293 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);
248 } else {301 } else {
249 const addr: u32 = wasm.tagIndexTableAddr(datas[inst].ip_index);302 const addr: u32 = wasm.tagIndexTableAddr(datas[inst].ip_index);
250 writeSleb128(code, addr);303 writeSleb128(code, addr);
251
252 inst += 1;
253 continue :loop tags[inst];
254 }304 }
305
306 inst += 1;
307 continue :loop tags[inst];
255 },308 },
256309
257 .call_intrinsic => {310 .call_intrinsic => {
...@@ -263,13 +316,13 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -263,13 +316,13 @@ pub fn lowerToCode(emit: *Emit) Error!void {
263 try code.ensureUnusedCapacity(gpa, 6);316 try code.ensureUnusedCapacity(gpa, 6);
264 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call));317 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call));
265 if (is_obj) {318 if (is_obj) {
266 try wasm.out_relocs.append(gpa, .{319 try wasm.zcu_relocations.append(gpa, .{
267 .offset = @intCast(code.items.len),320 .offset = @intCast(code.items.len),
268 .pointee = .{ .symbol_index = try wasm.symbolNameIndex(symbol_name) },321 .pointee = .{ .function_name = symbol_name },
269 .tag = .function_index_leb,322 .tag = .function_index_leb,
270 .addend = 0,323 .addend = 0,
271 });324 });
272 code.appendNTimesAssumeCapacity(0, 5);325 appendUlebRelocPlaceholder(code);
273 } else {326 } else {
274 appendOutputFunctionIndex(code, .fromSymbolName(wasm, symbol_name));327 appendOutputFunctionIndex(code, .fromSymbolName(wasm, symbol_name));
275 }328 }
...@@ -281,18 +334,7 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -281,18 +334,7 @@ pub fn lowerToCode(emit: *Emit) Error!void {
281 .global_set_sp => {334 .global_set_sp => {
282 try code.ensureUnusedCapacity(gpa, 6);335 try code.ensureUnusedCapacity(gpa, 6);
283 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.global_set));336 code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.global_set));
284 if (is_obj) {337 try appendStackPointerGlobalIndex(wasm, code, 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 }
296338
297 inst += 1;339 inst += 1;
298 continue :loop tags[inst];340 continue :loop tags[inst];
...@@ -960,13 +1002,13 @@ fn uavRefObj(wasm: *Wasm, code: *ArrayList(u8), value: InternPool.Index, offset:...@@ -960,13 +1002,13 @@ fn uavRefObj(wasm: *Wasm, code: *ArrayList(u8), value: InternPool.Index, offset:
960 try code.ensureUnusedCapacity(gpa, 11);1002 try code.ensureUnusedCapacity(gpa, 11);
961 code.appendAssumeCapacity(@backingInt(opcode));1003 code.appendAssumeCapacity(@backingInt(opcode));
9621004
963 try wasm.out_relocs.append(gpa, .{1005 try wasm.zcu_relocations.append(gpa, .{
964 .offset = @intCast(code.items.len),1006 .offset = @intCast(code.items.len),
965 .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(value) },1007 .pointee = .{ .data_uav = value },
966 .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64,1008 .tag = if (is_wasm32) .memory_addr_sleb else .memory_addr_sleb64,
967 .addend = offset,1009 .addend = offset,
968 });1010 });
969 code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10);1011 appendSlebRelocPlaceholder(code, is_wasm32);
970}1012}
9711013
972fn uavRefExe(wasm: *Wasm, code: *ArrayList(u8), value: InternPool.Index, offset: i32, is_wasm32: bool) !void {1014fn 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:...@@ -978,7 +1020,7 @@ fn uavRefExe(wasm: *Wasm, code: *ArrayList(u8), value: InternPool.Index, offset:
978 code.appendAssumeCapacity(@backingInt(opcode));1020 code.appendAssumeCapacity(@backingInt(opcode));
9791021
980 const addr = wasm.uavAddr(value);1022 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)));
982}1024}
9831025
984fn navRefOff(wasm: *Wasm, code: *ArrayList(u8), data: Mir.NavRefOff, is_wasm32: bool) !void {1026fn 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:...@@ -995,16 +1037,16 @@ fn navRefOff(wasm: *Wasm, code: *ArrayList(u8), data: Mir.NavRefOff, is_wasm32:
995 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;1037 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;
996 code.appendAssumeCapacity(@backingInt(opcode));1038 code.appendAssumeCapacity(@backingInt(opcode));
997 if (is_obj) {1039 if (is_obj) {
998 try wasm.out_relocs.append(gpa, .{1040 try wasm.zcu_relocations.append(gpa, .{
999 .offset = @intCast(code.items.len),1041 .offset = @intCast(code.items.len),
1000 .pointee = .{ .symbol_index = try wasm.navSymbolIndex(data.nav_index) },1042 .pointee = .{ .data_nav = data.nav_index },
1001 .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64,1043 .tag = if (is_wasm32) .memory_addr_sleb else .memory_addr_sleb64,
1002 .addend = data.offset,1044 .addend = data.offset,
1003 });1045 });
1004 code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10);1046 appendSlebRelocPlaceholder(code, is_wasm32);
1005 } else {1047 } else {
1006 const addr = wasm.navAddr(data.nav_index);1048 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)));
1008 }1050 }
1009}1051}
10101052
...@@ -1012,6 +1054,40 @@ fn appendOutputFunctionIndex(code: *ArrayList(u8), i: Wasm.OutputFunctionIndex)...@@ -1012,6 +1054,40 @@ fn appendOutputFunctionIndex(code: *ArrayList(u8), i: Wasm.OutputFunctionIndex)
1012 writeUleb128(code, @backingInt(i));1054 writeUleb128(code, @backingInt(i));
1013}1055}
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
1015fn writeUleb128(code: *ArrayList(u8), arg: anytype) void {1091fn writeUleb128(code: *ArrayList(u8), arg: anytype) void {
1016 var w: std.Io.Writer = .fixed(code.unusedCapacitySlice());1092 var w: std.Io.Writer = .fixed(code.unusedCapacitySlice());
1017 w.writeUleb128(arg) catch unreachable;1093 w.writeUleb128(arg) catch unreachable;
src/codegen/wasm/Mir.zig+22-70
...@@ -114,7 +114,7 @@ pub const Inst = struct {...@@ -114,7 +114,7 @@ pub const Inst = struct {
114 ///114 ///
115 /// Uses `payload` pointing to a `NavRefOff`.115 /// Uses `payload` pointing to a `NavRefOff`.
116 nav_ref_off,116 nav_ref_off,
117 /// Lowers to an i32_const which is the index of the function in the117 /// Lowers to an iNN_const which is the index of the function in the
118 /// table section.118 /// table section.
119 ///119 ///
120 /// Uses `nav_index`.120 /// Uses `nav_index`.
...@@ -661,8 +661,8 @@ pub const Inst = struct {...@@ -661,8 +661,8 @@ pub const Inst = struct {
661661
662 comptime {662 comptime {
663 switch (builtin.mode) {663 switch (builtin.mode) {
664 .Debug, .ReleaseSafe => {},664 .debug, .safe => {},
665 .ReleaseFast, .ReleaseSmall => assert(@sizeOf(Data) == 4),665 .fast, .small => assert(@sizeOf(Data) == 4),
666 }666 }
667 }667 }
668 };668 };
...@@ -679,60 +679,12 @@ pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {...@@ -679,60 +679,12 @@ pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
679}679}
680680
681pub fn lower(mir: *const Mir, wasm: *Wasm, code: *std.ArrayList(u8)) std.mem.Allocator.Error!void {681pub 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
730 var emit: Emit = .{682 var emit: Emit = .{
731 .mir = mir.*,683 .mir = mir.*,
732 .wasm = wasm,684 .wasm = wasm,
733 .code = code,685 .code = code,
734 };686 };
735 try emit.lowerToCode();687 try emit.lower();
736}688}
737689
738pub fn extraData(self: *const Mir, comptime T: type, index: usize) struct { data: T, end: usize } {690pub fn extraData(self: *const Mir, comptime T: type, index: usize) struct { data: T, end: usize } {
...@@ -991,48 +943,48 @@ pub const Intrinsic = enum(u32) {...@@ -991,48 +943,48 @@ pub const Intrinsic = enum(u32) {
991 __udivti3,943 __udivti3,
992 __umodei5,944 __umodei5,
993 __umodti3,945 __umodti3,
994 ceilq,946 ceilf128,
995 cos,947 cos,
996 cosf,948 cosf,
997 cosq,949 cosf128,
998 exp,950 exp,
999 exp2,951 exp2,
1000 exp2f,952 exp2f,
1001 exp2q,953 exp2f128,
1002 expf,954 expf,
1003 expq,955 expf128,
1004 fabsq,956 fabsf128,
1005 floorq,957 floorf128,
1006 fma,958 fma,
1007 fmaf,959 fmaf,
1008 fmaq,960 fmaf128,
1009 fmax,961 fmax,
1010 fmaxf,962 fmaxf,
1011 fmaxq,963 fmaxf128,
1012 fmin,964 fmin,
1013 fminf,965 fminf,
1014 fminq,966 fminf128,
1015 fmod,967 fmod,
1016 fmodf,968 fmodf,
1017 fmodq,969 fmodf128,
1018 log,970 log,
1019 log10,971 log10,
1020 log10f,972 log10f,
1021 log10q,973 log10f128,
1022 log2,974 log2,
1023 log2f,975 log2f,
1024 log2q,976 log2f128,
1025 logf,977 logf,
1026 logq,978 logf128,
1027 roundq,979 roundf128,
1028 sin,980 sin,
1029 sinf,981 sinf,
1030 sinq,982 sinf128,
1031 sqrtq,983 sqrtf128,
1032 tan,984 tan,
1033 tanf,985 tanf,
1034 tanq,986 tanf128,
1035 truncq,987 truncf128,
1036 memcpy,988 memcpy,
1037 memmove,989 memmove,
1038 memset,990 memset,
src/codegen/wasm/abi.zig+72-22
...@@ -11,21 +11,53 @@ const assert = std.debug.assert;...@@ -11,21 +11,53 @@ const assert = std.debug.assert;
11const Type = @import("../../Type.zig");11const Type = @import("../../Type.zig");
12const Zcu = @import("../../Zcu.zig");12const Zcu = @import("../../Zcu.zig");
1313
14/// Defines how to pass a type as part of a function signature,14/// Describes how the Wasm backend represents a C ABI value.
15/// both for parameters as well as return values.
16pub const Class = union(enum) {15pub const Class = union(enum) {
17 direct: Type,16 direct: Type,
17 double_i64,
18 indirect,18 indirect,
19 unrolled: struct {
20 elem_type: Type,
21 len: u32,
22 },
19};23};
2024
21/// Classifies a given Zig type to determine how they must be passed25pub const LlvmClass = union(enum) {
22/// or returned as value within a wasm function.26 direct: Type,
23pub fn classifyType(ty: Type, zcu: *const Zcu) Class {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 {
24 const ip = &zcu.intern_pool;52 const ip = &zcu.intern_pool;
25 assert(ty.hasRuntimeBits(zcu));53 assert(ty.hasRuntimeBits(zcu));
26 switch (ty.zigTypeTag(zcu)) {54 switch (ty.zigTypeTag(zcu)) {
27 .int, .@"enum", .error_set => return .{ .direct = ty },55 .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 },
29 .bool => return .{ .direct = ty },61 .bool => return .{ .direct = ty },
30 .vector => return .{ .direct = ty },62 .vector => return .{ .direct = ty },
31 .array => return .indirect,63 .array => return .indirect,
...@@ -39,20 +71,35 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {...@@ -39,20 +71,35 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
39 },71 },
40 .@"struct" => {72 .@"struct" => {
41 const struct_type = zcu.typeToStruct(ty).?;73 const struct_type = zcu.typeToStruct(ty).?;
42 if (struct_type.layout == .@"packed") {74 switch (struct_type.layout) {
43 return .{ .direct = ty };75 .auto => unreachable,
44 }76 .@"packed" => return .{ .direct = ty },
45 if (struct_type.field_types.len > 1) {77 .@"extern" => {},
46 // The struct type is non-scalar.
47 return .indirect;
48 }78 }
49 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[0]);79 var opt_single_field_ty: ?Type = null;
50 const explicit_align = struct_type.field_aligns.getOrNone(ip, 0);80 for (struct_type.field_types.get(ip), 0..) |field_ty_index, field_index| {
51 if (explicit_align != .none) {81 const field_ty: Type = .fromInterned(field_ty_index);
52 if (explicit_align.compareStrict(.gt, field_ty.abiAlignment(zcu)))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))) {
53 return .indirect;90 return .indirect;
91 }
92 opt_single_field_ty = field_ty;
54 }93 }
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);
56 },103 },
57 .@"union" => {104 .@"union" => {
58 const union_obj = zcu.typeToUnion(ty).?;105 const union_obj = zcu.typeToUnion(ty).?;
...@@ -63,7 +110,14 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {...@@ -63,7 +110,14 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
63 assert(layout.tag_size == 0);110 assert(layout.tag_size == 0);
64 if (union_obj.field_types.len > 1) return .indirect;111 if (union_obj.field_types.len > 1) return .indirect;
65 const first_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]);112 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);
67 },121 },
68 .error_union,122 .error_union,
69 .frame,123 .frame,
...@@ -82,7 +136,3 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {...@@ -82,7 +136,3 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
82 => unreachable,136 => unreachable,
83 }137 }
84}138}
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 {...@@ -1301,7 +1301,7 @@ fn addInst(self: *CodeGen, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {
1301}1301}
13021302
1303fn addExtra(self: *CodeGen, extra: anytype) Allocator.Error!u32 {1303fn 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;
1305 try self.mir_extra.ensureUnusedCapacity(self.gpa, field_count);1305 try self.mir_extra.ensureUnusedCapacity(self.gpa, field_count);
1306 return self.addExtraAssumeCapacity(extra);1306 return self.addExtraAssumeCapacity(extra);
1307}1307}
...@@ -2152,7 +2152,7 @@ fn gen(...@@ -2152,7 +2152,7 @@ fn gen(
21522152
2153 const epilogue = if (self.epilogue_relocs.items.len > 0) epilogue: {2153 const epilogue = if (self.epilogue_relocs.items.len > 0) epilogue: {
2154 var last_inst: Mir.Inst.Index = @intCast(self.mir_instructions.len - 1);2154 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) {
2156 self.epilogue_relocs.items.len -= 1;2156 self.epilogue_relocs.items.len -= 1;
2157 self.mir_instructions.set(last_inst, .{2157 self.mir_instructions.set(last_inst, .{
2158 .tag = .pseudo,2158 .tag = .pseudo,
...@@ -34436,7 +34436,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -34436,7 +34436,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
34436 .call_frame = .{ .alignment = .@"16" },34436 .call_frame = .{ .alignment = .@"16" },
34437 .extra_temps = .{34437 .extra_temps = .{
34438 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },34438 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
34439 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },34439 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
34440 .unused,34440 .unused,
34441 .unused,34441 .unused,
34442 .unused,34442 .unused,
...@@ -34470,7 +34470,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -34470,7 +34470,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
34470 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },34470 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
34471 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },34471 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
34472 .{ .type = .f128, .kind = .mem },34472 .{ .type = .f128, .kind = .mem },
34473 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },34473 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
34474 .unused,34474 .unused,
34475 .unused,34475 .unused,
34476 .unused,34476 .unused,
...@@ -34505,7 +34505,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -34505,7 +34505,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
34505 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },34505 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
34506 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },34506 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
34507 .{ .type = .f128, .kind = .mem },34507 .{ .type = .f128, .kind = .mem },
34508 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },34508 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
34509 .unused,34509 .unused,
34510 .unused,34510 .unused,
34511 .unused,34511 .unused,
...@@ -34540,7 +34540,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -34540,7 +34540,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
34540 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },34540 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
34541 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },34541 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
34542 .{ .type = .f128, .kind = .mem },34542 .{ .type = .f128, .kind = .mem },
34543 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },34543 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
34544 .unused,34544 .unused,
34545 .unused,34545 .unused,
34546 .unused,34546 .unused,
...@@ -34575,7 +34575,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -34575,7 +34575,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
34575 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },34575 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
34576 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },34576 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
34577 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },34577 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
34578 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },34578 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
34579 .unused,34579 .unused,
34580 .unused,34580 .unused,
34581 .unused,34581 .unused,
...@@ -34612,7 +34612,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -34612,7 +34612,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
34612 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },34612 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
34613 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },34613 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
34614 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },34614 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
34615 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },34615 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
34616 .unused,34616 .unused,
34617 .unused,34617 .unused,
34618 .unused,34618 .unused,
...@@ -34649,7 +34649,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -34649,7 +34649,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
34649 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },34649 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
34650 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },34650 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
34651 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },34651 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
34652 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },34652 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
34653 .unused,34653 .unused,
34654 .unused,34654 .unused,
34655 .unused,34655 .unused,
...@@ -34688,7 +34688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -34688,7 +34688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
34688 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },34688 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
34689 .{ .type = .f128, .kind = .mem },34689 .{ .type = .f128, .kind = .mem },
34690 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },34690 .{ .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" } },
34692 .unused,34692 .unused,
34693 .unused,34693 .unused,
34694 .unused,34694 .unused,
...@@ -34727,7 +34727,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -34727,7 +34727,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
34727 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },34727 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
34728 .{ .type = .f128, .kind = .mem },34728 .{ .type = .f128, .kind = .mem },
34729 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },34729 .{ .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" } },
34731 .unused,34731 .unused,
34732 .unused,34732 .unused,
34733 .unused,34733 .unused,
...@@ -34766,7 +34766,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -34766,7 +34766,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
34766 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },34766 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
34767 .{ .type = .f128, .kind = .mem },34767 .{ .type = .f128, .kind = .mem },
34768 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },34768 .{ .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" } },
34770 .unused,34770 .unused,
34771 .unused,34771 .unused,
34772 .unused,34772 .unused,
...@@ -35960,8 +35960,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -35960,8 +35960,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
35960 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },35960 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
35961 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {35961 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
35962 else => unreachable,35962 else => unreachable,
35963 .zero => "truncq",35963 .zero => "truncf128",
35964 .down => "floorq",35964 .down => "floorf128",
35965 } } },35965 } } },
35966 .unused,35966 .unused,
35967 .unused,35967 .unused,
...@@ -35998,8 +35998,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -35998,8 +35998,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
35998 .{ .type = .f128, .kind = .mem },35998 .{ .type = .f128, .kind = .mem },
35999 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {35999 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
36000 else => unreachable,36000 else => unreachable,
36001 .zero => "truncq",36001 .zero => "truncf128",
36002 .down => "floorq",36002 .down => "floorf128",
36003 } } },36003 } } },
36004 .unused,36004 .unused,
36005 .unused,36005 .unused,
...@@ -36037,8 +36037,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -36037,8 +36037,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
36037 .{ .type = .f128, .kind = .mem },36037 .{ .type = .f128, .kind = .mem },
36038 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {36038 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
36039 else => unreachable,36039 else => unreachable,
36040 .zero => "truncq",36040 .zero => "truncf128",
36041 .down => "floorq",36041 .down => "floorf128",
36042 } } },36042 } } },
36043 .unused,36043 .unused,
36044 .unused,36044 .unused,
...@@ -36076,8 +36076,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -36076,8 +36076,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
36076 .{ .type = .f128, .kind = .mem },36076 .{ .type = .f128, .kind = .mem },
36077 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {36077 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
36078 else => unreachable,36078 else => unreachable,
36079 .zero => "truncq",36079 .zero => "truncf128",
36080 .down => "floorq",36080 .down => "floorf128",
36081 } } },36081 } } },
36082 .unused,36082 .unused,
36083 .unused,36083 .unused,
...@@ -36115,8 +36115,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -36115,8 +36115,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
36115 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },36115 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
36116 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {36116 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
36117 else => unreachable,36117 else => unreachable,
36118 .zero => "truncq",36118 .zero => "truncf128",
36119 .down => "floorq",36119 .down => "floorf128",
36120 } } },36120 } } },
36121 .unused,36121 .unused,
36122 .unused,36122 .unused,
...@@ -36156,8 +36156,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -36156,8 +36156,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
36156 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },36156 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
36157 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {36157 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
36158 else => unreachable,36158 else => unreachable,
36159 .zero => "truncq",36159 .zero => "truncf128",
36160 .down => "floorq",36160 .down => "floorf128",
36161 } } },36161 } } },
36162 .unused,36162 .unused,
36163 .unused,36163 .unused,
...@@ -36197,8 +36197,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -36197,8 +36197,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
36197 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },36197 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
36198 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {36198 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
36199 else => unreachable,36199 else => unreachable,
36200 .zero => "truncq",36200 .zero => "truncf128",
36201 .down => "floorq",36201 .down => "floorf128",
36202 } } },36202 } } },
36203 .unused,36203 .unused,
36204 .unused,36204 .unused,
...@@ -36240,8 +36240,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -36240,8 +36240,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
36240 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },36240 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
36241 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {36241 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
36242 else => unreachable,36242 else => unreachable,
36243 .zero => "truncq",36243 .zero => "truncf128",
36244 .down => "floorq",36244 .down => "floorf128",
36245 } } },36245 } } },
36246 .unused,36246 .unused,
36247 .unused,36247 .unused,
...@@ -36283,8 +36283,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -36283,8 +36283,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
36283 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },36283 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
36284 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {36284 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
36285 else => unreachable,36285 else => unreachable,
36286 .zero => "truncq",36286 .zero => "truncf128",
36287 .down => "floorq",36287 .down => "floorf128",
36288 } } },36288 } } },
36289 .unused,36289 .unused,
36290 .unused,36290 .unused,
...@@ -36326,8 +36326,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -36326,8 +36326,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
36326 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },36326 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
36327 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {36327 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
36328 else => unreachable,36328 else => unreachable,
36329 .zero => "truncq",36329 .zero => "truncf128",
36330 .down => "floorq",36330 .down => "floorf128",
36331 } } },36331 } } },
36332 .unused,36332 .unused,
36333 .unused,36333 .unused,
...@@ -37691,7 +37691,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -37691,7 +37691,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
37691 .call_frame = .{ .alignment = .@"16" },37691 .call_frame = .{ .alignment = .@"16" },
37692 .extra_temps = .{37692 .extra_temps = .{
37693 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },37693 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
37694 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },37694 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
37695 .unused,37695 .unused,
37696 .unused,37696 .unused,
37697 .unused,37697 .unused,
...@@ -37725,7 +37725,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -37725,7 +37725,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
37725 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },37725 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
37726 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },37726 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
37727 .{ .type = .f128, .kind = .mem },37727 .{ .type = .f128, .kind = .mem },
37728 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },37728 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
37729 .unused,37729 .unused,
37730 .unused,37730 .unused,
37731 .unused,37731 .unused,
...@@ -37760,7 +37760,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -37760,7 +37760,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
37760 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },37760 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
37761 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },37761 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
37762 .{ .type = .f128, .kind = .mem },37762 .{ .type = .f128, .kind = .mem },
37763 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },37763 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
37764 .unused,37764 .unused,
37765 .unused,37765 .unused,
37766 .unused,37766 .unused,
...@@ -37795,7 +37795,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -37795,7 +37795,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
37795 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },37795 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
37796 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },37796 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
37797 .{ .type = .f128, .kind = .mem },37797 .{ .type = .f128, .kind = .mem },
37798 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },37798 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
37799 .unused,37799 .unused,
37800 .unused,37800 .unused,
37801 .unused,37801 .unused,
...@@ -37830,7 +37830,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -37830,7 +37830,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
37830 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },37830 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
37831 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },37831 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
37832 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },37832 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
37833 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },37833 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
37834 .unused,37834 .unused,
37835 .unused,37835 .unused,
37836 .unused,37836 .unused,
...@@ -37867,7 +37867,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -37867,7 +37867,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
37867 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },37867 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
37868 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },37868 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
37869 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },37869 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
37870 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },37870 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
37871 .unused,37871 .unused,
37872 .unused,37872 .unused,
37873 .unused,37873 .unused,
...@@ -37904,7 +37904,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -37904,7 +37904,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
37904 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },37904 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
37905 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },37905 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
37906 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },37906 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
37907 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },37907 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
37908 .unused,37908 .unused,
37909 .unused,37909 .unused,
37910 .unused,37910 .unused,
...@@ -37943,7 +37943,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -37943,7 +37943,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
37943 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },37943 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
37944 .{ .type = .f128, .kind = .mem },37944 .{ .type = .f128, .kind = .mem },
37945 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },37945 .{ .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" } },
37947 .unused,37947 .unused,
37948 .unused,37948 .unused,
37949 .unused,37949 .unused,
...@@ -37982,7 +37982,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -37982,7 +37982,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
37982 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },37982 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
37983 .{ .type = .f128, .kind = .mem },37983 .{ .type = .f128, .kind = .mem },
37984 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },37984 .{ .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" } },
37986 .unused,37986 .unused,
37987 .unused,37987 .unused,
37988 .unused,37988 .unused,
...@@ -38021,7 +38021,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -38021,7 +38021,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
38021 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },38021 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
38022 .{ .type = .f128, .kind = .mem },38022 .{ .type = .f128, .kind = .mem },
38023 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },38023 .{ .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" } },
38025 .unused,38025 .unused,
38026 .unused,38026 .unused,
38027 .unused,38027 .unused,
...@@ -39558,7 +39558,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -39558,7 +39558,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
39558 },39558 },
39559 .call_frame = .{ .alignment = .@"16" },39559 .call_frame = .{ .alignment = .@"16" },
39560 .extra_temps = .{39560 .extra_temps = .{
39561 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },39561 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
39562 .unused,39562 .unused,
39563 .unused,39563 .unused,
39564 .unused,39564 .unused,
...@@ -39590,7 +39590,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -39590,7 +39590,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
39590 .extra_temps = .{39590 .extra_temps = .{
39591 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },39591 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
39592 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },39592 .{ .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" } },
39594 .unused,39594 .unused,
39595 .unused,39595 .unused,
39596 .unused,39596 .unused,
...@@ -39623,7 +39623,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -39623,7 +39623,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
39623 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },39623 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
39624 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },39624 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
39625 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },39625 .{ .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" } },
39627 .unused,39627 .unused,
39628 .unused,39628 .unused,
39629 .unused,39629 .unused,
...@@ -39659,7 +39659,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -39659,7 +39659,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
39659 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },39659 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
39660 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },39660 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
39661 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },39661 .{ .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" } },
39663 .unused,39663 .unused,
39664 .unused,39664 .unused,
39665 .unused,39665 .unused,
...@@ -39695,7 +39695,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -39695,7 +39695,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
39695 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },39695 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
39696 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },39696 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
39697 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },39697 .{ .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" } },
39699 .unused,39699 .unused,
39700 .unused,39700 .unused,
39701 .unused,39701 .unused,
...@@ -39731,7 +39731,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -39731,7 +39731,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
39731 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },39731 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
39732 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },39732 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
39733 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },39733 .{ .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" } },
39735 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },39735 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
39736 .unused,39736 .unused,
39737 .unused,39737 .unused,
...@@ -39767,7 +39767,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -39767,7 +39767,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
39767 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },39767 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
39768 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },39768 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
39769 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },39769 .{ .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" } },
39771 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },39771 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
39772 .unused,39772 .unused,
39773 .unused,39773 .unused,
...@@ -39803,7 +39803,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -39803,7 +39803,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
39803 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },39803 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
39804 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },39804 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
39805 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },39805 .{ .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" } },
39807 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },39807 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
39808 .unused,39808 .unused,
39809 .unused,39809 .unused,
...@@ -42803,7 +42803,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -42803,7 +42803,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
42803 .call_frame = .{ .alignment = .@"16" },42803 .call_frame = .{ .alignment = .@"16" },
42804 .extra_temps = .{42804 .extra_temps = .{
42805 .{ .type = .f128, .kind = .mem },42805 .{ .type = .f128, .kind = .mem },
42806 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },42806 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
42807 .{ .type = .u64, .kind = .{ .reg = .rcx } },42807 .{ .type = .u64, .kind = .{ .reg = .rcx } },
42808 .{ .type = .u64, .kind = .{ .reg = .rdx } },42808 .{ .type = .u64, .kind = .{ .reg = .rdx } },
42809 .{ .type = .u64, .kind = .{ .reg = .rax } },42809 .{ .type = .u64, .kind = .{ .reg = .rax } },
...@@ -42849,7 +42849,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -42849,7 +42849,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
42849 .call_frame = .{ .alignment = .@"16" },42849 .call_frame = .{ .alignment = .@"16" },
42850 .extra_temps = .{42850 .extra_temps = .{
42851 .{ .type = .f128, .kind = .mem },42851 .{ .type = .f128, .kind = .mem },
42852 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },42852 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
42853 .{ .type = .u64, .kind = .{ .reg = .rcx } },42853 .{ .type = .u64, .kind = .{ .reg = .rcx } },
42854 .{ .type = .u64, .kind = .{ .reg = .rdx } },42854 .{ .type = .u64, .kind = .{ .reg = .rdx } },
42855 .{ .type = .u64, .kind = .{ .reg = .rax } },42855 .{ .type = .u64, .kind = .{ .reg = .rax } },
...@@ -42895,7 +42895,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -42895,7 +42895,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
42895 .call_frame = .{ .alignment = .@"16" },42895 .call_frame = .{ .alignment = .@"16" },
42896 .extra_temps = .{42896 .extra_temps = .{
42897 .{ .type = .f128, .kind = .mem },42897 .{ .type = .f128, .kind = .mem },
42898 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },42898 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
42899 .{ .type = .u64, .kind = .{ .reg = .rcx } },42899 .{ .type = .u64, .kind = .{ .reg = .rcx } },
42900 .{ .type = .u64, .kind = .{ .reg = .rdx } },42900 .{ .type = .u64, .kind = .{ .reg = .rdx } },
42901 .{ .type = .u64, .kind = .{ .reg = .rax } },42901 .{ .type = .u64, .kind = .{ .reg = .rax } },
...@@ -42942,7 +42942,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -42942,7 +42942,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
42942 .call_frame = .{ .alignment = .@"16" },42942 .call_frame = .{ .alignment = .@"16" },
42943 .extra_temps = .{42943 .extra_temps = .{
42944 .{ .type = .f128, .kind = .mem },42944 .{ .type = .f128, .kind = .mem },
42945 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },42945 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
42946 .{ .type = .u64, .kind = .{ .reg = .rdx } },42946 .{ .type = .u64, .kind = .{ .reg = .rdx } },
42947 .{ .type = .f128, .kind = .mem },42947 .{ .type = .f128, .kind = .mem },
42948 .{ .type = .u64, .kind = .{ .reg = .rax } },42948 .{ .type = .u64, .kind = .{ .reg = .rax } },
...@@ -42984,7 +42984,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -42984,7 +42984,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
42984 .extra_temps = .{42984 .extra_temps = .{
42985 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },42985 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
42986 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },42986 .{ .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" } },
42988 .{ .type = .f128, .kind = .mem },42988 .{ .type = .f128, .kind = .mem },
42989 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },42989 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
42990 .{ .type = .u64, .kind = .{ .reg = .rax } },42990 .{ .type = .u64, .kind = .{ .reg = .rax } },
...@@ -43029,7 +43029,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -43029,7 +43029,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
43029 .extra_temps = .{43029 .extra_temps = .{
43030 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },43030 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
43031 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },43031 .{ .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" } },
43033 .{ .type = .f128, .kind = .mem },43033 .{ .type = .f128, .kind = .mem },
43034 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },43034 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
43035 .{ .type = .u64, .kind = .{ .reg = .rax } },43035 .{ .type = .u64, .kind = .{ .reg = .rax } },
...@@ -43074,7 +43074,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -43074,7 +43074,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
43074 .extra_temps = .{43074 .extra_temps = .{
43075 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },43075 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
43076 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },43076 .{ .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" } },
43078 .{ .type = .f128, .kind = .mem },43078 .{ .type = .f128, .kind = .mem },
43079 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },43079 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
43080 .{ .type = .u64, .kind = .{ .reg = .rax } },43080 .{ .type = .u64, .kind = .{ .reg = .rax } },
...@@ -43120,7 +43120,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -43120,7 +43120,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
43120 .extra_temps = .{43120 .extra_temps = .{
43121 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },43121 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
43122 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },43122 .{ .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" } },
43124 .{ .type = .f128, .kind = .mem },43124 .{ .type = .f128, .kind = .mem },
43125 .{ .type = .usize, .kind = .{ .reg = .rax } },43125 .{ .type = .usize, .kind = .{ .reg = .rax } },
43126 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },43126 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
...@@ -43164,7 +43164,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -43164,7 +43164,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
43164 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },43164 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
43165 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },43165 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
43166 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },43166 .{ .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" } },
43168 .{ .type = .f128, .kind = .{ .reg = .rcx } },43168 .{ .type = .f128, .kind = .{ .reg = .rcx } },
43169 .{ .type = .f128, .kind = .{ .reg = .rdx } },43169 .{ .type = .f128, .kind = .{ .reg = .rdx } },
43170 .{ .type = .f128, .kind = .{ .reg = .rax } },43170 .{ .type = .f128, .kind = .{ .reg = .rax } },
...@@ -43211,7 +43211,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -43211,7 +43211,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
43211 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },43211 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
43212 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },43212 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
43213 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },43213 .{ .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" } },
43215 .{ .type = .f128, .kind = .{ .reg = .rcx } },43215 .{ .type = .f128, .kind = .{ .reg = .rcx } },
43216 .{ .type = .f128, .kind = .{ .reg = .rdx } },43216 .{ .type = .f128, .kind = .{ .reg = .rdx } },
43217 .{ .type = .f128, .kind = .{ .reg = .rax } },43217 .{ .type = .f128, .kind = .{ .reg = .rax } },
...@@ -43258,7 +43258,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -43258,7 +43258,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
43258 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },43258 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
43259 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },43259 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
43260 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },43260 .{ .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" } },
43262 .{ .type = .f128, .kind = .{ .reg = .rcx } },43262 .{ .type = .f128, .kind = .{ .reg = .rcx } },
43263 .{ .type = .f128, .kind = .{ .reg = .rdx } },43263 .{ .type = .f128, .kind = .{ .reg = .rdx } },
43264 .{ .type = .f128, .kind = .{ .reg = .rax } },43264 .{ .type = .f128, .kind = .{ .reg = .rax } },
...@@ -43306,7 +43306,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -43306,7 +43306,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
43306 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },43306 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
43307 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },43307 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
43308 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },43308 .{ .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" } },
43310 .{ .type = .f128, .kind = .{ .reg = .rdx } },43310 .{ .type = .f128, .kind = .{ .reg = .rdx } },
43311 .{ .type = .f128, .kind = .mem },43311 .{ .type = .f128, .kind = .mem },
43312 .{ .type = .f128, .kind = .{ .reg = .rax } },43312 .{ .type = .f128, .kind = .{ .reg = .rax } },
...@@ -47623,7 +47623,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -47623,7 +47623,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
47623 },47623 },
47624 .call_frame = .{ .alignment = .@"16" },47624 .call_frame = .{ .alignment = .@"16" },
47625 .extra_temps = .{47625 .extra_temps = .{
47626 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },47626 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
47627 .unused,47627 .unused,
47628 .unused,47628 .unused,
47629 .unused,47629 .unused,
...@@ -47655,7 +47655,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -47655,7 +47655,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
47655 .extra_temps = .{47655 .extra_temps = .{
47656 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },47656 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
47657 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },47657 .{ .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" } },
47659 .unused,47659 .unused,
47660 .unused,47660 .unused,
47661 .unused,47661 .unused,
...@@ -47688,7 +47688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -47688,7 +47688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
47688 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },47688 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
47689 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },47689 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
47690 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },47690 .{ .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" } },
47692 .unused,47692 .unused,
47693 .unused,47693 .unused,
47694 .unused,47694 .unused,
...@@ -47724,7 +47724,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -47724,7 +47724,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
47724 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },47724 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
47725 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },47725 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
47726 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },47726 .{ .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" } },
47728 .unused,47728 .unused,
47729 .unused,47729 .unused,
47730 .unused,47730 .unused,
...@@ -47760,7 +47760,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -47760,7 +47760,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
47760 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },47760 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
47761 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },47761 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
47762 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },47762 .{ .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" } },
47764 .unused,47764 .unused,
47765 .unused,47765 .unused,
47766 .unused,47766 .unused,
...@@ -47796,7 +47796,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -47796,7 +47796,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
47796 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },47796 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
47797 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },47797 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
47798 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },47798 .{ .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" } },
47800 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },47800 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
47801 .unused,47801 .unused,
47802 .unused,47802 .unused,
...@@ -47832,7 +47832,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -47832,7 +47832,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
47832 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },47832 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
47833 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },47833 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
47834 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },47834 .{ .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" } },
47836 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },47836 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
47837 .unused,47837 .unused,
47838 .unused,47838 .unused,
...@@ -47868,7 +47868,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -47868,7 +47868,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
47868 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },47868 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
47869 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },47869 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
47870 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },47870 .{ .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" } },
47872 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },47872 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
47873 .unused,47873 .unused,
47874 .unused,47874 .unused,
...@@ -51926,7 +51926,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -51926,7 +51926,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
51926 },51926 },
51927 .call_frame = .{ .alignment = .@"16" },51927 .call_frame = .{ .alignment = .@"16" },
51928 .extra_temps = .{51928 .extra_temps = .{
51929 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },51929 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
51930 .unused,51930 .unused,
51931 .unused,51931 .unused,
51932 .unused,51932 .unused,
...@@ -51958,7 +51958,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -51958,7 +51958,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
51958 .extra_temps = .{51958 .extra_temps = .{
51959 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },51959 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
51960 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },51960 .{ .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" } },
51962 .unused,51962 .unused,
51963 .unused,51963 .unused,
51964 .unused,51964 .unused,
...@@ -51991,7 +51991,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -51991,7 +51991,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
51991 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },51991 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
51992 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },51992 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
51993 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },51993 .{ .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" } },
51995 .unused,51995 .unused,
51996 .unused,51996 .unused,
51997 .unused,51997 .unused,
...@@ -52027,7 +52027,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -52027,7 +52027,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
52027 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },52027 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
52028 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },52028 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
52029 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },52029 .{ .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" } },
52031 .unused,52031 .unused,
52032 .unused,52032 .unused,
52033 .unused,52033 .unused,
...@@ -52063,7 +52063,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -52063,7 +52063,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
52063 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },52063 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
52064 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },52064 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
52065 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },52065 .{ .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" } },
52067 .unused,52067 .unused,
52068 .unused,52068 .unused,
52069 .unused,52069 .unused,
...@@ -52099,7 +52099,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -52099,7 +52099,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
52099 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },52099 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
52100 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },52100 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
52101 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },52101 .{ .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" } },
52103 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },52103 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
52104 .unused,52104 .unused,
52105 .unused,52105 .unused,
...@@ -52135,7 +52135,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -52135,7 +52135,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
52135 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },52135 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
52136 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },52136 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
52137 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },52137 .{ .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" } },
52139 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },52139 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
52140 .unused,52140 .unused,
52141 .unused,52141 .unused,
...@@ -52171,7 +52171,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -52171,7 +52171,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
52171 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },52171 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
52172 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },52172 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
52173 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },52173 .{ .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" } },
52175 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },52175 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
52176 .unused,52176 .unused,
52177 .unused,52177 .unused,
...@@ -76457,7 +76457,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -76457,7 +76457,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
76457 },76457 },
76458 .call_frame = .{ .alignment = .@"16" },76458 .call_frame = .{ .alignment = .@"16" },
76459 .extra_temps = .{76459 .extra_temps = .{
76460 .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },76460 .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } },
76461 .unused,76461 .unused,
76462 .unused,76462 .unused,
76463 .unused,76463 .unused,
...@@ -76484,7 +76484,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -76484,7 +76484,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
76484 .call_frame = .{ .alignment = .@"16" },76484 .call_frame = .{ .alignment = .@"16" },
76485 .extra_temps = .{76485 .extra_temps = .{
76486 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },76486 .{ .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" } },
76488 .unused,76488 .unused,
76489 .unused,76489 .unused,
76490 .unused,76490 .unused,
...@@ -76512,7 +76512,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -76512,7 +76512,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
76512 .extra_temps = .{76512 .extra_temps = .{
76513 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },76513 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
76514 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },76514 .{ .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" } },
76516 .unused,76516 .unused,
76517 .unused,76517 .unused,
76518 .unused,76518 .unused,
...@@ -76543,7 +76543,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -76543,7 +76543,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
76543 .extra_temps = .{76543 .extra_temps = .{
76544 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },76544 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
76545 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },76545 .{ .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" } },
76547 .unused,76547 .unused,
76548 .unused,76548 .unused,
76549 .unused,76549 .unused,
...@@ -76574,7 +76574,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -76574,7 +76574,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
76574 .extra_temps = .{76574 .extra_temps = .{
76575 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },76575 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
76576 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },76576 .{ .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" } },
76578 .unused,76578 .unused,
76579 .unused,76579 .unused,
76580 .unused,76580 .unused,
...@@ -76605,7 +76605,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -76605,7 +76605,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
76605 .extra_temps = .{76605 .extra_temps = .{
76606 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },76606 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
76607 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },76607 .{ .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" } },
76609 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },76609 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
76610 .unused,76610 .unused,
76611 .unused,76611 .unused,
...@@ -76636,7 +76636,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -76636,7 +76636,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
76636 .extra_temps = .{76636 .extra_temps = .{
76637 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },76637 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
76638 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },76638 .{ .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" } },
76640 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },76640 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
76641 .unused,76641 .unused,
76642 .unused,76642 .unused,
...@@ -76667,7 +76667,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -76667,7 +76667,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
76667 .extra_temps = .{76667 .extra_temps = .{
76668 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },76668 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
76669 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },76669 .{ .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" } },
76671 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },76671 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
76672 .unused,76672 .unused,
76673 .unused,76673 .unused,
...@@ -77306,7 +77306,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -77306,7 +77306,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
77306 },77306 },
77307 .call_frame = .{ .alignment = .@"16" },77307 .call_frame = .{ .alignment = .@"16" },
77308 .extra_temps = .{77308 .extra_temps = .{
77309 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },77309 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } },
77310 .unused,77310 .unused,
77311 .unused,77311 .unused,
77312 .unused,77312 .unused,
...@@ -77333,7 +77333,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -77333,7 +77333,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
77333 .call_frame = .{ .alignment = .@"16" },77333 .call_frame = .{ .alignment = .@"16" },
77334 .extra_temps = .{77334 .extra_temps = .{
77335 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },77335 .{ .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" } },
77337 .unused,77337 .unused,
77338 .unused,77338 .unused,
77339 .unused,77339 .unused,
...@@ -77361,7 +77361,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -77361,7 +77361,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
77361 .extra_temps = .{77361 .extra_temps = .{
77362 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },77362 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
77363 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },77363 .{ .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" } },
77365 .unused,77365 .unused,
77366 .unused,77366 .unused,
77367 .unused,77367 .unused,
...@@ -77392,7 +77392,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -77392,7 +77392,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
77392 .extra_temps = .{77392 .extra_temps = .{
77393 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },77393 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
77394 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },77394 .{ .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" } },
77396 .unused,77396 .unused,
77397 .unused,77397 .unused,
77398 .unused,77398 .unused,
...@@ -77423,7 +77423,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -77423,7 +77423,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
77423 .extra_temps = .{77423 .extra_temps = .{
77424 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },77424 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
77425 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },77425 .{ .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" } },
77427 .unused,77427 .unused,
77428 .unused,77428 .unused,
77429 .unused,77429 .unused,
...@@ -77454,7 +77454,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -77454,7 +77454,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
77454 .extra_temps = .{77454 .extra_temps = .{
77455 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },77455 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
77456 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },77456 .{ .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" } },
77458 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },77458 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
77459 .unused,77459 .unused,
77460 .unused,77460 .unused,
...@@ -77485,7 +77485,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -77485,7 +77485,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
77485 .extra_temps = .{77485 .extra_temps = .{
77486 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },77486 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
77487 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },77487 .{ .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" } },
77489 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },77489 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
77490 .unused,77490 .unused,
77491 .unused,77491 .unused,
...@@ -77516,7 +77516,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -77516,7 +77516,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
77516 .extra_temps = .{77516 .extra_temps = .{
77517 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },77517 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
77518 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },77518 .{ .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" } },
77520 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },77520 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
77521 .unused,77521 .unused,
77522 .unused,77522 .unused,
...@@ -80155,9 +80155,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -80155,9 +80155,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
80155 .extra_temps = .{80155 .extra_temps = .{
80156 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {80156 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
80157 else => unreachable,80157 else => unreachable,
80158 .down => "floorq",80158 .down => "floorf128",
80159 .up => "ceilq",80159 .up => "ceilf128",
80160 .zero => "truncq",80160 .zero => "truncf128",
80161 } } },80161 } } },
80162 .unused,80162 .unused,
80163 .unused,80163 .unused,
...@@ -80187,9 +80187,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -80187,9 +80187,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
80187 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },80187 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
80188 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {80188 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
80189 else => unreachable,80189 else => unreachable,
80190 .down => "floorq",80190 .down => "floorf128",
80191 .up => "ceilq",80191 .up => "ceilf128",
80192 .zero => "truncq",80192 .zero => "truncf128",
80193 } } },80193 } } },
80194 .unused,80194 .unused,
80195 .unused,80195 .unused,
...@@ -80220,9 +80220,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -80220,9 +80220,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
80220 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },80220 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
80221 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {80221 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
80222 else => unreachable,80222 else => unreachable,
80223 .down => "floorq",80223 .down => "floorf128",
80224 .up => "ceilq",80224 .up => "ceilf128",
80225 .zero => "truncq",80225 .zero => "truncf128",
80226 } } },80226 } } },
80227 .unused,80227 .unused,
80228 .unused,80228 .unused,
...@@ -80256,9 +80256,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -80256,9 +80256,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
80256 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },80256 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
80257 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {80257 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
80258 else => unreachable,80258 else => unreachable,
80259 .down => "floorq",80259 .down => "floorf128",
80260 .up => "ceilq",80260 .up => "ceilf128",
80261 .zero => "truncq",80261 .zero => "truncf128",
80262 } } },80262 } } },
80263 .unused,80263 .unused,
80264 .unused,80264 .unused,
...@@ -80292,9 +80292,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -80292,9 +80292,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
80292 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },80292 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
80293 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {80293 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
80294 else => unreachable,80294 else => unreachable,
80295 .down => "floorq",80295 .down => "floorf128",
80296 .up => "ceilq",80296 .up => "ceilf128",
80297 .zero => "truncq",80297 .zero => "truncf128",
80298 } } },80298 } } },
80299 .unused,80299 .unused,
80300 .unused,80300 .unused,
...@@ -80328,9 +80328,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -80328,9 +80328,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
80328 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },80328 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
80329 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {80329 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
80330 else => unreachable,80330 else => unreachable,
80331 .down => "floorq",80331 .down => "floorf128",
80332 .up => "ceilq",80332 .up => "ceilf128",
80333 .zero => "truncq",80333 .zero => "truncf128",
80334 } } },80334 } } },
80335 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },80335 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
80336 .unused,80336 .unused,
...@@ -80364,9 +80364,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -80364,9 +80364,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
80364 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },80364 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
80365 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {80365 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
80366 else => unreachable,80366 else => unreachable,
80367 .down => "floorq",80367 .down => "floorf128",
80368 .up => "ceilq",80368 .up => "ceilf128",
80369 .zero => "truncq",80369 .zero => "truncf128",
80370 } } },80370 } } },
80371 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },80371 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
80372 .unused,80372 .unused,
...@@ -80400,9 +80400,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -80400,9 +80400,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
80400 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },80400 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
80401 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {80401 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
80402 else => unreachable,80402 else => unreachable,
80403 .down => "floorq",80403 .down => "floorf128",
80404 .up => "ceilq",80404 .up => "ceilf128",
80405 .zero => "truncq",80405 .zero => "truncf128",
80406 } } },80406 } } },
80407 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },80407 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
80408 .unused,80408 .unused,
...@@ -125531,7 +125531,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -125531,7 +125531,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
125531 .{ ._, ._, .call, .tmp1d, ._, ._, ._ },125531 .{ ._, ._, .call, .tmp1d, ._, ._, ._ },
125532 } },125532 } },
125533 }, .{125533 }, .{
125534 .required_cc_abi = .sysv64,
125535 .required_features = .{ .sse, null, null, null },125534 .required_features = .{ .sse, null, null, null },
125536 .src_constraints = .{ .{ .unsigned_int = .xword }, .any, .any },125535 .src_constraints = .{ .{ .unsigned_int = .xword }, .any, .any },
125537 .dst_constraints = .{ .{ .float = .xword }, .any },125536 .dst_constraints = .{ .{ .float = .xword }, .any },
...@@ -125557,34 +125556,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -125557,34 +125556,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
125557 .each = .{ .once = &.{125556 .each = .{ .once = &.{
125558 .{ ._, ._, .call, .tmp0d, ._, ._, ._ },125557 .{ ._, ._, .call, .tmp0d, ._, ._, ._ },
125559 } },125558 } },
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 } },
125588 }, .{125559 }, .{
125589 .required_features = .{ .@"64bit", .sse, null, null },125560 .required_features = .{ .@"64bit", .sse, null, null },
125590 .src_constraints = .{ .{ .remainder_signed_int = .{ .of = .dword, .is = .dword } }, .any, .any },125561 .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 {...@@ -126791,7 +126762,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
126791 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },126762 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
126792 } },126763 } },
126793 }, .{126764 }, .{
126794 .required_cc_abi = .sysv64,
126795 .required_features = .{ .avx, null, null, null },126765 .required_features = .{ .avx, null, null, null },
126796 .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any },126766 .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any },
126797 .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any },126767 .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 {...@@ -126824,39 +126794,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
126824 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },126794 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
126825 } },126795 } },
126826 }, .{126796 }, .{
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,
126860 .required_features = .{ .sse2, null, null, null },126797 .required_features = .{ .sse2, null, null, null },
126861 .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any },126798 .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any },
126862 .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any },126799 .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 {...@@ -126889,39 +126826,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
126889 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },126826 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
126890 } },126827 } },
126891 }, .{126828 }, .{
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,
126925 .required_features = .{ .sse, null, null, null },126829 .required_features = .{ .sse, null, null, null },
126926 .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any },126830 .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any },
126927 .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any },126831 .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 {...@@ -126953,38 +126857,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
126953 .{ ._, ._, .sub, .tmp0d, .si(16), ._, ._ },126857 .{ ._, ._, .sub, .tmp0d, .si(16), ._, ._ },
126954 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },126858 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
126955 } },126859 } },
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 } },
126988 }, .{126860 }, .{
126989 .required_features = .{ .@"64bit", .avx, null, null },126861 .required_features = .{ .@"64bit", .avx, null, null },
126990 .src_constraints = .{ .{ .scalar_remainder_signed_int = .{ .of = .dword, .is = .dword } }, .any, .any },126862 .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 {...@@ -142552,7 +142424,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
142552 .extra_temps = .{142424 .extra_temps = .{
142553 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },142425 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
142554 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },142426 .{ .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" } },
142556 .unused,142428 .unused,
142557 .unused,142429 .unused,
142558 .unused,142430 .unused,
...@@ -142584,7 +142456,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -142584,7 +142456,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
142584 .extra_temps = .{142456 .extra_temps = .{
142585 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },142457 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
142586 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },142458 .{ .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" } },
142588 .unused,142460 .unused,
142589 .unused,142461 .unused,
142590 .unused,142462 .unused,
...@@ -142616,7 +142488,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -142616,7 +142488,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
142616 .extra_temps = .{142488 .extra_temps = .{
142617 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },142489 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
142618 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },142490 .{ .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" } },
142620 .unused,142492 .unused,
142621 .unused,142493 .unused,
142622 .unused,142494 .unused,
...@@ -142649,7 +142521,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -142649,7 +142521,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
142649 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },142521 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
142650 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },142522 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
142651 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },142523 .{ .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" } },
142653 .{ .type = .f128, .kind = .mem },142525 .{ .type = .f128, .kind = .mem },
142654 .unused,142526 .unused,
142655 .unused,142527 .unused,
...@@ -142683,7 +142555,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -142683,7 +142555,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
142683 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },142555 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
142684 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },142556 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
142685 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },142557 .{ .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" } },
142687 .{ .type = .f128, .kind = .mem },142559 .{ .type = .f128, .kind = .mem },
142688 .unused,142560 .unused,
142689 .unused,142561 .unused,
...@@ -142717,7 +142589,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -142717,7 +142589,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
142717 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },142589 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
142718 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },142590 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
142719 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },142591 .{ .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" } },
142721 .{ .type = .f128, .kind = .mem },142593 .{ .type = .f128, .kind = .mem },
142722 .unused,142594 .unused,
142723 .unused,142595 .unused,
...@@ -152785,7 +152657,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -152785,7 +152657,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
152785 .extra_temps = .{152657 .extra_temps = .{
152786 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },152658 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
152787 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },152659 .{ .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" } },
152789 .unused,152661 .unused,
152790 .unused,152662 .unused,
152791 .unused,152663 .unused,
...@@ -152817,7 +152689,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -152817,7 +152689,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
152817 .extra_temps = .{152689 .extra_temps = .{
152818 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },152690 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
152819 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },152691 .{ .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" } },
152821 .unused,152693 .unused,
152822 .unused,152694 .unused,
152823 .unused,152695 .unused,
...@@ -152849,7 +152721,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -152849,7 +152721,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
152849 .extra_temps = .{152721 .extra_temps = .{
152850 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },152722 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
152851 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },152723 .{ .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" } },
152853 .unused,152725 .unused,
152854 .unused,152726 .unused,
152855 .unused,152727 .unused,
...@@ -152882,7 +152754,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -152882,7 +152754,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
152882 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },152754 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
152883 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },152755 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
152884 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },152756 .{ .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" } },
152886 .{ .type = .f128, .kind = .mem },152758 .{ .type = .f128, .kind = .mem },
152887 .unused,152759 .unused,
152888 .unused,152760 .unused,
...@@ -152916,7 +152788,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -152916,7 +152788,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
152916 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },152788 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
152917 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },152789 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
152918 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },152790 .{ .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" } },
152920 .{ .type = .f128, .kind = .mem },152792 .{ .type = .f128, .kind = .mem },
152921 .unused,152793 .unused,
152922 .unused,152794 .unused,
...@@ -152950,7 +152822,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -152950,7 +152822,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
152950 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },152822 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
152951 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },152823 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
152952 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },152824 .{ .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" } },
152954 .{ .type = .f128, .kind = .mem },152826 .{ .type = .f128, .kind = .mem },
152955 .unused,152827 .unused,
152956 .unused,152828 .unused,
...@@ -163019,7 +162891,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -163019,7 +162891,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
163019 .extra_temps = .{162891 .extra_temps = .{
163020 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },162892 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
163021 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },162893 .{ .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" } },
163023 .unused,162895 .unused,
163024 .unused,162896 .unused,
163025 .unused,162897 .unused,
...@@ -163051,7 +162923,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -163051,7 +162923,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
163051 .extra_temps = .{162923 .extra_temps = .{
163052 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },162924 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
163053 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },162925 .{ .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" } },
163055 .unused,162927 .unused,
163056 .unused,162928 .unused,
163057 .unused,162929 .unused,
...@@ -163083,7 +162955,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -163083,7 +162955,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
163083 .extra_temps = .{162955 .extra_temps = .{
163084 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },162956 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
163085 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },162957 .{ .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" } },
163087 .unused,162959 .unused,
163088 .unused,162960 .unused,
163089 .unused,162961 .unused,
...@@ -163116,7 +162988,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -163116,7 +162988,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
163116 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },162988 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
163117 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },162989 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
163118 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },162990 .{ .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" } },
163120 .{ .type = .f128, .kind = .mem },162992 .{ .type = .f128, .kind = .mem },
163121 .unused,162993 .unused,
163122 .unused,162994 .unused,
...@@ -163150,7 +163022,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -163150,7 +163022,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
163150 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },163022 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
163151 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },163023 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
163152 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },163024 .{ .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" } },
163154 .{ .type = .f128, .kind = .mem },163026 .{ .type = .f128, .kind = .mem },
163155 .unused,163027 .unused,
163156 .unused,163028 .unused,
...@@ -163184,7 +163056,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -163184,7 +163056,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
163184 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },163056 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
163185 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },163057 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
163186 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },163058 .{ .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" } },
163188 .{ .type = .f128, .kind = .mem },163060 .{ .type = .f128, .kind = .mem },
163189 .unused,163061 .unused,
163190 .unused,163062 .unused,
...@@ -164816,7 +164688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -164816,7 +164688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
164816 .extra_temps = .{164688 .extra_temps = .{
164817 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },164689 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
164818 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },164690 .{ .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" } },
164820 .unused,164692 .unused,
164821 .unused,164693 .unused,
164822 .unused,164694 .unused,
...@@ -164848,7 +164720,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -164848,7 +164720,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
164848 .extra_temps = .{164720 .extra_temps = .{
164849 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },164721 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
164850 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },164722 .{ .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" } },
164852 .unused,164724 .unused,
164853 .unused,164725 .unused,
164854 .unused,164726 .unused,
...@@ -164880,7 +164752,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -164880,7 +164752,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
164880 .extra_temps = .{164752 .extra_temps = .{
164881 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },164753 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
164882 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },164754 .{ .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" } },
164884 .unused,164756 .unused,
164885 .unused,164757 .unused,
164886 .unused,164758 .unused,
...@@ -164913,7 +164785,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -164913,7 +164785,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
164913 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },164785 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
164914 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },164786 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
164915 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },164787 .{ .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" } },
164917 .{ .type = .f128, .kind = .mem },164789 .{ .type = .f128, .kind = .mem },
164918 .unused,164790 .unused,
164919 .unused,164791 .unused,
...@@ -164947,7 +164819,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -164947,7 +164819,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
164947 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },164819 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
164948 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },164820 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
164949 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },164821 .{ .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" } },
164951 .{ .type = .f128, .kind = .mem },164823 .{ .type = .f128, .kind = .mem },
164952 .unused,164824 .unused,
164953 .unused,164825 .unused,
...@@ -164981,7 +164853,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -164981,7 +164853,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
164981 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },164853 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
164982 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },164854 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
164983 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },164855 .{ .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" } },
164985 .{ .type = .f128, .kind = .mem },164857 .{ .type = .f128, .kind = .mem },
164986 .unused,164858 .unused,
164987 .unused,164859 .unused,
...@@ -172785,7 +172657,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -172785,7 +172657,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
172785 },172657 },
172786 .call_frame = .{ .alignment = .@"16" },172658 .call_frame = .{ .alignment = .@"16" },
172787 .extra_temps = .{172659 .extra_temps = .{
172788 .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },172660 .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } },
172789 .unused,172661 .unused,
172790 .unused,172662 .unused,
172791 .unused,172663 .unused,
...@@ -172818,7 +172690,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -172818,7 +172690,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
172818 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },172690 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
172819 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },172691 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
172820 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 2, .at = 2 } } },172692 .{ .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" } },
172822 .unused,172694 .unused,
172823 .unused,172695 .unused,
172824 .unused,172696 .unused,
...@@ -172852,7 +172724,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -172852,7 +172724,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
172852 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },172724 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
172853 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },172725 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
172854 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 2, .at = 2 } } },172726 .{ .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" } },
172856 .unused,172728 .unused,
172857 .unused,172729 .unused,
172858 .unused,172730 .unused,
...@@ -172889,7 +172761,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -172889,7 +172761,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
172889 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },172761 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
172890 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },172762 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
172891 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 2, .at = 2 } } },172763 .{ .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" } },
172893 .unused,172765 .unused,
172894 .unused,172766 .unused,
172895 .unused,172767 .unused,
...@@ -172926,7 +172798,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -172926,7 +172798,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
172926 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },172798 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
172927 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },172799 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
172928 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 2, .at = 2 } } },172800 .{ .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" } },
172930 .unused,172802 .unused,
172931 .unused,172803 .unused,
172932 .unused,172804 .unused,
...@@ -172963,7 +172835,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -172963,7 +172835,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
172963 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },172835 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
172964 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },172836 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
172965 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 2, .at = 2 } } },172837 .{ .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" } },
172967 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },172839 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
172968 .unused,172840 .unused,
172969 .unused,172841 .unused,
...@@ -173000,7 +172872,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -173000,7 +172872,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
173000 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },172872 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
173001 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },172873 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
173002 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 2, .at = 2 } } },172874 .{ .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" } },
173004 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },172876 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
173005 .unused,172877 .unused,
173006 .unused,172878 .unused,
...@@ -173037,7 +172909,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -173037,7 +172909,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
173037 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },172909 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
173038 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },172910 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
173039 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 2, .at = 2 } } },172911 .{ .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" } },
173041 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },172913 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
173042 .unused,172914 .unused,
173043 .unused,172915 .unused,
...@@ -176621,10 +176493,20 @@ fn genCall(cg: *CodeGen, info: union(enum) {...@@ -176621,10 +176493,20 @@ fn genCall(cg: *CodeGen, info: union(enum) {
176621176493
176622 for (call_info.args, arg_types, args, frame_indices) |dst_arg, arg_ty, src_arg, frame_index| switch (dst_arg) {176494 for (call_info.args, arg_types, args, frame_indices) |dst_arg, arg_ty, src_arg, frame_index| switch (dst_arg) {
176623 .none, .load_frame, .indirect_load_frame => {},176495 .none, .load_frame, .indirect_load_frame => {},
176624 .register => |dst_reg| try cg.genSetReg(registerAlias(176496 .register => |dst_reg| switch (fn_info.cc) {
176625 dst_reg,176497 else => try cg.genSetReg(registerAlias(
176626 @intCast(cg.unalignedSize(arg_ty)),176498 dst_reg,
176627 ), arg_ty, src_arg, opts),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 },
176628 .register_pair,176510 .register_pair,
176629 .register_triple,176511 .register_triple,
176630 .register_quadruple,176512 .register_quadruple,
...@@ -177096,7 +176978,7 @@ fn lowerBlock(self: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index...@@ -177096,7 +176978,7 @@ fn lowerBlock(self: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index
177096 defer block_data.value.deinit(self.gpa);176978 defer block_data.value.deinit(self.gpa);
177097 if (block_data.value.relocs.items.len > 0) {176979 if (block_data.value.relocs.items.len > 0) {
177098 var last_inst: Mir.Inst.Index = @intCast(self.mir_instructions.len - 1);176980 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) {
177100 block_data.value.relocs.items.len -= 1;176982 block_data.value.relocs.items.len -= 1;
177101 self.mir_instructions.set(last_inst, .{176983 self.mir_instructions.set(last_inst, .{
177102 .tag = .pseudo,176984 .tag = .pseudo,
...@@ -178017,7 +177899,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -178017,7 +177899,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
178017 else if (std.mem.endsWith(u8, mnem_str, "l"))177899 else if (std.mem.endsWith(u8, mnem_str, "l"))
178018 .dword177900 .dword
178019 else if (std.mem.endsWith(u8, mnem_str, "q") and177901 else if (std.mem.endsWith(u8, mnem_str, "q") and
178020 (std.mem.indexOfScalar(u8, "vp", mnem_str[0]) == null or177902 (std.mem.findScalar(u8, "vp", mnem_str[0]) == null or
178021 !std.mem.endsWith(u8, mnem_str, "dq")))177903 !std.mem.endsWith(u8, mnem_str, "dq")))
178022 .qword177904 .qword
178023 else if (std.mem.endsWith(u8, mnem_str, "t"))177905 else if (std.mem.endsWith(u8, mnem_str, "t"))
...@@ -178084,8 +177966,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -178084,8 +177966,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
178084 }) + 1,177966 }) + 1,
178085 }177967 }
178086 };177968 };
178087 const untrimmed_op_str = if (std.mem.indexOfScalar(u8, full_op_str, '#') orelse177969 const untrimmed_op_str = if (std.mem.findScalar(u8, full_op_str, '#') orelse
178088 std.mem.indexOf(u8, full_op_str, "//")) |comment|177970 std.mem.find(u8, full_op_str, "//")) |comment|
178089 untrimmed_op_str: {177971 untrimmed_op_str: {
178090 ops_index = ops_str.len;177972 ops_index = ops_str.len;
178091 break :untrimmed_op_str full_op_str[0..comment];177973 break :untrimmed_op_str full_op_str[0..comment];
...@@ -178094,7 +177976,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -178094,7 +177976,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
178094 if (trimmed_op_str.len > 0) break trimmed_op_str;177976 if (trimmed_op_str.len > 0) break trimmed_op_str;
178095 };177977 };
178096 if (std.mem.startsWith(u8, op_str, "%%")) {177978 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, ':');
178098 const reg = parseRegName(op_str["%%".len .. colon orelse op_str.len]) orelse177980 const reg = parseRegName(op_str["%%".len .. colon orelse op_str.len]) orelse
178099 return self.fail("invalid register: '{s}'", .{op_str});177981 return self.fail("invalid register: '{s}'", .{op_str});
178100 if (colon) |colon_pos| {177982 if (colon) |colon_pos| {
...@@ -178115,7 +177997,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -178115,7 +177997,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
178115 op.* = .{ .reg = reg };177997 op.* = .{ .reg = reg };
178116 }177998 }
178117 } else if (std.mem.startsWith(u8, op_str, "%[") and std.mem.endsWith(u8, op_str, "]")) {177999 } 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, ':');
178119 const modifier = if (colon) |colon_pos|178001 const modifier = if (colon) |colon_pos|
178120 op_str[colon_pos + ":".len .. op_str.len - "]".len]178002 op_str[colon_pos + ":".len .. op_str.len - "]".len]
178121 else178003 else
...@@ -178198,7 +178080,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -178198,7 +178080,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
178198 else |_|178080 else |_|
178199 return self.fail("invalid immediate: '{s}'", .{op_str});178081 return self.fail("invalid immediate: '{s}'", .{op_str});
178200 } else if (std.mem.endsWith(u8, op_str, ")")) {178082 } else if (std.mem.endsWith(u8, op_str, ")")) {
178201 const open = std.mem.indexOfScalar(u8, op_str, '(') orelse178083 const open = std.mem.findScalar(u8, op_str, '(') orelse
178202 return self.fail("invalid operand: '{s}'", .{op_str});178084 return self.fail("invalid operand: '{s}'", .{op_str});
178203 var sib_it =178085 var sib_it =
178204 std.mem.splitScalar(u8, op_str[open + "(".len .. op_str.len - ")".len], ',');178086 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 {...@@ -178259,7 +178141,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
178259 .disp = if (std.mem.startsWith(u8, op_str[0..open], "%[") and178141 .disp = if (std.mem.startsWith(u8, op_str[0..open], "%[") and
178260 std.mem.endsWith(u8, op_str[0..open], "]"))178142 std.mem.endsWith(u8, op_str[0..open], "]"))
178261 disp: {178143 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, ':');
178263 const modifier = if (colon) |colon_pos|178145 const modifier = if (colon) |colon_pos|
178264 op_str[colon_pos + ":".len .. open - "]".len]178146 op_str[colon_pos + ":".len .. open - "]".len]
178265 else178147 else
...@@ -178328,14 +178210,14 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -178328,14 +178210,14 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
178328 .{ ._, .pseudo }178210 .{ ._, .pseudo }
178329 else for (std.enums.values(Mir.Inst.Fixes)) |fixes| {178211 else for (std.enums.values(Mir.Inst.Fixes)) |fixes| {
178330 const fixes_name = @tagName(fixes);178212 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, ' ');
178332 const fixes_prefix = if (space_index) |index|178214 const fixes_prefix = if (space_index) |index|
178333 std.meta.stringToEnum(encoder.Instruction.Prefix, fixes_name[0..index]).?178215 std.meta.stringToEnum(encoder.Instruction.Prefix, fixes_name[0..index]).?
178334 else178216 else
178335 .none;178217 .none;
178336 if (fixes_prefix != prefix) continue;178218 if (fixes_prefix != prefix) continue;
178337 const pattern = fixes_name[if (space_index) |index| index + " ".len else 0..];178219 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, '_').?;
178339 const mnem_prefix = pattern[0..wildcard_index];178221 const mnem_prefix = pattern[0..wildcard_index];
178340 const mnem_suffix = pattern[wildcard_index + "_".len ..];178222 const mnem_suffix = pattern[wildcard_index + "_".len ..];
178341 if (!std.mem.startsWith(u8, mnem_name, mnem_prefix)) continue;178223 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...@@ -178581,11 +178463,11 @@ fn moveStrategy(cg: *CodeGen, ty: Type, class: Register.Class, aligned: bool) !M
178581 .sse => switch (ty.zigTypeTag(zcu)) {178463 .sse => switch (ty.zigTypeTag(zcu)) {
178582 else => {178464 else => {
178583 const classes = std.mem.sliceTo(&abi.classifySystemV(ty, zcu, cg.target, .other), .none);178465 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, &.{
178585 .integer, .sse, .sseup, .memory, .float, .float_combine,178467 .integer, .sse, .sseup, .memory, .float, .float_combine,
178586 }) == null);178468 }) == null);
178587 const abi_size = ty.abiSize(zcu);178469 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) {
178589 1 => return if (cg.hasFeature(.avx)) .{ .vex_insert_extract = .{178471 1 => return if (cg.hasFeature(.avx)) .{ .vex_insert_extract = .{
178590 .insert = .{ .vp_b, .insr },178472 .insert = .{ .vp_b, .insr },
178591 .extract = .{ .vp_b, .extr },178473 .extract = .{ .vp_b, .extr },
...@@ -181994,7 +181876,7 @@ fn resolveCallingConventionValues(...@@ -181994,7 +181876,7 @@ fn resolveCallingConventionValues(
181994 }181876 }
181995181877
181996 const save_param_gpr_index = param_gpr_index;181878 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
181999 var arg_mcv: [4]MCValue = undefined;181881 var arg_mcv: [4]MCValue = undefined;
182000 var arg_mcv_len: u32 = 0;181882 var arg_mcv_len: u32 = 0;
...@@ -182502,8 +182384,8 @@ fn hasFeature(cg: *CodeGen, feature: std.Target.x86.Feature) bool {...@@ -182502,8 +182384,8 @@ fn hasFeature(cg: *CodeGen, feature: std.Target.x86.Feature) bool {
182502 .slow_unaligned_mem_16,182384 .slow_unaligned_mem_16,
182503 .slow_unaligned_mem_32,182385 .slow_unaligned_mem_32,
182504 => switch (cg.mod.optimize_mode) {182386 => switch (cg.mod.optimize_mode) {
182505 .Debug, .ReleaseSafe, .ReleaseFast => null,182387 .debug, .safe, .fast => null,
182506 .ReleaseSmall => false,182388 .small => false,
182507 },182389 },
182508 .fast_11bytenop,182390 .fast_11bytenop,
182509 .fast_15bytenop,182391 .fast_15bytenop,
...@@ -182523,8 +182405,8 @@ fn hasFeature(cg: *CodeGen, feature: std.Target.x86.Feature) bool {...@@ -182523,8 +182405,8 @@ fn hasFeature(cg: *CodeGen, feature: std.Target.x86.Feature) bool {
182523 .fast_vector_fsqrt,182405 .fast_vector_fsqrt,
182524 .fast_vector_shift_masks,182406 .fast_vector_shift_masks,
182525 => switch (cg.mod.optimize_mode) {182407 => switch (cg.mod.optimize_mode) {
182526 .Debug, .ReleaseSafe, .ReleaseFast => null,182408 .debug, .safe, .fast => null,
182527 .ReleaseSmall => true,182409 .small => true,
182528 },182410 },
182529 .mmx => false,182411 .mmx => false,
182530 .sahf => switch (cg.target.cpu.arch) {182412 .sahf => switch (cg.target.cpu.arch) {
...@@ -182626,15 +182508,15 @@ fn intInfo(cg: *CodeGen, ty: Type) ?std.lang.Type.Int {...@@ -182626,15 +182508,15 @@ fn intInfo(cg: *CodeGen, ty: Type) ?std.lang.Type.Int {
182626 .anyerror => .{ .signedness = .unsigned, .bits = zcu.errorSetBits() },182508 .anyerror => .{ .signedness = .unsigned, .bits = zcu.errorSetBits() },
182627 .isize => .{ .signedness = .signed, .bits = cg.target.ptrBitWidth() },182509 .isize => .{ .signedness = .signed, .bits = cg.target.ptrBitWidth() },
182628 .usize => .{ .signedness = .unsigned, .bits = cg.target.ptrBitWidth() },182510 .usize => .{ .signedness = .unsigned, .bits = cg.target.ptrBitWidth() },
182629 .c_char => .{ .signedness = cg.target.cCharSignedness(), .bits = cg.target.cTypeBitSize(.char) },182511 .c_char => .{ .signedness = cg.target.cCharSignedness().?, .bits = cg.target.cTypeBitSize(.char).? },
182630 .c_short => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.short) },182512 .c_short => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.short).? },
182631 .c_ushort => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.short) },182513 .c_ushort => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.short).? },
182632 .c_int => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.int) },182514 .c_int => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.int).? },
182633 .c_uint => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.int) },182515 .c_uint => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.int).? },
182634 .c_long => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.long) },182516 .c_long => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.long).? },
182635 .c_ulong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.long) },182517 .c_ulong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.long).? },
182636 .c_longlong => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.longlong) },182518 .c_longlong => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.longlong).? },
182637 .c_ulonglong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.longlong) },182519 .c_ulonglong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.longlong).? },
182638 .f16, .f32, .f64, .f80, .f128, .c_longdouble => null,182520 .f16, .f32, .f64, .f80, .f128, .c_longdouble => null,
182639 .anyopaque,182521 .anyopaque,
182640 .void,182522 .void,
...@@ -183696,8 +183578,8 @@ const Temp = struct {...@@ -183696,8 +183578,8 @@ const Temp = struct {
183696 const class = classes[class_index];183578 const class = classes[class_index];
183697 next_class_index = @intCast(switch (class) {183579 next_class_index = @intCast(switch (class) {
183698 .integer, .memory, .float, .float_combine => class_index + 1,183580 .integer, .memory, .float, .float_combine => class_index + 1,
183699 .sse => std.mem.indexOfNonePos(abi.Class, classes, class_index + 1, &.{.sseup}) orelse classes.len,183581 .sse => std.mem.findNonePos(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,183582 .x87 => std.mem.findNonePos(abi.Class, classes, class_index + 1, &.{.x87up}) orelse classes.len,
183701 .sseup,183583 .sseup,
183702 .x87up,183584 .x87up,
183703 .none,183585 .none,
...@@ -189943,7 +189825,7 @@ const Select = struct {...@@ -189943,7 +189825,7 @@ const Select = struct {
189943 s.cg.asmOps(mir_tag, mir_ops) catch |err| switch (err) {189825 s.cg.asmOps(mir_tag, mir_ops) catch |err| switch (err) {
189944 error.InvalidInstruction => {189826 error.InvalidInstruction => {
189945 const fixes = @tagName(mir_tag[0]);189827 const fixes = @tagName(mir_tag[0]);
189946 const fixes_blank = std.mem.indexOfScalar(u8, fixes, '_').?;189828 const fixes_blank = std.mem.findScalar(u8, fixes, '_').?;
189947 return s.cg.fail("invalid instruction: '{s}{s}{s} {s} {s} {s} {s}'", .{189829 return s.cg.fail("invalid instruction: '{s}{s}{s} {s} {s} {s} {s}'", .{
189948 fixes[0..fixes_blank],189830 fixes[0..fixes_blank],
189949 @tagName(mir_tag[1]),189831 @tagName(mir_tag[1]),
...@@ -190023,7 +189905,7 @@ const Select = struct {...@@ -190023,7 +189905,7 @@ const Select = struct {
190023 .add, .com, .comi, .div, .divr, .mul, .st, .sub, .subr, .ucom, .ucomi => s.top +%= 1,189905 .add, .com, .comi, .div, .divr, .mul, .st, .sub, .subr, .ucom, .ucomi => s.top +%= 1,
190024 else => {189906 else => {
190025 const fixes = @tagName(mir_tag[0]);189907 const fixes = @tagName(mir_tag[0]);
190026 const fixes_blank = std.mem.indexOfScalar(u8, fixes, '_').?;189908 const fixes_blank = std.mem.findScalar(u8, fixes, '_').?;
190027 std.debug.panic("{s}: {s}{s}{s}\n", .{189909 std.debug.panic("{s}: {s}{s}{s}\n", .{
190028 @src().fn_name,189910 @src().fn_name,
190029 fixes[0..fixes_blank],189911 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: {...@@ -435,11 +435,11 @@ const mnemonic_table: [inst_tags_len * inst_fixes_len]?Mnemonic = table: {
435 for (0..inst_fixes_len) |fixes_i| {435 for (0..inst_fixes_len) |fixes_i| {
436 const fixes: Mir.Inst.Fixes = @fromBackingInt(@intCast(fixes_i));436 const fixes: Mir.Inst.Fixes = @fromBackingInt(@intCast(fixes_i));
437 const prefix, const suffix = affix: {437 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|
439 @tagName(fixes)[i + 1 ..]439 @tagName(fixes)[i + 1 ..]
440 else440 else
441 @tagName(fixes);441 @tagName(fixes);
442 const wildcard_idx = std.mem.indexOfScalar(u8, pattern, '_').?;442 const wildcard_idx = std.mem.findScalar(u8, pattern, '_').?;
443 break :affix .{ pattern[0..wildcard_idx], pattern[wildcard_idx + 1 ..] };443 break :affix .{ pattern[0..wildcard_idx], pattern[wildcard_idx + 1 ..] };
444 };444 };
445 for (0..inst_tags_len) |inst_tag_i| {445 for (0..inst_tags_len) |inst_tag_i| {
...@@ -477,7 +477,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {...@@ -477,7 +477,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
477 else => return lower.fail("TODO lower .{s}", .{@tagName(inst.ops)}),477 else => return lower.fail("TODO lower .{s}", .{@tagName(inst.ops)}),
478 };478 };
479 try lower.encode(switch (fixes) {479 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|
481 @field(Prefix, @tagName(tag)[0..space])481 @field(Prefix, @tagName(tag)[0..space])
482 else482 else
483 .none,483 .none,
...@@ -487,8 +487,8 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {...@@ -487,8 +487,8 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
487 }487 }
488 // This combination is invalid; make the theoretical mnemonic name and emit an error with it.488 // This combination is invalid; make the theoretical mnemonic name and emit an error with it.
489 const fixes_name = @tagName(fixes);489 const fixes_name = @tagName(fixes);
490 const pattern = fixes_name[if (std.mem.indexOfScalar(u8, fixes_name, ' ')) |i| i + " ".len else 0..];490 const pattern = fixes_name[if (std.mem.findScalar(u8, fixes_name, ' ')) |i| i + " ".len else 0..];
491 const wildcard_index = std.mem.indexOfScalar(u8, pattern, '_').?;491 const wildcard_index = std.mem.findScalar(u8, pattern, '_').?;
492 return lower.fail("unsupported mnemonic: '{s}{s}{s}'", .{492 return lower.fail("unsupported mnemonic: '{s}{s}{s}'", .{
493 pattern[0..wildcard_index],493 pattern[0..wildcard_index],
494 @tagName(inst.tag),494 @tagName(inst.tag),
src/codegen/x86_64/Mir.zig+3-3
...@@ -1745,8 +1745,8 @@ pub const Inst = struct {...@@ -1745,8 +1745,8 @@ pub const Inst = struct {
1745 for (@typeInfo(Mnemonic).@"enum".field_names) |mnemonic_name| {1745 for (@typeInfo(Mnemonic).@"enum".field_names) |mnemonic_name| {
1746 if (mnemonic_name[0] == '.') continue;1746 if (mnemonic_name[0] == '.') continue;
1747 for (@typeInfo(Fixes).@"enum".field_names) |fixes_name| {1747 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..];1748 const pattern = fixes_name[if (std.mem.findScalar(u8, fixes_name, ' ')) |index| index + " ".len else 0..];
1749 const wildcard_index = std.mem.indexOfScalar(u8, pattern, '_').?;1749 const wildcard_index = std.mem.findScalar(u8, pattern, '_').?;
1750 const mnem_prefix = pattern[0..wildcard_index];1750 const mnem_prefix = pattern[0..wildcard_index];
1751 const mnem_suffix = pattern[wildcard_index + "_".len ..];1751 const mnem_suffix = pattern[wildcard_index + "_".len ..];
1752 if (!std.mem.startsWith(u8, mnemonic_name, mnem_prefix)) continue;1752 if (!std.mem.startsWith(u8, mnemonic_name, mnem_prefix)) continue;
...@@ -1823,7 +1823,7 @@ pub const NullTerminatedString = enum(u32) {...@@ -1823,7 +1823,7 @@ pub const NullTerminatedString = enum(u32) {
1823 pub fn toSlice(nts: NullTerminatedString, mir: *const Mir) ?[:0]const u8 {1823 pub fn toSlice(nts: NullTerminatedString, mir: *const Mir) ?[:0]const u8 {
1824 if (nts == .none) return null;1824 if (nts == .none) return null;
1825 const string_bytes = mir.string_bytes[@backingInt(nts)..];1825 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];
1827 }1827 }
1828};1828};
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:...@@ -133,7 +133,7 @@ pub fn classifyWindows(init_ty: Type, zcu: *Zcu, target: *const std.Target, ctx:
133 .float => switch (ty.floatBits(target)) {133 .float => switch (ty.floatBits(target)) {
134 16, 32, 64 => .sse,134 16, 32, 64 => .sse,
135 80 => .memory,135 80 => .memory,
136 128 => if (ctx == .arg) .memory else .sse,136 128 => .win_i128,
137 else => unreachable,137 else => unreachable,
138 },138 },
139 .vector => {139 .vector => {
...@@ -238,16 +238,18 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont...@@ -238,16 +238,18 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont
238 };238 };
239 const unaligned_size = elem_ty.abiSize(zcu) * len;239 const unaligned_size = elem_ty.abiSize(zcu) * len;
240 if (unaligned_size <= 4) return Class.one_integer;240 if (unaligned_size <= 4) return Class.one_integer;
241 if (ctx == .arg and unaligned_size == 8 * 1 * 1 and len == 1 and241 if (unaligned_size == 8 * 1 * 1 and len == 1) {
242 elem_ty.isRuntimeFloat()) return Class.stack; // what242 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 }
243 if (unaligned_size <= 8 * 1) return .{ .sse, .none, .none, .none, .none, .none, .none, .none };245 if (unaligned_size <= 8 * 1) return .{ .sse, .none, .none, .none, .none, .none, .none, .none };
244 if (unaligned_size <= 8 * 2) return .{ .sse, .sseup, .none, .none, .none, .none, .none, .none };246 if (unaligned_size <= 8 * 2) return .{ .sse, .sseup, .none, .none, .none, .none, .none, .none };
245 if (!target.cpu.has(.x86, .avx)) {247 if (!target.cpu.has(.x86, .avx)) {
246 if (ctx == .ret) switch (unaligned_size) {248 if (ctx == .ret) switch (unaligned_size) {
247 else => {},249 else => {},
248 8 * 3 => if (len == 3) return if (elem_ty.isRuntimeFloat()) .{250 8 * 3 => if (len == 3) return if (elem_ty.isRuntimeFloat()) .{
249 .sse_sse_x87_per_qword, .none, .none, .none, .none, .none, .none, .none, // how251 .sse_sse_x87_per_qword, .none, .none, .none, .none, .none, .none, .none, // how?
250 } else Class.len_integers, // why252 } else Class.len_integers, // why?
251 8 * 2 * 2, 8 * 2 * 4 => return .{ .sse_per_xword, .none, .none, .none, .none, .none, .none, .none },253 8 * 2 * 2, 8 * 2 * 4 => return .{ .sse_per_xword, .none, .none, .none, .none, .none, .none, .none },
252 };254 };
253 return Class.stack;255 return Class.stack;
...@@ -316,7 +318,7 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont...@@ -316,7 +318,7 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont
316 // byte isn't SSE or any other eightbyte isn't SSEUP, the whole argument318 // byte isn't SSE or any other eightbyte isn't SSEUP, the whole argument
317 // is passed in memory."319 // is passed in memory."
318 if (ty_size > 16 and (result[0] != .sse or320 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
321 // "If SSEUP is not preceded by SSE or SSEUP, it is converted to SSE."323 // "If SSEUP is not preceded by SSE or SSEUP, it is converted to SSE."
322 for (&result, 0..) |*class, i| switch (class.*) {324 for (&result, 0..) |*class, i| switch (class.*) {
...@@ -356,11 +358,10 @@ fn classifySystemVStruct(...@@ -356,11 +358,10 @@ fn classifySystemVStruct(
356 while (field_it.next()) |field_index| {358 while (field_it.next()) |field_index| {
357 const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]);359 const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]);
358 const field_align = loaded_struct.field_aligns.getOrNone(ip, field_index);360 const field_align = loaded_struct.field_aligns.getOrNone(ip, field_index);
359 byte_offset = std.mem.alignForward(361 byte_offset = switch (field_align) {
360 u64,362 .none => field_ty.abiAlignment(zcu),
361 byte_offset,363 else => field_align,
362 field_align.toByteUnits() orelse field_ty.abiAlignment(zcu).toByteUnits().?,364 }.forward(byte_offset);
363 );
364 if (zcu.typeToStruct(field_ty)) |field_loaded_struct| {365 if (zcu.typeToStruct(field_ty)) |field_loaded_struct| {
365 switch (field_loaded_struct.layout) {366 switch (field_loaded_struct.layout) {
366 .auto => unreachable,367 .auto => unreachable,
...@@ -379,6 +380,9 @@ fn classifySystemVStruct(...@@ -379,6 +380,9 @@ fn classifySystemVStruct(
379 },380 },
380 .@"packed" => {},381 .@"packed" => {},
381 }382 }
383 } else if (field_ty.zigTypeTag(zcu) == .array) {
384 byte_offset = classifySystemVArray(result, byte_offset, field_ty, zcu, target);
385 continue;
382 }386 }
383 const field_classes = std.mem.sliceTo(&classifySystemV(field_ty, zcu, target, .other), .none);387 const field_classes = std.mem.sliceTo(&classifySystemV(field_ty, zcu, target, .other), .none);
384 for (result[@intCast(byte_offset / 8)..][0..field_classes.len], field_classes) |*result_class, field_class|388 for (result[@intCast(byte_offset / 8)..][0..field_classes.len], field_classes) |*result_class, field_class|
...@@ -386,11 +390,7 @@ fn classifySystemVStruct(...@@ -386,11 +390,7 @@ fn classifySystemVStruct(
386 byte_offset += field_ty.abiSize(zcu);390 byte_offset += field_ty.abiSize(zcu);
387 }391 }
388 const final_byte_offset = starting_byte_offset + loaded_struct.size;392 const final_byte_offset = starting_byte_offset + loaded_struct.size;
389 std.debug.assert(final_byte_offset == std.mem.alignForward(393 std.debug.assert(final_byte_offset == loaded_struct.alignment.forward(byte_offset));
390 u64,
391 byte_offset,
392 loaded_struct.alignment.toByteUnits().?,
393 ));
394 return final_byte_offset;394 return final_byte_offset;
395}395}
396396
...@@ -422,6 +422,9 @@ fn classifySystemVUnion(...@@ -422,6 +422,9 @@ fn classifySystemVUnion(
422 },422 },
423 .@"packed" => {},423 .@"packed" => {},
424 }424 }
425 } else if (field_ty.zigTypeTag(zcu) == .array) {
426 _ = classifySystemVArray(result, starting_byte_offset, field_ty, zcu, target);
427 continue;
425 }428 }
426 const field_classes = std.mem.sliceTo(&classifySystemV(field_ty, zcu, target, .other), .none);429 const field_classes = std.mem.sliceTo(&classifySystemV(field_ty, zcu, target, .other), .none);
427 for (result[@intCast(starting_byte_offset / 8)..][0..field_classes.len], field_classes) |*result_class, field_class|430 for (result[@intCast(starting_byte_offset / 8)..][0..field_classes.len], field_classes) |*result_class, field_class|
...@@ -430,6 +433,26 @@ fn classifySystemVUnion(...@@ -430,6 +433,26 @@ fn classifySystemVUnion(
430 return starting_byte_offset + loaded_union.size;433 return starting_byte_offset + loaded_union.size;
431}434}
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
433pub const zigcc = struct {456pub const zigcc = struct {
434 pub const stack_align: ?InternPool.Alignment = null;457 pub const stack_align: ?InternPool.Alignment = null;
435 pub const return_in_regs = true;458 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...@@ -1171,7 +1171,7 @@ fn expectEqualHexStrings(expected: []const u8, given: []const u8, assembly: []co
1171 defer testing.allocator.free(expected_fmt);1171 defer testing.allocator.free(expected_fmt);
1172 const given_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{given});1172 const given_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{given});
1173 defer testing.allocator.free(given_fmt);1173 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).?;
1175 const padding = try testing.allocator.alloc(u8, idx + 5);1175 const padding = try testing.allocator.alloc(u8, idx + 5);
1176 defer testing.allocator.free(padding);1176 defer testing.allocator.free(padding);
1177 @memset(padding, ' ');1177 @memset(padding, ' ');
src/libs/freebsd.zig-1
...@@ -1077,7 +1077,6 @@ fn buildSharedLib(...@@ -1077,7 +1077,6 @@ fn buildSharedLib(
1077 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,1077 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,
1078 .valgrind = false,1078 .valgrind = false,
1079 .optimize_mode = optimize_mode,1079 .optimize_mode = optimize_mode,
1080 .structured_cfg = comp.root_mod.structured_cfg,
1081 },1080 },
1082 .global = config,1081 .global = config,
1083 .cc_argv = &.{},1082 .cc_argv = &.{},
src/libs/glibc.zig+1-4
...@@ -398,7 +398,7 @@ fn start_asm_path(comp: *Compilation, arena: Allocator, basename: []const u8) ![...@@ -398,7 +398,7 @@ fn start_asm_path(comp: *Compilation, arena: Allocator, basename: []const u8) ![
398 try result.appendSlice("powerpc" ++ s ++ "powerpc32");398 try result.appendSlice("powerpc" ++ s ++ "powerpc32");
399 }399 }
400 } else if (arch == .s390x) {400 } else if (arch == .s390x) {
401 try result.appendSlice("s390" ++ s ++ "s390-64");401 try result.appendSlice("s390");
402 } else if (arch.isLoongArch()) {402 } else if (arch.isLoongArch()) {
403 try result.appendSlice("loongarch");403 try result.appendSlice("loongarch");
404 } else if (arch == .m68k) {404 } else if (arch == .m68k) {
...@@ -607,8 +607,6 @@ fn add_include_dirs_arch(...@@ -607,8 +607,6 @@ fn add_include_dirs_arch(
607 try args.append("-I");607 try args.append("-I");
608 try args.append(try path.join(arena, &[_][]const u8{ dir, "s390", nptl }));608 try args.append(try path.join(arena, &[_][]const u8{ dir, "s390", nptl }));
609 } else {609 } else {
610 try args.append("-I");
611 try args.append(try path.join(arena, &[_][]const u8{ dir, "s390" ++ s ++ "s390-64" }));
612 try args.append("-I");610 try args.append("-I");
613 try args.append(try path.join(arena, &[_][]const u8{ dir, "s390" }));611 try args.append(try path.join(arena, &[_][]const u8{ dir, "s390" }));
614 }612 }
...@@ -1223,7 +1221,6 @@ fn buildSharedLib(...@@ -1223,7 +1221,6 @@ fn buildSharedLib(
1223 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,1221 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,
1224 .valgrind = false,1222 .valgrind = false,
1225 .optimize_mode = optimize_mode,1223 .optimize_mode = optimize_mode,
1226 .structured_cfg = comp.root_mod.structured_cfg,
1227 },1224 },
1228 .global = config,1225 .global = config,
1229 .cc_argv = &.{},1226 .cc_argv = &.{},
src/libs/libcxx.zig+3-5
...@@ -172,7 +172,6 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!...@@ -172,7 +172,6 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
172 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,172 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,
173 .valgrind = false,173 .valgrind = false,
174 .optimize_mode = optimize_mode,174 .optimize_mode = optimize_mode,
175 .structured_cfg = comp.root_mod.structured_cfg,
176 .pic = if (target_util.supports_fpic(target)) true else null,175 .pic = if (target_util.supports_fpic(target)) true else null,
177 .code_model = comp.root_mod.code_model,176 .code_model = comp.root_mod.code_model,
178 },177 },
...@@ -366,7 +365,6 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -366,7 +365,6 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
366 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,365 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,
367 .valgrind = false,366 .valgrind = false,
368 .optimize_mode = optimize_mode,367 .optimize_mode = optimize_mode,
369 .structured_cfg = comp.root_mod.structured_cfg,
370 .unwind_tables = unwind_tables,368 .unwind_tables = unwind_tables,
371 .pic = if (target_util.supports_fpic(target)) true else null,369 .pic = if (target_util.supports_fpic(target)) true else null,
372 .code_model = comp.root_mod.code_model,370 .code_model = comp.root_mod.code_model,
...@@ -539,15 +537,15 @@ pub fn addCxxArgs(...@@ -539,15 +537,15 @@ pub fn addCxxArgs(
539 // is simple and works everywhere.537 // is simple and works everywhere.
540 try cflags.append("-D_LIBCPP_PSTL_BACKEND_SERIAL");538 try cflags.append("-D_LIBCPP_PSTL_BACKEND_SERIAL");
541 switch (optimize_mode) {539 switch (optimize_mode) {
542 .Debug => {540 .debug => {
543 try cflags.append("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG");541 try cflags.append("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG");
544 try cflags.append("-D_LIBCPP_ASSERTION_SEMANTIC_DEFAULT=_LIBCPP_ASSERTION_SEMANTIC_ENFORCE");542 try cflags.append("-D_LIBCPP_ASSERTION_SEMANTIC_DEFAULT=_LIBCPP_ASSERTION_SEMANTIC_ENFORCE");
545 },543 },
546 .ReleaseFast, .ReleaseSmall => {544 .fast, .small => {
547 try cflags.append("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_NONE");545 try cflags.append("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_NONE");
548 try cflags.append("-D_LIBCPP_ASSERTION_SEMANTIC_DEFAULT=_LIBCPP_ASSERTION_SEMANTIC_IGNORE");546 try cflags.append("-D_LIBCPP_ASSERTION_SEMANTIC_DEFAULT=_LIBCPP_ASSERTION_SEMANTIC_IGNORE");
549 },547 },
550 .ReleaseSafe => {548 .safe => {
551 try cflags.append("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST");549 try cflags.append("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST");
552 try cflags.append("-D_LIBCPP_ASSERTION_SEMANTIC_DEFAULT=_LIBCPP_ASSERTION_SEMANTIC_ENFORCE");550 try cflags.append("-D_LIBCPP_ASSERTION_SEMANTIC_DEFAULT=_LIBCPP_ASSERTION_SEMANTIC_ENFORCE");
553 },551 },
src/libs/libtsan.zig-1
...@@ -100,7 +100,6 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo...@@ -100,7 +100,6 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
100 .valgrind = false,100 .valgrind = false,
101 .unwind_tables = unwind_tables,101 .unwind_tables = unwind_tables,
102 .optimize_mode = optimize_mode,102 .optimize_mode = optimize_mode,
103 .structured_cfg = comp.root_mod.structured_cfg,
104 .pic = true,103 .pic = true,
105 .no_builtin = true,104 .no_builtin = true,
106 .code_model = comp.root_mod.code_model,105 .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...@@ -118,7 +118,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
118 // defines will be correct.118 // defines will be correct.
119 try cflags.append("-D_LIBUNWIND_IS_NATIVE_ONLY");119 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) {
122 try cflags.append("-D_DEBUG");122 try cflags.append("-D_DEBUG");
123 }123 }
124 if (!comp.config.any_non_single_threaded) {124 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...@@ -135,8 +135,8 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
135 });135 });
136136
137 switch (comp.compilerRtOptMode()) {137 switch (comp.compilerRtOptMode()) {
138 .Debug, .ReleaseSafe => try winpthreads_args.append("-DWINPTHREAD_DBG"),138 .debug, .safe => try winpthreads_args.append("-DWINPTHREAD_DBG"),
139 .ReleaseFast, .ReleaseSmall => {},139 .fast, .small => {},
140 }140 }
141141
142 for (mingw32_winpthreads_src) |dep| {142 for (mingw32_winpthreads_src) |dep| {
src/libs/mingw/Preprocessor.zig+4-4
...@@ -15,7 +15,7 @@ const RawTokenList = std.ArrayList(Token);...@@ -15,7 +15,7 @@ const RawTokenList = std.ArrayList(Token);
15const ExpandBuf = std.ArrayList(Token);15const ExpandBuf = std.ArrayList(Token);
1616
17const Preprocessor = @This();17const Preprocessor = @This();
18const DefineMap = std.StringArrayHashMapUnmanaged(Macro);18const DefineMap = std.array_hash_map.String(Macro);
1919
20const GeneratedTokens = std.ArrayList(u8);20const GeneratedTokens = std.ArrayList(u8);
2121
...@@ -29,7 +29,7 @@ pub const Source = struct {...@@ -29,7 +29,7 @@ pub const Source = struct {
29 buf: []const u8,29 buf: []const u8,
30};30};
3131
32sources: std.StringArrayHashMapUnmanaged(Source) = .empty,32sources: std.array_hash_map.String(Source) = .empty,
3333
34arena: Allocator,34arena: Allocator,
35io: std.Io,35io: std.Io,
...@@ -91,9 +91,9 @@ fn addTokenAssumeCapacity(pp: *Preprocessor, tok: Token) void {...@@ -91,9 +91,9 @@ fn addTokenAssumeCapacity(pp: *Preprocessor, tok: Token) void {
9191
92fn defineBuiltins(pp: *Preprocessor) !void {92fn defineBuiltins(pp: *Preprocessor) !void {
93 var buf: [5]u8 = undefined;93 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;
95 try pp.defineBuiltinValue("__SIZEOF_LONG_DOUBLE__", val, .pp_num);95 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;
97 try pp.defineBuiltinValue("__SIZEOF_DOUBLE__", val, .pp_num);97 try pp.defineBuiltinValue("__SIZEOF_DOUBLE__", val, .pp_num);
9898
99 if (pp.target.abi.isGnu()) {99 if (pp.target.abi.isGnu()) {
src/libs/mingw/def.zig+4-4
...@@ -61,7 +61,7 @@ pub const ModuleDefinition = struct {...@@ -61,7 +61,7 @@ pub const ModuleDefinition = struct {
61 // or ? for C++ functions). Vectorcall functions won't have any61 // or ? for C++ functions). Vectorcall functions won't have any
62 // fixed prefix, but the function base name will still be at least62 // fixed prefix, but the function base name will still be at least
63 // one char.63 // 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;
65 e.name = e.name[0..name_len_without_at_suffix];65 e.name = e.name[0..name_len_without_at_suffix];
66 }66 }
67 }67 }
...@@ -452,7 +452,7 @@ pub const Parser = struct {...@@ -452,7 +452,7 @@ pub const Parser = struct {
452 var ext_name_needs_underscore = false;452 var ext_name_needs_underscore = false;
453 if (self.machine_type == .I386) {453 if (self.machine_type == .I386) {
454 const is_decorated = isDecorated(name_tok.slice(self.tokenizer.source), self.module_definition_type);454 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;
456 name_needs_underscore = !is_decorated and !is_forward_target;456 name_needs_underscore = !is_decorated and !is_forward_target;
457457
458 if (ext_name_tok) |ext_name| {458 if (ext_name_tok) |ext_name| {
...@@ -578,9 +578,9 @@ pub const Parser = struct {...@@ -578,9 +578,9 @@ pub const Parser = struct {
578 // themselves can start with an underscore, while a second one still needs578 // themselves can start with an underscore, while a second one still needs
579 // to be added.579 // to be added.
580 if (std.mem.startsWith(u8, symbol, "@")) return true;580 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;
582 if (std.mem.startsWith(u8, symbol, "?")) return true;582 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;
584 return false;584 return false;
585 }585 }
586586
src/libs/mingw/implib.zig+1-1
...@@ -351,7 +351,7 @@ fn getNameType(...@@ -351,7 +351,7 @@ fn getNameType(
351 // the leading underscore. In MinGW on the other hand, a decorated351 // the leading underscore. In MinGW on the other hand, a decorated
352 // stdcall function still omits the underscore (IMPORT_NAME_NOPREFIX).352 // stdcall function still omits the underscore (IMPORT_NAME_NOPREFIX).
353 if (std.mem.startsWith(u8, ext_name, "_") and353 if (std.mem.startsWith(u8, ext_name, "_") and
354 std.mem.indexOfScalar(u8, ext_name, '@') != null and354 std.mem.findScalar(u8, ext_name, '@') != null and
355 module_definition_type != .mingw)355 module_definition_type != .mingw)
356 return .NAME;356 return .NAME;
357 if (!std.mem.eql(u8, symbol, ext_name))357 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...@@ -225,7 +225,6 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
225 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,225 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,
226 .valgrind = false,226 .valgrind = false,
227 .optimize_mode = optimize_mode,227 .optimize_mode = optimize_mode,
228 .structured_cfg = comp.root_mod.structured_cfg,
229 },228 },
230 .global = config,229 .global = config,
231 .cc_argv = cc_argv,230 .cc_argv = cc_argv,
src/libs/netbsd.zig-1
...@@ -727,7 +727,6 @@ fn buildSharedLib(...@@ -727,7 +727,6 @@ fn buildSharedLib(
727 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,727 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,
728 .valgrind = false,728 .valgrind = false,
729 .optimize_mode = optimize_mode,729 .optimize_mode = optimize_mode,
730 .structured_cfg = comp.root_mod.structured_cfg,
731 },730 },
732 .global = config,731 .global = config,
733 .cc_argv = &.{},732 .cc_argv = &.{},
src/libs/openbsd.zig-1
...@@ -647,7 +647,6 @@ fn buildSharedLib(...@@ -647,7 +647,6 @@ fn buildSharedLib(
647 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,647 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,
648 .valgrind = false,648 .valgrind = false,
649 .optimize_mode = optimize_mode,649 .optimize_mode = optimize_mode,
650 .structured_cfg = comp.root_mod.structured_cfg,
651 },650 },
652 .global = config,651 .global = config,
653 .cc_argv = &.{},652 .cc_argv = &.{},
src/link.zig+57-3
...@@ -1238,11 +1238,11 @@ pub const File = struct {...@@ -1238,11 +1238,11 @@ pub const File = struct {
1238 }1238 }
12391239
1240 switch (base.tag) {1240 switch (base.tag) {
1241 inline .elf2, .coff2, .wasm => |tag| {1241 inline .elf2, .coff2, .wasm, .c => |tag| {
1242 dev.check(tag.devFeature());1242 dev.check(tag.devFeature());
1243 try @as(*tag.Type(), @fieldParentPtr("base", base)).prelink(base.comp.link_prog_node);1243 try @as(*tag.Type(), @fieldParentPtr("base", base)).prelink(base.comp.link_prog_node);
1244 },1244 },
1245 else => {},1245 else => base.comp.link_prog_node.completeOne(),
1246 }1246 }
12471247
1248 base.post_prelink = true;1248 base.post_prelink = true;
...@@ -2127,7 +2127,7 @@ pub fn resolveInputs(...@@ -2127,7 +2127,7 @@ pub fn resolveInputs(
2127 continue;2127 continue;
2128 },2128 },
2129 }2129 }
2130 @compileError("unreachable");2130 comptime unreachable;
2131 }2131 }
21322132
2133 if (failed_libs.items.len > 0) {2133 if (failed_libs.items.len > 0) {
...@@ -2239,6 +2239,60 @@ fn resolveLibInput(...@@ -2239,6 +2239,60 @@ fn resolveLibInput(
2239 return finishResolveLibInput(io, resolved_inputs, archive_dedup, test_path, file, link_mode, name_query.query);2239 return finishResolveLibInput(io, resolved_inputs, archive_dedup, test_path, file, link_mode, name_query.query);
2240 }2240 }
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
2242 return .no_match;2296 return .no_match;
2243}2297}
22442298
src/link/C.zig+26-25
...@@ -43,6 +43,8 @@ type_dependencies: std.ArrayList(link.ConstPool.Index),...@@ -43,6 +43,8 @@ type_dependencies: std.ArrayList(link.ConstPool.Index),
43/// one array.43/// one array.
44align_dependency_masks: std.ArrayList(u64),44align_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,
46/// All NAVs, regardless of whether they are functions or simple constants, are put in this map.48/// All NAVs, regardless of whether they are functions or simple constants, are put in this map.
47navs: std.array_hash_map.Auto(InternPool.Nav.Index, RenderedDecl),49navs: std.array_hash_map.Auto(InternPool.Nav.Index, RenderedDecl),
48/// All UAVs which may be referenced are in this map. The UAV alignment is not included in the50/// 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(...@@ -404,9 +406,8 @@ pub fn createEmpty(
404 emit: Path,406 emit: Path,
405 options: link.File.OpenOptions,407 options: link.File.OpenOptions,
406) !*C {408) !*C {
409 assert(comp.root_mod.resolved_target.result.ofmt == .c);
407 const io = comp.io;410 const io = comp.io;
408 const target = &comp.root_mod.resolved_target.result;
409 assert(target.ofmt == .c);
410 const optimize_mode = comp.root_mod.optimize_mode;411 const optimize_mode = comp.root_mod.optimize_mode;
411 const use_lld = build_options.have_llvm and comp.config.use_lld;412 const use_lld = build_options.have_llvm and comp.config.use_lld;
412 const use_llvm = comp.config.use_llvm;413 const use_llvm = comp.config.use_llvm;
...@@ -422,14 +423,13 @@ pub fn createEmpty(...@@ -422,14 +423,13 @@ pub fn createEmpty(
422 });423 });
423 errdefer file.close(io);424 errdefer file.close(io);
424425
425 const c_file = try arena.create(C);426 const c = try arena.create(C);
426427 c.* = .{
427 c_file.* = .{
428 .base = .{428 .base = .{
429 .tag = .c,429 .tag = .c,
430 .comp = comp,430 .comp = comp,
431 .emit = emit,431 .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),
433 .print_gc_sections = options.print_gc_sections,433 .print_gc_sections = options.print_gc_sections,
434 .stack_size = options.stack_size orelse 16777216,434 .stack_size = options.stack_size orelse 16777216,
435 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,435 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
...@@ -439,6 +439,7 @@ pub fn createEmpty(...@@ -439,6 +439,7 @@ pub fn createEmpty(
439 .string_bytes = .empty,439 .string_bytes = .empty,
440 .type_dependencies = .empty,440 .type_dependencies = .empty,
441 .align_dependency_masks = .empty,441 .align_dependency_masks = .empty,
442 .header = .empty,
442 .navs = .empty,443 .navs = .empty,
443 .uavs = .empty,444 .uavs = .empty,
444 .type_pool = .empty,445 .type_pool = .empty,
...@@ -447,8 +448,7 @@ pub fn createEmpty(...@@ -447,8 +448,7 @@ pub fn createEmpty(
447 .exported_navs = .empty,448 .exported_navs = .empty,
448 .exported_uavs = .empty,449 .exported_uavs = .empty,
449 };450 };
450451 return c;
451 return c_file;
452}452}
453453
454pub fn deinit(c: *C) void {454pub fn deinit(c: *C) void {
...@@ -469,6 +469,21 @@ pub fn deinit(c: *C) void {...@@ -469,6 +469,21 @@ pub fn deinit(c: *C) void {
469 c.exported_uavs.deinit(gpa);469 c.exported_uavs.deinit(gpa);
470}470}
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
472pub fn updateContainerType(487pub fn updateContainerType(
473 c: *C,488 c: *C,
474 pt: Zcu.PerThread,489 pt: Zcu.PerThread,
...@@ -727,7 +742,6 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog...@@ -727,7 +742,6 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
727 const io = comp.io;742 const io = comp.io;
728 const zcu = c.base.comp.zcu.?;743 const zcu = c.base.comp.zcu.?;
729 const ip = &zcu.intern_pool;744 const ip = &zcu.intern_pool;
730 const target = zcu.getTarget();
731 const active = zcu.activate(tid);745 const active = zcu.activate(tid);
732 defer active.deactivate();746 defer active.deactivate();
733 const pt = active.pt;747 const pt = active.pt;
...@@ -943,7 +957,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog...@@ -943,7 +957,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
943 // We have discovered the full set of NAVs, UAVs, and types we need to emit, and will now begin957 // We have discovered the full set of NAVs, UAVs, and types we need to emit, and will now begin
944 // to build the output buffer. Our strategy is to emit the C source in this order:958 // to build the output buffer. Our strategy is to emit the C source in this order:
945 //959 //
946 // * ABI defines and `#include "zig.h"`960 // * Header
947 // * Big-int type definitions961 // * Big-int type definitions
948 // * Other CType definitions (traversing the dependency graph to sort topologically)962 // * Other CType definitions (traversing the dependency graph to sort topologically)
949 // * Global assembly963 // * Global assembly
...@@ -968,7 +982,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog...@@ -968,7 +982,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
968982
969 // We know exactly what we'll be emitting, so can reserve capacity for all of our buffers!983 // 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
972 1 + // Big-int type definitions986 1 + // Big-int type definitions
973 need_types.count() + // `RenderedType.fwd_decl` (worst-case)987 need_types.count() + // `RenderedType.fwd_decl` (worst-case)
974 need_types.count() + // `RenderedType.definition`988 need_types.count() + // `RenderedType.definition`
...@@ -984,20 +998,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog...@@ -984,20 +998,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
984 need_uavs.count() * 3 + // UAV definitions ("static ", "zig_align(4)", "<definition body>")998 need_uavs.count() * 3 + // UAV definitions ("static ", "zig_align(4)", "<definition body>")
985 need_navs.count() * 2); // NAV definitions ("static ", "<definition body>")999 need_navs.count() * 2); // NAV definitions ("static ", "<definition body>")
9861000
987 // ABI defines and `#include "zig.h"`1001 f.appendBufAssumeCapacity(c.header.get(c));
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 );
10011002
1002 // Big-int type definitions1003 // Big-int type definitions
1003 var bigint_aw: std.Io.Writer.Allocating = .init(gpa);1004 var bigint_aw: std.Io.Writer.Allocating = .init(gpa);
src/link/Coff.zig+22-18
...@@ -621,7 +621,7 @@ pub const LongNamesTable = struct {...@@ -621,7 +621,7 @@ pub const LongNamesTable = struct {
621 }621 }
622622
623 pub fn hash(_: Adapter, key: []const u8) u32 {623 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);
625 return std.array_hash_map.hashString(key);625 return std.array_hash_map.hashString(key);
626 }626 }
627 };627 };
...@@ -711,7 +711,7 @@ pub const ExportTable = struct {...@@ -711,7 +711,7 @@ pub const ExportTable = struct {
711 }711 }
712712
713 pub fn hash(_: Adapter, key: []const u8) u32 {713 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);
715 return std.array_hash_map.hashString(key);715 return std.array_hash_map.hashString(key);
716 }716 }
717 };717 };
...@@ -759,7 +759,7 @@ pub const ImportTable = struct {...@@ -759,7 +759,7 @@ pub const ImportTable = struct {
759 }759 }
760760
761 pub fn hash(_: Adapter, key: []const u8) u32 {761 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);
763 return std.array_hash_map.hashString(key);763 return std.array_hash_map.hashString(key);
764 }764 }
765 };765 };
...@@ -822,7 +822,7 @@ pub const String = enum(u32) {...@@ -822,7 +822,7 @@ pub const String = enum(u32) {
822822
823 pub fn toSlice(s: String, coff: *Coff) [:0]const u8 {823 pub fn toSlice(s: String, coff: *Coff) [:0]const u8 {
824 const slice = coff.string_bytes.items[@backingInt(s)..];824 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];
826 }826 }
827827
828 pub fn toOptional(s: String) String.Optional {828 pub fn toOptional(s: String) String.Optional {
...@@ -3535,7 +3535,7 @@ fn objectSectionParentName(coff: *Coff, name: []const u8) []const u8 {...@@ -3535,7 +3535,7 @@ fn objectSectionParentName(coff: *Coff, name: []const u8) []const u8 {
3535 // Otherwise, we want to keep the full name so that this sort can occur correctly when3535 // Otherwise, we want to keep the full name so that this sort can occur correctly when
3536 // the object is finally linked into an image.3536 // the object is finally linked into an image.
3537 return if (coff.isImage())3537 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]
3539 else3539 else
3540 name;3540 name;
3541}3541}
...@@ -3654,7 +3654,7 @@ fn verifyParentSectionAttributes(...@@ -3654,7 +3654,7 @@ fn verifyParentSectionAttributes(
3654 parent.name(coff).toSlice(coff),3654 parent.name(coff).toSlice(coff),
3655 });3655 });
36563656
3657 inline for (comptime std.meta.fieldNames(ObjectSectionAttributes)) |field| {3657 inline for (@typeInfo(ObjectSectionAttributes).@"struct".field_names) |field| {
3658 if (@field(child_attrs, field) != @field(parent_attrs, field)) {3658 if (@field(child_attrs, field) != @field(parent_attrs, field)) {
3659 err.addNote("flags.{s} was {d} in {s}, but {d} in {s}", .{3659 err.addNote("flags.{s} was {d} in {s}, but {d} in {s}", .{
3660 field,3660 field,
...@@ -5370,7 +5370,9 @@ fn loadDll(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) LoadInp...@@ -5370,7 +5370,9 @@ fn loadDll(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) LoadInp
5370}5370}
53715371
5372pub fn prelink(coff: *Coff, prog_node: std.Progress.Node) link.Error!void {5372pub 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
5374 const base = coff.base;5376 const base = coff.base;
5375 const comp = base.comp;5377 const comp = base.comp;
53765378
...@@ -5598,11 +5600,11 @@ fn updateFuncInner(...@@ -5598,11 +5600,11 @@ fn updateFuncInner(
5598 const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{5600 const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{
5599 .alignment = switch (nav.resolved.?.@"align") {5601 .alignment = switch (nav.resolved.?.@"align") {
5600 .none => switch (mod.optimize_mode) {5602 .none => switch (mod.optimize_mode) {
5601 .Debug,5603 .debug,
5602 .ReleaseSafe,5604 .safe,
5603 .ReleaseFast,5605 .fast,
5604 => target_util.defaultFunctionAlignment(target),5606 => target_util.defaultFunctionAlignment(target),
5605 .ReleaseSmall => target_util.minFunctionAlignment(target),5607 .small => target_util.minFunctionAlignment(target),
5606 },5608 },
5607 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),5609 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
5608 }.toStdMem(),5610 }.toStdMem(),
...@@ -5735,7 +5737,7 @@ fn reportUndefs(coff: *Coff, tid: Zcu.PerThread.Id) !void {...@@ -5735,7 +5737,7 @@ fn reportUndefs(coff: *Coff, tid: Zcu.PerThread.Id) !void {
5735 const gpa = comp.gpa;5737 const gpa = comp.gpa;
5736 const max_notes = 4;5738 const max_notes = 4;
57375739
5738 var undef_indices: std.ArrayListUnmanaged(u32) = .empty;5740 var undef_indices: std.ArrayList(u32) = .empty;
5739 for (coff.relocs.items, 0..) |reloc, reloc_i| {5741 for (coff.relocs.items, 0..) |reloc, reloc_i| {
5740 if (reloc.flags.free) continue;5742 if (reloc.flags.free) continue;
5741 const target_sym = reloc.target.get(coff);5743 const target_sym = reloc.target.get(coff);
...@@ -5886,7 +5888,9 @@ pub fn flush(...@@ -5886,7 +5888,9 @@ pub fn flush(
5886 prog_node: std.Progress.Node,5888 prog_node: std.Progress.Node,
5887) link.Error!void {5889) link.Error!void {
5888 _ = arena;5890 _ = arena;
5889 _ = prog_node;5891 const sub_prog_node = prog_node.start("COFF Flush", 0);
5892 defer sub_prog_node.end();
5893
5890 const comp = coff.base.comp;5894 const comp = coff.base.comp;
58915895
5892 // TODO: When https://github.com/ziglang/zig/issues/23617 is in,5896 // TODO: When https://github.com/ziglang/zig/issues/23617 is in,
...@@ -6649,11 +6653,11 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {...@@ -6649,11 +6653,11 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
66496653
6650 const target = &comp.root_mod.resolved_target.result;6654 const target = &comp.root_mod.resolved_target.result;
6651 const alignment = switch (comp.root_mod.optimize_mode) {6655 const alignment = switch (comp.root_mod.optimize_mode) {
6652 .Debug,6656 .debug,
6653 .ReleaseSafe,6657 .safe,
6654 .ReleaseFast,6658 .fast,
6655 => target_util.defaultFunctionAlignment(target),6659 => target_util.defaultFunctionAlignment(target),
6656 .ReleaseSmall => target_util.minFunctionAlignment(target),6660 .small => target_util.minFunctionAlignment(target),
6657 }.toStdMem();6661 }.toStdMem();
6658 const parent_si = (try coff.pseudoSectionMapIndex(6662 const parent_si = (try coff.pseudoSectionMapIndex(
6659 .@".thunks",6663 .@".thunks",
...@@ -6983,7 +6987,7 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void {...@@ -6983,7 +6987,7 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void {
6983 continue;6987 continue;
69846988
6985 import_hint_name_index = @intCast(import_hint_name_align.forward(6989 import_hint_name_index = @intCast(import_hint_name_align.forward(
6986 std.mem.indexOfScalarPos(6990 std.mem.findScalarPos(
6987 u8,6991 u8,
6988 import_hint_name_slice,6992 import_hint_name_slice,
6989 import_hint_name_index,6993 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...@@ -4151,8 +4151,8 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
4151 .x86_64_regcall_v3_sysv => .LLVM_X86RegCall,4151 .x86_64_regcall_v3_sysv => .LLVM_X86RegCall,
4152 .x86_64_regcall_v4_win => .LLVM_X86RegCall,4152 .x86_64_regcall_v4_win => .LLVM_X86RegCall,
4153 .x86_64_vectorcall => .LLVM_vectorcall,4153 .x86_64_vectorcall => .LLVM_vectorcall,
4154 .x86_sysv => .normal,4154 .x86_sysv, .x86_win, .x86_mingw => .normal,
4155 .x86_win => .normal,4155 .x86_64_preserve_none => .LLVM_PreserveNone,
4156 .x86_stdcall => .BORLAND_stdcall,4156 .x86_stdcall => .BORLAND_stdcall,
4157 .x86_fastcall => .BORLAND_msfastcall,4157 .x86_fastcall => .BORLAND_msfastcall,
4158 .x86_thiscall => .BORLAND_thiscall,4158 .x86_thiscall => .BORLAND_thiscall,
...@@ -4166,6 +4166,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co...@@ -4166,6 +4166,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
4166 .aarch64_aapcs_win => .normal,4166 .aarch64_aapcs_win => .normal,
4167 .aarch64_vfabi => .LLVM_AAPCS,4167 .aarch64_vfabi => .LLVM_AAPCS,
4168 .aarch64_vfabi_sve => .LLVM_AAPCS,4168 .aarch64_vfabi_sve => .LLVM_AAPCS,
4169 .aarch64_preserve_none => .LLVM_PreserveNone,
41694170
4170 .arm_aapcs => .LLVM_AAPCS,4171 .arm_aapcs => .LLVM_AAPCS,
4171 .arm_aapcs_vfp => .LLVM_AAPCS_VFP,4172 .arm_aapcs_vfp => .LLVM_AAPCS_VFP,
src/link/Elf.zig+136-137
...@@ -127,7 +127,7 @@ const SectionIndexes = struct {...@@ -127,7 +127,7 @@ const SectionIndexes = struct {
127 symtab: ?u32 = null,127 symtab: ?u32 = null,
128};128};
129129
130const ProgramHeaderList = std.ArrayList(elf.Elf64_Phdr);130const ProgramHeaderList = std.ArrayList(elf.Elf64.Phdr);
131131
132const OptionalProgramHeaderIndex = enum(u16) {132const OptionalProgramHeaderIndex = enum(u16) {
133 none = std.math.maxInt(u16),133 none = std.math.maxInt(u16),
...@@ -159,21 +159,21 @@ const ProgramHeaderIndex = enum(u16) {...@@ -159,21 +159,21 @@ const ProgramHeaderIndex = enum(u16) {
159};159};
160160
161const ProgramHeaderIndexes = struct {161const ProgramHeaderIndexes = struct {
162 /// PT_PHDR162 /// PT.PHDR
163 table: OptionalProgramHeaderIndex = .none,163 table: OptionalProgramHeaderIndex = .none,
164 /// PT_LOAD for PHDR table164 /// PT.LOAD for PHDR table
165 /// We add this special load segment to ensure the EHDR and PHDR table are always165 /// We add this special load segment to ensure the EHDR and PHDR table are always
166 /// loaded into memory.166 /// loaded into memory.
167 table_load: OptionalProgramHeaderIndex = .none,167 table_load: OptionalProgramHeaderIndex = .none,
168 /// PT_INTERP168 /// PT.INTERP
169 interp: OptionalProgramHeaderIndex = .none,169 interp: OptionalProgramHeaderIndex = .none,
170 /// PT_DYNAMIC170 /// PT.DYNAMIC
171 dynamic: OptionalProgramHeaderIndex = .none,171 dynamic: OptionalProgramHeaderIndex = .none,
172 /// PT_GNU_EH_FRAME172 /// PT.GNU_EH_FRAME
173 gnu_eh_frame: OptionalProgramHeaderIndex = .none,173 gnu_eh_frame: OptionalProgramHeaderIndex = .none,
174 /// PT_GNU_STACK174 /// PT.GNU_STACK
175 gnu_stack: OptionalProgramHeaderIndex = .none,175 gnu_stack: OptionalProgramHeaderIndex = .none,
176 /// PT_TLS176 /// PT.TLS
177 /// TODO I think ELF permits multiple TLS segments but for now, assume one per file.177 /// TODO I think ELF permits multiple TLS segments but for now, assume one per file.
178 tls: OptionalProgramHeaderIndex = .none,178 tls: OptionalProgramHeaderIndex = .none,
179};179};
...@@ -260,7 +260,7 @@ pub fn createEmpty(...@@ -260,7 +260,7 @@ pub fn createEmpty(
260 .tag = .elf,260 .tag = .elf,
261 .comp = comp,261 .comp = comp,
262 .emit = emit,262 .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),
264 .print_gc_sections = options.print_gc_sections,264 .print_gc_sections = options.print_gc_sections,
265 .stack_size = options.stack_size orelse 16777216,265 .stack_size = options.stack_size orelse 16777216,
266 .allow_shlib_undefined = options.allow_shlib_undefined orelse !is_native_os,266 .allow_shlib_undefined = options.allow_shlib_undefined orelse !is_native_os,
...@@ -334,23 +334,23 @@ pub fn createEmpty(...@@ -334,23 +334,23 @@ pub fn createEmpty(
334 if (!is_obj_or_ar) {334 if (!is_obj_or_ar) {
335 try self.dynstrtab.append(gpa, 0);335 try self.dynstrtab.append(gpa, 0);
336336
337 // Initialize PT_PHDR program header337 // Initialize PT.PHDR program header
338 const p_align: u16 = switch (self.ptr_width) {338 const p_align: u16 = switch (self.ptr_width) {
339 .p32 => @alignOf(elf.Elf32_Phdr),339 .p32 => @alignOf(elf.Elf32.Phdr),
340 .p64 => @alignOf(elf.Elf64_Phdr),340 .p64 => @alignOf(elf.Elf64.Phdr),
341 };341 };
342 const ehsize: u64 = switch (self.ptr_width) {342 const ehsize: u64 = switch (self.ptr_width) {
343 .p32 => @sizeOf(elf.Elf32_Ehdr),343 .p32 => @sizeOf(elf.Elf32_Ehdr),
344 .p64 => @sizeOf(elf.Elf64_Ehdr),344 .p64 => @sizeOf(elf.Elf64_Ehdr),
345 };345 };
346 const phsize: u64 = switch (self.ptr_width) {346 const phsize: u64 = switch (self.ptr_width) {
347 .p32 => @sizeOf(elf.Elf32_Phdr),347 .p32 => @sizeOf(elf.Elf32.Phdr),
348 .p64 => @sizeOf(elf.Elf64_Phdr),348 .p64 => @sizeOf(elf.Elf64.Phdr),
349 };349 };
350 const max_nphdrs = comptime getMaxNumberOfPhdrs();350 const max_nphdrs = comptime getMaxNumberOfPhdrs();
351 const reserved: u64 = mem.alignForward(u64, padToIdeal(max_nphdrs * phsize), self.page_size);351 const reserved: u64 = mem.alignForward(u64, padToIdeal(max_nphdrs * phsize), self.page_size);
352 self.phdr_indexes.table = (try self.addPhdr(.{352 self.phdr_indexes.table = (try self.addPhdr(.{
353 .type = elf.PT_PHDR,353 .type = @backingInt(elf.PT.PHDR),
354 .flags = elf.PF_R,354 .flags = elf.PF_R,
355 .@"align" = p_align,355 .@"align" = p_align,
356 .addr = self.image_base + ehsize,356 .addr = self.image_base + ehsize,
...@@ -359,7 +359,7 @@ pub fn createEmpty(...@@ -359,7 +359,7 @@ pub fn createEmpty(
359 .memsz = reserved,359 .memsz = reserved,
360 })).toOptional();360 })).toOptional();
361 self.phdr_indexes.table_load = (try self.addPhdr(.{361 self.phdr_indexes.table_load = (try self.addPhdr(.{
362 .type = elf.PT_LOAD,362 .type = @backingInt(elf.PT.LOAD),
363 .flags = elf.PF_R,363 .flags = elf.PF_R,
364 .@"align" = self.page_size,364 .@"align" = self.page_size,
365 .addr = self.image_base,365 .addr = self.image_base,
...@@ -514,11 +514,11 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 {...@@ -514,11 +514,11 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 {
514 }514 }
515515
516 for (self.phdrs.items) |phdr| {516 for (self.phdrs.items) |phdr| {
517 if (phdr.p_type != elf.PT_LOAD) continue;517 if (phdr.type != .LOAD) continue;
518 const increased_size = padToIdeal(phdr.p_filesz);518 const increased_size = padToIdeal(phdr.filesz);
519 const test_end = phdr.p_offset +| increased_size;519 const test_end = phdr.offset +| increased_size;
520 if (start < test_end) {520 if (start < test_end) {
521 if (end > phdr.p_offset) return test_end;521 if (end > phdr.offset) return test_end;
522 if (test_end < std.math.maxInt(u64)) at_end = false;522 if (test_end < std.math.maxInt(u64)) at_end = false;
523 }523 }
524 }524 }
...@@ -538,8 +538,8 @@ pub fn allocatedSize(self: *Elf, start: u64) u64 {...@@ -538,8 +538,8 @@ pub fn allocatedSize(self: *Elf, start: u64) u64 {
538 if (section.sh_offset < min_pos) min_pos = section.sh_offset;538 if (section.sh_offset < min_pos) min_pos = section.sh_offset;
539 }539 }
540 for (self.phdrs.items) |phdr| {540 for (self.phdrs.items) |phdr| {
541 if (phdr.p_offset <= start) continue;541 if (phdr.offset <= start) continue;
542 if (phdr.p_offset < min_pos) min_pos = phdr.p_offset;542 if (phdr.offset < min_pos) min_pos = phdr.offset;
543 }543 }
544 return min_pos - start;544 return min_pos - start;
545}545}
...@@ -714,7 +714,6 @@ pub fn loadInput(self: *Elf, input: link.Input) !void {...@@ -714,7 +714,6 @@ pub fn loadInput(self: *Elf, input: link.Input) !void {
714 const target = self.getTarget();714 const target = self.getTarget();
715 const debug_fmt_strip = comp.config.debug_format == .strip;715 const debug_fmt_strip = comp.config.debug_format == .strip;
716 const default_sym_version = self.default_sym_version;716 const default_sym_version = self.default_sym_version;
717 const is_static_lib = self.base.isStaticLib();
718717
719 if (comp.verbose_link) {718 if (comp.verbose_link) {
720 comp.mutex.lockUncancelable(io); // protect comp.arena719 comp.mutex.lockUncancelable(io); // protect comp.arena
...@@ -733,7 +732,11 @@ pub fn loadInput(self: *Elf, input: link.Input) !void {...@@ -733,7 +732,11 @@ pub fn loadInput(self: *Elf, input: link.Input) !void {
733 .res => unreachable,732 .res => unreachable,
734 .dso_exact => @panic("TODO"),733 .dso_exact => @panic("TODO"),
735 .object => |obj| try parseObject(self, obj),734 .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 },
737 .dso => |dso| try parseDso(gpa, io, diags, dso, &self.shared_objects, &self.files, target),740 .dso => |dso| try parseDso(gpa, io, diags, dso, &self.shared_objects, &self.files, target),
738 }741 }
739}742}
...@@ -1083,7 +1086,6 @@ fn parseArchive(...@@ -1083,7 +1086,6 @@ fn parseArchive(
1083 default_sym_version: elf.Versym,1086 default_sym_version: elf.Versym,
1084 objects: *std.ArrayList(File.Index),1087 objects: *std.ArrayList(File.Index),
1085 obj: link.Input.Object,1088 obj: link.Input.Object,
1086 is_static_lib: bool,
1087) !void {1089) !void {
1088 const tracy = trace(@src());1090 const tracy = trace(@src());
1089 defer tracy.end();1091 defer tracy.end();
...@@ -1092,17 +1094,14 @@ fn parseArchive(...@@ -1092,17 +1094,14 @@ fn parseArchive(
1092 var archive = try Archive.parse(gpa, io, diags, file_handles, obj.path, fh);1094 var archive = try Archive.parse(gpa, io, diags, file_handles, obj.path, fh);
1093 defer archive.deinit(gpa);1095 defer archive.deinit(gpa);
10941096
1095 const init_alive = if (is_static_lib) true else obj.must_link;
1096
1097 for (archive.objects) |extracted| {1097 for (archive.objects) |extracted| {
1098 const index: File.Index = @intCast(try files.addOne(gpa));1098 const index: File.Index = @intCast(try files.addOne(gpa));
1099 files.set(index, .{ .object = extracted });1099 files.set(index, .{ .object = extracted });
1100 const object = &files.items(.data)[index].object;1100 const object = &files.items(.data)[index].object;
1101 object.index = index;1101 object.index = index;
1102 object.alive = init_alive;1102 object.alive = obj.must_link;
1103 try object.parseCommon(gpa, io, diags, obj.path, obj.file, target);1103 try object.parseCommon(gpa, io, diags, obj.path, obj.file, target);
1104 if (!is_static_lib)1104 try object.parse(gpa, io, diags, obj.path, obj.file, target, debug_fmt_strip, default_sym_version);
1105 try object.parse(gpa, io, diags, obj.path, obj.file, target, debug_fmt_strip, default_sym_version);
1106 try objects.append(gpa, index);1105 try objects.append(gpa, index);
1107 }1106 }
1108}1107}
...@@ -1471,34 +1470,34 @@ fn writePhdrTable(self: *Elf) !void {...@@ -1471,34 +1470,34 @@ fn writePhdrTable(self: *Elf) !void {
1471 const phdr_table = &self.phdrs.items[self.phdr_indexes.table.int().?];1470 const phdr_table = &self.phdrs.items[self.phdr_indexes.table.int().?];
14721471
1473 log.debug("writing program headers from 0x{x} to 0x{x}", .{1472 log.debug("writing program headers from 0x{x} to 0x{x}", .{
1474 phdr_table.p_offset,1473 phdr_table.offset,
1475 phdr_table.p_offset + phdr_table.p_filesz,1474 phdr_table.offset + phdr_table.filesz,
1476 });1475 });
14771476
1478 switch (self.ptr_width) {1477 switch (self.ptr_width) {
1479 .p32 => {1478 .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);
1481 defer gpa.free(buf);1480 defer gpa.free(buf);
14821481
1483 for (buf, 0..) |*phdr, i| {1482 for (buf, 0..) |*phdr, i| {
1484 phdr.* = phdrTo32(self.phdrs.items[i]);1483 phdr.* = phdrTo32(self.phdrs.items[i]);
1485 if (foreign_endian) {1484 if (foreign_endian) {
1486 mem.byteSwapAllFields(elf.Elf32_Phdr, phdr);1485 mem.byteSwapAllFields(elf.Elf32.Phdr, phdr);
1487 }1486 }
1488 }1487 }
1489 try self.pwriteAll(@ptrCast(buf), phdr_table.p_offset);1488 try self.pwriteAll(@ptrCast(buf), phdr_table.offset);
1490 },1489 },
1491 .p64 => {1490 .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);
1493 defer gpa.free(buf);1492 defer gpa.free(buf);
14941493
1495 for (buf, 0..) |*phdr, i| {1494 for (buf, 0..) |*phdr, i| {
1496 phdr.* = self.phdrs.items[i];1495 phdr.* = self.phdrs.items[i];
1497 if (foreign_endian) {1496 if (foreign_endian) {
1498 mem.byteSwapAllFields(elf.Elf64_Phdr, phdr);1497 mem.byteSwapAllFields(elf.Elf64.Phdr, phdr);
1499 }1498 }
1500 }1499 }
1501 try self.pwriteAll(@ptrCast(buf), phdr_table.p_offset);1500 try self.pwriteAll(@ptrCast(buf), phdr_table.offset);
1502 },1501 },
1503 }1502 }
1504}1503}
...@@ -1581,7 +1580,7 @@ pub fn writeElfHeader(self: *Elf) !void {...@@ -1581,7 +1580,7 @@ pub fn writeElfHeader(self: *Elf) !void {
1581 const entry_sym = obj.entrySymbol(self) orelse break :blk 0;1580 const entry_sym = obj.entrySymbol(self) orelse break :blk 0;
1582 break :blk @intCast(entry_sym.address(.{}, self));1581 break :blk @intCast(entry_sym.address(.{}, self));
1583 } else 0;1582 } 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;
1585 switch (self.ptr_width) {1584 switch (self.ptr_width) {
1586 .p32 => {1585 .p32 => {
1587 mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(e_entry), endian);1586 mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(e_entry), endian);
...@@ -1622,8 +1621,8 @@ pub fn writeElfHeader(self: *Elf) !void {...@@ -1622,8 +1621,8 @@ pub fn writeElfHeader(self: *Elf) !void {
1622 index += 2;1621 index += 2;
16231622
1624 const e_phentsize: u16 = switch (self.ptr_width) {1623 const e_phentsize: u16 = switch (self.ptr_width) {
1625 .p32 => @sizeOf(elf.Elf32_Phdr),1624 .p32 => @sizeOf(elf.Elf32.Phdr),
1626 .p64 => @sizeOf(elf.Elf64_Phdr),1625 .p64 => @sizeOf(elf.Elf64.Phdr),
1627 };1626 };
1628 mem.writeInt(u16, hdr_buf[index..][0..2], e_phentsize, endian);1627 mem.writeInt(u16, hdr_buf[index..][0..2], e_phentsize, endian);
1629 index += 2;1628 index += 2;
...@@ -2091,26 +2090,26 @@ fn initSpecialPhdrs(self: *Elf) !void {...@@ -2091,26 +2090,26 @@ fn initSpecialPhdrs(self: *Elf) !void {
20912090
2092 if (self.section_indexes.interp != null and self.phdr_indexes.interp == .none) {2091 if (self.section_indexes.interp != null and self.phdr_indexes.interp == .none) {
2093 self.phdr_indexes.interp = (try self.addPhdr(.{2092 self.phdr_indexes.interp = (try self.addPhdr(.{
2094 .type = elf.PT_INTERP,2093 .type = @backingInt(elf.PT.INTERP),
2095 .flags = elf.PF_R,2094 .flags = elf.PF_R,
2096 .@"align" = 1,2095 .@"align" = 1,
2097 })).toOptional();2096 })).toOptional();
2098 }2097 }
2099 if (self.section_indexes.dynamic != null and self.phdr_indexes.dynamic == .none) {2098 if (self.section_indexes.dynamic != null and self.phdr_indexes.dynamic == .none) {
2100 self.phdr_indexes.dynamic = (try self.addPhdr(.{2099 self.phdr_indexes.dynamic = (try self.addPhdr(.{
2101 .type = elf.PT_DYNAMIC,2100 .type = @backingInt(elf.PT.DYNAMIC),
2102 .flags = elf.PF_R | elf.PF_W,2101 .flags = elf.PF_R | elf.PF_W,
2103 })).toOptional();2102 })).toOptional();
2104 }2103 }
2105 if (self.section_indexes.eh_frame_hdr != null and self.phdr_indexes.gnu_eh_frame == .none) {2104 if (self.section_indexes.eh_frame_hdr != null and self.phdr_indexes.gnu_eh_frame == .none) {
2106 self.phdr_indexes.gnu_eh_frame = (try self.addPhdr(.{2105 self.phdr_indexes.gnu_eh_frame = (try self.addPhdr(.{
2107 .type = elf.PT_GNU_EH_FRAME,2106 .type = @backingInt(elf.PT.GNU_EH_FRAME),
2108 .flags = elf.PF_R,2107 .flags = elf.PF_R,
2109 })).toOptional();2108 })).toOptional();
2110 }2109 }
2111 if (self.phdr_indexes.gnu_stack == .none) {2110 if (self.phdr_indexes.gnu_stack == .none) {
2112 self.phdr_indexes.gnu_stack = (try self.addPhdr(.{2111 self.phdr_indexes.gnu_stack = (try self.addPhdr(.{
2113 .type = elf.PT_GNU_STACK,2112 .type = @backingInt(elf.PT.GNU_STACK),
2114 .flags = elf.PF_W | elf.PF_R,2113 .flags = elf.PF_W | elf.PF_R,
2115 .memsz = self.base.stack_size,2114 .memsz = self.base.stack_size,
2116 .@"align" = 1,2115 .@"align" = 1,
...@@ -2122,7 +2121,7 @@ fn initSpecialPhdrs(self: *Elf) !void {...@@ -2122,7 +2121,7 @@ fn initSpecialPhdrs(self: *Elf) !void {
2122 } else false;2121 } else false;
2123 if (has_tls and self.phdr_indexes.tls == .none) {2122 if (has_tls and self.phdr_indexes.tls == .none) {
2124 self.phdr_indexes.tls = (try self.addPhdr(.{2123 self.phdr_indexes.tls = (try self.addPhdr(.{
2125 .type = elf.PT_TLS,2124 .type = @backingInt(elf.PT.TLS),
2126 .flags = elf.PF_R,2125 .flags = elf.PF_R,
2127 .@"align" = 1,2126 .@"align" = 1,
2128 })).toOptional();2127 })).toOptional();
...@@ -2173,7 +2172,7 @@ fn sortInitFini(self: *Elf) !void {...@@ -2173,7 +2172,7 @@ fn sortInitFini(self: *Elf) !void {
2173 => is_init_fini = true,2172 => is_init_fini = true,
2174 else => {2173 else => {
2175 const name = self.getShString(shdr.sh_name);2174 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;
2177 },2176 },
2178 }2177 }
2179 if (!is_init_fini and !is_ctor_dtor) continue;2178 if (!is_init_fini and !is_ctor_dtor) continue;
...@@ -2260,15 +2259,15 @@ fn setHashSections(self: *Elf) !void {...@@ -2260,15 +2259,15 @@ fn setHashSections(self: *Elf) !void {
2260 }2259 }
2261}2260}
22622261
2263fn phdrRank(phdr: elf.Elf64_Phdr) u8 {2262fn phdrRank(phdr: elf.Elf64.Phdr) u8 {
2264 return switch (phdr.p_type) {2263 return switch (phdr.type) {
2265 elf.PT_NULL => 0,2264 .NULL => 0,
2266 elf.PT_PHDR => 1,2265 .PHDR => 1,
2267 elf.PT_INTERP => 2,2266 .INTERP => 2,
2268 elf.PT_LOAD => 3,2267 .LOAD => 3,
2269 elf.PT_DYNAMIC, elf.PT_TLS => 4,2268 .DYNAMIC, .TLS => 4,
2270 elf.PT_GNU_EH_FRAME => 5,2269 .GNU_EH_FRAME => 5,
2271 elf.PT_GNU_STACK => 6,2270 .GNU_STACK => 6,
2272 else => 7,2271 else => 7,
2273 };2272 };
2274}2273}
...@@ -2282,12 +2281,12 @@ fn sortPhdrs(...@@ -2282,12 +2281,12 @@ fn sortPhdrs(
2282 const Entry = struct {2281 const Entry = struct {
2283 phndx: u16,2282 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 {
2286 const lhs_phdr = program_headers[lhs.phndx];2285 const lhs_phdr = program_headers[lhs.phndx];
2287 const rhs_phdr = program_headers[rhs.phndx];2286 const rhs_phdr = program_headers[rhs.phndx];
2288 const lhs_rank = phdrRank(lhs_phdr);2287 const lhs_rank = phdrRank(lhs_phdr);
2289 const rhs_rank = phdrRank(rhs_phdr);2288 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;
2291 return lhs_rank < rhs_rank;2290 return lhs_rank < rhs_rank;
2292 }2291 }
2293 };2292 };
...@@ -2299,7 +2298,7 @@ fn sortPhdrs(...@@ -2299,7 +2298,7 @@ fn sortPhdrs(
2299 }2298 }
23002299
2301 // The `@as` here works around a bug in the C backend.2300 // 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
2304 const backlinks = try gpa.alloc(u16, entries.len);2303 const backlinks = try gpa.alloc(u16, entries.len);
2305 defer gpa.free(backlinks);2304 defer gpa.free(backlinks);
...@@ -2655,8 +2654,8 @@ fn addLoadPhdrs(self: *Elf) error{OutOfMemory}!void {...@@ -2655,8 +2654,8 @@ fn addLoadPhdrs(self: *Elf) error{OutOfMemory}!void {
2655 if (shdr.sh_type == elf.SHT_NULL) continue;2654 if (shdr.sh_type == elf.SHT_NULL) continue;
2656 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;2655 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
2657 const flags = shdrToPhdrFlags(shdr.sh_flags);2656 const flags = shdrToPhdrFlags(shdr.sh_flags);
2658 if (self.getPhdr(.{ .flags = flags, .type = elf.PT_LOAD }) == .none) {2657 if (self.getPhdr(.{ .flags = flags, .type = @backingInt(elf.PT.LOAD) }) == .none) {
2659 _ = try self.addPhdr(.{ .flags = flags, .type = elf.PT_LOAD });2658 _ = try self.addPhdr(.{ .flags = flags, .type = @backingInt(elf.PT.LOAD) });
2660 }2659 }
2661 }2660 }
2662}2661}
...@@ -2672,11 +2671,11 @@ fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void {...@@ -2672,11 +2671,11 @@ fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void {
2672 .p64 => @sizeOf(elf.Elf64_Ehdr),2671 .p64 => @sizeOf(elf.Elf64_Ehdr),
2673 };2672 };
2674 const phsize: u64 = switch (self.ptr_width) {2673 const phsize: u64 = switch (self.ptr_width) {
2675 .p32 => @sizeOf(elf.Elf32_Phdr),2674 .p32 => @sizeOf(elf.Elf32.Phdr),
2676 .p64 => @sizeOf(elf.Elf64_Phdr),2675 .p64 => @sizeOf(elf.Elf64.Phdr),
2677 };2676 };
2678 const needed_size = self.phdrs.items.len * phsize;2677 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
2681 if (needed_size > available_space) {2680 if (needed_size > available_space) {
2682 // In this case, we have two options:2681 // In this case, we have two options:
...@@ -2689,10 +2688,10 @@ fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void {...@@ -2689,10 +2688,10 @@ fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void {
2689 err.addNote("required 0x{x}, available 0x{x}", .{ needed_size, available_space });2688 err.addNote("required 0x{x}, available 0x{x}", .{ needed_size, available_space });
2690 }2689 }
26912690
2692 phdr_table_load.p_filesz = needed_size + ehsize;2691 phdr_table_load.filesz = needed_size + ehsize;
2693 phdr_table_load.p_memsz = needed_size + ehsize;2692 phdr_table_load.memsz = needed_size + ehsize;
2694 phdr_table.p_filesz = needed_size;2693 phdr_table.filesz = needed_size;
2695 phdr_table.p_memsz = needed_size;2694 phdr_table.memsz = needed_size;
2696}2695}
26972696
2698/// Allocates alloc sections and creates load segments for sections2697/// Allocates alloc sections and creates load segments for sections
...@@ -2758,7 +2757,7 @@ pub fn allocateAllocSections(self: *Elf) !void {...@@ -2758,7 +2757,7 @@ pub fn allocateAllocSections(self: *Elf) !void {
2758 // of any section that is contained in a cover and use it to align2757 // of any section that is contained in a cover and use it to align
2759 // the start address of the segement (and first section).2758 // the start address of the segement (and first section).
2760 const phdr_table = &self.phdrs.items[self.phdr_indexes.table_load.int().?];2759 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
2763 for (covers) |cover| {2762 for (covers) |cover| {
2764 if (cover.items.len == 0) continue;2763 if (cover.items.len == 0) continue;
...@@ -2817,14 +2816,14 @@ pub fn allocateAllocSections(self: *Elf) !void {...@@ -2817,14 +2816,14 @@ pub fn allocateAllocSections(self: *Elf) !void {
2817 }2816 }
28182817
2819 const first = slice.items(.shdr)[cover.items[0]];2818 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().?;
2821 const phdr = &self.phdrs.items[phndx.int()];2820 const phdr = &self.phdrs.items[phndx.int()];
2822 const allocated_size = self.allocatedSize(phdr.p_offset);2821 const allocated_size = self.allocatedSize(phdr.offset);
2823 if (filesz > allocated_size) {2822 if (filesz > allocated_size) {
2824 const old_offset = phdr.p_offset;2823 const old_offset = phdr.offset;
2825 phdr.p_offset = 0;2824 phdr.offset = 0;
2826 var new_offset = try self.findFreeSpace(filesz, @"align");2825 var new_offset = try self.findFreeSpace(filesz, @"align");
2827 phdr.p_offset = new_offset;2826 phdr.offset = new_offset;
28282827
2829 log.debug("moving phdr({d}) from 0x{x} to 0x{x}", .{ phndx, old_offset, new_offset });2828 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 {...@@ -2854,11 +2853,11 @@ pub fn allocateAllocSections(self: *Elf) !void {
2854 }2853 }
2855 }2854 }
28562855
2857 phdr.p_vaddr = first.sh_addr;2856 phdr.vaddr = first.sh_addr;
2858 phdr.p_paddr = first.sh_addr;2857 phdr.paddr = first.sh_addr;
2859 phdr.p_memsz = memsz;2858 phdr.memsz = memsz;
2860 phdr.p_filesz = filesz;2859 phdr.filesz = filesz;
2861 phdr.p_align = @"align";2860 phdr.@"align" = @"align";
28622861
2863 addr = mem.alignForward(u64, addr, self.page_size);2862 addr = mem.alignForward(u64, addr, self.page_size);
2864 }2863 }
...@@ -2902,12 +2901,12 @@ fn allocateSpecialPhdrs(self: *Elf) void {...@@ -2902,12 +2901,12 @@ fn allocateSpecialPhdrs(self: *Elf) void {
2902 if (pair[0].int()) |index| {2901 if (pair[0].int()) |index| {
2903 const shdr = slice.items(.shdr)[pair[1].?];2902 const shdr = slice.items(.shdr)[pair[1].?];
2904 const phdr = &self.phdrs.items[index];2903 const phdr = &self.phdrs.items[index];
2905 phdr.p_align = shdr.sh_addralign;2904 phdr.@"align" = shdr.sh_addralign;
2906 phdr.p_offset = shdr.sh_offset;2905 phdr.offset = shdr.sh_offset;
2907 phdr.p_vaddr = shdr.sh_addr;2906 phdr.vaddr = shdr.sh_addr;
2908 phdr.p_paddr = shdr.sh_addr;2907 phdr.paddr = shdr.sh_addr;
2909 phdr.p_filesz = shdr.sh_size;2908 phdr.filesz = shdr.sh_size;
2910 phdr.p_memsz = shdr.sh_size;2909 phdr.memsz = shdr.sh_size;
2911 }2910 }
2912 }2911 }
29132912
...@@ -2924,25 +2923,25 @@ fn allocateSpecialPhdrs(self: *Elf) void {...@@ -2924,25 +2923,25 @@ fn allocateSpecialPhdrs(self: *Elf) void {
2924 shndx += 1;2923 shndx += 1;
2925 continue;2924 continue;
2926 }2925 }
2927 phdr.p_offset = shdr.sh_offset;2926 phdr.offset = shdr.sh_offset;
2928 phdr.p_vaddr = shdr.sh_addr;2927 phdr.vaddr = shdr.sh_addr;
2929 phdr.p_paddr = shdr.sh_addr;2928 phdr.paddr = shdr.sh_addr;
2930 phdr.p_align = shdr.sh_addralign;2929 phdr.@"align" = shdr.sh_addralign;
2931 shndx += 1;2930 shndx += 1;
2932 phdr.p_align = @max(phdr.p_align, shdr.sh_addralign);2931 phdr.@"align" = @max(phdr.@"align", shdr.sh_addralign);
2933 if (shdr.sh_type != elf.SHT_NOBITS) {2932 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;
2935 }2934 }
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
2938 while (shndx < shdrs.len) : (shndx += 1) {2937 while (shndx < shdrs.len) : (shndx += 1) {
2939 const next = shdrs[shndx];2938 const next = shdrs[shndx];
2940 if (next.sh_flags & elf.SHF_TLS == 0) break;2939 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);
2942 if (next.sh_type != elf.SHT_NOBITS) {2941 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;
2944 }2943 }
2945 phdr.p_memsz = next.sh_addr + next.sh_size - phdr.p_vaddr;2944 phdr.memsz = next.sh_addr + next.sh_size - phdr.vaddr;
2946 }2945 }
2947 }2946 }
2948 }2947 }
...@@ -3347,16 +3346,16 @@ pub fn archPtrWidthBytes(self: Elf) u8 {...@@ -3347,16 +3346,16 @@ pub fn archPtrWidthBytes(self: Elf) u8 {
3347 return @intCast(@divExact(self.getTarget().ptrBitWidth(), 8));3346 return @intCast(@divExact(self.getTarget().ptrBitWidth(), 8));
3348}3347}
33493348
3350fn phdrTo32(phdr: elf.Elf64_Phdr) elf.Elf32_Phdr {3349fn phdrTo32(phdr: elf.Elf64.Phdr) elf.Elf32.Phdr {
3351 return .{3350 return .{
3352 .p_type = phdr.p_type,3351 .type = phdr.type,
3353 .p_flags = phdr.p_flags,3352 .flags = phdr.flags,
3354 .p_offset = @as(u32, @intCast(phdr.p_offset)),3353 .offset = @intCast(phdr.offset),
3355 .p_vaddr = @as(u32, @intCast(phdr.p_vaddr)),3354 .vaddr = @intCast(phdr.vaddr),
3356 .p_paddr = @as(u32, @intCast(phdr.p_paddr)),3355 .paddr = @intCast(phdr.paddr),
3357 .p_filesz = @as(u32, @intCast(phdr.p_filesz)),3356 .filesz = @intCast(phdr.filesz),
3358 .p_memsz = @as(u32, @intCast(phdr.p_memsz)),3357 .memsz = @intCast(phdr.memsz),
3359 .p_align = @as(u32, @intCast(phdr.p_align)),3358 .@"align" = @intCast(phdr.@"align"),
3360 };3359 };
3361}3360}
33623361
...@@ -3397,7 +3396,7 @@ fn getPhdr(self: *Elf, opts: struct {...@@ -3397,7 +3396,7 @@ fn getPhdr(self: *Elf, opts: struct {
3397 if (self.phdr_indexes.table_load.int()) |index| {3396 if (self.phdr_indexes.table_load.int()) |index| {
3398 if (phndx == index) continue;3397 if (phndx == index) continue;
3399 }3398 }
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)
3401 return @fromBackingInt(@intCast(phndx));3400 return @fromBackingInt(@intCast(phndx));
3402 }3401 }
3403 return .none;3402 return .none;
...@@ -3415,14 +3414,14 @@ fn addPhdr(self: *Elf, opts: struct {...@@ -3415,14 +3414,14 @@ fn addPhdr(self: *Elf, opts: struct {
3415 const gpa = self.base.comp.gpa;3414 const gpa = self.base.comp.gpa;
3416 const index: ProgramHeaderIndex = @fromBackingInt(@intCast(self.phdrs.items.len));3415 const index: ProgramHeaderIndex = @fromBackingInt(@intCast(self.phdrs.items.len));
3417 try self.phdrs.append(gpa, .{3416 try self.phdrs.append(gpa, .{
3418 .p_type = opts.type,3417 .type = @fromBackingInt(opts.type),
3419 .p_flags = opts.flags,3418 .flags = @fromBackingInt(opts.flags),
3420 .p_offset = opts.offset,3419 .offset = opts.offset,
3421 .p_vaddr = opts.addr,3420 .vaddr = opts.addr,
3422 .p_paddr = opts.addr,3421 .paddr = opts.addr,
3423 .p_filesz = opts.filesz,3422 .filesz = opts.filesz,
3424 .p_memsz = opts.memsz,3423 .memsz = opts.memsz,
3425 .p_align = opts.@"align",3424 .@"align" = opts.@"align",
3426 });3425 });
3427 return index;3426 return index;
3428}3427}
...@@ -3673,9 +3672,9 @@ pub fn tpAddress(self: *Elf) i64 {...@@ -3673,9 +3672,9 @@ pub fn tpAddress(self: *Elf) i64 {
3673 const index = self.phdr_indexes.tls.int() orelse return 0;3672 const index = self.phdr_indexes.tls.int() orelse return 0;
3674 const phdr = self.phdrs.items[index];3673 const phdr = self.phdrs.items[index];
3675 const addr = switch (self.getTarget().cpu.arch) {3674 const addr = switch (self.getTarget().cpu.arch) {
3676 .x86_64 => mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, phdr.p_align),3675 .x86_64 => mem.alignForward(u64, phdr.vaddr + phdr.memsz, phdr.@"align"),
3677 .aarch64, .aarch64_be => mem.alignBackward(u64, phdr.p_vaddr - 16, phdr.p_align),3676 .aarch64, .aarch64_be => mem.alignBackward(u64, phdr.vaddr - 16, phdr.@"align"),
3678 .riscv64, .riscv64be => phdr.p_vaddr,3677 .riscv64, .riscv64be => phdr.vaddr,
3679 else => |arch| std.debug.panic("TODO implement getTpAddress for {s}", .{@tagName(arch)}),3678 else => |arch| std.debug.panic("TODO implement getTpAddress for {s}", .{@tagName(arch)}),
3680 };3679 };
3681 return @intCast(addr);3680 return @intCast(addr);
...@@ -3684,13 +3683,13 @@ pub fn tpAddress(self: *Elf) i64 {...@@ -3684,13 +3683,13 @@ pub fn tpAddress(self: *Elf) i64 {
3684pub fn dtpAddress(self: *Elf) i64 {3683pub fn dtpAddress(self: *Elf) i64 {
3685 const index = self.phdr_indexes.tls.int() orelse return 0;3684 const index = self.phdr_indexes.tls.int() orelse return 0;
3686 const phdr = self.phdrs.items[index];3685 const phdr = self.phdrs.items[index];
3687 return @intCast(phdr.p_vaddr);3686 return @intCast(phdr.vaddr);
3688}3687}
36893688
3690pub fn tlsAddress(self: *Elf) i64 {3689pub fn tlsAddress(self: *Elf) i64 {
3691 const index = self.phdr_indexes.tls.int() orelse return 0;3690 const index = self.phdr_indexes.tls.int() orelse return 0;
3692 const phdr = self.phdrs.items[index];3691 const phdr = self.phdrs.items[index];
3693 return @intCast(phdr.p_vaddr);3692 return @intCast(phdr.vaddr);
3694}3693}
36953694
3696pub fn getShString(self: Elf, off: u32) [:0]const u8 {3695pub fn getShString(self: Elf, off: u32) [:0]const u8 {
...@@ -3702,7 +3701,7 @@ fn shString(...@@ -3702,7 +3701,7 @@ fn shString(
3702 off: u32,3701 off: u32,
3703) [:0]const u8 {3702) [:0]const u8 {
3704 const slice = shstrtab[off..];3703 const slice = shstrtab[off..];
3705 return slice[0..mem.indexOfScalar(u8, slice, 0).? :0];3704 return slice[0..mem.findScalar(u8, slice, 0).? :0];
3706}3705}
37073706
3708pub fn insertShString(self: *Elf, name: [:0]const u8) error{OutOfMemory}!u32 {3707pub 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...@@ -3886,10 +3885,10 @@ fn formatShdrFlags(sh_flags: u64, writer: *std.Io.Writer) std.Io.Writer.Error!vo
38863885
3887const FormatPhdr = struct {3886const FormatPhdr = struct {
3888 elf_file: *Elf,3887 elf_file: *Elf,
3889 phdr: elf.Elf64_Phdr,3888 phdr: elf.Elf64.Phdr,
3890};3889};
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) {
3893 return .{ .data = .{3892 return .{ .data = .{
3894 .phdr = phdr,3893 .phdr = phdr,
3895 .elf_file = self,3894 .elf_file = self,
...@@ -3898,28 +3897,28 @@ fn fmtPhdr(self: *Elf, phdr: elf.Elf64_Phdr) std.fmt.Alt(FormatPhdr, formatPhdr)...@@ -3898,28 +3897,28 @@ fn fmtPhdr(self: *Elf, phdr: elf.Elf64_Phdr) std.fmt.Alt(FormatPhdr, formatPhdr)
38983897
3899fn formatPhdr(ctx: FormatPhdr, writer: *std.Io.Writer) std.Io.Writer.Error!void {3898fn formatPhdr(ctx: FormatPhdr, writer: *std.Io.Writer) std.Io.Writer.Error!void {
3900 const phdr = ctx.phdr;3899 const phdr = ctx.phdr;
3901 const write = phdr.p_flags & elf.PF_W != 0;3900 const write = phdr.flags.W;
3902 const read = phdr.p_flags & elf.PF_R != 0;3901 const read = phdr.flags.R;
3903 const exec = phdr.p_flags & elf.PF_X != 0;3902 const exec = phdr.flags.X;
3904 var flags: [3]u8 = @splat('_');3903 var flags: [3]u8 = @splat('_');
3905 if (exec) flags[0] = 'X';3904 if (exec) flags[0] = 'X';
3906 if (write) flags[1] = 'W';3905 if (write) flags[1] = 'W';
3907 if (read) flags[2] = 'R';3906 if (read) flags[2] = 'R';
3908 const p_type = switch (phdr.p_type) {3907 const p_type = switch (phdr.type) {
3909 elf.PT_LOAD => "LOAD",3908 .LOAD => "LOAD",
3910 elf.PT_TLS => "TLS",3909 .TLS => "TLS",
3911 elf.PT_GNU_EH_FRAME => "GNU_EH_FRAME",3910 .GNU_EH_FRAME => "GNU_EH_FRAME",
3912 elf.PT_GNU_STACK => "GNU_STACK",3911 .GNU_STACK => "GNU_STACK",
3913 elf.PT_DYNAMIC => "DYNAMIC",3912 .DYNAMIC => "DYNAMIC",
3914 elf.PT_INTERP => "INTERP",3913 .INTERP => "INTERP",
3915 elf.PT_NULL => "NULL",3914 .NULL => "NULL",
3916 elf.PT_PHDR => "PHDR",3915 .PHDR => "PHDR",
3917 elf.PT_NOTE => "NOTE",3916 .NOTE => "NOTE",
3918 else => "UNKNOWN",3917 else => "UNKNOWN",
3919 };3918 };
3920 try writer.print("{s} : {s} : @{x} ({x}) : align({x}) : filesz({x}) : memsz({x})", .{3919 try writer.print("{s} : {s} : @{x} ({x}) : align({x}) : filesz({x}) : memsz({x})", .{
3921 p_type, flags, phdr.p_offset, phdr.p_vaddr,3920 p_type, flags, phdr.offset, phdr.vaddr,
3922 phdr.p_align, phdr.p_filesz, phdr.p_memsz,3921 phdr.@"align", phdr.filesz, phdr.memsz,
3923 });3922 });
3924}3923}
39253924
...@@ -4376,7 +4375,7 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {...@@ -4376,7 +4375,7 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {
43764375
4377pub fn stringTableLookup(strtab: []const u8, off: u32) [:0]const u8 {4376pub fn stringTableLookup(strtab: []const u8, off: u32) [:0]const u8 {
4378 const slice = strtab[off..];4377 const slice = strtab[off..];
4379 return slice[0..mem.indexOfScalar(u8, slice, 0).? :0];4378 return slice[0..mem.findScalar(u8, slice, 0).? :0];
4380}4379}
43814380
4382pub fn pwriteAll(elf_file: *Elf, bytes: []const u8, offset: u64) error{AlreadyReported}!void {4381pub 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(...@@ -118,7 +118,7 @@ pub fn parse(
118118
119pub fn stringTableLookup(strtab: []const u8, off: u32) [:'\n']const u8 {119pub fn stringTableLookup(strtab: []const u8, off: u32) [:'\n']const u8 {
120 const slice = strtab[off..];120 const slice = strtab[off..];
121 return slice[0..mem.indexOfScalar(u8, slice, '\n').? :'\n'];121 return slice[0..mem.findScalar(u8, slice, '\n').? :'\n'];
122}122}
123123
124pub fn setArHdr(opts: struct {124pub fn setArHdr(opts: struct {
src/link/Elf/ZigObject.zig+4-4
...@@ -1299,7 +1299,7 @@ fn getNavShdrIndex(...@@ -1299,7 +1299,7 @@ fn getNavShdrIndex(
1299 }1299 }
1300 if (nav_val.isUndef(zcu))1300 if (nav_val.isUndef(zcu))
1301 return switch (zcu.navFileScope(nav_index).mod.?.optimize_mode) {1301 return switch (zcu.navFileScope(nav_index).mod.?.optimize_mode) {
1302 .Debug, .ReleaseSafe => {1302 .debug, .safe => {
1303 if (self.data_index) |symbol_index|1303 if (self.data_index) |symbol_index|
1304 return self.symbol(symbol_index).outputShndx(elf_file).?;1304 return self.symbol(symbol_index).outputShndx(elf_file).?;
1305 const osec = try elf_file.addSection(.{1305 const osec = try elf_file.addSection(.{
...@@ -1311,7 +1311,7 @@ fn getNavShdrIndex(...@@ -1311,7 +1311,7 @@ fn getNavShdrIndex(
1311 self.data_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".data"), osec);1311 self.data_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".data"), osec);
1312 return osec;1312 return osec;
1313 },1313 },
1314 .ReleaseFast, .ReleaseSmall => {1314 .fast, .small => {
1315 if (self.bss_index) |symbol_index|1315 if (self.bss_index) |symbol_index|
1316 return self.symbol(symbol_index).outputShndx(elf_file).?;1316 return self.symbol(symbol_index).outputShndx(elf_file).?;
1317 const osec = try elf_file.addSection(.{1317 const osec = try elf_file.addSection(.{
...@@ -1374,8 +1374,8 @@ fn updateNavCode(...@@ -1374,8 +1374,8 @@ fn updateNavCode(
1374 const target = &mod.resolved_target.result;1374 const target = &mod.resolved_target.result;
1375 const required_alignment = switch (nav.resolved.?.@"align") {1375 const required_alignment = switch (nav.resolved.?.@"align") {
1376 .none => switch (mod.optimize_mode) {1376 .none => switch (mod.optimize_mode) {
1377 .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),1377 .debug, .safe, .fast => target_util.defaultFunctionAlignment(target),
1378 .ReleaseSmall => target_util.minFunctionAlignment(target),1378 .small => target_util.minFunctionAlignment(target),
1379 }.maxStrict(Type.fromInterned(nav.resolved.?.type).abiAlignment(zcu)),1379 }.maxStrict(Type.fromInterned(nav.resolved.?.type).abiAlignment(zcu)),
1380 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),1380 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
1381 };1381 };
src/link/Elf2.zig+464-218
...@@ -126,8 +126,14 @@ needed: std.array_hash_map.Auto(String(.dynstr), void),...@@ -126,8 +126,14 @@ needed: std.array_hash_map.Auto(String(.dynstr), void),
126inputs: std.ArrayList(struct {126inputs: std.ArrayList(struct {
127 path: std.Build.Cache.Path,127 path: std.Build.Cache.Path,
128 member: ?[]const u8,128 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 },
130}),135}),
136input_pending_index: u32,
131input_sections: std.ArrayList(InputSection),137input_sections: std.ArrayList(InputSection),
132input_section_pending_index: u32,138input_section_pending_index: u32,
133navs: std.array_hash_map.Auto(InternPool.Nav.Index, struct {139navs: std.array_hash_map.Auto(InternPool.Nav.Index, struct {
...@@ -181,7 +187,10 @@ input_prog_node: std.Progress.Node,...@@ -181,7 +187,10 @@ input_prog_node: std.Progress.Node,
181const Error = link.Error || error{MappedFileIo};187const Error = link.Error || error{MappedFileIo};
182188
183const Node = union(enum) {189const Node = union(enum) {
184 file,190 archive,
191 /// This includes the archive magic and long file member.
192 archive_header,
193 elf,
185 ehdr,194 ehdr,
186 shdr,195 shdr,
187 segment: u32,196 segment: u32,
...@@ -189,6 +198,8 @@ const Node = union(enum) {...@@ -189,6 +198,8 @@ const Node = union(enum) {
189 ///198 ///
190 /// The section '.dynamic' may contain relocations via `elf.dynamic_first_symbol_reloc`.199 /// The section '.dynamic' may contain relocations via `elf.dynamic_first_symbol_reloc`.
191 section: Section.Index,200 section: Section.Index,
201 /// Only valid for static libraries, represents one non-zcu archive member.
202 input_member: InputIndex,
192 /// May contain relocations.203 /// May contain relocations.
193 input_section: InputSection.Index,204 input_section: InputSection.Index,
194 /// Value is the name of a global which has an entry in `elf.copied_globals`, so, a global for205 /// 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) {...@@ -219,19 +230,23 @@ const Node = union(enum) {
219 return elf.inputs.items[@backingInt(ii)].member;230 return elf.inputs.items[@backingInt(ii)].member;
220 }231 }
221232
233 pub fn node(ii: InputIndex, elf: *const Elf) MappedFile.Node.Index {
234 return elf.inputs.items[@backingInt(ii)].extra.node;
235 }
236
222 pub fn fileSymbol(ii: InputIndex, elf: *const Elf) Symbol.LocalIndex {237 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;
224 }239 }
225240
226 pub fn localSymbolRange(ii: InputIndex, elf: *Elf) [2]Symbol.LocalIndex {241 pub fn localSymbolRange(ii: InputIndex, elf: *Elf) [2]Symbol.LocalIndex {
227 if (@backingInt(ii) + 1 < elf.inputs.items.len) {242 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);
229 return .{ ii.fileSymbol(elf), next_ii.fileSymbol(elf) };244 return .{ ii.fileSymbol(elf), next_ii.fileSymbol(elf) };
230 } else {245 } else {
231 const local_symbols_len = switch (elf.shdrPtr(.symtab)) {246 const local_symbols_len = switch (elf.shdrPtr(.symtab)) {
232 inline else => |shdr| elf.targetLoad(&shdr.info),247 inline else => |shdr| elf.targetLoad(&shdr.info),
233 };248 };
234 return .{ ii.fileSymbol(elf), @fromBackingInt(@intCast(local_symbols_len)) };249 return .{ ii.fileSymbol(elf), @fromBackingInt(local_symbols_len) };
235 }250 }
236 }251 }
237 };252 };
...@@ -315,15 +330,16 @@ const Node = union(enum) {...@@ -315,15 +330,16 @@ const Node = union(enum) {
315 };330 };
316331
317 pub const Known = struct {332 pub const Known = struct {
318 comptime file: MappedFile.Node.Index = .root,333 archive: MappedFile.Node.Index,
319 comptime ehdr: MappedFile.Node.Index = @fromBackingInt(@intCast(1)),334 archive_header: MappedFile.Node.Index,
320 comptime shdr: MappedFile.Node.Index = @fromBackingInt(@intCast(2)),335 elf: MappedFile.Node.Index,
321 comptime rodata: MappedFile.Node.Index = @fromBackingInt(@intCast(3)),336 ehdr: MappedFile.Node.Index,
322 comptime phdr: MappedFile.Node.Index = @fromBackingInt(@intCast(4)),337 shdr: MappedFile.Node.Index,
323 comptime text: MappedFile.Node.Index = @fromBackingInt(@intCast(5)),338 rodata: MappedFile.Node.Index,
324 comptime data: MappedFile.Node.Index = @fromBackingInt(@intCast(6)),339 phdr: MappedFile.Node.Index,
325 comptime data_rel_ro: MappedFile.Node.Index = @fromBackingInt(@intCast(7)),340 text: MappedFile.Node.Index,
326341 data: MappedFile.Node.Index,
342 data_rel_ro: MappedFile.Node.Index,
327 tls: MappedFile.Node.Index,343 tls: MappedFile.Node.Index,
328 };344 };
329345
...@@ -333,11 +349,11 @@ const Node = union(enum) {...@@ -333,11 +349,11 @@ const Node = union(enum) {
333349
334 /// In this linker implementation, `link.File.AtomId` is a type-erased `MappedFile.Node.Index`.350 /// In this linker implementation, `link.File.AtomId` is a type-erased `MappedFile.Node.Index`.
335 fn toAtom(ni: MappedFile.Node.Index) link.File.AtomId {351 fn toAtom(ni: MappedFile.Node.Index) link.File.AtomId {
336 return @fromBackingInt(@intCast(@backingInt(ni)));352 return @fromBackingInt(@backingInt(ni));
337 }353 }
338 /// In this linker implementation, `link.File.AtomId` is a type-erased `MappedFile.Node.Index`.354 /// In this linker implementation, `link.File.AtomId` is a type-erased `MappedFile.Node.Index`.
339 fn fromAtom(atom: link.File.AtomId) MappedFile.Node.Index {355 fn fromAtom(atom: link.File.AtomId) MappedFile.Node.Index {
340 return @fromBackingInt(@intCast(@backingInt(atom)));356 return @fromBackingInt(@backingInt(atom));
341 }357 }
342};358};
343359
...@@ -424,13 +440,13 @@ const Section = struct {...@@ -424,13 +440,13 @@ const Section = struct {
424 fn unwrap(opt: RelaIndex.Optional) ?RelaIndex {440 fn unwrap(opt: RelaIndex.Optional) ?RelaIndex {
425 return switch (opt) {441 return switch (opt) {
426 .none => null,442 .none => null,
427 _ => @fromBackingInt(@intCast(@backingInt(opt))),443 _ => @fromBackingInt(@backingInt(opt)),
428 };444 };
429 }445 }
430 };446 };
431447
432 fn toOptional(i: RelaIndex) RelaIndex.Optional {448 fn toOptional(i: RelaIndex) RelaIndex.Optional {
433 return @fromBackingInt(@intCast(@backingInt(i)));449 return @fromBackingInt(@backingInt(i));
434 }450 }
435 };451 };
436452
...@@ -465,8 +481,8 @@ const Section = struct {...@@ -465,8 +481,8 @@ const Section = struct {
465481
466 pub fn fromSection(sec: std.elf.Section) Index {482 pub fn fromSection(sec: std.elf.Section) Index {
467 return switch (sec) {483 return switch (sec) {
468 std.elf.SHN_UNDEF...std.elf.SHN_LORESERVE - 1 => @fromBackingInt(@intCast(sec)),484 std.elf.SHN_UNDEF...std.elf.SHN_LORESERVE - 1 => @fromBackingInt(sec),
469 std.elf.SHN_LORESERVE...std.elf.SHN_HIRESERVE => @fromBackingInt(@intCast(reserve(sec))),485 std.elf.SHN_LORESERVE...std.elf.SHN_HIRESERVE => @fromBackingInt(reserve(sec)),
470 };486 };
471 }487 }
472 pub fn toSection(s: Index) ?std.elf.Section {488 pub fn toSection(s: Index) ?std.elf.Section {
...@@ -485,7 +501,7 @@ const Section = struct {...@@ -485,7 +501,7 @@ const Section = struct {
485501
486 fn name(s: Index, elf: *Elf) String(.shstrtab) {502 fn name(s: Index, elf: *Elf) String(.shstrtab) {
487 return switch (elf.shdrPtr(s)) {503 return switch (elf.shdrPtr(s)) {
488 inline else => |shdr| @fromBackingInt(@intCast(elf.targetLoad(&shdr.name))),504 inline else => |shdr| @fromBackingInt(elf.targetLoad(&shdr.name)),
489 };505 };
490 }506 }
491507
...@@ -928,21 +944,7 @@ const GotReloc = struct {...@@ -928,21 +944,7 @@ const GotReloc = struct {
928 }944 }
929 }945 }
930 fn applyInner(reloc: *const GotReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void {946 fn applyInner(reloc: *const GotReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void {
931 const node_vaddr: u64 = switch (elf.getNode(reloc.node)) {947 const dest_vaddr = elf.getNodeVAddr(reloc.node) + reloc.offset;
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;
946 const dest_slice = reloc.node.slice(&elf.mf)[@intCast(reloc.offset)..];948 const dest_slice = reloc.node.slice(&elf.mf)[@intCast(reloc.offset)..];
947949
948 const got_vaddr = elf.shndx.got.vaddr(elf);950 const got_vaddr = elf.shndx.got.vaddr(elf);
...@@ -1131,12 +1133,12 @@ pub const MachineRelocType = union {...@@ -1131,12 +1133,12 @@ pub const MachineRelocType = union {
11311133
1132 pub fn wrap(int: u32, elf: *const Elf) MachineRelocType {1134 pub fn wrap(int: u32, elf: *const Elf) MachineRelocType {
1133 return switch (elf.ehdrMachine()) {1135 return switch (elf.ehdrMachine()) {
1134 .AARCH64 => .{ .AARCH64 = @fromBackingInt(@intCast(int)) },1136 .AARCH64 => .{ .AARCH64 = @fromBackingInt(int) },
1135 .LOONGARCH => .{ .LARCH = @fromBackingInt(@intCast(int)) },1137 .LOONGARCH => .{ .LARCH = @fromBackingInt(int) },
1136 .PPC64 => .{ .PPC64 = @fromBackingInt(@intCast(int)) },1138 .PPC64 => .{ .PPC64 = @fromBackingInt(int) },
1137 .RISCV => .{ .RISCV = @fromBackingInt(@intCast(int)) },1139 .RISCV => .{ .RISCV = @fromBackingInt(int) },
1138 .SPARCV9 => .{ .SPARC = @fromBackingInt(@intCast(int)) },1140 .SPARCV9 => .{ .SPARC = @fromBackingInt(int) },
1139 .X86_64 => .{ .X86_64 = @fromBackingInt(@intCast(int)) },1141 .X86_64 => .{ .X86_64 = @fromBackingInt(int) },
1140 };1142 };
1141 }1143 }
1142 pub fn unwrap(rt: MachineRelocType, elf: *const Elf) u32 {1144 pub fn unwrap(rt: MachineRelocType, elf: *const Elf) u32 {
...@@ -1646,21 +1648,7 @@ const SymbolReloc = struct {...@@ -1646,21 +1648,7 @@ const SymbolReloc = struct {
1646 }1648 }
1647 }1649 }
1648 fn applyInner(reloc: *const SymbolReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void {1650 fn applyInner(reloc: *const SymbolReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void {
1649 const node_vaddr: u64 = switch (elf.getNode(reloc.node)) {1651 const dest_vaddr = elf.getNodeVAddr(reloc.node) + reloc.offset;
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;
1664 const dest_slice = reloc.node.slice(&elf.mf)[@intCast(reloc.offset)..];1652 const dest_slice = reloc.node.slice(&elf.mf)[@intCast(reloc.offset)..];
16651653
1666 const addend: u64 = @bitCast(reloc.addend);1654 const addend: u64 = @bitCast(reloc.addend);
...@@ -1875,7 +1863,7 @@ fn addLocalSymbolAssumeCapacity(elf: *Elf, opts: AddLocalSymbolOptions) Symbol.L...@@ -1875,7 +1863,7 @@ fn addLocalSymbolAssumeCapacity(elf: *Elf, opts: AddLocalSymbolOptions) Symbol.L
18751863
1876 // `shdr.info` stores the index of the first global symbol. We will replace it with our1864 // `shdr.info` stores the index of the first global symbol. We will replace it with our
1877 // new local symbol, and move the global symbol to a new index at the end of the symtab.1865 // 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
1880 const old_size = elf.targetLoad(&shdr.size);1868 const old_size = elf.targetLoad(&shdr.size);
1881 const new_size = old_size + ent_size;1869 const new_size = old_size + ent_size;
...@@ -1897,7 +1885,7 @@ fn addLocalSymbolAssumeCapacity(elf: *Elf, opts: AddLocalSymbolOptions) Symbol.L...@@ -1897,7 +1885,7 @@ fn addLocalSymbolAssumeCapacity(elf: *Elf, opts: AddLocalSymbolOptions) Symbol.L
1897 // ...then the `elf.symtab` metadata...1885 // ...then the `elf.symtab` metadata...
1898 new_index.ptr(elf).* = target_index.ptr(elf).*;1886 new_index.ptr(elf).* = target_index.ptr(elf).*;
1899 // ...then update the `elf.globals` tracking.1887 // ...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));
1901 elf.globalByName(global_name).?.symtab_index = new_index;1889 elf.globalByName(global_name).?.symtab_index = new_index;
19021890
1903 if (elf.ehdrType() == .REL and target_index.ptr(elf).first_target_reloc != .none) {1891 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...@@ -1923,7 +1911,7 @@ fn addLocalSymbolAssumeCapacity(elf: *Elf, opts: AddLocalSymbolOptions) Symbol.L
1923 std.mem.byteSwapAllFields(class.ElfN().Sym, target_sym);1911 std.mem.byteSwapAllFields(class.ElfN().Sym, target_sym);
1924 }1912 }
19251913
1926 return @fromBackingInt(@intCast(@backingInt(target_index)));1914 return @fromBackingInt(@backingInt(target_index));
1927 },1915 },
1928 }1916 }
1929}1917}
...@@ -2371,7 +2359,7 @@ fn moveDemotedGlobal(elf: *Elf, global_ptr: *Symbol.Global) void {...@@ -2371,7 +2359,7 @@ fn moveDemotedGlobal(elf: *Elf, global_ptr: *Symbol.Global) void {
2371 inline else => |shdr, class| {2359 inline else => |shdr, class| {
2372 // `shdr.info` stores the index of the first global symbol. We are going to swap the2360 // `shdr.info` stores the index of the first global symbol. We are going to swap the
2373 // demoted symbol with that first global symbol, then increment that start index.2361 // 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));
2375 const src_index = global_ptr.symtab_index;2363 const src_index = global_ptr.symtab_index;
23762364
2377 // This global should currently be in the "global symbols" part of the symtab, since our2365 // 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 {...@@ -2387,10 +2375,10 @@ fn moveDemotedGlobal(elf: *Elf, global_ptr: *Symbol.Global) void {
2387 const src_sym_ptr = @field(elf.symPtr(src_index), @tagName(class));2375 const src_sym_ptr = @field(elf.symPtr(src_index), @tagName(class));
2388 const dest_sym_ptr = @field(elf.symPtr(dest_index), @tagName(class));2376 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));
2391 assert(elf.globalByName(this_name).? == global_ptr);2379 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));
2394 const other_global_ptr = elf.globalByName(other_name).?;2382 const other_global_ptr = elf.globalByName(other_name).?;
2395 assert(other_global_ptr.symtab_index == dest_index);2383 assert(other_global_ptr.symtab_index == dest_index);
23962384
...@@ -2426,7 +2414,7 @@ fn moveDemotedGlobal(elf: *Elf, global_ptr: *Symbol.Global) void {...@@ -2426,7 +2414,7 @@ fn moveDemotedGlobal(elf: *Elf, global_ptr: *Symbol.Global) void {
2426 const src_dynsym_ptr = @field(elf.dynsymPtr(remove_dynsym_index), @tagName(class));2414 const src_dynsym_ptr = @field(elf.dynsymPtr(remove_dynsym_index), @tagName(class));
2427 const dest_dynsym_ptr = @field(elf.dynsymPtr(free_dynsym_index), @tagName(class));2415 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));
2430 const moved_name = elf.stringExisting(.strtab, moved_name_dynstr.slice(elf));2418 const moved_name = elf.stringExisting(.strtab, moved_name_dynstr.slice(elf));
2431 const moved_global_ptr = elf.globalByName(moved_name).?;2419 const moved_global_ptr = elf.globalByName(moved_name).?;
24322420
...@@ -2505,7 +2493,7 @@ const Symbol = struct {...@@ -2505,7 +2493,7 @@ const Symbol = struct {
2505 _,2493 _,
25062494
2507 fn index(li: LocalIndex) Index {2495 fn index(li: LocalIndex) Index {
2508 return @fromBackingInt(@intCast(@backingInt(li)));2496 return @fromBackingInt(@backingInt(li));
2509 }2497 }
2510 };2498 };
25112499
...@@ -2527,16 +2515,16 @@ const Symbol = struct {...@@ -2527,16 +2515,16 @@ const Symbol = struct {
2527 global: String(.strtab),2515 global: String(.strtab),
2528 } {2516 } {
2529 return switch (s.kind) {2517 return switch (s.kind) {
2530 .local => .{ .local = @fromBackingInt(@intCast(s.raw)) },2518 .local => .{ .local = @fromBackingInt(s.raw) },
2531 .global => .{ .global = @fromBackingInt(@intCast(s.raw)) },2519 .global => .{ .global = @fromBackingInt(s.raw) },
2532 };2520 };
2533 }2521 }
25342522
2535 fn toTypeErased(s: Symbol.Id) link.File.SymbolId {2523 fn toTypeErased(s: Symbol.Id) link.File.SymbolId {
2536 return @fromBackingInt(@intCast(@as(u32, @bitCast(s))));2524 return @bitCast(s);
2537 }2525 }
2538 fn fromTypeErased(s: link.File.SymbolId) Symbol.Id {2526 fn fromTypeErased(s: link.File.SymbolId) Symbol.Id {
2539 return @bitCast(@backingInt(s));2527 return @bitCast(s);
2540 }2528 }
25412529
2542 fn index(s: Symbol.Id, elf: *const Elf) Symbol.Index {2530 fn index(s: Symbol.Id, elf: *const Elf) Symbol.Index {
...@@ -2648,24 +2636,10 @@ const Symbol = struct {...@@ -2648,24 +2636,10 @@ const Symbol = struct {
2648 .yes_textrel => elf.textrel_count += 1,2636 .yes_textrel => elf.textrel_count += 1,
2649 .yes => {},2637 .yes => {},
2650 }2638 }
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 };
2665 // There is capacity for a relocation because we just deleted one earlier.2639 // There is capacity for a relocation because we just deleted one earlier.
2666 reloc.rela_index = elf.shndx.rela_dyn.relaAddOneAssumeCapacity(elf, .{2640 reloc.rela_index = elf.shndx.rela_dyn.relaAddOneAssumeCapacity(elf, .{
2667 .type = .relative(elf),2641 .type = .relative(elf),
2668 .offset = node_vaddr + reloc.offset,2642 .offset = elf.getNodeVAddr(reloc.node) + reloc.offset,
2669 .raw_sym_index = 0,2643 .raw_sym_index = 0,
2670 .addend = 0,2644 .addend = 0,
2671 }).toOptional();2645 }).toOptional();
...@@ -2771,11 +2745,14 @@ fn classifySymbolValue(elf: *Elf, sym: Symbol.Id) enum {...@@ -2771,11 +2745,14 @@ fn classifySymbolValue(elf: *Elf, sym: Symbol.Id) enum {
27712745
2772pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId {2746pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId {
2773 const lsi: Symbol.LocalIndex = switch (elf.getNode(Node.fromAtom(atom))) {2747 const lsi: Symbol.LocalIndex = switch (elf.getNode(Node.fromAtom(atom))) {
2774 .file,2748 .archive,
2749 .archive_header,
2750 .elf,
2775 .ehdr,2751 .ehdr,
2776 .shdr,2752 .shdr,
2777 .segment,2753 .segment,
2778 .section,2754 .section,
2755 .input_member,
2779 .input_section,2756 .input_section,
2780 .copied_global,2757 .copied_global,
2781 => unreachable,2758 => unreachable,
...@@ -3001,12 +2978,12 @@ fn String(section: StringSection) type {...@@ -3001,12 +2978,12 @@ fn String(section: StringSection) type {
3001}2978}
3002fn string(elf: *Elf, comptime section: StringSection, key: []const u8) Error!String(section) {2979fn string(elf: *Elf, comptime section: StringSection, key: []const u8) Error!String(section) {
3003 const st: *StringTable = &@field(elf, @tagName(section));2980 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));
3005}2982}
3006/// Like `string`, but asserts that the string is already in `section`.2983/// Like `string`, but asserts that the string is already in `section`.
3007fn stringExisting(elf: *Elf, comptime section: StringSection, key: []const u8) String(section) {2984fn stringExisting(elf: *Elf, comptime section: StringSection, key: []const u8) String(section) {
3008 const st: *StringTable = &@field(elf, @tagName(section));2985 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));
3010}2987}
30112988
3012const StringTable = struct {2989const StringTable = struct {
...@@ -3033,7 +3010,7 @@ const StringTable = struct {...@@ -3033,7 +3010,7 @@ const StringTable = struct {
3033 }3010 }
30343011
3035 pub fn hash(_: Adapter, key: []const u8) u64 {3012 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);
3037 return std.hash_map.hashString(key);3014 return std.hash_map.hashString(key);
3038 }3015 }
3039 };3016 };
...@@ -3172,6 +3149,16 @@ fn create(...@@ -3172,6 +3149,16 @@ fn create(
3172 .options = options,3149 .options = options,
3173 .mf = try .init(file, comp.gpa, io),3150 .mf = try .init(file, comp.gpa, io),
3174 .ni = .{3151 .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,
3175 .tls = .none,3162 .tls = .none,
3176 },3163 },
3177 .nodes = .empty,3164 .nodes = .empty,
...@@ -3218,6 +3205,7 @@ fn create(...@@ -3218,6 +3205,7 @@ fn create(
3218 .dynamic_first_symbol_reloc = .none,3205 .dynamic_first_symbol_reloc = .none,
3219 .needed = .empty,3206 .needed = .empty,
3220 .inputs = .empty,3207 .inputs = .empty,
3208 .input_pending_index = 0,
3221 .input_sections = .empty,3209 .input_sections = .empty,
3222 .input_section_pending_index = 0,3210 .input_section_pending_index = 0,
3223 .navs = .empty,3211 .navs = .empty,
...@@ -3293,6 +3281,7 @@ fn initHeaders(...@@ -3293,6 +3281,7 @@ fn initHeaders(
3293 const comp = elf.base.comp;3281 const comp = elf.base.comp;
3294 const gpa = comp.gpa;3282 const gpa = comp.gpa;
32953283
3284 const is_archive = comp.config.output_mode == .Lib and comp.config.link_mode == .static;
3296 const have_dynamic_section = switch (@"type") {3285 const have_dynamic_section = switch (@"type") {
3297 .REL => false,3286 .REL => false,
3298 .EXEC => comp.config.link_mode == .dynamic,3287 .EXEC => comp.config.link_mode == .dynamic,
...@@ -3389,7 +3378,8 @@ fn initHeaders(...@@ -3389,7 +3378,8 @@ fn initHeaders(
3389 }, phnum };3378 }, phnum };
3390 };3379 };
33913380
3392 const expected_nodes_len = 3 + // `.file`, `.ehdr`, and `.shdr` nodes3381 const expected_nodes_len = @as(usize, if (is_archive) 2 else 0) + // .archive, .archive_header
3382 3 + // `.file`, `.ehdr`, and `.shdr` nodes
3393 (shnum - 1) + // -1 because the null shdr does not have a `.section` node3383 (shnum - 1) + // -1 because the null shdr does not have a `.section` node
3394 (phnum -| 1); // -1 because the GNU_STACK phdr does not have a `.segment` node3384 (phnum -| 1); // -1 because the GNU_STACK phdr does not have a `.segment` node
33953385
...@@ -3398,17 +3388,49 @@ fn initHeaders(...@@ -3398,17 +3388,49 @@ fn initHeaders(
3398 try elf.section_by_name.ensureUnusedCapacity(gpa, shnum);3388 try elf.section_by_name.ensureUnusedCapacity(gpa, shnum);
3399 try elf.phdrs.resize(gpa, phnum);3389 try elf.phdrs.resize(gpa, phnum);
3400 try elf.symtab.ensureTotalCapacity(gpa, 1);3390 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
3403 const entsize: struct { ph: u32, sh: u32 } = switch (class) {3425 const entsize: struct { ph: u32, sh: u32 } = switch (class) {
3404 .NONE, _ => unreachable,3426 .NONE, _ => unreachable,
3405 inline else => |ct_class| entsize: {3427 inline else => |ct_class| entsize: {
3406 const ElfN = ct_class.ElfN();3428 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, .{
3408 .size = @sizeOf(ElfN.Ehdr),3430 .size = @sizeOf(ElfN.Ehdr),
3409 .alignment = addr_align,3431 .alignment = addr_align,
3410 .fixed = true,3432 .fixed = true,
3411 }));3433 });
3412 elf.nodes.appendAssumeCapacity(.ehdr);3434 elf.nodes.appendAssumeCapacity(.ehdr);
34133435
3414 const ehdr: *ElfN.Ehdr = @ptrCast(@alignCast(elf.ni.ehdr.slice(&elf.mf)));3436 const ehdr: *ElfN.Ehdr = @ptrCast(@alignCast(elf.ni.ehdr.slice(&elf.mf)));
...@@ -3461,12 +3483,12 @@ fn initHeaders(...@@ -3461,12 +3483,12 @@ fn initHeaders(
3461 },3483 },
3462 };3484 };
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, .{
3465 .size = 1 * entsize.sh, // as above, only the null shdr initially3487 .size = 1 * entsize.sh, // as above, only the null shdr initially
3466 .alignment = elf.mf.flags.block_size,3488 .alignment = elf.mf.flags.block_size,
3467 .moved = true,3489 .moved = true,
3468 .resized = true,3490 .resized = true,
3469 }));3491 });
3470 elf.nodes.appendAssumeCapacity(.shdr);3492 elf.nodes.appendAssumeCapacity(.shdr);
34713493
3472 const page_align: std.mem.Alignment = .fromByteUnits(switch (machine) {3494 const page_align: std.mem.Alignment = .fromByteUnits(switch (machine) {
...@@ -3491,45 +3513,45 @@ fn initHeaders(...@@ -3491,45 +3513,45 @@ fn initHeaders(
3491 });3513 });
34923514
3493 var ph_vaddr: u32 = if (@"type" != .REL) ph_vaddr: {3515 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, .{
3495 .alignment = elf.mf.flags.block_size,3517 .alignment = elf.mf.flags.block_size,
3496 .moved = true,3518 .moved = true,
3497 .bubbles_moved = false,3519 .bubbles_moved = false,
3498 }));3520 });
3499 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.rodata });3521 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.rodata });
3500 elf.phdrs.items[phndx.rodata] = elf.ni.rodata;3522 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, .{
3503 .size = @as(u64, phnum) * entsize.ph,3525 .size = @as(u64, phnum) * entsize.ph,
3504 .alignment = addr_align,3526 .alignment = addr_align,
3505 .moved = true,3527 .moved = true,
3506 .resized = true,3528 .resized = true,
3507 .bubbles_moved = false,3529 .bubbles_moved = false,
3508 }));3530 });
3509 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.phdr });3531 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.phdr });
3510 elf.phdrs.items[phndx.phdr] = elf.ni.phdr;3532 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, .{
3513 .alignment = elf.mf.flags.block_size,3535 .alignment = elf.mf.flags.block_size,
3514 .moved = true,3536 .moved = true,
3515 .bubbles_moved = false,3537 .bubbles_moved = false,
3516 }));3538 });
3517 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.text });3539 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.text });
3518 elf.phdrs.items[phndx.text] = elf.ni.text;3540 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, .{
3521 .alignment = elf.mf.flags.block_size,3543 .alignment = elf.mf.flags.block_size,
3522 .moved = true,3544 .moved = true,
3523 .bubbles_moved = false,3545 .bubbles_moved = false,
3524 }));3546 });
3525 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.data });3547 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.data });
3526 elf.phdrs.items[phndx.data] = elf.ni.data;3548 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, .{
3529 .alignment = elf.mf.flags.block_size,3551 .alignment = elf.mf.flags.block_size,
3530 .moved = true,3552 .moved = true,
3531 .bubbles_moved = false,3553 .bubbles_moved = false,
3532 }));3554 });
3533 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.relro });3555 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.relro });
3534 elf.phdrs.items[phndx.relro] = elf.ni.data_rel_ro;3556 elf.phdrs.items[phndx.relro] = elf.ni.data_rel_ro;
35353557
...@@ -3706,7 +3728,7 @@ fn initHeaders(...@@ -3706,7 +3728,7 @@ fn initHeaders(
3706 .node = .none,3728 .node = .none,
3707 .first_target_reloc = .none,3729 .first_target_reloc = .none,
3708 };3730 };
3709 assert(.symtab == try elf.addSection(elf.ni.file, .{3731 assert(.symtab == try elf.addSection(elf.ni.elf, .{
3710 .type = .SYMTAB,3732 .type = .SYMTAB,
3711 .size = @sizeOf(ElfN.Sym) * 1,3733 .size = @sizeOf(ElfN.Sym) * 1,
3712 .addralign = addr_align,3734 .addralign = addr_align,
...@@ -3729,7 +3751,7 @@ fn initHeaders(...@@ -3729,7 +3751,7 @@ fn initHeaders(
3729 ehdr.shstrndx = ehdr.shnum;3751 ehdr.shstrndx = ehdr.shnum;
3730 },3752 },
3731 }3753 }
3732 assert(.shstrtab == try elf.addSection(elf.ni.file, .{3754 assert(.shstrtab == try elf.addSection(elf.ni.elf, .{
3733 .type = .STRTAB,3755 .type = .STRTAB,
3734 .size = 1,3756 .size = 1,
3735 .entsize = 1,3757 .entsize = 1,
...@@ -3740,7 +3762,7 @@ fn initHeaders(...@@ -3740,7 +3762,7 @@ fn initHeaders(
3740 try Section.Index.symtab.rename(elf, ".symtab");3762 try Section.Index.symtab.rename(elf, ".symtab");
3741 try Section.Index.shstrtab.rename(elf, ".shstrtab");3763 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, .{
3744 .name = ".strtab",3766 .name = ".strtab",
3745 .type = .STRTAB,3767 .type = .STRTAB,
3746 .size = 1,3768 .size = 1,
...@@ -4210,6 +4232,8 @@ fn initHeaders(...@@ -4210,6 +4232,8 @@ fn initHeaders(
4210 break :str try elf.string(.dynstr, slice);4232 break :str try elf.string(.dynstr, slice);
4211 },4233 },
4212 };4234 };
4235
4236 try elf.ensureElfNodeSize();
4213}4237}
42144238
4215pub fn startProgress(elf: *Elf, prog_node: std.Progress.Node) void {4239pub 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 {...@@ -4221,10 +4245,8 @@ pub fn startProgress(elf: *Elf, prog_node: std.Progress.Node) void {
4221 break :count count;4245 break :count count;
4222 });4246 });
4223 elf.mf.update_prog_node = prog_node.start("Relocations", elf.mf.updates.items.len);4247 elf.mf.update_prog_node = prog_node.start("Relocations", elf.mf.updates.items.len);
4224 elf.input_prog_node = prog_node.start(4248 elf.input_prog_node = prog_node.start("Inputs", (elf.inputs.items.len - elf.input_pending_index) +
4225 "Inputs",4249 (elf.input_sections.items.len - elf.input_section_pending_index));
4226 elf.input_sections.items.len - elf.input_section_pending_index,
4227 );
4228}4250}
42294251
4230pub fn endProgress(elf: *Elf) void {4252pub fn endProgress(elf: *Elf) void {
...@@ -4244,13 +4266,15 @@ fn getNode(elf: *const Elf, ni: MappedFile.Node.Index) Node {...@@ -4244,13 +4266,15 @@ fn getNode(elf: *const Elf, ni: MappedFile.Node.Index) Node {
4244/// Asserts that `ni` is a section, input section, copied global, NAV, UAV, or lazy code/data.4266/// Asserts that `ni` is a section, input section, copied global, NAV, UAV, or lazy code/data.
4245fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {4267fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {
4246 return switch (elf.getNode(ni)) {4268 return switch (elf.getNode(ni)) {
4247 .file => unreachable,4269 .archive,
4248 .ehdr => unreachable,4270 .archive_header,
4249 .shdr => unreachable,4271 .elf,
4250 .segment => unreachable,4272 .ehdr,
42514273 .shdr,
4274 .segment,
4275 .input_member,
4276 => unreachable,
4252 .section => |shndx| shndx,4277 .section => |shndx| shndx,
4253
4254 .input_section,4278 .input_section,
4255 .copied_global,4279 .copied_global,
4256 .nav,4280 .nav,
...@@ -4260,21 +4284,44 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {...@@ -4260,21 +4284,44 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {
4260 => elf.getNode(ni.parent(&elf.mf)).section,4284 => elf.getNode(ni.parent(&elf.mf)).section,
4261 };4285 };
4262}4286}
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}
4263fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {4307fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
4264 const parent_vaddr = switch (elf.getNode(ni.parent(&elf.mf))) {4308 const parent_vaddr = switch (elf.getNode(ni.parent(&elf.mf))) {
4265 .file => return 0,4309 .archive, .archive_header => unreachable,
4310 .elf => return 0,
4266 .ehdr, .shdr => unreachable,4311 .ehdr, .shdr => unreachable,
4267 .segment => |phndx| switch (elf.phdrSlice()) {4312 .segment => |phndx| switch (elf.phdrSlice()) {
4268 inline else => |phdr| elf.targetLoad(&phdr[phndx].vaddr),4313 inline else => |phdr| elf.targetLoad(&phdr[phndx].vaddr),
4269 },4314 },
4270 .section => |shndx| if (shndx == elf.shndx.tdata) 0 else shndx.vaddr(elf),4315 .section => |shndx| if (shndx == elf.shndx.tdata) 0 else shndx.vaddr(elf),
4271 .input_section => unreachable,4316 .input_member, .input_section, .copied_global => unreachable,
4272 .copied_global => unreachable,
4273 inline .nav, .uav, .lazy_code, .lazy_const_data => |i| Symbol.Id.local(i.symbol(elf)).value(elf),4317 inline .nav, .uav, .lazy_code, .lazy_const_data => |i| Symbol.Id.local(i.symbol(elf)).value(elf),
4274 };4318 };
4275 const offset, _ = ni.location(&elf.mf).resolve(&elf.mf);4319 const offset, _ = ni.location(&elf.mf).resolve(&elf.mf);
4276 return parent_vaddr + offset;4320 return parent_vaddr + offset;
4277}4321}
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
4279/// Deletes any existing relocations in the given node, and marks the start of the node's contiguous4326/// Deletes any existing relocations in the given node, and marks the start of the node's contiguous
4280/// sequence of relocations, so that the caller may append the node's updated relocations.4327/// 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 {...@@ -4283,12 +4330,16 @@ fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
4283/// the special-case sections '.plt' and '.dynamic'.4330/// the special-case sections '.plt' and '.dynamic'.
4284fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {4331fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
4285 const symbol_relocs: *SymbolReloc.Index, const got_relocs: ?*GotReloc.Index = switch (elf.getNode(ni)) {4332 const symbol_relocs: *SymbolReloc.Index, const got_relocs: ?*GotReloc.Index = switch (elf.getNode(ni)) {
4286 .file => unreachable, // cannot contain relocs4333 .archive,
4287 .ehdr => unreachable, // cannot contain relocs4334 .archive_header,
4288 .shdr => unreachable, // cannot contain relocs4335 .elf,
4289 .segment => unreachable, // cannot contain relocs4336 .ehdr,
4337 .shdr,
4338 .segment,
4339 .input_member,
4340 .copied_global,
4341 => unreachable, // cannot contain relocs
4290 .section => unreachable, // cannot contain relocs (.plt and .dynamic unsupported)4342 .section => unreachable, // cannot contain relocs (.plt and .dynamic unsupported)
4291 .copied_global => unreachable, // cannot contain relocs
4292 .input_section => |isi| .{4343 .input_section => |isi| .{
4293 &elf.input_sections.items[@backingInt(isi)].first_symbol_reloc,4344 &elf.input_sections.items[@backingInt(isi)].first_symbol_reloc,
4294 &elf.input_sections.items[@backingInt(isi)].first_got_reloc,4345 &elf.input_sections.items[@backingInt(isi)].first_got_reloc,
...@@ -4359,7 +4410,7 @@ fn flushMovedNodeRelocs(...@@ -4359,7 +4410,7 @@ fn flushMovedNodeRelocs(
4359}4410}
43604411
4361fn identClass(elf: *const Elf) std.elf.CLASS {4412fn 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]);
4363}4414}
43644415
4365/// Like `std.elf.ET`, but only includes the ELF machine architectures we support, so that we can4416/// 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 {...@@ -4415,7 +4466,7 @@ fn targetPtrSize(elf: *const Elf) u8 {
4415 return elf.identClass().size();4466 return elf.identClass().size();
4416}4467}
4417fn targetEndian(elf: *const Elf) std.lang.Endian {4468fn 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]);
4419 return ident_data.endian();4470 return ident_data.endian();
4420}4471}
4421fn targetTlsVariant(elf: *const Elf) union(enum) {4472fn targetTlsVariant(elf: *const Elf) union(enum) {
...@@ -4487,7 +4538,7 @@ fn targetLoad(elf: *const Elf, ptr: anytype) @typeInfo(@TypeOf(ptr)).pointer.chi...@@ -4487,7 +4538,7 @@ fn targetLoad(elf: *const Elf, ptr: anytype) @typeInfo(@TypeOf(ptr)).pointer.chi
4487 return switch (@typeInfo(Child)) {4538 return switch (@typeInfo(Child)) {
4488 else => @compileError(@typeName(Child)),4539 else => @compileError(@typeName(Child)),
4489 .int => std.mem.toNative(Child, ptr.*, elf.targetEndian()),4540 .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)))),
4491 .@"struct" => |@"struct"| @bitCast(4542 .@"struct" => |@"struct"| @bitCast(
4492 elf.targetLoad(@as(*align(alignment) @"struct".backing_integer.?, @ptrCast(ptr))),4543 elf.targetLoad(@as(*align(alignment) @"struct".backing_integer.?, @ptrCast(ptr))),
4493 ),4544 ),
...@@ -4563,6 +4614,16 @@ fn shdrPtr(elf: *Elf, shndx: Section.Index) ShdrPtr {...@@ -4563,6 +4614,16 @@ fn shdrPtr(elf: *Elf, shndx: Section.Index) ShdrPtr {
4563 }4614 }
4564}4615}
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
4566const SymPtr = union(std.elf.CLASS) {4627const SymPtr = union(std.elf.CLASS) {
4567 NONE: noreturn,4628 NONE: noreturn,
4568 @"32": *std.elf.Elf32.Sym,4629 @"32": *std.elf.Elf32.Sym,
...@@ -4657,7 +4718,7 @@ fn mapInputSection(elf: *Elf, opts: struct {...@@ -4657,7 +4718,7 @@ fn mapInputSection(elf: *Elf, opts: struct {
4657 }4718 }
4658 errdefer assert(elf.section_by_name.pop().?.key == name_shstrtab);4719 errdefer assert(elf.section_by_name.pop().?.key == name_shstrtab);
4659 const parent_node: MappedFile.Node.Index = parent: {4720 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;
4661 if (opts.flags.EXECINSTR) break :parent elf.ni.text;4722 if (opts.flags.EXECINSTR) break :parent elf.ni.text;
4662 if (opts.flags.TLS) break :parent elf.ni.tls;4723 if (opts.flags.TLS) break :parent elf.ni.tls;
4663 if (opts.flags.WRITE) break :parent elf.ni.data;4724 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...@@ -4782,11 +4843,11 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node
4782 break :a switch (nav.resolved.?.@"align") {4843 break :a switch (nav.resolved.?.@"align") {
4783 else => |a| a.maxStrict(min),4844 else => |a| a.maxStrict(min),
4784 .none => switch (mod.optimize_mode) {4845 .none => switch (mod.optimize_mode) {
4785 .Debug,4846 .debug,
4786 .ReleaseSafe,4847 .safe,
4787 .ReleaseFast,4848 .fast,
4788 => target_util.defaultFunctionAlignment(target),4849 => target_util.defaultFunctionAlignment(target),
4789 .ReleaseSmall => min,4850 .small => min,
4790 }.maxStrict(Type.fromInterned(nav.resolved.?.type).abiAlignment(zcu)),4851 }.maxStrict(Type.fromInterned(nav.resolved.?.type).abiAlignment(zcu)),
4791 };4852 };
4792 },4853 },
...@@ -4878,7 +4939,7 @@ const LoadParseInputError = Error || Io.File.SeekError || Io.Reader.Error;...@@ -4878,7 +4939,7 @@ const LoadParseInputError = Error || Io.File.SeekError || Io.Reader.Error;
4878/// indicates to the frontend that the input could be a GNU ld script instead.4939/// indicates to the frontend that the input could be a GNU ld script instead.
4879pub fn loadInput(elf: *Elf, input: link.Input) (link.Error || error{BadMagic})!void {4940pub fn loadInput(elf: *Elf, input: link.Input) (link.Error || error{BadMagic})!void {
4880 const diags = &elf.base.comp.link_diags;4941 const diags = &elf.base.comp.link_diags;
4881 return elf.loadInputInner(input) catch |err| switch (err) {4942 elf.loadInputInner(input) catch |err| switch (err) {
4882 else => |e| return e,4943 else => |e| return e,
4883 error.MappedFileIo => return diags.fail(4944 error.MappedFileIo => return diags.fail(
4884 "failed to write output file: {t}",4945 "failed to write output file: {t}",
...@@ -4986,6 +5047,9 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (Load...@@ -4986,6 +5047,9 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (Load
4986 const r = &fr.interface;5047 const r = &fr.interface;
49875048
4988 log.debug("loadArchive({f})", .{path.fmtEscapeString()});5049 log.debug("loadArchive({f})", .{path.fmtEscapeString()});
5050
5051 if (elf.ehdrType() == .REL) return; // this input does not affect the output artifact
5052
4989 {5053 {
4990 const magic = r.take(std.elf.ARMAG.len) catch |err| switch (err) {5054 const magic = r.take(std.elf.ARMAG.len) catch |err| switch (err) {
4991 error.ReadFailed => |e| return e,5055 error.ReadFailed => |e| return e,
...@@ -5071,21 +5135,40 @@ fn loadObject(...@@ -5071,21 +5135,40 @@ fn loadObject(
5071 .{},5135 .{},
5072 ),5136 ),
5073 };5137 };
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;
5074 try elf.ensureUnusedSymbolCapacity(1, .all_local);5163 try elf.ensureUnusedSymbolCapacity(1, .all_local);
5075 try elf.inputs.ensureUnusedCapacity(gpa, 1);5164 input.extra = .{ .file_symbol = elf.addLocalSymbolAssumeCapacity(.{
5076 const file_symbol = elf.addLocalSymbolAssumeCapacity(.{
5077 .node = .none,5165 .node = .none,
5078 .name = try elf.string(.strtab, std.fs.path.stem(member orelse path.sub_path)),5166 .name = try elf.string(.strtab, std.fs.path.stem(member orelse path.sub_path)),
5079 .value = 0,5167 .value = 0,
5080 .size = 0,5168 .size = 0,
5081 .type = .FILE,5169 .type = .FILE,
5082 .shndx = .ABS,5170 .shndx = .ABS,
5083 });5171 }) };
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 };
5089 const target_endian = elf.targetEndian();5172 const target_endian = elf.targetEndian();
5090 switch (elf.identClass()) {5173 switch (elf.identClass()) {
5091 .NONE, _ => unreachable,5174 .NONE, _ => unreachable,
...@@ -5267,7 +5350,7 @@ fn loadObject(...@@ -5267,7 +5350,7 @@ fn loadObject(
5267 .first_symbol_reloc = .none,5350 .first_symbol_reloc = .none,
5268 .first_got_reloc = .none,5351 .first_got_reloc = .none,
5269 };5352 };
5270 elf.synth_prog_node.increaseEstimatedTotalItems(1);5353 elf.input_prog_node.increaseEstimatedTotalItems(1);
5271 }5354 }
5272 var symmap: std.ArrayList(Symbol.Id) = .empty;5355 var symmap: std.ArrayList(Symbol.Id) = .empty;
5273 defer symmap.deinit(gpa);5356 defer symmap.deinit(gpa);
...@@ -5479,6 +5562,9 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (LoadPars...@@ -5479,6 +5562,9 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (LoadPars
54795562
5480 log.debug("loadDso({f})", .{path.fmtEscapeString()});5563 log.debug("loadDso({f})", .{path.fmtEscapeString()});
5481 try elf.checkInputIdent(path, r);5564 try elf.checkInputIdent(path, r);
5565
5566 if (elf.ehdrType() == .REL) return; // this input does not affect the output artifact
5567
5482 const target_endian = elf.targetEndian();5568 const target_endian = elf.targetEndian();
5483 switch (elf.identClass()) {5569 switch (elf.identClass()) {
5484 .NONE, _ => unreachable,5570 .NONE, _ => unreachable,
...@@ -5709,7 +5795,8 @@ fn checkInputIdent(...@@ -5709,7 +5795,8 @@ fn checkInputIdent(
5709 }5795 }
57105796
5711 const ident = try r.peekStructPointer(std.elf.Ident);5797 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
5714 if (ident.class != target.class) return diags.failParse(5801 if (ident.class != target.class) return diags.failParse(
5715 path,5802 path,
...@@ -5812,7 +5899,9 @@ fn updateInitFiniArraySectionSize(...@@ -5812,7 +5899,9 @@ fn updateInitFiniArraySectionSize(
5812}5899}
58135900
5814pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) link.Error!void {5901pub 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
5816 const diags = &elf.base.comp.link_diags;5905 const diags = &elf.base.comp.link_diags;
5817 elf.prelinkInner() catch |err| switch (err) {5906 elf.prelinkInner() catch |err| switch (err) {
5818 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),5907 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 {...@@ -5823,13 +5912,11 @@ fn prelinkInner(elf: *Elf) Error!void {
5823 const comp = elf.base.comp;5912 const comp = elf.base.comp;
5824 const gpa = comp.gpa;5913 const gpa = comp.gpa;
58255914
5826 if (comp.zcu != null and !comp.config.use_llvm) {5915 if (comp.zcu != null and !comp.config.use_llvm and elf.ni.elf == MappedFile.Node.Index.root) {
5827 // We're use self-hosted codegen---add an input representing the Zig "object".5916 // We're using self-hosted codegen---add an input representing the Zig "object".
5828 try elf.ensureUnusedSymbolCapacity(1, .all_local);5917 try elf.ensureUnusedSymbolCapacity(1, .all_local);
5829 try elf.inputs.ensureUnusedCapacity(gpa, 1);5918 try elf.inputs.ensureUnusedCapacity(gpa, 1);
5830 const zcu_name = try std.fmt.allocPrint(gpa, "{s}_zcu", .{5919 const zcu_name = try std.fmt.allocPrint(gpa, "{s}_zcu", .{comp.root_name});
5831 std.fs.path.stem(elf.base.emit.sub_path),
5832 });
5833 defer gpa.free(zcu_name);5920 defer gpa.free(zcu_name);
5834 const zcu_file_symbol = elf.addLocalSymbolAssumeCapacity(.{5921 const zcu_file_symbol = elf.addLocalSymbolAssumeCapacity(.{
5835 .node = .none,5922 .node = .none,
...@@ -5842,9 +5929,12 @@ fn prelinkInner(elf: *Elf) Error!void {...@@ -5842,9 +5929,12 @@ fn prelinkInner(elf: *Elf) Error!void {
5842 elf.inputs.addOneAssumeCapacity().* = .{5929 elf.inputs.addOneAssumeCapacity().* = .{
5843 .path = elf.base.emit,5930 .path = elf.base.emit,
5844 .member = null,5931 .member = null,
5845 .file_symbol = zcu_file_symbol,5932 .extra = .{ .file_symbol = zcu_file_symbol },
5846 };5933 };
5934 elf.input_pending_index += 1;
5847 }5935 }
5936
5937 try elf.ensureElfNodeSize();
5848}5938}
58495939
5850fn prepareDynamic(elf: *Elf) Error!void {5940fn prepareDynamic(elf: *Elf) Error!void {
...@@ -6034,12 +6124,12 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {...@@ -6034,12 +6124,12 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
6034 },6124 },
6035 };6125 };
6036 assert(shndx < @backingInt(Section.Index.LORESERVE));6126 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) };
6038 },6128 },
6039 };6129 };
6040 try elf.ensureNodeSize(elf.ni.shdr, new_shdr_size);6130 try elf.ensureNodeSize(elf.ni.shdr, new_shdr_size);
6041 const ni = try elf.mf.addLastChildNode(gpa, switch (elf.ehdrType()) {6131 const ni = try elf.mf.addLastChildNode(gpa, switch (elf.ehdrType()) {
6042 .REL => elf.ni.file,6132 .REL => elf.ni.elf,
6043 .EXEC, .DYN => segment_ni,6133 .EXEC, .DYN => segment_ni,
6044 }, .{6134 }, .{
6045 .size = opts.size,6135 .size = opts.size,
...@@ -6062,7 +6152,6 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {...@@ -6062,7 +6152,6 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
6062 else => .{ .shndx = .UNDEF },6152 else => .{ .shndx = .UNDEF },
6063 } });6153 } });
6064 elf.nodes.appendAssumeCapacity(.{ .section = shndx });6154 elf.nodes.appendAssumeCapacity(.{ .section = shndx });
6065 const offset = ni.fileLocation(&elf.mf, false).offset;
6066 switch (elf.shdrPtr(shndx)) {6155 switch (elf.shdrPtr(shndx)) {
6067 inline else => |shdr, class| {6156 inline else => |shdr, class| {
6068 shdr.* = .{6157 shdr.* = .{
...@@ -6070,7 +6159,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {...@@ -6070,7 +6159,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
6070 .type = opts.type,6159 .type = opts.type,
6071 .flags = .{ .shf = opts.flags },6160 .flags = .{ .shf = opts.flags },
6072 .addr = @intCast(addr),6161 .addr = @intCast(addr),
6073 .offset = @intCast(offset),6162 .offset = @intCast(elf.getNodeElfOffset(ni)),
6074 .size = @intCast(opts.size),6163 .size = @intCast(opts.size),
6075 .link = opts.link,6164 .link = opts.link,
6076 .info = opts.info,6165 .info = opts.info,
...@@ -6504,20 +6593,7 @@ fn addSymbolRelocAssumeCapacity(...@@ -6504,20 +6593,7 @@ fn addSymbolRelocAssumeCapacity(
65046593
6505 // If we emit a runtime relocation entry, its `offset` is a virtual address, so we need to6594 // If we emit a runtime relocation entry, its `offset` is a virtual address, so we need to
6506 // determine the vaddr of `node`.6595 // determine the vaddr of `node`.
6507 const node_vaddr: u64 = switch (elf.getNode(node)) {6596 const node_vaddr = elf.getNodeVAddr(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 };
65216597
6522 // If this is `true`, we will try to create a copy relocation for the target symbol if it is6598 // If this is `true`, we will try to create a copy relocation for the target symbol if it is
6523 // not locally defined. If the relocation value is always computed from the target symbol's6599 // not locally defined. If the relocation value is always computed from the target symbol's
...@@ -6656,20 +6732,23 @@ fn addGotRelocAssumeCapacity(...@@ -6656,20 +6732,23 @@ fn addGotRelocAssumeCapacity(
6656) void {6732) void {
6657 assert(elf.ehdrType() != .REL);6733 assert(elf.ehdrType() != .REL);
6658 switch (elf.getNode(node)) {6734 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
6659 .input_section,6747 .input_section,
6660 .nav,6748 .nav,
6661 .lazy_code,6749 .lazy_code,
6662 .lazy_const_data,6750 .lazy_const_data,
6663 => {},6751 => {},
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
6673 }6752 }
66746753
6675 const gop = elf.got.getOrPutAssumeCapacity(target);6754 const gop = elf.got.getOrPutAssumeCapacity(target);
...@@ -7053,11 +7132,24 @@ pub fn flush(...@@ -7053,11 +7132,24 @@ pub fn flush(
7053 tid: Zcu.PerThread.Id,7132 tid: Zcu.PerThread.Id,
7054 prog_node: std.Progress.Node,7133 prog_node: std.Progress.Node,
7055) link.Error!void {7134) 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 {
7056 const comp = elf.base.comp;7146 const comp = elf.base.comp;
7057 const diags = &comp.link_diags;7147 const diags = &comp.link_diags;
7058 _ = prog_node;
7059 _ = arena;7148 _ = arena;
70607149
7150 const sub_prog_node = prog_node.start("ELF Flush", 0);
7151 defer sub_prog_node.end();
7152
7061 if (comp.config.output_mode == .Exe) {7153 if (comp.config.output_mode == .Exe) {
7062 var any_undef = false;7154 var any_undef = false;
7063 for (elf.globals.strong_undef.keys()) |name| {7155 for (elf.globals.strong_undef.keys()) |name| {
...@@ -7068,11 +7160,9 @@ pub fn flush(...@@ -7068,11 +7160,9 @@ pub fn flush(
7068 if (any_undef) return error.AlreadyReported;7160 if (any_undef) return error.AlreadyReported;
7069 }7161 }
70707162
7071 elf.prepareDynamic() catch |err| switch (err) {7163 try elf.prepareDynamic();
7072 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
7073 else => |e| return e,
7074 };
70757164
7165 try elf.ensureElfNodeSize();
7076 while (try elf.idle(tid)) {}7166 while (try elf.idle(tid)) {}
70777167
7078 // We've done the final `idle` loop, so everything is at its final place in the file. We have a7168 // 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(...@@ -7097,10 +7187,7 @@ pub fn flush(
7097 .enabled => "_start",7187 .enabled => "_start",
7098 .named => |named| named,7188 .named => |named| named,
7099 };7189 };
7100 const sym_name_strtab = elf.string(.strtab, sym_name_slice) catch |err| switch (err) {7190 const sym_name_strtab = try elf.string(.strtab, sym_name_slice);
7101 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
7102 else => |e| return e,
7103 };
7104 if (elf.globalByName(sym_name_strtab) == null) break :entry 0;7191 if (elf.globalByName(sym_name_strtab) == null) break :entry 0;
7105 break :entry Symbol.Id.global(sym_name_strtab).value(elf);7192 break :entry Symbol.Id.global(sym_name_strtab).value(elf);
7106 };7193 };
...@@ -7108,10 +7195,11 @@ pub fn flush(...@@ -7108,10 +7195,11 @@ pub fn flush(
7108 inline else => |ehdr| elf.targetStore(&ehdr.entry, @intCast(entry_addr)),7195 inline else => |ehdr| elf.targetStore(&ehdr.entry, @intCast(entry_addr)),
7109 }7196 }
71107197
7111 elf.mf.flush() catch |err| switch (err) {7198 try elf.mf.flush();
7112 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),7199
7113 else => |e| return e,7200 if (elf.options.enable_link_snapshots)
7114 };7201 elf.dumpStderr(tid) catch |err|
7202 return comp.link_diags.fail("dumping link snapshot failed: {t}", .{err});
7115}7203}
71167204
7117pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {7205pub 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 {...@@ -7124,8 +7212,19 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {
7124 }7212 }
71257213
7126 task: {7214 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 }
7127 if (elf.input_section_pending_index < elf.input_sections.items.len) {7226 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);
7129 elf.input_section_pending_index += 1;7228 elf.input_section_pending_index += 1;
7130 const sub_prog_node = elf.idleProgNode(tid, elf.input_prog_node, elf.getNode(isi.node(elf)));7229 const sub_prog_node = elf.idleProgNode(tid, elf.input_prog_node, elf.getNode(isi.node(elf)));
7131 defer sub_prog_node.end();7230 defer sub_prog_node.end();
...@@ -7213,11 +7312,13 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {...@@ -7213,11 +7312,13 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {
7213 while (elf.mf.updates.pop()) |ni| {7312 while (elf.mf.updates.pop()) |ni| {
7214 const clean_moved = ni.cleanMoved(&elf.mf);7313 const clean_moved = ni.cleanMoved(&elf.mf);
7215 const clean_resized = ni.cleanResized(&elf.mf);7314 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) {
7217 const sub_prog_node = elf.idleProgNode(tid, elf.mf.update_prog_node, elf.getNode(ni));7317 const sub_prog_node = elf.idleProgNode(tid, elf.mf.update_prog_node, elf.getNode(ni));
7218 defer sub_prog_node.end();7318 defer sub_prog_node.end();
7219 if (clean_moved) try elf.flushMoved(ni);7319 if (clean_moved) try elf.flushMoved(ni);
7220 if (clean_resized) try elf.flushResized(ni);7320 if (clean_resized) try elf.flushResized(ni);
7321 if (clean_next_moved) try elf.flushNextMoved(ni);
7221 break :task;7322 break :task;
7222 } else elf.mf.update_prog_node.completeOne();7323 } else elf.mf.update_prog_node.completeOne();
7223 }7324 }
...@@ -7238,6 +7339,10 @@ fn idleProgNode(...@@ -7238,6 +7339,10 @@ fn idleProgNode(
7238 return prog_node.start(name: switch (node) {7339 return prog_node.start(name: switch (node) {
7239 else => |tag| @tagName(tag),7340 else => |tag| @tagName(tag),
7240 .section => |shndx| shndx.name(elf).slice(elf),7341 .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,
7241 .input_section => |isi| {7346 .input_section => |isi| {
7242 const ii = isi.input(elf);7347 const ii = isi.input(elf);
7243 break :name std.fmt.bufPrint(&name, "{f}{f} {s}", .{7348 break :name std.fmt.bufPrint(&name, "{f}{f} {s}", .{
...@@ -7290,6 +7395,8 @@ fn genPending(elf: *Elf, pt: Zcu.PerThread) Error!void {...@@ -7290,6 +7395,8 @@ fn genPending(elf: *Elf, pt: Zcu.PerThread) Error!void {
7290 };7395 };
7291 break;7396 break;
7292 }7397 }
7398
7399 try elf.ensureElfNodeSize();
7293}7400}
72947401
7295fn genUav(7402fn genUav(
...@@ -7358,6 +7465,36 @@ fn genLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void {...@@ -7358,6 +7465,36 @@ fn genLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void {
7358 }7465 }
7359}7466}
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
7361fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void {7498fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void {
7362 const file_loc = isi.fileLocation(elf);7499 const file_loc = isi.fileLocation(elf);
7363 if (file_loc.size == 0) return;7500 if (file_loc.size == 0) return;
...@@ -7404,33 +7541,29 @@ fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void {...@@ -7404,33 +7541,29 @@ fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void {
7404 assert(isi.node(elf).hasMoved(&elf.mf));7541 assert(isi.node(elf).hasMoved(&elf.mf));
7405}7542}
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);
7408 switch (elf.getNode(ni)) {7546 switch (elf.getNode(ni)) {
7409 else => unreachable,7547 else => unreachable,
7410 .ehdr => assert(ni.fileLocation(&elf.mf, false).offset == 0),7548 .ehdr => assert(elf_offset == 0),
7411 .shdr => switch (elf.ehdrPtr()) {7549 .shdr => switch (elf.ehdrPtr()) {
7412 inline else => |ehdr| elf.targetStore(7550 inline else => |ehdr| elf.targetStore(&ehdr.shoff, @intCast(elf_offset)),
7413 &ehdr.shoff,
7414 @intCast(ni.fileLocation(&elf.mf, false).offset),
7415 ),
7416 },7551 },
7417 .segment => |phndx| {7552 .segment => |phndx| {
7418 switch (elf.phdrSlice()) {7553 switch (elf.phdrSlice()) {
7419 inline else => |phdr, class| {7554 inline else => |phdr, class| {
7420 const ph = &phdr[phndx];7555 const ph = &phdr[phndx];
7421 elf.targetStore(&ph.offset, @intCast(ni.fileLocation(&elf.mf, false).offset));7556 elf.targetStore(&ph.offset, @intCast(elf_offset));
7422 if (elf.targetLoad(&ph.type) == .PHDR) {7557 if (elf.targetLoad(&ph.type) == .PHDR) {
7423 @field(elf.ehdrPtr(), @tagName(class)).phoff = ph.offset;7558 @field(elf.ehdrPtr(), @tagName(class)).phoff = ph.offset;
7424 }7559 }
7425 },7560 },
7426 }7561 }
7427 var child_it = ni.children(&elf.mf);7562 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);
7429 },7564 },
7430 .section => |shndx| switch (elf.shdrPtr(shndx)) {7565 .section => |shndx| switch (elf.shdrPtr(shndx)) {
7431 inline else => |shdr| elf.targetStore(&shdr.offset, @intCast(7566 inline else => |shdr| elf.targetStore(&shdr.offset, @intCast(elf_offset)),
7432 ni.fileLocation(&elf.mf, false).offset,
7433 )),
7434 },7567 },
7435 }7568 }
7436}7569}
...@@ -7443,10 +7576,11 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void...@@ -7443,10 +7576,11 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
7443 defer elf.mf.nodes_lock.unlock();7576 defer elf.mf.nodes_lock.unlock();
74447577
7445 switch (elf.getNode(ni)) {7578 switch (elf.getNode(ni)) {
7446 .file => unreachable,7579 .archive, .archive_header => unreachable,
7447 .ehdr, .shdr => elf.flushFileOffset(ni),7580 .elf => {},
7581 .ehdr, .shdr => elf.flushElfOffset(ni),
7448 .segment => |phndx| {7582 .segment => |phndx| {
7449 elf.flushFileOffset(ni);7583 elf.flushElfOffset(ni);
7450 switch (elf.phdrSlice()) {7584 switch (elf.phdrSlice()) {
7451 inline else => |phdr| {7585 inline else => |phdr| {
7452 const ph = &phdr[phndx];7586 const ph = &phdr[phndx];
...@@ -7467,7 +7601,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void...@@ -7467,7 +7601,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
7467 }7601 }
7468 },7602 },
7469 .section => |shndx| {7603 .section => |shndx| {
7470 elf.flushFileOffset(ni);7604 elf.flushElfOffset(ni);
7471 const addr = elf.computeNodeVAddr(ni);7605 const addr = elf.computeNodeVAddr(ni);
7472 const old_addr: u64, const flags: std.elf.SHF = switch (elf.shdrPtr(shndx)) {7606 const old_addr: u64, const flags: std.elf.SHF = switch (elf.shdrPtr(shndx)) {
7473 inline else => |shdr| .{7607 inline else => |shdr| .{
...@@ -7518,6 +7652,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void...@@ -7518,6 +7652,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
7518 elf.flushMovedNodeRelocs(ni, addr, elf.dynamic_first_symbol_reloc, .none);7652 elf.flushMovedNodeRelocs(ni, addr, elf.dynamic_first_symbol_reloc, .none);
7519 }7653 }
7520 },7654 },
7655 .input_member => {},
7521 .input_section => |isi| {7656 .input_section => |isi| {
7522 const old_section_addr = isi.ptr(elf).vaddr;7657 const old_section_addr = isi.ptr(elf).vaddr;
7523 const new_section_addr = elf.computeNodeVAddr(ni);7658 const new_section_addr = elf.computeNodeVAddr(ni);
...@@ -7526,7 +7661,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void...@@ -7526,7 +7661,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
7526 // Update local symbols7661 // Update local symbols
7527 const ii = isi.input(elf);7662 const ii = isi.input(elf);
7528 var lsi, const end_lsi = ii.localSymbolRange(elf);7663 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)) {
7530 if (lsi.index().ptr(elf).node != ni) continue;7665 if (lsi.index().ptr(elf).node != ni) continue;
7531 const visibility: std.elf.STV = switch (elf.symPtr(lsi.index())) {7666 const visibility: std.elf.STV = switch (elf.symPtr(lsi.index())) {
7532 inline else => |sym| elf.targetLoad(&sym.other).visibility,7667 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...@@ -7613,7 +7748,17 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo
76137748
7614 _, const size = ni.location(&elf.mf).resolve(&elf.mf);7749 _, const size = ni.location(&elf.mf).resolve(&elf.mf);
7615 switch (elf.getNode(ni)) {7750 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 => {},
7617 .ehdr => unreachable,7762 .ehdr => unreachable,
7618 .shdr => {},7763 .shdr => {},
7619 .segment => |phndx| switch (elf.phdrSlice()) {7764 .segment => |phndx| switch (elf.phdrSlice()) {
...@@ -7713,9 +7858,88 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo...@@ -7713,9 +7858,88 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo
7713 }7858 }
7714 },7859 },
7715 },7860 },
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 => {},
7717 }7862 }
7718}7863}
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
7719fn updateDynamicEntry(elf: *Elf, key: u32, new_val: u64) void {7943fn updateDynamicEntry(elf: *Elf, key: u32, new_val: u64) void {
7720 switch (elf.shdrPtr(elf.shndx.dynamic)) {7944 switch (elf.shdrPtr(elf.shndx.dynamic)) {
7721 inline else => |shdr, class| {7945 inline else => |shdr, class| {
...@@ -7756,7 +7980,7 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void...@@ -7756,7 +7980,7 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void
7756 };7980 };
77577981
7758 // Now that we know the index, we can set the relocation's offset.7982 // 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
7761 if (plt_index < elf.plt.count()) {7985 if (plt_index < elf.plt.count()) {
7762 // We reused a free entry, so we're already done!7986 // We reused a free entry, so we're already done!
...@@ -8096,7 +8320,10 @@ fn updateExportsInner(...@@ -8096,7 +8320,10 @@ fn updateExportsInner(
8096 },8320 },
8097 .uav => |uav| .{ (try elf.uavMapIndex(uav, .none)).symbol(elf), .OBJECT },8321 .uav => |uav| .{ (try elf.uavMapIndex(uav, .none)).symbol(elf), .OBJECT },
8098 };8322 };
8323
8324 try elf.ensureElfNodeSize();
8099 while (try elf.idle(pt.tid)) {}8325 while (try elf.idle(pt.tid)) {}
8326
8100 const value: u64 = Symbol.Id.local(exported_lsi).value(elf);8327 const value: u64 = Symbol.Id.local(exported_lsi).value(elf);
8101 const size: u64, const shndx: Section.Index = switch (elf.symPtr(exported_lsi.index())) {8328 const size: u64, const shndx: Section.Index = switch (elf.symPtr(exported_lsi.index())) {
8102 inline else => |exported_sym| .{8329 inline else => |exported_sym| .{
...@@ -8150,6 +8377,16 @@ pub fn deleteExport(elf: *Elf, exported: Zcu.Exported, name: InternPool.NullTerm...@@ -8150,6 +8377,16 @@ pub fn deleteExport(elf: *Elf, exported: Zcu.Exported, name: InternPool.NullTerm
8150 _ = name;8377 _ = name;
8151}8378}
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
8153pub fn dump(elf: *Elf, w: *Io.Writer, tid: Zcu.PerThread.Id) !link.File.DumpResult {8390pub fn dump(elf: *Elf, w: *Io.Writer, tid: Zcu.PerThread.Id) !link.File.DumpResult {
8154 if (elf.options.enable_link_snapshots) {8391 if (elf.options.enable_link_snapshots) {
8155 try elf.printNode(tid, w, .root, 0);8392 try elf.printNode(tid, w, .root, 0);
...@@ -8227,13 +8464,14 @@ pub fn printNode(...@@ -8227,13 +8464,14 @@ pub fn printNode(
8227 {8464 {
8228 const mf_node = &elf.mf.nodes.items[@backingInt(ni)];8465 const mf_node = &elf.mf.nodes.items[@backingInt(ni)];
8229 const off, const size = mf_node.location().resolve(&elf.mf);8466 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", .{
8231 @backingInt(ni),8468 @backingInt(ni),
8232 off,8469 off,
8233 size,8470 size,
8234 mf_node.flags.alignment.toByteUnits(),8471 mf_node.flags.alignment.toByteUnits(),
8235 if (mf_node.flags.fixed) " fixed" else "",8472 if (mf_node.flags.fixed) " fixed" else "",
8236 if (mf_node.flags.moved) " moved" else "",8473 if (mf_node.flags.moved) " moved" else "",
8474 if (mf_node.flags.next_moved) " next_moved" else "",
8237 if (mf_node.flags.resized) " resized" else "",8475 if (mf_node.flags.resized) " resized" else "",
8238 if (mf_node.flags.has_content) " has_content" else "",8476 if (mf_node.flags.has_content) " has_content" else "",
8239 });8477 });
...@@ -8269,11 +8507,19 @@ pub fn printNode(...@@ -8269,11 +8507,19 @@ pub fn printNode(
8269 }8507 }
8270}8508}
82718509
8272fn ensureNodeSize(8510/// Must be called deterministically after any call to `MappedFile.Node.Index.resize`
8273 elf: *Elf,8511/// (of `elf.ni.elf` or one of its children) before any possible calls to `idle`.
8274 node: MappedFile.Node.Index,8512fn ensureElfNodeSize(elf: *Elf) MappedFile.Error!void {
8275 need_size: u64,8513 if (elf.ni.elf == MappedFile.Node.Index.root) return;
8276) Error!void {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 {
8277 _, const node_size = node.location(&elf.mf).resolve(&elf.mf);8523 _, const node_size = node.location(&elf.mf).resolve(&elf.mf);
8278 if (need_size <= node_size) return;8524 if (need_size <= node_size) return;
8279 const gpa = elf.base.comp.gpa;8525 const gpa = elf.base.comp.gpa;
src/link/Lld.zig+39-26
...@@ -99,8 +99,6 @@ pub const Elf = struct {...@@ -99,8 +99,6 @@ pub const Elf = struct {
99 bind_global_refs_locally: bool,99 bind_global_refs_locally: bool,
100 pub const HashStyle = enum { sysv, gnu, both };100 pub const HashStyle = enum { sysv, gnu, both };
101 pub const SortSection = enum { name, alignment };101 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
105 fn init(comp: *Compilation, options: link.File.OpenOptions) !Elf {103 fn init(comp: *Compilation, options: link.File.OpenOptions) !Elf {
106 const PtrWidth = enum { p32, p64 };104 const PtrWidth = enum { p32, p64 };
...@@ -208,8 +206,8 @@ pub fn createEmpty(...@@ -208,8 +206,8 @@ pub fn createEmpty(
208 const optimize_mode = comp.root_mod.optimize_mode;206 const optimize_mode = comp.root_mod.optimize_mode;
209207
210 const gc_sections: bool = options.gc_sections orelse switch (target.ofmt) {208 const gc_sections: bool = options.gc_sections orelse switch (target.ofmt) {
211 .coff => optimize_mode != .Debug,209 .coff => optimize_mode != .debug,
212 .elf => optimize_mode != .Debug and output_mode != .Obj,210 .elf => optimize_mode != .debug and output_mode != .Obj,
213 .wasm => output_mode != .Obj,211 .wasm => output_mode != .Obj,
214 else => unreachable,212 else => unreachable,
215 };213 };
...@@ -271,12 +269,12 @@ pub fn flush(...@@ -271,12 +269,12 @@ pub fn flush(
271 .wasm => wasmLink(lld, arena),269 .wasm => wasmLink(lld, arena),
272 };270 };
273 result catch |err| switch (err) {271 result catch |err| switch (err) {
274 error.OutOfMemory, error.AlreadyReported => |e| return e,272 error.OutOfMemory, error.AlreadyReported, error.Canceled => |e| return e,
275 else => |e| return lld.base.comp.link_diags.fail("failed to link with LLD: {t}", .{e}),273 else => |e| return lld.base.comp.link_diags.fail("failed to link with LLD: {t}", .{e}),
276 };274 };
277}275}
278276
279fn linkAsArchive(lld: *Lld, arena: Allocator) !void {277fn linkAsArchive(lld: *Lld, arena: Allocator) link.Error!void {
280 const base = &lld.base;278 const base = &lld.base;
281 const comp = base.comp;279 const comp = base.comp;
282 const directory = base.emit.root_dir; // Just an alias to make it shorter to type.280 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 {...@@ -308,8 +306,8 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void {
308306
309 try object_files.ensureUnusedCapacity(arena, comp.link_inputs.len);307 try object_files.ensureUnusedCapacity(arena, comp.link_inputs.len);
310 for (comp.link_inputs) |input| switch (input) {308 for (comp.link_inputs) |input| switch (input) {
311 .res, .dso, .dso_exact => {}, // shared libraries should not be included in static archives309 .dso, .dso_exact, .archive => {}, // static archives should not contain shared libraries or other static archives
312 .object, .archive => {310 .res, .object => {
313 const path = try input.path().?.toStringZ(arena);311 const path = try input.path().?.toStringZ(arena);
314 object_files.appendAssumeCapacity(path);312 object_files.appendAssumeCapacity(path);
315 },313 },
...@@ -340,7 +338,9 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void {...@@ -340,7 +338,9 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void {
340 const llvm = @import("../codegen/llvm.zig");338 const llvm = @import("../codegen/llvm.zig");
341 const target = &comp.root_mod.resolved_target.result;339 const target = &comp.root_mod.resolved_target.result;
342 llvm.initializeLLVMTarget(target.cpu.arch);340 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(
344 full_out_path_z,344 full_out_path_z,
345 object_files.items.ptr,345 object_files.items.ptr,
346 object_files.items.len,346 object_files.items.len,
...@@ -348,8 +348,19 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void {...@@ -348,8 +348,19 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void {
348 .windows => .COFF,348 .windows => .COFF,
349 else => if (target.os.tag.isDarwin()) .DARWIN else .GNU,349 else => if (target.os.tag.isDarwin()) .DARWIN else .GNU,
350 },350 },
351 );351 &err_file_index,
352 if (bad) return error.UnableToWriteArchive;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 }
353}364}
354365
355fn addCommonArgs(argv: *std.array_list.Managed([]const u8), coff: bool) !void {366fn addCommonArgs(argv: *std.array_list.Managed([]const u8), coff: bool) !void {
...@@ -383,7 +394,7 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {...@@ -383,7 +394,7 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {
383 const target = &comp.root_mod.resolved_target.result;394 const target = &comp.root_mod.resolved_target.result;
384 const optimize_mode = comp.root_mod.optimize_mode;395 const optimize_mode = comp.root_mod.optimize_mode;
385 const entry_name: ?[]const u8 = switch (coff.entry) {396 const entry_name: ?[]const u8 = switch (coff.entry) {
386 // This logic isn't quite right for disabled or enabled. No point in fixing it397 // This logic isn't quite right for default or enabled. No point in fixing it
387 // when the goal is to eliminate dependency on LLD anyway.398 // when the goal is to eliminate dependency on LLD anyway.
388 // https://github.com/ziglang/zig/issues/17751399 // https://github.com/ziglang/zig/issues/17751
389 .disabled, .default, .enabled => null,400 .disabled, .default, .enabled => null,
...@@ -456,9 +467,9 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {...@@ -456,9 +467,9 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {
456467
457 if (comp.config.lto != .none) {468 if (comp.config.lto != .none) {
458 switch (optimize_mode) {469 switch (optimize_mode) {
459 .Debug => {},470 .debug => {},
460 .ReleaseSmall => try argv.append("-OPT:lldlto=2"),471 .small => try argv.append("-OPT:lldlto=2"),
461 .ReleaseFast, .ReleaseSafe => try argv.append("-OPT:lldlto=3"),472 .fast, .safe => try argv.append("-OPT:lldlto=3"),
462 }473 }
463 }474 }
464 if (comp.config.output_mode == .Exe) {475 if (comp.config.output_mode == .Exe) {
...@@ -492,6 +503,8 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {...@@ -492,6 +503,8 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {
492503
493 if (entry_name) |name| {504 if (entry_name) |name| {
494 try argv.append(try arena.print("-ENTRY:{s}", .{name}));505 try argv.append(try arena.print("-ENTRY:{s}", .{name}));
506 } else if (coff.entry == .disabled) {
507 try argv.append("-NOENTRY");
495 }508 }
496509
497 if (coff.repro) {510 if (coff.repro) {
...@@ -865,15 +878,15 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {...@@ -865,15 +878,15 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {
865878
866 if (comp.config.lto != .none) {879 if (comp.config.lto != .none) {
867 switch (comp.root_mod.optimize_mode) {880 switch (comp.root_mod.optimize_mode) {
868 .Debug => {},881 .debug => {},
869 .ReleaseSmall => try argv.append("--lto-O2"),882 .small => try argv.append("--lto-O2"),
870 .ReleaseFast, .ReleaseSafe => try argv.append("--lto-O3"),883 .fast, .safe => try argv.append("--lto-O3"),
871 }884 }
872 }885 }
873 switch (comp.root_mod.optimize_mode) {886 switch (comp.root_mod.optimize_mode) {
874 .Debug => {},887 .debug => {},
875 .ReleaseSmall => try argv.append("-O2"),888 .small => try argv.append("-O2"),
876 .ReleaseFast, .ReleaseSafe => try argv.append("-O3"),889 .fast, .safe => try argv.append("-O3"),
877 }890 }
878891
879 if (elf.entry_name) |name| {892 if (elf.entry_name) |name| {
...@@ -1010,8 +1023,8 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {...@@ -1010,8 +1023,8 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {
1010 }1023 }
10111024
1012 if (is_exe_or_dyn_lib and target.os.tag == .netbsd) {1025 if (is_exe_or_dyn_lib and target.os.tag == .netbsd) {
1013 // Add options to produce shared objects with only 2 PT_LOAD segments.1026 // Add options to produce shared objects with only 2 PT.LOAD segments.
1014 // NetBSD expects 2 PT_LOAD segments in a shared object, otherwise1027 // NetBSD expects 2 PT.LOAD segments in a shared object, otherwise
1015 // ld.elf_so fails loading dynamic libraries with "not found" error.1028 // ld.elf_so fails loading dynamic libraries with "not found" error.
1016 // See https://github.com/ziglang/zig/issues/9109 .1029 // See https://github.com/ziglang/zig/issues/9109 .
1017 try argv.append("--no-rosegment");1030 try argv.append("--no-rosegment");
...@@ -1416,9 +1429,9 @@ fn wasmLink(lld: *Lld, arena: Allocator) !void {...@@ -1416,9 +1429,9 @@ fn wasmLink(lld: *Lld, arena: Allocator) !void {
14161429
1417 if (comp.config.lto != .none) {1430 if (comp.config.lto != .none) {
1418 switch (comp.root_mod.optimize_mode) {1431 switch (comp.root_mod.optimize_mode) {
1419 .Debug => {},1432 .debug => {},
1420 .ReleaseSmall => try argv.append("-O2"),1433 .small => try argv.append("-O2"),
1421 .ReleaseFast, .ReleaseSafe => try argv.append("-O3"),1434 .fast, .safe => try argv.append("-O3"),
1422 }1435 }
1423 }1436 }
14241437
src/link/MachO.zig+35-10
...@@ -24,6 +24,8 @@ dylibs: std.ArrayList(File.Index) = .empty,...@@ -24,6 +24,8 @@ dylibs: std.ArrayList(File.Index) = .empty,
2424
25segments: std.ArrayList(macho.segment_command_64) = .empty,25segments: std.ArrayList(macho.segment_command_64) = .empty,
26sections: std.MultiArrayList(Section) = .{},26sections: std.MultiArrayList(Section) = .{},
27/// Populated by `allocateSections`.
28header_size: ?u32 = null,
2729
28resolver: SymbolResolver = .{},30resolver: SymbolResolver = .{},
29/// This table will be populated after `scanRelocs` has run.31/// This table will be populated after `scanRelocs` has run.
...@@ -181,7 +183,7 @@ pub fn createEmpty(...@@ -181,7 +183,7 @@ pub fn createEmpty(
181 .tag = .macho,183 .tag = .macho,
182 .comp = comp,184 .comp = comp,
183 .emit = emit,185 .emit = emit,
184 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug),186 .gc_sections = options.gc_sections orelse (optimize_mode != .debug),
185 .print_gc_sections = options.print_gc_sections,187 .print_gc_sections = options.print_gc_sections,
186 .stack_size = options.stack_size orelse 16777216,188 .stack_size = options.stack_size orelse 16777216,
187 .allow_shlib_undefined = allow_shlib_undefined,189 .allow_shlib_undefined = allow_shlib_undefined,
...@@ -990,6 +992,11 @@ fn addArchive(self: *MachO, lib: link.Input.Object, handle: File.HandleIndex, fa...@@ -990,6 +992,11 @@ fn addArchive(self: *MachO, lib: link.Input.Object, handle: File.HandleIndex, fa
990 const tracy = trace(@src());992 const tracy = trace(@src());
991 defer tracy.end();993 defer tracy.end();
992994
995 if (self.base.isStaticLib()) {
996 // Ignore static library inputs when generating a static library.
997 return;
998 }
999
993 const gpa = self.base.comp.gpa;1000 const gpa = self.base.comp.gpa;
9941001
995 var archive: Archive = .{};1002 var archive: Archive = .{};
...@@ -1068,7 +1075,7 @@ fn isHoisted(self: *MachO, install_name: []const u8) bool {...@@ -1068,7 +1075,7 @@ fn isHoisted(self: *MachO, install_name: []const u8) bool {
1068 if (mem.startsWith(u8, dirname, "/usr/lib")) return true;1075 if (mem.startsWith(u8, dirname, "/usr/lib")) return true;
1069 if (eatPrefix(dirname, "/System/Library/Frameworks/")) |path| {1076 if (eatPrefix(dirname, "/System/Library/Frameworks/")) |path| {
1070 const basename = fs.path.basename(install_name);1077 const basename = fs.path.basename(install_name);
1071 if (mem.indexOfScalar(u8, path, '.')) |index| {1078 if (mem.findScalar(u8, path, '.')) |index| {
1072 if (mem.eql(u8, basename, path[0..index])) return true;1079 if (mem.eql(u8, basename, path[0..index])) return true;
1073 }1080 }
1074 }1081 }
...@@ -1737,14 +1744,14 @@ fn initSyntheticSections(self: *MachO) !void {...@@ -1737,14 +1744,14 @@ fn initSyntheticSections(self: *MachO) !void {
1737 });1744 });
1738 }1745 }
1739 } else if (eatPrefix(name, "section$start$")) |actual_name| {1746 } else if (eatPrefix(name, "section$start$")) |actual_name| {
1740 const sep = mem.indexOfScalar(u8, actual_name, '$').?; // TODO error rather than a panic1747 const sep = mem.findScalar(u8, actual_name, '$').?; // TODO error rather than a panic
1741 const segname = actual_name[0..sep]; // TODO check segname is valid1748 const segname = actual_name[0..sep]; // TODO check segname is valid
1742 const sectname = actual_name[sep + 1 ..]; // TODO check sectname is valid1749 const sectname = actual_name[sep + 1 ..]; // TODO check sectname is valid
1743 if (self.getSectionByName(segname, sectname) == null) {1750 if (self.getSectionByName(segname, sectname) == null) {
1744 _ = try self.addSection(segname, sectname, .{});1751 _ = try self.addSection(segname, sectname, .{});
1745 }1752 }
1746 } else if (eatPrefix(name, "section$end$")) |actual_name| {1753 } else if (eatPrefix(name, "section$end$")) |actual_name| {
1747 const sep = mem.indexOfScalar(u8, actual_name, '$').?; // TODO error rather than a panic1754 const sep = mem.findScalar(u8, actual_name, '$').?; // TODO error rather than a panic
1748 const segname = actual_name[0..sep]; // TODO check segname is valid1755 const segname = actual_name[0..sep]; // TODO check segname is valid
1749 const sectname = actual_name[sep + 1 ..]; // TODO check sectname is valid1756 const sectname = actual_name[sep + 1 ..]; // TODO check sectname is valid
1750 if (self.getSectionByName(segname, sectname) == null) {1757 if (self.getSectionByName(segname, sectname) == null) {
...@@ -1765,7 +1772,7 @@ fn getSegmentProt(segname: []const u8) macho.vm_prot_t {...@@ -1765,7 +1772,7 @@ fn getSegmentProt(segname: []const u8) macho.vm_prot_t {
1765fn getSegmentRank(segname: []const u8) u8 {1772fn getSegmentRank(segname: []const u8) u8 {
1766 if (mem.eql(u8, segname, "__PAGEZERO")) return 0x0;1773 if (mem.eql(u8, segname, "__PAGEZERO")) return 0x0;
1767 if (mem.eql(u8, segname, "__LINKEDIT")) return 0xf;1774 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;
1769 if (mem.startsWith(u8, segname, "__TEXT")) return 0x1;1776 if (mem.startsWith(u8, segname, "__TEXT")) return 0x1;
1770 if (mem.startsWith(u8, segname, "__DATA_CONST")) return 0x2;1777 if (mem.startsWith(u8, segname, "__DATA_CONST")) return 0x2;
1771 if (mem.startsWith(u8, segname, "__DATA")) return 0x3;1778 if (mem.startsWith(u8, segname, "__DATA")) return 0x3;
...@@ -2209,13 +2216,14 @@ fn initSegments(self: *MachO) !void {...@@ -2209,13 +2216,14 @@ fn initSegments(self: *MachO) !void {
2209}2216}
22102217
2211fn allocateSections(self: *MachO) !void {2218fn 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;
2213 var vmaddr: u64 = if (self.pagezero_seg_index) |index|2221 var vmaddr: u64 = if (self.pagezero_seg_index) |index|
2214 self.segments.items[index].vmaddr + self.segments.items[index].vmsize2222 self.segments.items[index].vmaddr + self.segments.items[index].vmsize
2215 else2223 else
2216 0;2224 0;
2217 vmaddr += headerpad;2225 vmaddr += header_size;
2218 var fileoff = headerpad;2226 var fileoff = header_size;
2219 var prev_seg_id: u8 = if (self.pagezero_seg_index) |index| index + 1 else 0;2227 var prev_seg_id: u8 = if (self.pagezero_seg_index) |index| index + 1 else 0;
22202228
2221 const page_size = self.getPageSize();2229 const page_size = self.getPageSize();
...@@ -2339,7 +2347,7 @@ fn allocateSyntheticSymbols(self: *MachO) void {...@@ -2339,7 +2347,7 @@ fn allocateSyntheticSymbols(self: *MachO) void {
2339 }2347 }
2340 } else if (mem.startsWith(u8, name, "section$start$")) {2348 } else if (mem.startsWith(u8, name, "section$start$")) {
2341 const actual_name = name["section$start$".len..];2349 const actual_name = name["section$start$".len..];
2342 const sep = mem.indexOfScalar(u8, actual_name, '$').?; // TODO error rather than a panic2350 const sep = mem.findScalar(u8, actual_name, '$').?; // TODO error rather than a panic
2343 const segname = actual_name[0..sep];2351 const segname = actual_name[0..sep];
2344 const sectname = actual_name[sep + 1 ..];2352 const sectname = actual_name[sep + 1 ..];
2345 if (self.getSectionByName(segname, sectname)) |sect_id| {2353 if (self.getSectionByName(segname, sectname)) |sect_id| {
...@@ -2349,7 +2357,7 @@ fn allocateSyntheticSymbols(self: *MachO) void {...@@ -2349,7 +2357,7 @@ fn allocateSyntheticSymbols(self: *MachO) void {
2349 }2357 }
2350 } else if (mem.startsWith(u8, name, "section$end$")) {2358 } else if (mem.startsWith(u8, name, "section$end$")) {
2351 const actual_name = name["section$end$".len..];2359 const actual_name = name["section$end$".len..];
2352 const sep = mem.indexOfScalar(u8, actual_name, '$').?; // TODO error rather than a panic2360 const sep = mem.findScalar(u8, actual_name, '$').?; // TODO error rather than a panic
2353 const segname = actual_name[0..sep];2361 const segname = actual_name[0..sep];
2354 const sectname = actual_name[sep + 1 ..];2362 const sectname = actual_name[sep + 1 ..];
2355 if (self.getSectionByName(segname, sectname)) |sect_id| {2363 if (self.getSectionByName(segname, sectname)) |sect_id| {
...@@ -2895,6 +2903,11 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } {...@@ -2895,6 +2903,11 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } {
2895 ncmds += 1;2903 ncmds += 1;
2896 }2904 }
28972905
2906 if (self.needsEncryptionInfo()) {
2907 try load_commands.writeEncryptionInfoLC(self, &writer);
2908 ncmds += 1;
2909 }
2910
2898 for (self.rpath_list) |rpath| {2911 for (self.rpath_list) |rpath| {
2899 try load_commands.writeRpathLC(rpath, &writer);2912 try load_commands.writeRpathLC(rpath, &writer);
2900 ncmds += 1;2913 ncmds += 1;
...@@ -5410,6 +5423,18 @@ pub fn alignPow(macho_file: *MachO, x: u32) error{AlreadyReported}!u32 {...@@ -5410,6 +5423,18 @@ pub fn alignPow(macho_file: *MachO, x: u32) error{AlreadyReported}!u32 {
5410 return result;5423 return result;
5411}5424}
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
5413/// Branch instruction has 26 bits immediate but is 4 byte aligned.5438/// Branch instruction has 26 bits immediate but is 4 byte aligned.
5414const jump_bits = @bitSizeOf(i28);5439const jump_bits = @bitSizeOf(i28);
5415const max_distance = (1 << (jump_bits - 1));5440const 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...@@ -45,7 +45,7 @@ pub fn unpack(self: *Archive, macho_file: *MachO, path: Path, handle_index: File
45 const amt = try handle.readPositionalAll(io, buf, pos);45 const amt = try handle.readPositionalAll(io, buf, pos);
46 if (amt != len) return error.InputOutput;46 if (amt != len) return error.InputOutput;
47 pos += len;47 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;
49 break :name buf[0..actual_len];49 break :name buf[0..actual_len];
50 }50 }
51 unreachable;51 unreachable;
...@@ -161,7 +161,7 @@ pub const ar_hdr = extern struct {...@@ -161,7 +161,7 @@ pub const ar_hdr = extern struct {
161 fn name(self: *const ar_hdr) ?[]const u8 {161 fn name(self: *const ar_hdr) ?[]const u8 {
162 const value = &self.ar_name;162 const value = &self.ar_name;
163 if (mem.startsWith(u8, value, "#1/")) return null;163 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;
165 return value[0..sentinel];165 return value[0..sentinel];
166 }166 }
167167
src/link/MachO/Symbol.zig+1-1
...@@ -43,7 +43,7 @@ pub fn isSymbolStab(symbol: Symbol, macho_file: *MachO) bool {...@@ -43,7 +43,7 @@ pub fn isSymbolStab(symbol: Symbol, macho_file: *MachO) bool {
4343
44pub fn isTlvInit(symbol: Symbol, macho_file: *MachO) bool {44pub fn isTlvInit(symbol: Symbol, macho_file: *MachO) bool {
45 const name = symbol.getName(macho_file);45 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;
47}47}
4848
49pub fn weakRef(symbol: Symbol, macho_file: *MachO) bool {49pub fn weakRef(symbol: Symbol, macho_file: *MachO) bool {
src/link/MachO/ZigObject.zig+4-4
...@@ -946,8 +946,8 @@ fn updateNavCode(...@@ -946,8 +946,8 @@ fn updateNavCode(
946 const target = &mod.resolved_target.result;946 const target = &mod.resolved_target.result;
947 const required_alignment = switch (nav.resolved.?.@"align") {947 const required_alignment = switch (nav.resolved.?.@"align") {
948 .none => switch (mod.optimize_mode) {948 .none => switch (mod.optimize_mode) {
949 .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),949 .debug, .safe, .fast => target_util.defaultFunctionAlignment(target),
950 .ReleaseSmall => target_util.minFunctionAlignment(target),950 .small => target_util.minFunctionAlignment(target),
951 },951 },
952 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),952 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
953 };953 };
...@@ -1172,8 +1172,8 @@ fn getNavOutputSection(...@@ -1172,8 +1172,8 @@ fn getNavOutputSection(
1172 if (nav.resolved.?.@"const") return macho_file.zig_const_sect_index.?;1172 if (nav.resolved.?.@"const") return macho_file.zig_const_sect_index.?;
1173 if (nav_val.isUndef(zcu))1173 if (nav_val.isUndef(zcu))
1174 return switch (zcu.navFileScope(nav_index).mod.?.optimize_mode) {1174 return switch (zcu.navFileScope(nav_index).mod.?.optimize_mode) {
1175 .Debug, .ReleaseSafe => macho_file.zig_data_sect_index.?,1175 .debug, .safe => macho_file.zig_data_sect_index.?,
1176 .ReleaseFast, .ReleaseSmall => macho_file.zig_bss_sect_index.?,1176 .fast, .small => macho_file.zig_bss_sect_index.?,
1177 };1177 };
1178 for (code) |byte| {1178 for (code) |byte| {
1179 if (byte != 0) break;1179 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...@@ -54,7 +54,7 @@ fn putNode(self: *Trie, node_index: Node.Index, allocator: Allocator, label: []c
54 // Check for match with edges from this node.54 // Check for match with edges from this node.
55 for (self.nodes.items(.edges)[node_index].items) |edge_index| {55 for (self.nodes.items(.edges)[node_index].items) |edge_index| {
56 const edge = &self.edges.items[edge_index];56 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;
58 if (match == 0) continue;58 if (match == 0) continue;
59 if (match == edge.label.len) return self.putNode(edge.node, allocator, label[match..]);59 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 {...@@ -351,7 +351,7 @@ fn expectEqualHexStrings(expected: []const u8, given: []const u8) !void {
351 defer testing.allocator.free(expected_fmt);351 defer testing.allocator.free(expected_fmt);
352 const given_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{given});352 const given_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{given});
353 defer testing.allocator.free(given_fmt);353 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).?;
355 const padding = try testing.allocator.alloc(u8, idx + 5);355 const padding = try testing.allocator.alloc(u8, idx + 5);
356 defer testing.allocator.free(padding);356 defer testing.allocator.free(padding);
357 @memset(padding, ' ');357 @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...@@ -62,6 +62,10 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) !u32
62 assume_max_path_len,62 assume_max_path_len,
63 );63 );
64 }64 }
65 // LC_ENCRYPTION_INFO_64
66 if (macho_file.needsEncryptionInfo()) {
67 sizeofcmds += @sizeOf(macho.encryption_info_command_64);
68 }
65 // LC_RPATH69 // LC_RPATH
66 {70 {
67 for (macho_file.rpath_list) |rpath| {71 for (macho_file.rpath_list) |rpath| {
...@@ -163,23 +167,29 @@ pub fn calcLoadCommandsSizeObject(macho_file: *MachO) u32 {...@@ -163,23 +167,29 @@ pub fn calcLoadCommandsSizeObject(macho_file: *MachO) u32 {
163 return @as(u32, @intCast(sizeofcmds));167 return @as(u32, @intCast(sizeofcmds));
164}168}
165169
166pub fn calcMinHeaderPadSize(macho_file: *MachO) !u32 {170pub fn calcMinHeaderSize(macho_file: *MachO) !u32 {
167 var padding: u32 = (try calcLoadCommandsSize(macho_file, false)) +171 var padding: u32 = (try calcLoadCommandsSize(macho_file, false)) +
168 (macho_file.headerpad_size orelse MachO.default_headerpad_size);172 (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
171 if (macho_file.headerpad_max_install_names) {175 if (macho_file.headerpad_max_install_names) {
172 const min_headerpad_size: u32 = try calcLoadCommandsSize(macho_file, true);176 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}", .{
174 min_headerpad_size + @sizeOf(macho.mach_header_64),178 min_headerpad_size + @sizeOf(macho.mach_header_64),
175 });179 });
176 padding = @max(padding, min_headerpad_size);180 padding = @max(padding, min_headerpad_size);
177 }181 }
178182
179 const offset = @sizeOf(macho.mach_header_64) + padding;183 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;
183}193}
184194
185pub fn writeDylinkerLC(writer: *Writer) !void {195pub fn writeDylinkerLC(writer: *Writer) !void {
...@@ -260,6 +270,13 @@ pub fn writeDylibIdLC(macho_file: *MachO, writer: *Writer) !void {...@@ -260,6 +270,13 @@ pub fn writeDylibIdLC(macho_file: *MachO, writer: *Writer) !void {
260 }, writer);270 }, writer);
261}271}
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
263pub fn writeRpathLC(rpath: []const u8, writer: *Writer) !void {280pub fn writeRpathLC(rpath: []const u8, writer: *Writer) !void {
264 const rpath_len = rpath.len + 1;281 const rpath_len = rpath.len + 1;
265 const cmdsize = @as(u32, @intCast(mem.alignForward(282 const cmdsize = @as(u32, @intCast(mem.alignForward(
src/link/MappedFile.zig+93-41
...@@ -23,6 +23,7 @@ nodes: std.ArrayList(Node),...@@ -23,6 +23,7 @@ nodes: std.ArrayList(Node),
23free_ni: Node.Index,23free_ni: Node.Index,
24large: std.ArrayList(u64),24large: std.ArrayList(u64),
25updates: std.ArrayList(Node.Index),25updates: std.ArrayList(Node.Index),
26/// This progress node's estimated total items is increased once for each node appended to `updates`.
26update_prog_node: std.Progress.Node,27update_prog_node: std.Progress.Node,
27writers: std.SinglyLinkedList,28writers: std.SinglyLinkedList,
28io_err: ?IoError,29io_err: ?IoError,
...@@ -61,7 +62,7 @@ pub const Error = Allocator.Error || Io.Cancelable || error{...@@ -61,7 +62,7 @@ pub const Error = Allocator.Error || Io.Cancelable || error{
61 MappedFileIo,62 MappedFileIo,
62};63};
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 {
65 var mf: MappedFile = .{66 var mf: MappedFile = .{
66 .io = io,67 .io = io,
67 .flags = undefined,68 .flags = undefined,
...@@ -105,7 +106,7 @@ pub fn init(file: Io.File, gpa: std.mem.Allocator, io: Io) (Allocator.Error || I...@@ -105,7 +106,7 @@ pub fn init(file: Io.File, gpa: std.mem.Allocator, io: Io) (Allocator.Error || I
105 return mf;106 return mf;
106}107}
107108
108pub fn deinit(mf: *MappedFile, gpa: std.mem.Allocator) void {109pub fn deinit(mf: *MappedFile, gpa: Allocator) void {
109 mf.unmap();110 mf.unmap();
110 mf.nodes.deinit(gpa);111 mf.nodes.deinit(gpa);
111 mf.large.deinit(gpa);112 mf.large.deinit(gpa);
...@@ -133,11 +134,15 @@ pub const Node = extern struct {...@@ -133,11 +134,15 @@ pub const Node = extern struct {
133 moved: bool,134 moved: bool,
134 /// Whether this node has been resized.135 /// Whether this node has been resized.
135 resized: bool,136 resized: bool,
137 /// Whether the next sibling has moved or is a different node.
138 next_moved: bool,
136 /// Whether this node might contain non-zero bytes.139 /// Whether this node might contain non-zero bytes.
137 has_content: bool,140 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.
139 bubbles_moved: bool,142 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,
141 };146 };
142147
143 pub const Location = union(enum(u1)) {148 pub const Location = union(enum(u1)) {
...@@ -191,6 +196,22 @@ pub const Node = extern struct {...@@ -191,6 +196,22 @@ pub const Node = extern struct {
191 pub fn next(ni: Node.Index, mf: *const MappedFile) Node.Index {196 pub fn next(ni: Node.Index, mf: *const MappedFile) Node.Index {
192 return ni.get(mf).next;197 return ni.get(mf).next;
193 }198 }
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
195 pub fn ChildIterator(comptime direction: enum { prev, next }) type {216 pub fn ChildIterator(comptime direction: enum { prev, next }) type {
196 return struct {217 return struct {
...@@ -211,7 +232,7 @@ pub const Node = extern struct {...@@ -211,7 +232,7 @@ pub const Node = extern struct {
211 return .{ .mf = mf, .ni = ni.get(mf).last };232 return .{ .mf = mf, .ni = ni.get(mf).last };
212 }233 }
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 {
215 var child_ni = ni.get(mf).last;236 var child_ni = ni.get(mf).last;
216 while (child_ni != .none) {237 while (child_ni != .none) {
217 try child_ni.moved(gpa, mf);238 try child_ni.moved(gpa, mf);
...@@ -229,11 +250,11 @@ pub const Node = extern struct {...@@ -229,11 +250,11 @@ pub const Node = extern struct {
229 }250 }
230 return false;251 return false;
231 }252 }
232 pub fn moved(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) Allocator.Error!void {253 pub fn moved(ni: Node.Index, gpa: Allocator, mf: *MappedFile) Allocator.Error!void {
233 try mf.updates.ensureUnusedCapacity(gpa, 1);254 try mf.updates.ensureUnusedCapacity(gpa, 2);
234 ni.movedAssumeCapacity(mf);255 ni.movedAssumeCapacity(mf);
235 }256 }
236 pub fn cleanMoved(ni: Node.Index, mf: *const MappedFile) bool {257 pub fn cleanMoved(ni: Node.Index, mf: *MappedFile) bool {
237 const node_moved = &ni.get(mf).flags.moved;258 const node_moved = &ni.get(mf).flags.moved;
238 defer node_moved.* = false;259 defer node_moved.* = false;
239 return node_moved.*;260 return node_moved.*;
...@@ -242,7 +263,11 @@ pub const Node = extern struct {...@@ -242,7 +263,11 @@ pub const Node = extern struct {
242 if (ni.hasMoved(mf)) return;263 if (ni.hasMoved(mf)) return;
243 const node = ni.get(mf);264 const node = ni.get(mf);
244 node.flags.moved = true;265 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;
246 mf.updates.appendAssumeCapacity(ni);271 mf.updates.appendAssumeCapacity(ni);
247 mf.update_prog_node.increaseEstimatedTotalItems(1);272 mf.update_prog_node.increaseEstimatedTotalItems(1);
248 }273 }
...@@ -250,11 +275,11 @@ pub const Node = extern struct {...@@ -250,11 +275,11 @@ pub const Node = extern struct {
250 pub fn hasResized(ni: Node.Index, mf: *const MappedFile) bool {275 pub fn hasResized(ni: Node.Index, mf: *const MappedFile) bool {
251 return ni.get(mf).flags.resized;276 return ni.get(mf).flags.resized;
252 }277 }
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 {
254 try mf.updates.ensureUnusedCapacity(gpa, 1);279 try mf.updates.ensureUnusedCapacity(gpa, 1);
255 ni.resizedAssumeCapacity(mf);280 ni.resizedAssumeCapacity(mf);
256 }281 }
257 pub fn cleanResized(ni: Node.Index, mf: *const MappedFile) bool {282 pub fn cleanResized(ni: Node.Index, mf: *MappedFile) bool {
258 const node_resized = &ni.get(mf).flags.resized;283 const node_resized = &ni.get(mf).flags.resized;
259 defer node_resized.* = false;284 defer node_resized.* = false;
260 return node_resized.*;285 return node_resized.*;
...@@ -263,7 +288,28 @@ pub const Node = extern struct {...@@ -263,7 +288,28 @@ pub const Node = extern struct {
263 const node = ni.get(mf);288 const node = ni.get(mf);
264 if (node.flags.resized) return;289 if (node.flags.resized) return;
265 node.flags.resized = true;290 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;
267 mf.updates.appendAssumeCapacity(ni);313 mf.updates.appendAssumeCapacity(ni);
268 mf.update_prog_node.increaseEstimatedTotalItems(1);314 mf.update_prog_node.increaseEstimatedTotalItems(1);
269 }315 }
...@@ -333,7 +379,7 @@ pub const Node = extern struct {...@@ -333,7 +379,7 @@ pub const Node = extern struct {
333 return mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)];379 return mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)];
334 }380 }
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 {
337 mf.resizeNode(gpa, ni, size) catch |err| switch (err) {383 mf.resizeNode(gpa, ni, size) catch |err| switch (err) {
338 error.OutOfMemory,384 error.OutOfMemory,
339 error.Canceled,385 error.Canceled,
...@@ -360,7 +406,7 @@ pub const Node = extern struct {...@@ -360,7 +406,7 @@ pub const Node = extern struct {
360 pub fn realign(406 pub fn realign(
361 ni: Node.Index,407 ni: Node.Index,
362 mf: *MappedFile,408 mf: *MappedFile,
363 gpa: std.mem.Allocator,409 gpa: Allocator,
364 new_alignment: std.mem.Alignment,410 new_alignment: std.mem.Alignment,
365 opts: RealignNodeOptions,411 opts: RealignNodeOptions,
366 ) Error!void {412 ) Error!void {
...@@ -384,7 +430,7 @@ pub const Node = extern struct {...@@ -384,7 +430,7 @@ pub const Node = extern struct {
384 pub fn shrink(430 pub fn shrink(
385 ni: Node.Index,431 ni: Node.Index,
386 mf: *MappedFile,432 mf: *MappedFile,
387 gpa: std.mem.Allocator,433 gpa: Allocator,
388 size: u64,434 size: u64,
389 shift_next: bool,435 shift_next: bool,
390 ) Error!void {436 ) Error!void {
...@@ -392,7 +438,7 @@ pub const Node = extern struct {...@@ -392,7 +438,7 @@ pub const Node = extern struct {
392 mf.updateWriters();438 mf.updateWriters();
393 }439 }
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 {
396 w.* = .{442 w.* = .{
397 .gpa = gpa,443 .gpa = gpa,
398 .mf = mf,444 .mf = mf,
...@@ -419,7 +465,7 @@ pub const Node = extern struct {...@@ -419,7 +465,7 @@ pub const Node = extern struct {
419 }465 }
420466
421 pub const Writer = struct {467 pub const Writer = struct {
422 gpa: std.mem.Allocator,468 gpa: Allocator,
423 mf: *MappedFile,469 mf: *MappedFile,
424 writer_node: std.SinglyLinkedList.Node,470 writer_node: std.SinglyLinkedList.Node,
425 ni: Node.Index,471 ni: Node.Index,
...@@ -543,14 +589,13 @@ pub const Node = extern struct {...@@ -543,14 +589,13 @@ pub const Node = extern struct {
543 }589 }
544};590};
545591
546fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {592fn addNode(mf: *MappedFile, gpa: Allocator, opts: struct {
547 parent: Node.Index = .none,593 parent: Node.Index = .none,
548 prev: Node.Index = .none,594 prev: Node.Index = .none,
549 next: Node.Index = .none,595 next: Node.Index = .none,
550 offset: u64 = 0,596 offset: u64 = 0,
551 add_node: AddNodeOptions,597 add_node: AddNodeOptions,
552}) (Allocator.Error || Io.Cancelable || IoError)!Node.Index {598}) (Allocator.Error || Io.Cancelable || IoError)!Node.Index {
553 if (opts.add_node.moved or opts.add_node.resized) try mf.updates.ensureUnusedCapacity(gpa, 1);
554 mf.nodes_lock.assertUnlocked();599 mf.nodes_lock.assertUnlocked();
555 const location_tag: Node.Location.Tag, const location_payload: Node.Location.Payload = location: {600 const location_tag: Node.Location.Tag, const location_payload: Node.Location.Payload = location: {
556 if (std.math.cast(u32, opts.offset)) |small_offset| break :location .{ .small, .{601 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 {...@@ -570,7 +615,7 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {
570 };615 };
571 switch (opts.prev) {616 switch (opts.prev) {
572 .none => opts.parent.get(mf).first = free_ni,617 .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),
574 }619 }
575 switch (opts.next) {620 switch (opts.next) {
576 .none => opts.parent.get(mf).last = free_ni,621 .none => opts.parent.get(mf).last = free_ni,
...@@ -588,22 +633,27 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {...@@ -588,22 +633,27 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {
588 .fixed = opts.add_node.fixed,633 .fixed = opts.add_node.fixed,
589 .moved = true,634 .moved = true,
590 .resized = true,635 .resized = true,
636 .next_moved = true,
591 .has_content = false,637 .has_content = false,
592 .bubbles_moved = opts.add_node.bubbles_moved,638 .bubbles_moved = opts.add_node.bubbles_moved,
639 .enable_next_moved = opts.add_node.enable_next_moved,
593 },640 },
594 .location_payload = location_payload,641 .location_payload = location_payload,
595 };642 };
596643
597 {644 {
645 defer {
646 free_node.flags.moved = false;
647 free_node.flags.resized = false;
648 free_node.flags.next_moved = false;
649 }
598 try mf.realignNode(gpa, free_ni, opts.add_node.alignment, .{});650 try mf.realignNode(gpa, free_ni, opts.add_node.alignment, .{});
599 try mf.resizeNode(gpa, free_ni, opts.add_node.size);651 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;
603 }652 }
604 if (opts.add_node.moved) free_ni.movedAssumeCapacity(mf);
605 if (opts.add_node.resized) free_ni.resizedAssumeCapacity(mf);
606 mf.updateWriters();653 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);
607 return free_ni;657 return free_ni;
608}658}
609659
...@@ -613,12 +663,14 @@ pub const AddNodeOptions = struct {...@@ -613,12 +663,14 @@ pub const AddNodeOptions = struct {
613 fixed: bool = false,663 fixed: bool = false,
614 moved: bool = false,664 moved: bool = false,
615 resized: bool = false,665 resized: bool = false,
666 next_moved: bool = false,
616 bubbles_moved: bool = true,667 bubbles_moved: bool = true,
668 enable_next_moved: bool = false,
617};669};
618670
619pub fn addOnlyChildNode(671pub fn addOnlyChildNode(
620 mf: *MappedFile,672 mf: *MappedFile,
621 gpa: std.mem.Allocator,673 gpa: Allocator,
622 parent_ni: Node.Index,674 parent_ni: Node.Index,
623 opts: AddNodeOptions,675 opts: AddNodeOptions,
624) Error!Node.Index {676) Error!Node.Index {
...@@ -641,7 +693,7 @@ pub fn addOnlyChildNode(...@@ -641,7 +693,7 @@ pub fn addOnlyChildNode(
641693
642pub fn addFirstChildNode(694pub fn addFirstChildNode(
643 mf: *MappedFile,695 mf: *MappedFile,
644 gpa: std.mem.Allocator,696 gpa: Allocator,
645 parent_ni: Node.Index,697 parent_ni: Node.Index,
646 opts: AddNodeOptions,698 opts: AddNodeOptions,
647) Error!Node.Index {699) Error!Node.Index {
...@@ -664,7 +716,7 @@ pub fn addFirstChildNode(...@@ -664,7 +716,7 @@ pub fn addFirstChildNode(
664716
665pub fn addLastChildNode(717pub fn addLastChildNode(
666 mf: *MappedFile,718 mf: *MappedFile,
667 gpa: std.mem.Allocator,719 gpa: Allocator,
668 parent_ni: Node.Index,720 parent_ni: Node.Index,
669 opts: AddNodeOptions,721 opts: AddNodeOptions,
670) Error!Node.Index {722) Error!Node.Index {
...@@ -694,7 +746,7 @@ pub fn addLastChildNode(...@@ -694,7 +746,7 @@ pub fn addLastChildNode(
694746
695pub fn addNodeAfter(747pub fn addNodeAfter(
696 mf: *MappedFile,748 mf: *MappedFile,
697 gpa: std.mem.Allocator,749 gpa: Allocator,
698 prev_ni: Node.Index,750 prev_ni: Node.Index,
699 opts: AddNodeOptions,751 opts: AddNodeOptions,
700) Error!Node.Index {752) Error!Node.Index {
...@@ -721,7 +773,7 @@ pub fn addNodeAfter(...@@ -721,7 +773,7 @@ pub fn addNodeAfter(
721773
722fn shrinkNode(774fn shrinkNode(
723 mf: *MappedFile,775 mf: *MappedFile,
724 gpa: std.mem.Allocator,776 gpa: Allocator,
725 ni: Node.Index,777 ni: Node.Index,
726 size: u64,778 size: u64,
727 shift_next: bool,779 shift_next: bool,
...@@ -740,7 +792,7 @@ fn shrinkNode(...@@ -740,7 +792,7 @@ fn shrinkNode(
740 }792 }
741793
742 try mf.large.ensureUnusedCapacity(gpa, 4);794 try mf.large.ensureUnusedCapacity(gpa, 4);
743 try mf.updates.ensureUnusedCapacity(gpa, 2);795 try mf.updates.ensureUnusedCapacity(gpa, 4);
744796
745 ni.setLocationAssumeCapacity(mf, old_offset, size);797 ni.setLocationAssumeCapacity(mf, old_offset, size);
746 if (!shift_next or node.next == .none) return;798 if (!shift_next or node.next == .none) return;
...@@ -765,7 +817,7 @@ fn shrinkNode(...@@ -765,7 +817,7 @@ fn shrinkNode(
765817
766fn resizeNode(818fn resizeNode(
767 mf: *MappedFile,819 mf: *MappedFile,
768 gpa: std.mem.Allocator,820 gpa: Allocator,
769 ni: Node.Index,821 ni: Node.Index,
770 requested_size: u64,822 requested_size: u64,
771) (Allocator.Error || Io.Cancelable || IoError)!void {823) (Allocator.Error || Io.Cancelable || IoError)!void {
...@@ -904,11 +956,11 @@ fn resizeNode(...@@ -904,11 +956,11 @@ fn resizeNode(
904 next_ni.get(mf).prev = node.prev;956 next_ni.get(mf).prev = node.prev;
905 switch (node.prev) {957 switch (node.prev) {
906 .none => parent.first = next_ni,958 .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),
908 }960 }
909 last.next = ni;961 try parent.last.setNext(gpa, ni, mf);
910 node.prev = parent.last;962 node.prev = parent.last;
911 node.next = .none;963 try ni.setNext(gpa, .none, mf);
912 parent.last = ni;964 parent.last = ni;
913 if (node.flags.has_content) {965 if (node.flags.has_content) {
914 const parent_file_offset = node.parent.fileLocation(mf, false).offset;966 const parent_file_offset = node.parent.fileLocation(mf, false).offset;
...@@ -972,13 +1024,13 @@ fn resizeNode(...@@ -972,13 +1024,13 @@ fn resizeNode(
972 if (parent.last != first_floating_ni) {1024 if (parent.last != first_floating_ni) {
973 first_floating.prev = parent.last;1025 first_floating.prev = parent.last;
974 parent.last = first_floating_ni;1026 parent.last = first_floating_ni;
975 last.next = first_floating_ni;1027 try parent.last.setNext(gpa, first_floating_ni, mf);
976 last_fixed.next = first_floating.next;1028 try last_fixed_ni.setNext(gpa, first_floating.next, mf);
977 switch (first_floating.next) {1029 switch (first_floating.next) {
978 .none => {},1030 .none => {},
979 else => |next_ni| next_ni.get(mf).prev = last_fixed_ni,1031 else => |next_ni| next_ni.get(mf).prev = last_fixed_ni,
980 }1032 }
981 first_floating.next = .none;1033 try first_floating_ni.setNext(gpa, .none, mf);
982 }1034 }
983 if (first_floating.flags.has_content) {1035 if (first_floating.flags.has_content) {
984 const parent_file_offset =1036 const parent_file_offset =
...@@ -1040,7 +1092,7 @@ fn resizeNode(...@@ -1040,7 +1092,7 @@ fn resizeNode(
10401092
1041fn realignNode(1093fn realignNode(
1042 mf: *MappedFile,1094 mf: *MappedFile,
1043 gpa: std.mem.Allocator,1095 gpa: Allocator,
1044 ni: Node.Index,1096 ni: Node.Index,
1045 new_alignment: std.mem.Alignment,1097 new_alignment: std.mem.Alignment,
1046 opts: Node.Index.RealignNodeOptions,1098 opts: Node.Index.RealignNodeOptions,
...@@ -1241,9 +1293,9 @@ fn copyFileRange(...@@ -1241,9 +1293,9 @@ fn copyFileRange(
1241 return size - remaining_size;1293 return size - remaining_size;
1242}1294}
12431295
1244fn ensureCapacityForSetLocation(mf: *MappedFile, gpa: std.mem.Allocator) Allocator.Error!void {1296fn ensureCapacityForSetLocation(mf: *MappedFile, gpa: Allocator) Allocator.Error!void {
1245 try mf.large.ensureUnusedCapacity(gpa, 2);1297 try mf.large.ensureUnusedCapacity(gpa, 2);
1246 try mf.updates.ensureUnusedCapacity(gpa, 1);1298 try mf.updates.ensureUnusedCapacity(gpa, 2);
1247}1299}
12481300
1249pub fn ensureTotalCapacity(mf: *MappedFile, new_capacity: usize) Error!void {1301pub 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");...@@ -25,10 +25,10 @@ const Mir = @import("../codegen/spirv/Mir.zig");
25const Linker = @This();25const Linker = @This();
2626
27base: link.File,27base: link.File,
28fragments: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, Mir) = .empty,28fragments: std.array_hash_map.Auto(InternPool.Nav.Index, Mir) = .empty,
29pending_navs: std.ArrayListUnmanaged(InternPool.Nav.Index) = .empty,29pending_navs: std.ArrayList(InternPool.Nav.Index) = .empty,
30entry_points: std.ArrayListUnmanaged(EntryPointDecl) = .empty,30entry_points: std.ArrayList(EntryPointDecl) = .empty,
31external_objects: std.ArrayListUnmanaged(ExternalObject) = .empty,31external_objects: std.ArrayList(ExternalObject) = .empty,
3232
33const EntryPointDecl = struct {33const EntryPointDecl = struct {
34 nav: InternPool.Nav.Index,34 nav: InternPool.Nav.Index,
...@@ -363,16 +363,16 @@ fn mergeFragments(linker: *Linker, gpa: Allocator, arena: Allocator) error{OutOf...@@ -363,16 +363,16 @@ fn mergeFragments(linker: *Linker, gpa: Allocator, arena: Allocator) error{OutOf
363 }363 }
364364
365 // Resolve Zig extern navs against external objects.365 // 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;
367 defer ext_id_offsets.deinit(gpa);367 defer ext_id_offsets.deinit(gpa);
368 try ext_id_offsets.ensureTotalCapacity(gpa, linker.external_objects.items.len);368 try ext_id_offsets.ensureTotalCapacity(gpa, linker.external_objects.items.len);
369369
370 var unresolved_extern_count: u32 = 0;370 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;
372 defer resolved_ids.deinit(gpa);372 defer resolved_ids.deinit(gpa);
373373
374 if (maybe_ip) |ip| {374 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;
376 defer extern_name_map.deinit(gpa);376 defer extern_name_map.deinit(gpa);
377377
378 var nav_it = nav_final_ids.iterator();378 var nav_it = nav_final_ids.iterator();
...@@ -518,14 +518,14 @@ fn mergeZigFragments(...@@ -518,14 +518,14 @@ fn mergeZigFragments(
518 frag_infos: []const FragmentInfo,518 frag_infos: []const FragmentInfo,
519 nav_final_ids: *const std.AutoHashMapUnmanaged(InternPool.Nav.Index, Id),519 nav_final_ids: *const std.AutoHashMapUnmanaged(InternPool.Nav.Index, Id),
520 uav_final_ids: *const std.AutoHashMapUnmanaged(struct { InternPool.Index, spec.StorageClass }, Id),520 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),
522 maybe_ip: ?*InternPool,522 maybe_ip: ?*InternPool,
523) error{OutOfMemory}!void {523) error{OutOfMemory}!void {
524 for (linker.fragments.values(), frag_infos) |*mir, frag_info| {524 for (linker.fragments.values(), frag_infos) |*mir, frag_info| {
525 var id_remap: std.AutoHashMapUnmanaged(Id, Id) = .empty;525 var id_remap: std.AutoHashMapUnmanaged(Id, Id) = .empty;
526 defer id_remap.deinit(gpa);526 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;
529 defer resolved_local_ids.deinit(gpa);529 defer resolved_local_ids.deinit(gpa);
530530
531 for (mir.nav_refs) |ref| {531 for (mir.nav_refs) |ref| {
...@@ -569,7 +569,7 @@ fn remapFilteredInsts(...@@ -569,7 +569,7 @@ fn remapFilteredInsts(
569 id_offset: Word,569 id_offset: Word,
570 id_remap: *const std.AutoHashMapUnmanaged(Id, Id),570 id_remap: *const std.AutoHashMapUnmanaged(Id, Id),
571 parser: *BinaryModule.Parser,571 parser: *BinaryModule.Parser,
572 skip_ids: *const std.AutoArrayHashMapUnmanaged(Id, void),572 skip_ids: *const std.array_hash_map.Auto(Id, void),
573 mode: FilterMode,573 mode: FilterMode,
574) error{OutOfMemory}!void {574) error{OutOfMemory}!void {
575 if (words.len == 0) return;575 if (words.len == 0) return;
...@@ -887,9 +887,9 @@ fn appendExternalObjects(...@@ -887,9 +887,9 @@ fn appendExternalObjects(
887 has_linkage: *bool,887 has_linkage: *bool,
888 keep_entry_points: bool,888 keep_entry_points: bool,
889 is_obj: bool,889 is_obj: bool,
890 resolved_ids: *const std.AutoArrayHashMapUnmanaged(Id, void),890 resolved_ids: *const std.array_hash_map.Auto(Id, void),
891) error{OutOfMemory}!void {891) error{OutOfMemory}!void {
892 var export_map: std.StringArrayHashMapUnmanaged(Id) = .empty;892 var export_map: std.array_hash_map.String(Id) = .empty;
893 defer export_map.deinit(gpa);893 defer export_map.deinit(gpa);
894894
895 for (linker.external_objects.items, ext_id_offsets) |ext_obj, id_offset| {895 for (linker.external_objects.items, ext_id_offsets) |ext_obj, id_offset| {
...@@ -908,7 +908,7 @@ fn appendExternalObjects(...@@ -908,7 +908,7 @@ fn appendExternalObjects(
908 }908 }
909 for (per_obj_remaps) |*m| m.* = .empty;909 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;
912 defer resolved_linkage_ids.deinit(gpa);912 defer resolved_linkage_ids.deinit(gpa);
913913
914 for (resolved_ids.keys()) |id| {914 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 {...@@ -85,7 +85,7 @@ pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule) !void {
8585
86 for (inst.operands, 0..) |word, i| {86 for (inst.operands, 0..) |word, i| {
87 if (i == result_id_index) continue;87 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) {
89 const canonical = id_remap.get(@fromBackingInt(@intCast(word))) orelse @as(Id, @fromBackingInt(@intCast(word)));89 const canonical = id_remap.get(@fromBackingInt(@intCast(word))) orelse @as(Id, @fromBackingInt(@intCast(word)));
90 try key_words.append(gpa, @backingInt(canonical));90 try key_words.append(gpa, @backingInt(canonical));
91 } else {91 } else {
...@@ -182,7 +182,7 @@ pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule) !void {...@@ -182,7 +182,7 @@ pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule) !void {
182 } else null;182 } else null;
183183
184 for (inst_slice, 0..) |*word, i| {184 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;
186 max_id = @max(max_id, word.*);186 max_id = @max(max_id, word.*);
187 if (maybe_result_id_index != null and i == maybe_result_id_index.?) continue;187 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(...@@ -187,7 +187,7 @@ fn markAlive(
187 parser: *BinaryModule.Parser,187 parser: *BinaryModule.Parser,
188 binary: BinaryModule,188 binary: BinaryModule,
189 inst: BinaryModule.Instruction,189 inst: BinaryModule.Instruction,
190 alive: *std.DynamicBitSetUnmanaged,190 alive: *std.bit_set.Dynamic,
191 id_to_index: *const std.AutoHashMapUnmanaged(ResultId, u32),191 id_to_index: *const std.AutoHashMapUnmanaged(ResultId, u32),
192 code_offsets: *const std.ArrayList(usize),192 code_offsets: *const std.ArrayList(usize),
193 id_offset_buf: *std.ArrayList(u16),193 id_offset_buf: *std.ArrayList(u16),
src/link/Wasm.zig+953-206
...@@ -133,25 +133,21 @@ object_total_sections: u32 = 0,...@@ -133,25 +133,21 @@ object_total_sections: u32 = 0,
133/// All comdat symbols from all objects concatenated.133/// All comdat symbols from all objects concatenated.
134object_comdat_symbols: std.MultiArrayList(Comdat.Symbol) = .empty,134object_comdat_symbols: std.MultiArrayList(Comdat.Symbol) = .empty,
135135
136/// Relocations to be emitted into an object file. Remains empty when not136/// Relocations produced by Zig code and data lowering. These retain semantic
137/// emitting an object file.137/// targets until `flush`, where final output indexes are known.
138out_relocs: std.MultiArrayList(OutReloc) = .empty,138zcu_relocations: std.MultiArrayList(ZcuRelocation) = .empty,
139/// List of locations within `string_bytes` that must be patched with the virtual139/// List of locations within `string_bytes` that must be patched with the virtual
140/// memory address of a Uav during `flush`.140/// 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.
142uav_fixups: std.ArrayList(UavFixup) = .empty,142uav_fixups: std.ArrayList(UavFixup) = .empty,
143/// List of locations within `string_bytes` that must be patched with the virtual143/// List of locations within `string_bytes` that must be patched with the virtual
144/// memory address of a Nav during `flush`.144/// 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.
146/// No functions here only global variables.146/// No functions here only global variables.
147nav_fixups: std.ArrayList(NavFixup) = .empty,147nav_fixups: std.ArrayList(NavFixup) = .empty,
148/// When a nav reference is a function pointer, this tracks the required function148/// When a nav reference is a function pointer, this tracks the required function
149/// table entry index that needs to overwrite the code in the final output.149/// table entry index that needs to overwrite the code in the final output.
150func_table_fixups: std.ArrayList(FuncTableFixup) = .empty,150func_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
155/// When importing objects from the host environment, a name must be supplied.151/// When importing objects from the host environment, a name must be supplied.
156/// LLVM uses "env" by default when none is given.152/// LLVM uses "env" by default when none is given.
157/// This value is passed to object files since wasm tooling conventions provides153/// 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,...@@ -244,7 +240,9 @@ function_imports: std.array_hash_map.Auto(String, FunctionImportId) = .empty,
244/// remove elements from the table, and the remainder are either undefined240/// remove elements from the table, and the remainder are either undefined
245/// symbol errors, or symbol table entries depending on the output mode.241/// symbol errors, or symbol table entries depending on the output mode.
246data_imports: std.array_hash_map.Auto(String, DataImportId) = .empty,242data_imports: std.array_hash_map.Auto(String, DataImportId) = .empty,
247/// Set of data symbols that will appear in the final binary. Used to populate243/// 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
248/// `Flush.data_segments` before sorting.246/// `Flush.data_segments` before sorting.
249data_segments: std.array_hash_map.Auto(DataSegmentId, void) = .empty,247data_segments: std.array_hash_map.Auto(DataSegmentId, void) = .empty,
250248
...@@ -302,11 +300,6 @@ pub const TagNameOff = extern struct {...@@ -302,11 +300,6 @@ pub const TagNameOff = extern struct {
302 len: u32,300 len: u32,
303};301};
304302
305/// Index into `Wasm.zcu_indirect_function_set`.
306pub const ZcuIndirectFunctionSetIndex = enum(u32) {
307 _,
308};
309
310pub const UavFixup = extern struct {303pub const UavFixup = extern struct {
311 uavs_exe_index: UavsExeIndex,304 uavs_exe_index: UavsExeIndex,
312 /// Index into `string_bytes`.305 /// Index into `string_bytes`.
...@@ -315,14 +308,14 @@ pub const UavFixup = extern struct {...@@ -315,14 +308,14 @@ pub const UavFixup = extern struct {
315};308};
316309
317pub const NavFixup = extern struct {310pub const NavFixup = extern struct {
318 navs_exe_index: NavsExeIndex,311 nav_index: InternPool.Nav.Index,
319 /// Index into `string_bytes`.312 /// Index into `string_bytes`.
320 offset: u32,313 offset: u32,
321 addend: u32,314 addend: u32,
322};315};
323316
324pub const FuncTableFixup = extern struct {317pub const FuncTableFixup = extern struct {
325 table_index: ZcuIndirectFunctionSetIndex,318 nav_index: InternPool.Nav.Index,
326 /// Index into `string_bytes`.319 /// Index into `string_bytes`.
327 offset: u32,320 offset: u32,
328};321};
...@@ -355,7 +348,9 @@ pub const FunctionIndex = enum(u32) {...@@ -355,7 +348,9 @@ pub const FunctionIndex = enum(u32) {
355348
356 pub fn fromSymbolName(wasm: *const Wasm, name: String) ?FunctionIndex {349 pub fn fromSymbolName(wasm: *const Wasm, name: String) ?FunctionIndex {
357 if (wasm.object_function_imports.getPtr(name)) |import| {350 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 }
359 }354 }
360 if (wasm.function_exports.get(name)) |index| return index;355 if (wasm.function_exports.get(name)) |index| return index;
361 if (wasm.hidden_function_exports.get(name)) |index| return index;356 if (wasm.hidden_function_exports.get(name)) |index| return index;
...@@ -374,7 +369,8 @@ pub const GlobalExport = extern struct {...@@ -374,7 +369,8 @@ pub const GlobalExport = extern struct {
374};369};
375370
376/// 0. Index into `Flush.function_imports`371/// 0. Index into `Flush.function_imports`
377/// 1. Index into `functions`.372/// 1. Index into `Flush.intrinsic_function_imports`
373/// 2. Index into `functions`.
378///374///
379/// Note that function_imports indexes are subject to swap removals during375/// Note that function_imports indexes are subject to swap removals during
380/// `flush`.376/// `flush`.
...@@ -386,7 +382,11 @@ pub const OutputFunctionIndex = enum(u32) {...@@ -386,7 +382,11 @@ pub const OutputFunctionIndex = enum(u32) {
386 }382 }
387383
388 pub fn fromFunctionIndex(wasm: *const Wasm, index: FunctionIndex) OutputFunctionIndex {384 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 ));
390 }390 }
391391
392 pub fn fromObjectFunction(wasm: *const Wasm, index: ObjectFunctionIndex) OutputFunctionIndex {392 pub fn fromObjectFunction(wasm: *const Wasm, index: ObjectFunctionIndex) OutputFunctionIndex {
...@@ -429,6 +429,9 @@ pub const OutputFunctionIndex = enum(u32) {...@@ -429,6 +429,9 @@ pub const OutputFunctionIndex = enum(u32) {
429429
430 pub fn fromSymbolName(wasm: *const Wasm, name: String) OutputFunctionIndex {430 pub fn fromSymbolName(wasm: *const Wasm, name: String) OutputFunctionIndex {
431 if (wasm.flush_buffer.function_imports.getIndex(name)) |i| return @fromBackingInt(@intCast(i));431 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 ));
432 return fromFunctionIndex(wasm, FunctionIndex.fromSymbolName(wasm, name) orelse {435 return fromFunctionIndex(wasm, FunctionIndex.fromSymbolName(wasm, name) orelse {
433 if (std.debug.runtime_safety) {436 if (std.debug.runtime_safety) {
434 std.debug.panic("function index for symbol not found: {s}", .{name.slice(wasm)});437 std.debug.panic("function index for symbol not found: {s}", .{name.slice(wasm)});
...@@ -437,6 +440,56 @@ pub const OutputFunctionIndex = enum(u32) {...@@ -437,6 +440,56 @@ pub const OutputFunctionIndex = enum(u32) {
437 }440 }
438};441};
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
440/// Index into `Wasm.globals`.493/// Index into `Wasm.globals`.
441pub const GlobalIndex = enum(u32) {494pub const GlobalIndex = enum(u32) {
442 _,495 _,
...@@ -452,17 +505,17 @@ pub const GlobalIndex = enum(u32) {...@@ -452,17 +505,17 @@ pub const GlobalIndex = enum(u32) {
452 return .stack_pointer;505 return .stack_pointer;
453 }506 }
454507
455 pub fn ptr(index: GlobalIndex, f: *const Flush) *Wasm.GlobalImport.Resolution {508 pub fn fromResolution(wasm: *const Wasm, resolution: GlobalImport.Resolution) ?GlobalIndex {
456 return &f.globals.items[@backingInt(index)];509 const i = wasm.globals.getIndex(resolution) orelse return null;
510 return @fromBackingInt(@intCast(wasm.flush_buffer.global_imports.entries.len + i));
457 }511 }
458512
459 pub fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) ?GlobalIndex {513 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;514 return fromResolution(wasm, .fromIpNav(wasm, nav_index));
461 return @fromBackingInt(@intCast(i));
462 }515 }
463516
464 pub fn fromObjectGlobal(wasm: *const Wasm, i: ObjectGlobalIndex) GlobalIndex {517 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)).?;
466 }519 }
467520
468 pub fn fromObjectGlobalHandlingWeak(wasm: *const Wasm, index: ObjectGlobalIndex) GlobalIndex {521 pub fn fromObjectGlobalHandlingWeak(wasm: *const Wasm, index: ObjectGlobalIndex) GlobalIndex {
...@@ -474,8 +527,9 @@ pub const GlobalIndex = enum(u32) {...@@ -474,8 +527,9 @@ pub const GlobalIndex = enum(u32) {
474 }527 }
475528
476 pub fn fromSymbolName(wasm: *const Wasm, name: String) GlobalIndex {529 pub fn fromSymbolName(wasm: *const Wasm, name: String) GlobalIndex {
530 if (wasm.flush_buffer.global_imports.getIndex(name)) |i| return @fromBackingInt(@intCast(i));
477 const import = wasm.object_global_imports.getPtr(name).?;531 const import = wasm.object_global_imports.getPtr(name).?;
478 return @fromBackingInt(@intCast(wasm.globals.getIndex(import.resolution).?));532 return fromResolution(wasm, import.resolution).?;
479 }533 }
480};534};
481535
...@@ -483,10 +537,6 @@ pub const GlobalIndex = enum(u32) {...@@ -483,10 +537,6 @@ pub const GlobalIndex = enum(u32) {
483pub const TableIndex = enum(u32) {537pub const TableIndex = enum(u32) {
484 _,538 _,
485539
486 pub fn ptr(index: TableIndex, f: *const Flush) *Wasm.TableImport.Resolution {
487 return &f.tables.items[@backingInt(index)];
488 }
489
490 pub fn fromObjectTable(wasm: *const Wasm, i: ObjectTableIndex) TableIndex {540 pub fn fromObjectTable(wasm: *const Wasm, i: ObjectTableIndex) TableIndex {
491 return @fromBackingInt(@intCast(wasm.tables.getIndex(.fromObjectTable(i)).?));541 return @fromBackingInt(@intCast(wasm.tables.getIndex(.fromObjectTable(i)).?));
492 }542 }
...@@ -668,9 +718,10 @@ pub const SymbolFlags = packed struct(u32) {...@@ -668,9 +718,10 @@ pub const SymbolFlags = packed struct(u32) {
668 flags.ref_type = .funcref;718 flags.ref_type = .funcref;
669 }719 }
670720
671 pub fn isIncluded(flags: SymbolFlags, is_dynamic: bool) bool {721 pub fn isIncluded(flags: SymbolFlags, is_dynamic: bool, is_obj: bool) bool {
672 return flags.exported or722 return flags.exported or
673 (is_dynamic and !flags.visibility_hidden) or723 (is_dynamic and !flags.visibility_hidden) or
724 (is_obj and flags.binding != .local) or
674 (flags.no_strip and flags.must_link);725 (flags.no_strip and flags.must_link);
675 }726 }
676727
...@@ -696,8 +747,8 @@ pub const SymbolFlags = packed struct(u32) {...@@ -696,8 +747,8 @@ pub const SymbolFlags = packed struct(u32) {
696 /// Masks off the Zig-specific stuff.747 /// Masks off the Zig-specific stuff.
697 pub fn toAbiInteger(flags: SymbolFlags) u32 {748 pub fn toAbiInteger(flags: SymbolFlags) u32 {
698 var copy = flags;749 var copy = flags;
699 copy.initZigSpecific(false, false);750 copy.initZigSpecific(false, flags.no_strip);
700 return @bitCast(copy);751 return @backingInt(copy);
701 }752 }
702};753};
703754
...@@ -812,7 +863,7 @@ pub const UavsExeIndex = enum(u32) {...@@ -812,7 +863,7 @@ pub const UavsExeIndex = enum(u32) {
812/// Used when emitting a relocatable object.863/// Used when emitting a relocatable object.
813pub const ZcuDataObj = extern struct {864pub const ZcuDataObj = extern struct {
814 code: DataPayload,865 code: DataPayload,
815 relocs: OutReloc.Slice,866 relocs: ZcuRelocation.Slice,
816};867};
817868
818/// Used when not emitting a relocatable object.869/// Used when not emitting a relocatable object.
...@@ -855,7 +906,9 @@ const ZcuDataStarts = struct {...@@ -855,7 +906,9 @@ const ZcuDataStarts = struct {
855 var uavs_i = zds.uavs_i;906 var uavs_i = zds.uavs_i;
856 while (uavs_i < wasm.uavs_obj.entries.len) : (uavs_i += 1) {907 while (uavs_i < wasm.uavs_obj.entries.len) : (uavs_i += 1) {
857 // Call to `lowerZcuData` here possibly creates more entries in these tables.908 // 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;
859 }912 }
860 }913 }
861914
...@@ -906,6 +959,51 @@ pub const ZcuFunc = union {...@@ -906,6 +959,51 @@ pub const ZcuFunc = union {
906 return &wasm.zcu_funcs.values()[@backingInt(i)];959 return &wasm.zcu_funcs.values()[@backingInt(i)];
907 }960 }
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
909 pub fn name(i: @This(), wasm: *const Wasm) [:0]const u8 {1007 pub fn name(i: @This(), wasm: *const Wasm) [:0]const u8 {
910 const zcu = wasm.base.comp.zcu.?;1008 const zcu = wasm.base.comp.zcu.?;
911 const ip = &zcu.intern_pool;1009 const ip = &zcu.intern_pool;
...@@ -1034,6 +1132,15 @@ pub const FunctionImport = extern struct {...@@ -1034,6 +1132,15 @@ pub const FunctionImport = extern struct {
1034 return pack(wasm, .{ .object_function = object_function });1132 return pack(wasm, .{ .object_function = object_function });
1035 }1133 }
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
1037 pub fn isNavOrUnresolved(r: Resolution, wasm: *const Wasm) bool {1144 pub fn isNavOrUnresolved(r: Resolution, wasm: *const Wasm) bool {
1038 return switch (r.unpack(wasm)) {1145 return switch (r.unpack(wasm)) {
1039 .unresolved, .zcu_func => true,1146 .unresolved, .zcu_func => true,
...@@ -1136,6 +1243,7 @@ pub const GlobalImport = extern struct {...@@ -1136,6 +1243,7 @@ pub const GlobalImport = extern struct {
1136 __tls_base,1243 __tls_base,
1137 __tls_size,1244 __tls_size,
1138 // Next, index into `object_globals`.1245 // Next, index into `object_globals`.
1246 // Next, index into `uavs_obj` or `uavs_exe` depending on whether emitting an object.
1139 // Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object.1247 // Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object.
1140 _,1248 _,
11411249
...@@ -1150,6 +1258,8 @@ pub const GlobalImport = extern struct {...@@ -1150,6 +1258,8 @@ pub const GlobalImport = extern struct {
1150 __tls_base,1258 __tls_base,
1151 __tls_size,1259 __tls_size,
1152 object_global: ObjectGlobalIndex,1260 object_global: ObjectGlobalIndex,
1261 uav_exe: UavsExeIndex,
1262 uav_obj: UavsObjIndex,
1153 nav_exe: NavsExeIndex,1263 nav_exe: NavsExeIndex,
1154 nav_obj: NavsObjIndex,1264 nav_obj: NavsObjIndex,
1155 };1265 };
...@@ -1170,12 +1280,22 @@ pub const GlobalImport = extern struct {...@@ -1170,12 +1280,22 @@ pub const GlobalImport = extern struct {
1170 return .{ .object_global = @fromBackingInt(@intCast(object_global_index)) };1280 return .{ .object_global = @fromBackingInt(@intCast(object_global_index)) };
1171 const comp = wasm.base.comp;1281 const comp = wasm.base.comp;
1172 const is_obj = comp.config.output_mode == .Obj;1282 const is_obj = comp.config.output_mode == .Obj;
1173 const nav_index = object_global_index - wasm.object_globals.items.len;1283 const uav_index = object_global_index - wasm.object_globals.items.len;
1174 return if (is_obj) .{1284 if (is_obj) {
1175 .nav_obj = @fromBackingInt(@intCast(nav_index)),1285 if (uav_index < wasm.uavs_obj.entries.len) {
1176 } else .{1286 return .{ .uav_obj = @fromBackingInt(@intCast(uav_index)) };
1177 .nav_exe = @fromBackingInt(@intCast(nav_index)),1287 }
1178 };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 }
1179 },1299 },
1180 };1300 };
1181 }1301 }
...@@ -1190,11 +1310,29 @@ pub const GlobalImport = extern struct {...@@ -1190,11 +1310,29 @@ pub const GlobalImport = extern struct {
1190 .__tls_base => .__tls_base,1310 .__tls_base => .__tls_base,
1191 .__tls_size => .__tls_size,1311 .__tls_size => .__tls_size,
1192 .object_global => |i| @fromBackingInt(@intCast(first_object_global + @backingInt(i))),1312 .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))),1313 inline .uav_obj, .uav_exe => |i| @fromBackingInt(@intCast(
1194 .nav_exe => |i| @fromBackingInt(@intCast(first_object_global + wasm.object_globals.items.len + @backingInt(i))),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 )),
1195 };1324 };
1196 }1325 }
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
1198 pub fn fromIpNav(wasm: *const Wasm, ip_nav: InternPool.Nav.Index) Resolution {1336 pub fn fromIpNav(wasm: *const Wasm, ip_nav: InternPool.Nav.Index) Resolution {
1199 const comp = wasm.base.comp;1337 const comp = wasm.base.comp;
1200 const is_obj = comp.config.output_mode == .Obj;1338 const is_obj = comp.config.output_mode == .Obj;
...@@ -1209,7 +1347,22 @@ pub const GlobalImport = extern struct {...@@ -1209,7 +1347,22 @@ pub const GlobalImport = extern struct {
1209 return pack(wasm, .{ .object_global = object_global });1347 return pack(wasm, .{ .object_global = object_global });
1210 }1348 }
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 {
1213 return switch (unpack(r, wasm)) {1366 return switch (unpack(r, wasm)) {
1214 .unresolved => unreachable,1367 .unresolved => unreachable,
1215 .__heap_base => @tagName(Unpacked.__heap_base),1368 .__heap_base => @tagName(Unpacked.__heap_base),
...@@ -1219,6 +1372,11 @@ pub const GlobalImport = extern struct {...@@ -1219,6 +1372,11 @@ pub const GlobalImport = extern struct {
1219 .__tls_base => @tagName(Unpacked.__tls_base),1372 .__tls_base => @tagName(Unpacked.__tls_base),
1220 .__tls_size => @tagName(Unpacked.__tls_size),1373 .__tls_size => @tagName(Unpacked.__tls_size),
1221 .object_global => |i| i.name(wasm).slice(wasm),1374 .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,
1222 .nav_obj => |i| i.name(wasm),1380 .nav_obj => |i| i.name(wasm),
1223 .nav_exe => |i| i.name(wasm),1381 .nav_exe => |i| i.name(wasm),
1224 };1382 };
...@@ -1349,6 +1507,22 @@ pub const TableImport = extern struct {...@@ -1349,6 +1507,22 @@ pub const TableImport = extern struct {
1349 return pack(.{ .object_table = object_table });1507 return pack(.{ .object_table = object_table });
1350 }1508 }
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
1352 pub fn refType(r: Resolution, wasm: *const Wasm) std.wasm.RefType {1526 pub fn refType(r: Resolution, wasm: *const Wasm) std.wasm.RefType {
1353 return switch (unpack(r)) {1527 return switch (unpack(r)) {
1354 .unresolved => unreachable,1528 .unresolved => unreachable,
...@@ -1602,6 +1776,8 @@ pub const ObjectDataImport = extern struct {...@@ -1602,6 +1776,8 @@ pub const ObjectDataImport = extern struct {
1602 unresolved,1776 unresolved,
1603 __zig_error_names,1777 __zig_error_names,
1604 __zig_error_name_table,1778 __zig_error_name_table,
1779 __zig_tag_names,
1780 __zig_tag_name_table,
1605 __heap_base,1781 __heap_base,
1606 __heap_end,1782 __heap_end,
1607 /// Next, an `ObjectData.Index`.1783 /// Next, an `ObjectData.Index`.
...@@ -1615,6 +1791,8 @@ pub const ObjectDataImport = extern struct {...@@ -1615,6 +1791,8 @@ pub const ObjectDataImport = extern struct {
1615 unresolved,1791 unresolved,
1616 __zig_error_names,1792 __zig_error_names,
1617 __zig_error_name_table,1793 __zig_error_name_table,
1794 __zig_tag_names,
1795 __zig_tag_name_table,
1618 __heap_base,1796 __heap_base,
1619 __heap_end,1797 __heap_end,
1620 object: ObjectData.Index,1798 object: ObjectData.Index,
...@@ -1629,6 +1807,8 @@ pub const ObjectDataImport = extern struct {...@@ -1629,6 +1807,8 @@ pub const ObjectDataImport = extern struct {
1629 .unresolved => .unresolved,1807 .unresolved => .unresolved,
1630 .__zig_error_names => .__zig_error_names,1808 .__zig_error_names => .__zig_error_names,
1631 .__zig_error_name_table => .__zig_error_name_table,1809 .__zig_error_name_table => .__zig_error_name_table,
1810 .__zig_tag_names => .__zig_tag_names,
1811 .__zig_tag_name_table => .__zig_tag_name_table,
1632 .__heap_base => .__heap_base,1812 .__heap_base => .__heap_base,
1633 .__heap_end => .__heap_end,1813 .__heap_end => .__heap_end,
1634 _ => {1814 _ => {
...@@ -1665,6 +1845,8 @@ pub const ObjectDataImport = extern struct {...@@ -1665,6 +1845,8 @@ pub const ObjectDataImport = extern struct {
1665 .unresolved => .unresolved,1845 .unresolved => .unresolved,
1666 .__zig_error_names => .__zig_error_names,1846 .__zig_error_names => .__zig_error_names,
1667 .__zig_error_name_table => .__zig_error_name_table,1847 .__zig_error_name_table => .__zig_error_name_table,
1848 .__zig_tag_names => .__zig_tag_names,
1849 .__zig_tag_name_table => .__zig_tag_name_table,
1668 .__heap_base => .__heap_base,1850 .__heap_base => .__heap_base,
1669 .__heap_end => .__heap_end,1851 .__heap_end => .__heap_end,
1670 .object => |i| @fromBackingInt(@intCast(first_object + @backingInt(i))),1852 .object => |i| @fromBackingInt(@intCast(first_object + @backingInt(i))),
...@@ -1678,12 +1860,32 @@ pub const ObjectDataImport = extern struct {...@@ -1678,12 +1860,32 @@ pub const ObjectDataImport = extern struct {
1678 return pack(wasm, .{ .object = object_data_index });1860 return pack(wasm, .{ .object = object_data_index });
1679 }1861 }
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
1681 pub fn objectDataSegment(r: Resolution, wasm: *const Wasm) ?ObjectDataSegment.Index {1881 pub fn objectDataSegment(r: Resolution, wasm: *const Wasm) ?ObjectDataSegment.Index {
1682 return switch (unpack(r, wasm)) {1882 return switch (unpack(r, wasm)) {
1683 .unresolved => unreachable,1883 .unresolved => unreachable,
1684 .object => |i| i.ptr(wasm).segment,1884 .object => |i| i.ptr(wasm).segment,
1685 .__zig_error_names,1885 .__zig_error_names,
1686 .__zig_error_name_table,1886 .__zig_error_name_table,
1887 .__zig_tag_names,
1888 .__zig_tag_name_table,
1687 .__heap_base,1889 .__heap_base,
1688 .__heap_end,1890 .__heap_end,
1689 .uav_exe,1891 .uav_exe,
...@@ -1706,12 +1908,107 @@ pub const ObjectDataImport = extern struct {...@@ -1706,12 +1908,107 @@ pub const ObjectDataImport = extern struct {
1706 },1908 },
1707 .__zig_error_names => .{ .segment = .__zig_error_names, .offset = 0 },1909 .__zig_error_names => .{ .segment = .__zig_error_names, .offset = 0 },
1708 .__zig_error_name_table => .{ .segment = .__zig_error_name_table, .offset = 0 },1910 .__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 },
1709 .__heap_base => .{ .segment = .__heap_base, .offset = 0 },1913 .__heap_base => .{ .segment = .__heap_base, .offset = 0 },
1710 .__heap_end => .{ .segment = .__heap_end, .offset = 0 },1914 .__heap_end => .{ .segment = .__heap_end, .offset = 0 },
1711 .uav_exe => @panic("TODO"),1915 .uav_exe => |i| .{ .segment = .pack(wasm, .{ .uav_exe = i }), .offset = 0 },
1712 .uav_obj => @panic("TODO"),1916 .uav_obj => |i| .{ .segment = .pack(wasm, .{ .uav_obj = i }), .offset = 0 },
1713 .nav_exe => @panic("TODO"),1917 .nav_exe => |i| .{ .segment = .pack(wasm, .{ .nav_exe = i }), .offset = 0 },
1714 .nav_obj => @panic("TODO"),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,
1715 };2012 };
1716 }2013 }
1717 };2014 };
...@@ -1910,6 +2207,38 @@ pub const DataSegmentId = enum(u32) {...@@ -1910,6 +2207,38 @@ pub const DataSegmentId = enum(u32) {
1910 };2207 };
1911 }2208 }
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
1913 pub fn isBss(id: DataSegmentId, wasm: *const Wasm) bool {2242 pub fn isBss(id: DataSegmentId, wasm: *const Wasm) bool {
1914 return id.category(wasm) == .zero;2243 return id.category(wasm) == .zero;
1915 }2244 }
...@@ -2181,6 +2510,7 @@ const PreloadedStrings = struct {...@@ -2181,6 +2510,7 @@ const PreloadedStrings = struct {
2181 _initialize: String,2510 _initialize: String,
2182 _start: String,2511 _start: String,
2183 memory: String,2512 memory: String,
2513 env: String,
2184};2514};
21852515
2186/// Index into string_bytes2516/// Index into string_bytes
...@@ -2209,14 +2539,14 @@ pub const String = enum(u32) {...@@ -2209,14 +2539,14 @@ pub const String = enum(u32) {
2209 }2539 }
22102540
2211 pub fn hash(_: @This(), adapted_key: []const u8) u64 {2541 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);
2213 return std.hash_map.hashString(adapted_key);2543 return std.hash_map.hashString(adapted_key);
2214 }2544 }
2215 };2545 };
22162546
2217 pub fn slice(index: String, wasm: *const Wasm) [:0]const u8 {2547 pub fn slice(index: String, wasm: *const Wasm) [:0]const u8 {
2218 const start_slice = wasm.string_bytes.items[@backingInt(index)..];2548 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];
2220 }2550 }
22212551
2222 pub fn toOptional(i: String) OptionalString {2552 pub fn toOptional(i: String) OptionalString {
...@@ -2262,6 +2592,34 @@ pub const ZcuImportIndex = enum(u32) {...@@ -2262,6 +2592,34 @@ pub const ZcuImportIndex = enum(u32) {
2262 return &wasm.imports.keys()[@backingInt(index)];2592 return &wasm.imports.keys()[@backingInt(index)];
2263 }2593 }
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
2265 pub fn importName(index: ZcuImportIndex, wasm: *const Wasm) String {2623 pub fn importName(index: ZcuImportIndex, wasm: *const Wasm) String {
2266 const zcu = wasm.base.comp.zcu.?;2624 const zcu = wasm.base.comp.zcu.?;
2267 const ip = &zcu.intern_pool;2625 const ip = &zcu.intern_pool;
...@@ -2348,6 +2706,13 @@ pub const FunctionImportId = enum(u32) {...@@ -2348,6 +2706,13 @@ pub const FunctionImportId = enum(u32) {
2348 }2706 }
2349 }2707 }
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
2351 pub fn importName(id: FunctionImportId, wasm: *const Wasm) String {2716 pub fn importName(id: FunctionImportId, wasm: *const Wasm) String {
2352 return switch (unpack(id, wasm)) {2717 return switch (unpack(id, wasm)) {
2353 inline .object_function_import, .zcu_import => |i| i.importName(wasm),2718 inline .object_function_import, .zcu_import => |i| i.importName(wasm),
...@@ -2385,38 +2750,61 @@ pub const FunctionImportId = enum(u32) {...@@ -2385,38 +2750,61 @@ pub const FunctionImportId = enum(u32) {
2385 }2750 }
2386};2751};
23872752
2388/// 0. Index into `object_global_imports`.2753/// 0. `__stack_pointer`.
2389/// 1. Index into `imports`.2754/// 1. Index into `object_global_imports`.
2755/// 2. Index into `imports`.
2390pub const GlobalImportId = enum(u32) {2756pub const GlobalImportId = enum(u32) {
2757 __stack_pointer,
2391 _,2758 _,
23922759
2393 pub const Unpacked = union(enum) {2760 pub const Unpacked = union(enum) {
2761 __stack_pointer,
2394 object_global_import: GlobalImport.Index,2762 object_global_import: GlobalImport.Index,
2395 zcu_import: ZcuImportIndex,2763 zcu_import: ZcuImportIndex,
2396 };2764 };
23972765
2398 pub fn pack(unpacked: Unpacked, wasm: *const Wasm) GlobalImportId {2766 pub fn pack(unpacked: Unpacked, wasm: *const Wasm) GlobalImportId {
2399 return switch (unpacked) {2767 return switch (unpacked) {
2400 .object_global_import => |i| @fromBackingInt(@intCast(@backingInt(i))),2768 .__stack_pointer => .__stack_pointer,
2401 .zcu_import => |i| @fromBackingInt(@intCast(@backingInt(i) + wasm.object_global_imports.entries.len)),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)),
2402 };2771 };
2403 }2772 }
24042773
2405 pub fn unpack(id: GlobalImportId, wasm: *const Wasm) Unpacked {2774 pub fn unpack(id: GlobalImportId, wasm: *const Wasm) Unpacked {
2406 const i = @backingInt(id);2775 return switch (id) {
2407 if (i < wasm.object_global_imports.entries.len) return .{ .object_global_import = @fromBackingInt(@intCast(i)) };2776 .__stack_pointer => .__stack_pointer,
2408 const zcu_import_i = i - wasm.object_global_imports.entries.len;2777 _ => {
2409 return .{ .zcu_import = @fromBackingInt(@intCast(zcu_import_i)) };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 };
2410 }2786 }
24112787
2412 pub fn fromObject(object_global_import: GlobalImport.Index, wasm: *const Wasm) GlobalImportId {2788 pub fn fromObject(object_global_import: GlobalImport.Index, wasm: *const Wasm) GlobalImportId {
2413 return pack(.{ .object_global_import = object_global_import }, wasm);2789 return pack(.{ .object_global_import = object_global_import }, wasm);
2414 }2790 }
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
2416 /// This function is allowed O(N) lookup because it is only called during2803 /// This function is allowed O(N) lookup because it is only called during
2417 /// diagnostic generation.2804 /// diagnostic generation.
2418 pub fn sourceLocation(id: GlobalImportId, wasm: *const Wasm) SourceLocation {2805 pub fn sourceLocation(id: GlobalImportId, wasm: *const Wasm) SourceLocation {
2419 switch (id.unpack(wasm)) {2806 switch (id.unpack(wasm)) {
2807 .__stack_pointer => return .zig_object_nofile,
2420 .object_global_import => |obj_global_index| {2808 .object_global_import => |obj_global_index| {
2421 // TODO binary search2809 // TODO binary search
2422 for (wasm.objects.items, 0..) |o, i| {2810 for (wasm.objects.items, 0..) |o, i| {
...@@ -2433,18 +2821,28 @@ pub const GlobalImportId = enum(u32) {...@@ -2433,18 +2821,28 @@ pub const GlobalImportId = enum(u32) {
24332821
2434 pub fn importName(id: GlobalImportId, wasm: *const Wasm) String {2822 pub fn importName(id: GlobalImportId, wasm: *const Wasm) String {
2435 return switch (unpack(id, wasm)) {2823 return switch (unpack(id, wasm)) {
2824 .__stack_pointer => wasm.preloaded_strings.__stack_pointer,
2436 inline .object_global_import, .zcu_import => |i| i.importName(wasm),2825 inline .object_global_import, .zcu_import => |i| i.importName(wasm),
2437 };2826 };
2438 }2827 }
24392828
2440 pub fn moduleName(id: GlobalImportId, wasm: *const Wasm) OptionalString {2829 pub fn moduleName(id: GlobalImportId, wasm: *const Wasm) OptionalString {
2441 return switch (unpack(id, wasm)) {2830 return switch (unpack(id, wasm)) {
2831 .__stack_pointer => wasm.preloaded_strings.env.toOptional(),
2442 inline .object_global_import, .zcu_import => |i| i.moduleName(wasm),2832 inline .object_global_import, .zcu_import => |i| i.moduleName(wasm),
2443 };2833 };
2444 }2834 }
24452835
2446 pub fn globalType(id: GlobalImportId, wasm: *Wasm) ObjectGlobal.Type {2836 pub fn globalType(id: GlobalImportId, wasm: *Wasm) ObjectGlobal.Type {
2447 return switch (unpack(id, wasm)) {2837 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 },
2448 inline .object_global_import, .zcu_import => |i| i.globalType(wasm),2846 inline .object_global_import, .zcu_import => |i| i.globalType(wasm),
2449 };2847 };
2450 }2848 }
...@@ -2482,6 +2880,13 @@ pub const DataImportId = enum(u32) {...@@ -2482,6 +2880,13 @@ pub const DataImportId = enum(u32) {
2482 return pack(.{ .object_data_import = object_data_import }, wasm);2880 return pack(.{ .object_data_import = object_data_import }, wasm);
2483 }2881 }
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
2485 pub fn sourceLocation(id: DataImportId, wasm: *const Wasm) SourceLocation {2890 pub fn sourceLocation(id: DataImportId, wasm: *const Wasm) SourceLocation {
2486 switch (id.unpack(wasm)) {2891 switch (id.unpack(wasm)) {
2487 .object_data_import => |obj_data_index| {2892 .object_data_import => |obj_data_index| {
...@@ -2499,33 +2904,42 @@ pub const DataImportId = enum(u32) {...@@ -2499,33 +2904,42 @@ pub const DataImportId = enum(u32) {
2499 }2904 }
2500};2905};
25012906
2502/// Index into `Wasm.symbol_table`.2907pub const ZcuRelocation = struct {
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 {
2512 tag: Object.RelocationType,2908 tag: Object.RelocationType,
2513 offset: u32,2909 offset: u32,
2514 pointee: Pointee,2910 pointee: Pointee,
2515 addend: i32,2911 addend: i32,
25162912
2517 pub const Pointee = union {2913 pub const Pointee = union(enum) {
2518 symbol_index: SymbolTableIndex,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,
2519 type_index: FunctionType.Index,2921 type_index: FunctionType.Index,
2520 };2922 };
25212923
2522 pub const Slice = extern struct {2924 pub const Slice = extern struct {
2523 /// Index into `out_relocs`.2925 /// Index into `zcu_relocations`.
2524 off: u32,2926 off: u32,
2525 len: u32,2927 len: u32,
25262928
2527 pub fn slice(s: Slice, wasm: *const Wasm) []OutReloc {2929 pub fn tags(s: Slice, wasm: *const Wasm) []const Object.RelocationType {
2528 return wasm.relocations.items[s.off..][0..s.len];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];
2529 }2943 }
2530 };2944 };
2531};2945};
...@@ -3137,9 +3551,9 @@ pub fn deinit(wasm: *Wasm) void {...@@ -3137,9 +3551,9 @@ pub fn deinit(wasm: *Wasm) void {
3137 wasm.table_imports.deinit(gpa);3551 wasm.table_imports.deinit(gpa);
3138 wasm.tables.deinit(gpa);3552 wasm.tables.deinit(gpa);
3139 wasm.data_imports.deinit(gpa);3553 wasm.data_imports.deinit(gpa);
3554 wasm.datas.deinit(gpa);
3140 wasm.data_segments.deinit(gpa);3555 wasm.data_segments.deinit(gpa);
3141 wasm.symbol_table.deinit(gpa);3556 wasm.zcu_relocations.deinit(gpa);
3142 wasm.out_relocs.deinit(gpa);
3143 wasm.uav_fixups.deinit(gpa);3557 wasm.uav_fixups.deinit(gpa);
3144 wasm.nav_fixups.deinit(gpa);3558 wasm.nav_fixups.deinit(gpa);
3145 wasm.func_table_fixups.deinit(gpa);3559 wasm.func_table_fixups.deinit(gpa);
...@@ -3351,6 +3765,25 @@ pub fn updateExports(...@@ -3351,6 +3765,25 @@ pub fn updateExports(
3351 const zcu = pt.zcu;3765 const zcu = pt.zcu;
3352 const gpa = zcu.gpa;3766 const gpa = zcu.gpa;
3353 const ip = &zcu.intern_pool;3767 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 }
3354 for (export_indices) |export_idx| {3787 for (export_indices) |export_idx| {
3355 const exp = export_idx.ptr(zcu);3788 const exp = export_idx.ptr(zcu);
3356 const name_slice = exp.opts.name.toSlice(ip);3789 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 {...@@ -3443,7 +3876,11 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void {
3443 // Zig always depends on a stack pointer global.3876 // Zig always depends on a stack pointer global.
3444 // If emitting an object, it's an import. Otherwise, the linker synthesizes it.3877 // If emitting an object, it's an import. Otherwise, the linker synthesizes it.
3445 if (is_obj) {3878 if (is_obj) {
3446 @panic("TODO");3879 try wasm.global_imports.putNoClobber(
3880 gpa,
3881 wasm.preloaded_strings.__stack_pointer,
3882 .__stack_pointer,
3883 );
3447 } else {3884 } else {
3448 try wasm.globals.put(gpa, .__stack_pointer, {});3885 try wasm.globals.put(gpa, .__stack_pointer, {});
3449 assert(wasm.globals.entries.len - 1 == @backingInt(GlobalIndex.stack_pointer));3886 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 {...@@ -3453,7 +3890,7 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void {
3453 // These loops do both recursive marking of alive symbols well as checking for undefined symbols.3890 // These loops do both recursive marking of alive symbols well as checking for undefined symbols.
3454 // At the end, output functions and globals will be populated.3891 // At the end, output functions and globals will be populated.
3455 for (wasm.object_function_imports.keys(), wasm.object_function_imports.values(), 0..) |name, *import, i| {3892 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)) {
3457 try markFunctionImport(wasm, name, import, @fromBackingInt(@intCast(i)));3894 try markFunctionImport(wasm, name, import, @fromBackingInt(@intCast(i)));
3458 }3895 }
3459 }3896 }
...@@ -3467,7 +3904,7 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void {...@@ -3467,7 +3904,7 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void {
3467 wasm.functions_end_prelink = @intCast(wasm.functions.entries.len);3904 wasm.functions_end_prelink = @intCast(wasm.functions.entries.len);
34683905
3469 for (wasm.object_global_imports.keys(), wasm.object_global_imports.values(), 0..) |name, *import, i| {3906 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)) {
3471 try markGlobalImport(wasm, name, import, @fromBackingInt(@intCast(i)));3908 try markGlobalImport(wasm, name, import, @fromBackingInt(@intCast(i)));
3472 }3909 }
3473 }3910 }
...@@ -3475,13 +3912,13 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void {...@@ -3475,13 +3912,13 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void {
3475 wasm.global_exports_len = @intCast(wasm.global_exports.items.len);3912 wasm.global_exports_len = @intCast(wasm.global_exports.items.len);
34763913
3477 for (wasm.object_table_imports.keys(), wasm.object_table_imports.values(), 0..) |name, *import, i| {3914 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)) {
3479 try markTableImport(wasm, name, import, @fromBackingInt(@intCast(i)));3916 try markTableImport(wasm, name, import, @fromBackingInt(@intCast(i)));
3480 }3917 }
3481 }3918 }
34823919
3483 for (wasm.object_data_imports.keys(), wasm.object_data_imports.values(), 0..) |name, *import, i| {3920 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)) {
3485 try markDataImport(wasm, name, import, @fromBackingInt(@intCast(i)));3922 try markDataImport(wasm, name, import, @fromBackingInt(@intCast(i)));
3486 }3923 }
3487 }3924 }
...@@ -3512,18 +3949,23 @@ pub fn markFunctionImport(...@@ -3512,18 +3949,23 @@ pub fn markFunctionImport(
35123949
3513 const comp = wasm.base.comp;3950 const comp = wasm.base.comp;
3514 const gpa = comp.gpa;3951 const gpa = comp.gpa;
3952 const is_obj = comp.config.output_mode == .Obj;
35153953
3516 try wasm.functions.ensureUnusedCapacity(gpa, 1);3954 try wasm.functions.ensureUnusedCapacity(gpa, 1);
35173955
3518 if (import.resolution == .unresolved) {3956 if (import.resolution == .unresolved) {
3519 if (name == wasm.preloaded_strings.__wasm_init_memory) {3957 if (!is_obj) {
3520 try wasm.resolveFunctionSynthetic(import, .__wasm_init_memory, &.{}, &.{});3958 if (name == wasm.preloaded_strings.__wasm_init_memory) {
3521 } else if (name == wasm.preloaded_strings.__wasm_apply_global_tls_relocs) {3959 try wasm.resolveFunctionSynthetic(import, .__wasm_init_memory, &.{}, &.{});
3522 try wasm.resolveFunctionSynthetic(import, .__wasm_apply_global_tls_relocs, &.{}, &.{});3960 } else if (name == wasm.preloaded_strings.__wasm_apply_global_tls_relocs) {
3523 } else if (name == wasm.preloaded_strings.__wasm_call_ctors) {3961 try wasm.resolveFunctionSynthetic(import, .__wasm_apply_global_tls_relocs, &.{}, &.{});
3524 try wasm.resolveFunctionSynthetic(import, .__wasm_call_ctors, &.{}, &.{});3962 } else if (name == wasm.preloaded_strings.__wasm_call_ctors) {
3525 } else if (name == wasm.preloaded_strings.__wasm_init_tls) {3963 try wasm.resolveFunctionSynthetic(import, .__wasm_call_ctors, &.{}, &.{});
3526 try wasm.resolveFunctionSynthetic(import, .__wasm_init_tls, &.{.i32}, &.{});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 }
3527 } else {3969 } else {
3528 try wasm.function_imports.put(gpa, name, .fromObject(func_index, wasm));3970 try wasm.function_imports.put(gpa, name, .fromObject(func_index, wasm));
3529 }3971 }
...@@ -3576,28 +4018,33 @@ fn markGlobalImport(...@@ -3576,28 +4018,33 @@ fn markGlobalImport(
35764018
3577 const comp = wasm.base.comp;4019 const comp = wasm.base.comp;
3578 const gpa = comp.gpa;4020 const gpa = comp.gpa;
4021 const is_obj = comp.config.output_mode == .Obj;
35794022
3580 try wasm.globals.ensureUnusedCapacity(gpa, 1);4023 try wasm.globals.ensureUnusedCapacity(gpa, 1);
35814024
3582 if (import.resolution == .unresolved) {4025 if (import.resolution == .unresolved) {
3583 if (name == wasm.preloaded_strings.__heap_base) {4026 if (!is_obj) {
3584 import.resolution = .__heap_base;4027 if (name == wasm.preloaded_strings.__heap_base) {
3585 wasm.globals.putAssumeCapacity(.__heap_base, {});4028 import.resolution = .__heap_base;
3586 } else if (name == wasm.preloaded_strings.__heap_end) {4029 wasm.globals.putAssumeCapacity(.__heap_base, {});
3587 import.resolution = .__heap_end;4030 } else if (name == wasm.preloaded_strings.__heap_end) {
3588 wasm.globals.putAssumeCapacity(.__heap_end, {});4031 import.resolution = .__heap_end;
3589 } else if (name == wasm.preloaded_strings.__stack_pointer) {4032 wasm.globals.putAssumeCapacity(.__heap_end, {});
3590 import.resolution = .__stack_pointer;4033 } else if (name == wasm.preloaded_strings.__stack_pointer) {
3591 wasm.globals.putAssumeCapacity(.__stack_pointer, {});4034 import.resolution = .__stack_pointer;
3592 } else if (name == wasm.preloaded_strings.__tls_align) {4035 wasm.globals.putAssumeCapacity(.__stack_pointer, {});
3593 import.resolution = .__tls_align;4036 } else if (name == wasm.preloaded_strings.__tls_align) {
3594 wasm.globals.putAssumeCapacity(.__tls_align, {});4037 import.resolution = .__tls_align;
3595 } else if (name == wasm.preloaded_strings.__tls_base) {4038 wasm.globals.putAssumeCapacity(.__tls_align, {});
3596 import.resolution = .__tls_base;4039 } else if (name == wasm.preloaded_strings.__tls_base) {
3597 wasm.globals.putAssumeCapacity(.__tls_base, {});4040 import.resolution = .__tls_base;
3598 } else if (name == wasm.preloaded_strings.__tls_size) {4041 wasm.globals.putAssumeCapacity(.__tls_base, {});
3599 import.resolution = .__tls_size;4042 } else if (name == wasm.preloaded_strings.__tls_size) {
3600 wasm.globals.putAssumeCapacity(.__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 }
3601 } else {4048 } else {
3602 try wasm.global_imports.put(gpa, name, .fromObject(global_index, wasm));4049 try wasm.global_imports.put(gpa, name, .fromObject(global_index, wasm));
3603 }4050 }
...@@ -3625,7 +4072,7 @@ fn markGlobal(wasm: *Wasm, i: ObjectGlobalIndex, override_export: bool) link.Err...@@ -3625,7 +4072,7 @@ fn markGlobal(wasm: *Wasm, i: ObjectGlobalIndex, override_export: bool) link.Err
3625 try wasm.markRelocations(global.relocations(wasm));4072 try wasm.markRelocations(global.relocations(wasm));
3626}4073}
36274074
3628fn markTableImport(4075pub fn markTableImport(
3629 wasm: *Wasm,4076 wasm: *Wasm,
3630 name: String,4077 name: String,
3631 import: *TableImport,4078 import: *TableImport,
...@@ -3636,13 +4083,18 @@ fn markTableImport(...@@ -3636,13 +4083,18 @@ fn markTableImport(
36364083
3637 const comp = wasm.base.comp;4084 const comp = wasm.base.comp;
3638 const gpa = comp.gpa;4085 const gpa = comp.gpa;
4086 const is_obj = comp.config.output_mode == .Obj;
36394087
3640 try wasm.tables.ensureUnusedCapacity(gpa, 1);4088 try wasm.tables.ensureUnusedCapacity(gpa, 1);
36414089
3642 if (import.resolution == .unresolved) {4090 if (import.resolution == .unresolved) {
3643 if (name == wasm.preloaded_strings.__indirect_function_table) {4091 if (!is_obj) {
3644 import.resolution = .__indirect_function_table;4092 if (name == wasm.preloaded_strings.__indirect_function_table) {
3645 wasm.tables.putAssumeCapacity(.__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 }
3646 } else {4098 } else {
3647 try wasm.table_imports.put(gpa, name, table_index);4099 try wasm.table_imports.put(gpa, name, table_index);
3648 }4100 }
...@@ -3676,22 +4128,38 @@ pub fn markDataImport(...@@ -3676,22 +4128,38 @@ pub fn markDataImport(
36764128
3677 const comp = wasm.base.comp;4129 const comp = wasm.base.comp;
3678 const gpa = comp.gpa;4130 const gpa = comp.gpa;
4131 const is_obj = comp.config.output_mode == .Obj;
4132
4133 try wasm.data_segments.ensureUnusedCapacity(gpa, 1);
36794134
3680 if (import.resolution == .unresolved) {4135 if (import.resolution == .unresolved) {
3681 if (name == wasm.preloaded_strings.__heap_base) {4136 if (!is_obj) {
3682 import.resolution = .__heap_base;4137 if (name == wasm.preloaded_strings.__heap_base) {
3683 wasm.data_segments.putAssumeCapacity(.__heap_base, {});4138 import.resolution = .__heap_base;
3684 } else if (name == wasm.preloaded_strings.__heap_end) {4139 wasm.data_segments.putAssumeCapacity(.__heap_base, {});
3685 import.resolution = .__heap_end;4140 } else if (name == wasm.preloaded_strings.__heap_end) {
3686 wasm.data_segments.putAssumeCapacity(.__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 }
3687 } else {4146 } else {
3688 try wasm.data_imports.put(gpa, name, .fromObject(data_index, wasm));4147 try wasm.data_imports.put(gpa, name, .fromObject(data_index, wasm));
3689 }4148 }
3690 } else if (import.resolution.objectDataSegment(wasm)) |segment_index| {4149 } else switch (import.resolution.unpack(wasm)) {
3691 try markDataSegment(wasm, segment_index);4150 .object => |object_data_index| try markData(wasm, object_data_index),
4151 else => {},
3692 }4152 }
3693}4153}
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
3695fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Error!void {4163fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Error!void {
3696 const gpa = wasm.base.comp.gpa;4164 const gpa = wasm.base.comp.gpa;
3697 for (relocs.slice.tags(wasm), relocs.slice.pointees(wasm), relocs.slice.offsets(wasm)) |tag, pointee, offset| {4165 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...@@ -3782,7 +4250,7 @@ fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Err
3782 .memory_addr_tls_sleb,4250 .memory_addr_tls_sleb,
3783 .memory_addr_locrel_i32,4251 .memory_addr_locrel_i32,
3784 .memory_addr_tls_sleb64,4252 .memory_addr_tls_sleb64,
3785 => try markDataSegment(wasm, pointee.data.ptr(wasm).segment),4253 => try markData(wasm, pointee.data),
37864254
3787 .type_index_leb => continue,4255 .type_index_leb => continue,
3788 }4256 }
...@@ -3829,7 +4297,13 @@ pub fn flush(...@@ -3829,7 +4297,13 @@ pub fn flush(
3829 const hidden_function_exports_end_zcu: u32 = @intCast(wasm.hidden_function_exports.entries.len);4297 const hidden_function_exports_end_zcu: u32 = @intCast(wasm.hidden_function_exports.entries.len);
3830 defer wasm.hidden_function_exports.shrinkRetainingCapacity(hidden_function_exports_end_zcu);4298 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
3832 wasm.flush_buffer.clear();4303 wasm.flush_buffer.clear();
4304 wasm.tag_name_bytes.clearRetainingCapacity();
4305 wasm.tag_name_offs.clearRetainingCapacity();
4306 wasm.tag_name_table_ref_count = 0;
3833 try wasm.flush_buffer.missing_exports.reinit(gpa, wasm.missing_exports.keys(), &.{});4307 try wasm.flush_buffer.missing_exports.reinit(gpa, wasm.missing_exports.keys(), &.{});
3834 try wasm.flush_buffer.function_imports.reinit(gpa, wasm.function_imports.keys(), wasm.function_imports.values());4308 try wasm.flush_buffer.function_imports.reinit(gpa, wasm.function_imports.keys(), wasm.function_imports.values());
3835 try wasm.flush_buffer.global_imports.reinit(gpa, wasm.global_imports.keys(), wasm.global_imports.values());4309 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....@@ -3858,7 +4332,7 @@ pub fn internOptionalString(wasm: *Wasm, optional_bytes: ?[]const u8) Allocator.
3858}4332}
38594333
3860pub fn internString(wasm: *Wasm, bytes: []const u8) Allocator.Error!String {4334pub 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);
3862 wasm.string_bytes_lock.lock();4336 wasm.string_bytes_lock.lock();
3863 defer wasm.string_bytes_lock.unlock();4337 defer wasm.string_bytes_lock.unlock();
3864 const gpa = wasm.base.comp.gpa;4338 const gpa = wasm.base.comp.gpa;
...@@ -3889,7 +4363,7 @@ pub fn internStringFmt(wasm: *Wasm, comptime format: []const u8, args: anytype)...@@ -3889,7 +4363,7 @@ pub fn internStringFmt(wasm: *Wasm, comptime format: []const u8, args: anytype)
3889}4363}
38904364
3891pub fn getExistingString(wasm: *const Wasm, bytes: []const u8) ?String {4365pub 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);
3893 return wasm.string_table.getKeyAdapted(bytes, @as(String.TableIndexAdapter, .{4367 return wasm.string_table.getKeyAdapted(bytes, @as(String.TableIndexAdapter, .{
3894 .bytes = wasm.string_bytes.items,4368 .bytes = wasm.string_bytes.items,
3895 }));4369 }));
...@@ -3953,6 +4427,255 @@ pub fn getExistingFunctionType(...@@ -3953,6 +4427,255 @@ pub fn getExistingFunctionType(
3953 });4427 });
3954}4428}
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
3956pub fn addExpr(wasm: *Wasm, bytes: []const u8) Allocator.Error!Expr {4679pub fn addExpr(wasm: *Wasm, bytes: []const u8) Allocator.Error!Expr {
3957 const gpa = wasm.base.comp.gpa;4680 const gpa = wasm.base.comp.gpa;
3958 // We can't use string table deduplication here since these expressions can4681 // 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...@@ -3972,64 +4695,63 @@ pub fn addRelocatableDataPayload(wasm: *Wasm, bytes: []const u8) Allocator.Error
3972 };4695 };
3973}4696}
39744697
3975pub fn uavSymbolIndex(wasm: *Wasm, ip_index: InternPool.Index) Allocator.Error!SymbolTableIndex {4698pub fn addNavReloc(
3976 const comp = wasm.base.comp;4699 wasm: *Wasm,
3977 assert(comp.config.output_mode == .Obj);4700 reloc_offset: usize,
3978 const gpa = comp.gpa;4701 nav_index: InternPool.Nav.Index,
3979 const name = try wasm.internStringFmt("__anon_{d}", .{@backingInt(ip_index)});4702 nav_ty: Zcu.Type,
3980 const gop = try wasm.symbol_table.getOrPut(gpa, name);4703 addend: u32,
3981 gop.value_ptr.* = {};4704) !void {
3982 return @fromBackingInt(@intCast(gop.index));
3983}
3984
3985pub fn navSymbolIndex(wasm: *Wasm, nav_index: InternPool.Nav.Index) Allocator.Error!SymbolTableIndex {
3986 const comp = wasm.base.comp;4705 const comp = wasm.base.comp;
3987 assert(comp.config.output_mode == .Obj);
3988 const zcu = comp.zcu.?;4706 const zcu = comp.zcu.?;
3989 const ip = &zcu.intern_pool;4707 const ip = &zcu.intern_pool;
3990 const gpa = comp.gpa;4708 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 {4710 const is_obj = comp.config.output_mode == .Obj;
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}
40254711
4026pub fn symbolNameIndex(wasm: *Wasm, name: String) Allocator.Error!SymbolTableIndex {4712 if (nav_ty.zigTypeTag(zcu) == .@"fn") {
4027 const comp = wasm.base.comp;4713 const gop = try wasm.zcu_indirect_function_set.getOrPut(gpa, nav_index);
4028 assert(comp.config.output_mode == .Obj);4714 if (!gop.found_existing) gop.value_ptr.* = {};
4029 const gpa = comp.gpa;4715 if (is_obj) {
4030 const gop = try wasm.symbol_table.getOrPut(gpa, name);4716 assert(addend == 0);
4031 gop.value_ptr.* = {};4717 try wasm.zcu_relocations.append(gpa, .{
4032 return @fromBackingInt(@intCast(gop.index));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 }
4033}4755}
40344756
4035pub fn addUavReloc(4757pub fn addUavReloc(
...@@ -4057,12 +4779,12 @@ pub fn addUavReloc(...@@ -4057,12 +4779,12 @@ pub fn addUavReloc(
4057 if (comp.config.output_mode == .Obj) {4779 if (comp.config.output_mode == .Obj) {
4058 const gop = try wasm.uavs_obj.getOrPut(gpa, uav_val);4780 const gop = try wasm.uavs_obj.getOrPut(gpa, uav_val);
4059 if (!gop.found_existing) gop.value_ptr.* = undefined; // to avoid recursion, `ZcuDataStarts` will lower the value later4781 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, .{
4061 .offset = @intCast(reloc_offset),4783 .offset = @intCast(reloc_offset),
4062 .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(uav_val) },4784 .pointee = .{ .data_uav = uav_val },
4063 .tag = switch (wasm.pointerSize()) {4785 .tag = switch (wasm.pointerSize()) {
4064 32 => .memory_addr_i32,4786 4 => .memory_addr_i32,
4065 64 => .memory_addr_i64,4787 8 => .memory_addr_i64,
4066 else => unreachable,4788 else => unreachable,
4067 },4789 },
4068 .addend = @intCast(addend),4790 .addend = @intCast(addend),
...@@ -4085,7 +4807,7 @@ pub fn addUavReloc(...@@ -4085,7 +4807,7 @@ pub fn addUavReloc(
4085pub fn refNavObj(wasm: *Wasm, nav_index: InternPool.Nav.Index) !NavsObjIndex {4807pub fn refNavObj(wasm: *Wasm, nav_index: InternPool.Nav.Index) !NavsObjIndex {
4086 const comp = wasm.base.comp;4808 const comp = wasm.base.comp;
4087 const gpa = comp.gpa;4809 const gpa = comp.gpa;
4088 assert(comp.config.output_mode != .Obj);4810 assert(comp.config.output_mode == .Obj);
4089 const gop = try wasm.navs_obj.getOrPut(gpa, nav_index);4811 const gop = try wasm.navs_obj.getOrPut(gpa, nav_index);
4090 if (!gop.found_existing) gop.value_ptr.* = .{4812 if (!gop.found_existing) gop.value_ptr.* = .{
4091 // Lowering the value is delayed to avoid recursion.4813 // Lowering the value is delayed to avoid recursion.
...@@ -4113,7 +4835,7 @@ pub fn refNavExe(wasm: *Wasm, nav_index: InternPool.Nav.Index) !NavsExeIndex {...@@ -4113,7 +4835,7 @@ pub fn refNavExe(wasm: *Wasm, nav_index: InternPool.Nav.Index) !NavsExeIndex {
4113}4835}
41144836
4115/// Asserts it is called after `Flush.data_segments` is fully populated and sorted.4837/// 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 {
4117 assert(wasm.flush_buffer.memory_layout_finished);4839 assert(wasm.flush_buffer.memory_layout_finished);
4118 const comp = wasm.base.comp;4840 const comp = wasm.base.comp;
4119 assert(comp.config.output_mode != .Obj);4841 assert(comp.config.output_mode != .Obj);
...@@ -4123,7 +4845,7 @@ pub fn uavAddr(wasm: *Wasm, ip_index: InternPool.Index) u32 {...@@ -4123,7 +4845,7 @@ pub fn uavAddr(wasm: *Wasm, ip_index: InternPool.Index) u32 {
4123}4845}
41244846
4125/// Asserts it is called after `Flush.data_segments` is fully populated and sorted.4847/// 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 {
4127 assert(wasm.flush_buffer.memory_layout_finished);4849 assert(wasm.flush_buffer.memory_layout_finished);
4128 const comp = wasm.base.comp;4850 const comp = wasm.base.comp;
4129 assert(comp.config.output_mode != .Obj);4851 assert(comp.config.output_mode != .Obj);
...@@ -4139,23 +4861,34 @@ pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 {...@@ -4139,23 +4861,34 @@ pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 {
4139 .@"extern" => |ext| if (wasm.getExistingString(ext.name.toSlice(ip))) |symbol_name| {4861 .@"extern" => |ext| if (wasm.getExistingString(ext.name.toSlice(ip))) |symbol_name| {
4140 if (wasm.object_data_imports.getPtr(symbol_name)) |import| {4862 if (wasm.object_data_imports.getPtr(symbol_name)) |import| {
4141 switch (import.resolution.unpack(wasm)) {4863 switch (import.resolution.unpack(wasm)) {
4142 .unresolved => unreachable,4864 .unresolved => {},
4143 .object => |object_data_index| {4865 .object => |object_data_index| {
4144 const object_data = object_data_index.ptr(wasm);4866 const object_data = object_data_index.ptr(wasm);
4145 const ds_id: DataSegmentId = .fromObjectDataSegment(wasm, object_data.segment);4867 const ds_id: DataSegmentId = .fromObjectDataSegment(wasm, object_data.segment);
4146 const segment_base_addr = wasm.flush_buffer.data_segments.get(ds_id).?;4868 const segment_base_addr = wasm.flush_buffer.data_segments.get(ds_id).?;
4147 return segment_base_addr + object_data.offset;4869 return segment_base_addr + object_data.offset;
4148 },4870 },
4149 .__zig_error_names => @panic("TODO"),4871 .__heap_base,
4150 .__zig_error_name_table => @panic("TODO"),4872 .__heap_end,
4151 .__heap_base => @panic("TODO"),4873 .uav_exe,
4152 .__heap_end => @panic("TODO"),4874 .nav_exe,
4153 .uav_exe => @panic("TODO"),4875 => {
4154 .uav_obj => @panic("TODO"),4876 const data_loc = import.resolution.dataLoc(wasm);
4155 .nav_exe => @panic("TODO"),4877 return wasm.flush_buffer.data_segments.get(data_loc.segment).? + data_loc.offset;
4156 .nav_obj => @panic("TODO"),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,
4157 }4886 }
4158 }4887 }
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 }
4159 },4892 },
4160 else => {},4893 else => {},
4161 }4894 }
...@@ -4177,8 +4910,12 @@ pub fn tagIndexTableAddr(wasm: *Wasm, ip_index: InternPool.Index) u32 {...@@ -4177,8 +4910,12 @@ pub fn tagIndexTableAddr(wasm: *Wasm, ip_index: InternPool.Index) u32 {
4177 assert(comp.config.output_mode != .Obj);4910 assert(comp.config.output_mode != .Obj);
4178 const f = &wasm.flush_buffer;4911 const f = &wasm.flush_buffer;
4179 const table_base_addr = f.data_segments.get(.__zig_tag_name_table).?;4912 const table_base_addr = f.data_segments.get(.__zig_tag_name_table).?;
4180 const table_index = f.enum_tag_name_table.get(ip_index).?;4913 return table_base_addr + wasm.tagIndexTableOffset(ip_index);
4181 return table_base_addr + table_index * 8;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;
4182}4919}
41834920
4184fn convertZcuFnType(4921fn convertZcuFnType(
...@@ -4201,12 +4938,15 @@ fn convertZcuFnType(...@@ -4201,12 +4938,15 @@ fn convertZcuFnType(
4201 try params_buffer.append(gpa, .i32); // memory address is always a 32-bit handle4938 try params_buffer.append(gpa, .i32); // memory address is always a 32-bit handle
4202 } else if (return_type.hasRuntimeBits(zcu)) {4939 } else if (return_type.hasRuntimeBits(zcu)) {
4203 if (cc == .wasm_mvp) {4940 if (cc == .wasm_mvp) {
4204 switch (abi.classifyType(return_type, zcu)) {4941 switch (abi.classifyType(return_type, zcu, target)) {
4205 .direct => |scalar_ty| {4942 .direct => |scalar_type| {
4206 assert(!abi.lowerAsDoubleI64(scalar_ty, zcu));4943 try returns_buffer.append(gpa, CodeGen.typeToValtype(scalar_type, zcu, target));
4207 try returns_buffer.append(gpa, CodeGen.typeToValtype(scalar_ty, 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));
4208 },4949 },
4209 .indirect => unreachable,
4210 }4950 }
4211 } else {4951 } else {
4212 try returns_buffer.append(gpa, CodeGen.typeToValtype(return_type, zcu, target));4952 try returns_buffer.append(gpa, CodeGen.typeToValtype(return_type, zcu, target));
...@@ -4222,16 +4962,22 @@ fn convertZcuFnType(...@@ -4222,16 +4962,22 @@ fn convertZcuFnType(
42224962
4223 switch (cc) {4963 switch (cc) {
4224 .wasm_mvp => {4964 .wasm_mvp => {
4225 switch (abi.classifyType(param_type, zcu)) {4965 switch (abi.classifyType(param_type, zcu, target)) {
4226 .direct => |scalar_ty| {4966 .direct => |scalar_type| {
4227 if (!abi.lowerAsDoubleI64(scalar_ty, zcu)) {4967 try params_buffer.append(gpa, CodeGen.typeToValtype(scalar_type, zcu, target));
4228 try params_buffer.append(gpa, CodeGen.typeToValtype(scalar_ty, zcu, target));4968 },
4229 } else {4969 .double_i64 => {
4230 try params_buffer.append(gpa, .i64);4970 try params_buffer.append(gpa, .i64);
4231 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));
4232 }4979 }
4233 },4980 },
4234 .indirect => try params_buffer.append(gpa, CodeGen.typeToValtype(param_type, zcu, target)),
4235 }4981 }
4236 },4982 },
4237 else => try params_buffer.append(gpa, CodeGen.typeToValtype(param_type, zcu, target)),4983 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 {...@@ -4255,7 +5001,7 @@ pub fn isBss(wasm: *const Wasm, optional_name: OptionalString) bool {
4255/// those entries.5001/// those entries.
4256fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !ZcuDataObj {5002fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !ZcuDataObj {
4257 const code_start: u32 = @intCast(wasm.string_bytes.items.len);5003 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);
4259 const uav_fixups_start: u32 = @intCast(wasm.uav_fixups.items.len);5005 const uav_fixups_start: u32 = @intCast(wasm.uav_fixups.items.len);
4260 const nav_fixups_start: u32 = @intCast(wasm.nav_fixups.items.len);5006 const nav_fixups_start: u32 = @intCast(wasm.nav_fixups.items.len);
4261 const func_table_fixups_start: u32 = @intCast(wasm.func_table_fixups.items.len);5007 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...@@ -4271,8 +5017,9 @@ fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !Zcu
4271 }5017 }
42725018
4273 const code_len: u32 = @intCast(wasm.string_bytes.items.len - code_start);5019 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);
4275 const any_fixups =5021 const any_fixups =
5022 relocs_len != 0 or
4276 uav_fixups_start != wasm.uav_fixups.items.len or5023 uav_fixups_start != wasm.uav_fixups.items.len or
4277 nav_fixups_start != wasm.nav_fixups.items.len or5024 nav_fixups_start != wasm.nav_fixups.items.len or
4278 func_table_fixups_start != wasm.func_table_fixups.items.len;5025 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 {...@@ -45,7 +45,7 @@ const Header = extern struct {
4545
46 fn nameOrIndex(archive: Header) !NameOrIndex {46 fn nameOrIndex(archive: Header) !NameOrIndex {
47 const value = getValue(&archive.name);47 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;
49 const len = value.len;49 const len = value.len;
50 if (slash_index == len - 1) {50 if (slash_index == len - 1) {
51 // Name stored directly51 // Name stored directly
src/link/Wasm/Flush.zig+1148-137
...@@ -7,7 +7,6 @@ const Object = @import("Object.zig");...@@ -7,7 +7,6 @@ const Object = @import("Object.zig");
7const Zcu = @import("../../Zcu.zig");7const Zcu = @import("../../Zcu.zig");
8const Alignment = Wasm.Alignment;8const Alignment = Wasm.Alignment;
9const String = Wasm.String;9const String = Wasm.String;
10const Relocation = Wasm.Relocation;
11const InternPool = @import("../../InternPool.zig");10const InternPool = @import("../../InternPool.zig");
12const Mir = @import("../../codegen/wasm/Mir.zig");11const Mir = @import("../../codegen/wasm/Mir.zig");
1312
...@@ -33,8 +32,13 @@ data_segment_groups: ArrayList(DataSegmentGroup) = .empty,...@@ -33,8 +32,13 @@ data_segment_groups: ArrayList(DataSegmentGroup) = .empty,
33binary_bytes: ArrayList(u8) = .empty,32binary_bytes: ArrayList(u8) = .empty,
34missing_exports: std.array_hash_map.Auto(String, void) = .empty,33missing_exports: std.array_hash_map.Auto(String, void) = .empty,
35function_imports: std.array_hash_map.Auto(String, Wasm.FunctionImportId) = .empty,34function_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,
36global_imports: std.array_hash_map.Auto(String, Wasm.GlobalImportId) = .empty,38global_imports: std.array_hash_map.Auto(String, Wasm.GlobalImportId) = .empty,
37data_imports: std.array_hash_map.Auto(String, Wasm.DataImportId) = .empty,39data_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
39indirect_function_table: std.array_hash_map.Auto(Wasm.OutputFunctionIndex, void) = .empty,43indirect_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,...@@ -43,6 +47,9 @@ func_types: std.array_hash_map.Auto(Wasm.FunctionType.Index, void) = .empty,
4347
44enum_tag_name_table: std.array_hash_map.Auto(InternPool.Index, u32) = .empty,48enum_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
46/// For debug purposes only.53/// For debug purposes only.
47memory_layout_finished: bool = false,54memory_layout_finished: bool = false,
4855
...@@ -55,6 +62,74 @@ pub const FuncTypeIndex = enum(u32) {...@@ -55,6 +62,74 @@ pub const FuncTypeIndex = enum(u32) {
55 }62 }
56};63};
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
58/// Index into `indirect_function_table`.133/// Index into `indirect_function_table`.
59const IndirectFunctionTableIndex = enum(u32) {134const IndirectFunctionTableIndex = enum(u32) {
60 _,135 _,
...@@ -71,9 +146,8 @@ const IndirectFunctionTableIndex = enum(u32) {...@@ -71,9 +146,8 @@ const IndirectFunctionTableIndex = enum(u32) {
71 return @fromBackingInt(@intCast(f.indirect_function_table.getIndex(i).?));146 return @fromBackingInt(@intCast(f.indirect_function_table.getIndex(i).?));
72 }147 }
73148
74 fn fromZcuIndirectFunctionSetIndex(i: Wasm.ZcuIndirectFunctionSetIndex) IndirectFunctionTableIndex {149 fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) IndirectFunctionTableIndex {
75 // These are the same since those are added to the table first.150 return fromOutputFunctionIndex(&wasm.flush_buffer, .fromIpNav(wasm, nav_index));
76 return @fromBackingInt(@intCast(@backingInt(i)));
77 }151 }
78152
79 fn toAbi(i: IndirectFunctionTableIndex) u32 {153 fn toAbi(i: IndirectFunctionTableIndex) u32 {
...@@ -81,6 +155,39 @@ const IndirectFunctionTableIndex = enum(u32) {...@@ -81,6 +155,39 @@ const IndirectFunctionTableIndex = enum(u32) {
81 }155 }
82};156};
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
84const DataSegmentGroup = struct {191const DataSegmentGroup = struct {
85 first_segment: Wasm.DataSegmentId,192 first_segment: Wasm.DataSegmentId,
86 end_addr: u32,193 end_addr: u32,
...@@ -90,9 +197,14 @@ pub fn clear(f: *Flush) void {...@@ -90,9 +197,14 @@ pub fn clear(f: *Flush) void {
90 f.data_segments.clearRetainingCapacity();197 f.data_segments.clearRetainingCapacity();
91 f.data_segment_groups.clearRetainingCapacity();198 f.data_segment_groups.clearRetainingCapacity();
92 f.binary_bytes.clearRetainingCapacity();199 f.binary_bytes.clearRetainingCapacity();
200 f.intrinsic_function_imports.clearRetainingCapacity();
201 f.function_export_symbols.clearRetainingCapacity();
202 f.data_exports.clearRetainingCapacity();
93 f.indirect_function_table.clearRetainingCapacity();203 f.indirect_function_table.clearRetainingCapacity();
94 f.func_types.clearRetainingCapacity();204 f.func_types.clearRetainingCapacity();
95 f.enum_tag_name_table.clearRetainingCapacity();205 f.enum_tag_name_table.clearRetainingCapacity();
206 f.code_relocs.clearRetainingCapacity();
207 f.data_relocs.clearRetainingCapacity();
96 f.memory_layout_finished = false;208 f.memory_layout_finished = false;
97}209}
98210
...@@ -102,11 +214,16 @@ pub fn deinit(f: *Flush, gpa: Allocator) void {...@@ -102,11 +214,16 @@ pub fn deinit(f: *Flush, gpa: Allocator) void {
102 f.binary_bytes.deinit(gpa);214 f.binary_bytes.deinit(gpa);
103 f.missing_exports.deinit(gpa);215 f.missing_exports.deinit(gpa);
104 f.function_imports.deinit(gpa);216 f.function_imports.deinit(gpa);
217 f.intrinsic_function_imports.deinit(gpa);
218 f.function_export_symbols.deinit(gpa);
105 f.global_imports.deinit(gpa);219 f.global_imports.deinit(gpa);
106 f.data_imports.deinit(gpa);220 f.data_imports.deinit(gpa);
221 f.data_exports.deinit(gpa);
107 f.indirect_function_table.deinit(gpa);222 f.indirect_function_table.deinit(gpa);
108 f.func_types.deinit(gpa);223 f.func_types.deinit(gpa);
109 f.enum_tag_name_table.deinit(gpa);224 f.enum_tag_name_table.deinit(gpa);
225 f.code_relocs.deinit(gpa);
226 f.data_relocs.deinit(gpa);
110 f.* = undefined;227 f.* = undefined;
111}228}
112229
...@@ -131,51 +248,12 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -131,51 +248,12 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
131248
132 if (comp.zcu) |zcu| {249 if (comp.zcu) |zcu| {
133 const ip: *const InternPool = &zcu.intern_pool; // No mutations allowed!250 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
135 log.debug("total MIR instructions: {d}", .{wasm.mir_instructions.len});255 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
179 {257 {
180 var i = wasm.function_imports_len_prelink;258 var i = wasm.function_imports_len_prelink;
181 while (i < f.function_imports.entries.len) {259 while (i < f.function_imports.entries.len) {
...@@ -225,10 +303,24 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -225,10 +303,24 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
225 log.debug("flush export '{s}' nav={d}", .{ nav_export.name.slice(wasm), nav_export.nav_index });303 log.debug("flush export '{s}' nav={d}", .{ nav_export.name.slice(wasm), nav_export.nav_index });
226 const function_index = Wasm.FunctionIndex.fromIpNav(wasm, nav_export.nav_index).?;304 const function_index = Wasm.FunctionIndex.fromIpNav(wasm, nav_export.nav_index).?;
227 const explicit = f.missing_exports.swapRemove(nav_export.name);305 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) {
229 .hidden => true,308 .hidden => true,
230 .default, .protected => false,309 .default, .protected => false,
231 };310 };
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 });
232 if (is_hidden) {324 if (is_hidden) {
233 try wasm.hidden_function_exports.put(gpa, nav_export.name, function_index);325 try wasm.hidden_function_exports.put(gpa, nav_export.name, function_index);
234 } else {326 } else {
...@@ -239,17 +331,170 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -239,17 +331,170 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
239 if (nav_export.name.toOptional() == entry_name)331 if (nav_export.name.toOptional() == entry_name)
240 wasm.entry_resolution = .fromIpNav(wasm, nav_export.nav_index);332 wasm.entry_resolution = .fromIpNav(wasm, nav_export.nav_index);
241 } else {333 } else {
242 // This is a data export because Zcu currently has no way to334 // data exports are linker symbols
243 // export wasm globals.335 // explicit exports become address globals
244 _ = f.missing_exports.swapRemove(nav_export.name);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 });
245 _ = f.data_imports.swapRemove(nav_export.name);356 _ = f.data_imports.swapRemove(nav_export.name);
246 if (!is_obj) {357 if (explicit and !is_obj) {
247 diags.addError("unable to export data symbol '{s}'; not emitting a relocatable", .{358 const global_resolution: Wasm.GlobalImport.Resolution = .fromIpNav(
248 nav_export.name.slice(wasm),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).?,
249 });366 });
250 }367 }
251 }368 }
252 }369 }
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
254 for (f.missing_exports.keys()) |exp_name| {499 for (f.missing_exports.keys()) |exp_name| {
255 diags.addError("manually specified export name '{s}' undefined", .{exp_name.slice(wasm)});500 diags.addError("manually specified export name '{s}' undefined", .{exp_name.slice(wasm)});
...@@ -300,7 +545,27 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -300,7 +545,27 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
300 if (wasm.object_init_funcs.items.len > 0) {545 if (wasm.object_init_funcs.items.len > 0) {
301 // Zig has no constructors so these are only for object file inputs.546 // Zig has no constructors so these are only for object file inputs.
302 mem.sortUnstable(Wasm.InitFunc, wasm.object_init_funcs.items, {}, Wasm.InitFunc.lessThan);547 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 }
304 }569 }
305570
306 // Merge and order the data segments. Depends on garbage collection so that571 // Merge and order the data segments. Depends on garbage collection so that
...@@ -341,14 +606,33 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -341,14 +606,33 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
341 // dropped in __wasm_init_memory, which is registered as the start function606 // dropped in __wasm_init_memory, which is registered as the start function
342 // We also initialize bss segments (using memory.fill) as part of this607 // We also initialize bss segments (using memory.fill) as part of this
343 // function.608 // function.
344 if (wasm.any_passive_inits) {609 if (!is_obj and wasm.any_passive_inits) {
345 try wasm.addFunction(.__wasm_init_memory, &.{}, &.{});610 try wasm.addFunction(.__wasm_init_memory, &.{}, &.{});
346 }611 }
347612
348 try wasm.tables.ensureUnusedCapacity(gpa, 1);613 try wasm.tables.ensureUnusedCapacity(gpa, 1);
349614
350 if (f.indirect_function_table.entries.len > 0) {615 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 }
352 }636 }
353637
354 // Sort order:638 // Sort order:
...@@ -449,7 +733,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -449,7 +733,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
449 const start_addr = alignment.forward(memory_ptr);733 const start_addr = alignment.forward(memory_ptr);
450734
451 const want_new_segment = b: {735 const want_new_segment = b: {
452 if (is_obj) break :b false;736 if (is_obj) break :b i != 0;
453 switch (seen_tls) {737 switch (seen_tls) {
454 .before => switch (category) {738 .before => switch (category) {
455 .tls => {739 .tls => {
...@@ -489,7 +773,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -489,7 +773,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
489 log.debug("0x{x} {d} {s}", .{ start_addr, @backingInt(segment_id), segment_id.name(wasm) });773 log.debug("0x{x} {d} {s}", .{ start_addr, @backingInt(segment_id), segment_id.name(wasm) });
490 memory_ptr = start_addr + size;774 memory_ptr = start_addr + size;
491 }775 }
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, .{
493 .first_segment = first_segment,777 .first_segment = first_segment,
494 .end_addr = @intCast(memory_ptr),778 .end_addr = @intCast(memory_ptr),
495 });779 });
...@@ -555,7 +839,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -555,7 +839,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
555839
556 // When we have TLS GOT entries and shared memory is enabled, we must840 // When we have TLS GOT entries and shared memory is enabled, we must
557 // perform runtime relocations or else we don't create the function.841 // 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) {
559 // This logic that checks `any_tls_relocs` is missing the part where it843 // This logic that checks `any_tls_relocs` is missing the part where it
560 // also notices threadlocal globals from Zcu code.844 // also notices threadlocal globals from Zcu code.
561 if (wasm.any_tls_relocs) try wasm.addFunction(.__wasm_apply_global_tls_relocs, &.{}, &.{});845 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 {...@@ -582,6 +866,9 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
582 for (f.function_imports.values()) |id| {866 for (f.function_imports.values()) |id| {
583 try f.func_types.put(gpa, id.functionType(wasm), {});867 try f.func_types.put(gpa, id.functionType(wasm), {});
584 }868 }
869 for (f.intrinsic_function_imports.values()) |type_index| {
870 try f.func_types.put(gpa, type_index, {});
871 }
585 for (wasm.functions.keys()) |function| {872 for (wasm.functions.keys()) |function| {
586 try f.func_types.put(gpa, function.typeIndex(wasm), {});873 try f.func_types.put(gpa, function.typeIndex(wasm), {});
587 }874 }
...@@ -617,7 +904,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -617,7 +904,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
617 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);904 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
618905
619 for (f.function_imports.values()) |id| {906 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);
621 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(module_name.len)));908 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(module_name.len)));
622 try binary_bytes.appendSlice(gpa, module_name);909 try binary_bytes.appendSlice(gpa, module_name);
623910
...@@ -631,6 +918,20 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -631,6 +918,20 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
631 }918 }
632 total_imports += f.function_imports.entries.len;919 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
634 for (wasm.table_imports.values()) |id| {935 for (wasm.table_imports.values()) |id| {
635 const table_import = id.value(wasm);936 const table_import = id.value(wasm);
636 const module_name = table_import.module_name.slice(wasm);937 const module_name = table_import.module_name.slice(wasm);
...@@ -662,7 +963,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -662,7 +963,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
662 }963 }
663964
664 for (f.global_imports.values()) |id| {965 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);
666 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(module_name.len)));967 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(module_name.len)));
667 try binary_bytes.appendSlice(gpa, module_name);968 try binary_bytes.appendSlice(gpa, module_name);
668969
...@@ -726,12 +1027,12 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -726,12 +1027,12 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
726 for (wasm.globals.keys()) |global_resolution| {1027 for (wasm.globals.keys()) |global_resolution| {
727 switch (global_resolution.unpack(wasm)) {1028 switch (global_resolution.unpack(wasm)) {
728 .unresolved => unreachable,1029 .unresolved => unreachable,
729 .__heap_base => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_base),1030 .__heap_base => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_base, is64),
730 .__heap_end => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_end),1031 .__heap_end => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_end, is64),
731 .__stack_pointer => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.stack_pointer),1032 .__stack_pointer => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.stack_pointer, is64),
732 .__tls_align => try appendGlobal(gpa, binary_bytes, 0, @intCast(virtual_addrs.tls_align.toByteUnits().?)),1033 .__tls_align => try appendGlobal(gpa, binary_bytes, 0, @intCast(virtual_addrs.tls_align.toByteUnits().?), is64),
733 .__tls_base => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.tls_base.?),1034 .__tls_base => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.tls_base.?, is64),
734 .__tls_size => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.tls_size.?),1035 .__tls_size => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.tls_size.?, is64),
735 .object_global => |i| {1036 .object_global => |i| {
736 const global = i.ptr(wasm);1037 const global = i.ptr(wasm);
737 try binary_bytes.appendSlice(gpa, &.{1038 try binary_bytes.appendSlice(gpa, &.{
...@@ -740,8 +1041,9 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -740,8 +1041,9 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
740 });1041 });
741 try emitExpr(wasm, binary_bytes, global.expr);1042 try emitExpr(wasm, binary_bytes, global.expr);
742 },1043 },
743 .nav_exe => unreachable, // Zig source code currently cannot represent this.1044 .uav_exe => |i| try appendGlobal(gpa, binary_bytes, 0, wasm.uavAddr(i.key(wasm).*), is64),
744 .nav_obj => unreachable, // Zig source code currently cannot represent this.1045 .nav_exe => |i| try appendGlobal(gpa, binary_bytes, 0, wasm.navAddr(i.key(wasm).*), is64),
1046 .uav_obj, .nav_obj => unreachable,
745 }1047 }
746 }1048 }
7471049
...@@ -766,7 +1068,8 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -766,7 +1068,8 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
7661068
767 if (wasm.export_table and f.indirect_function_table.entries.len > 0) {1069 if (wasm.export_table and f.indirect_function_table.entries.len > 0) {
768 const name = "__indirect_function_table";1070 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).?);
770 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));1073 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));
771 try binary_bytes.appendSlice(gpa, name);1074 try binary_bytes.appendSlice(gpa, name);
772 try binary_bytes.append(gpa, @backingInt(std.wasm.ExternalKind.table));1075 try binary_bytes.append(gpa, @backingInt(std.wasm.ExternalKind.table));
...@@ -803,16 +1106,18 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -803,16 +1106,18 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
803 // start section1106 // start section
804 if (wasm.functions.getIndex(.__wasm_init_memory)) |func_index| {1107 if (wasm.functions.getIndex(.__wasm_init_memory)) |func_index| {
805 try emitStartSection(gpa, binary_bytes, .fromFunctionIndex(wasm, @fromBackingInt(@intCast(func_index))));1108 try emitStartSection(gpa, binary_bytes, .fromFunctionIndex(wasm, @fromBackingInt(@intCast(func_index))));
806 } else if (Wasm.OutputFunctionIndex.fromResolution(wasm, wasm.entry_resolution)) |func_index| {1109 section_index += 1;
807 try emitStartSection(gpa, binary_bytes, func_index);
808 }1110 }
8091111
810 // element section1112 // element section
811 if (f.indirect_function_table.entries.len > 0) {1113 if (!is_obj and f.indirect_function_table.entries.len > 0) {
812 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);1114 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
8131115
814 // indirect function table elements1116 // 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 );
816 // passive with implicit 0-index table or set table index manually1121 // passive with implicit 0-index table or set table index manually
817 const flags: u32 = if (table_index == 0) 0x0 else 0x02;1122 const flags: u32 = if (table_index == 0) 0x0 else 0x02;
818 try appendLeb128(gpa, binary_bytes, flags);1123 try appendLeb128(gpa, binary_bytes, flags);
...@@ -841,11 +1146,13 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -841,11 +1146,13 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
841 if (f.data_segment_groups.items.len > 0) {1146 if (f.data_segment_groups.items.len > 0) {
842 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);1147 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
843 replaceVecSectionHeader(binary_bytes, header_offset, .data_count, @intCast(f.data_segment_groups.items.len));1148 replaceVecSectionHeader(binary_bytes, header_offset, .data_count, @intCast(f.data_segment_groups.items.len));
1149 section_index += 1;
844 }1150 }
8451151
846 // Code section.1152 // Code section.
847 if (wasm.functions.count() != 0) {1153 if (wasm.functions.count() != 0) {
848 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);1154 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
1155 const section_offset = binary_bytes.items.len - uleb128size(@intCast(wasm.functions.count()));
8491156
850 for (wasm.functions.keys()) |resolution| switch (resolution.unpack(wasm)) {1157 for (wasm.functions.keys()) |resolution| switch (resolution.unpack(wasm)) {
851 .unresolved => unreachable,1158 .unresolved => unreachable,
...@@ -870,10 +1177,22 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -870,10 +1177,22 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
870 const code = ptr.code.slice(wasm);1177 const code = ptr.code.slice(wasm);
871 try appendLeb128(gpa, binary_bytes, code.len);1178 try appendLeb128(gpa, binary_bytes, code.len);
872 const code_start = binary_bytes.items.len;1179 const code_start = binary_bytes.items.len;
1180 const output_offset: u32 = @intCast(binary_bytes.items.len - section_offset);
873 try binary_bytes.appendSlice(gpa, code);1181 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 }
875 },1193 },
876 .zcu_func => |i| {1194 .zcu_func => |i| {
1195 const function_offset: u32 = @intCast(binary_bytes.items.len - section_offset);
877 const code_start = try reserveSize(gpa, binary_bytes);1196 const code_start = try reserveSize(gpa, binary_bytes);
878 defer replaceSize(binary_bytes, code_start);1197 defer replaceSize(binary_bytes, code_start);
8791198
...@@ -899,7 +1218,22 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -899,7 +1218,22 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
899 .func_tys = undefined,1218 .func_tys = undefined,
900 .error_name_table_ref_count = undefined,1219 .error_name_table_ref_count = undefined,
901 };1220 };
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);
902 try mir.lower(wasm, binary_bytes);1224 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 }
903 },1237 },
904 }1238 }
905 },1239 },
...@@ -921,8 +1255,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -921,8 +1255,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
921 }1255 }
922 }1256 }
923 for (wasm.nav_fixups.items) |nav_fixup| {1257 for (wasm.nav_fixups.items) |nav_fixup| {
924 const ds_id: Wasm.DataSegmentId = .pack(wasm, .{ .nav_exe = nav_fixup.navs_exe_index });1258 const vaddr = wasm.navAddr(nav_fixup.nav_index) + nav_fixup.addend;
925 const vaddr = f.data_segments.get(ds_id).? + nav_fixup.addend;
926 if (!is64) {1259 if (!is64) {
927 mem.writeInt(u32, wasm.string_bytes.items[nav_fixup.offset..][0..4], vaddr, .little);1260 mem.writeInt(u32, wasm.string_bytes.items[nav_fixup.offset..][0..4], vaddr, .little);
928 } else {1261 } else {
...@@ -930,7 +1263,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -930,7 +1263,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
930 }1263 }
931 }1264 }
932 for (wasm.func_table_fixups.items) |fixup| {1265 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);
934 if (!is64) {1267 if (!is64) {
935 mem.writeInt(u32, wasm.string_bytes.items[fixup.offset..][0..4], table_index.toAbi(), .little);1268 mem.writeInt(u32, wasm.string_bytes.items[fixup.offset..][0..4], table_index.toAbi(), .little);
936 } else {1269 } else {
...@@ -942,6 +1275,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -942,6 +1275,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
942 // Data section.1275 // Data section.
943 if (f.data_segment_groups.items.len != 0) {1276 if (f.data_segment_groups.items.len != 0) {
944 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);1277 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
946 var group_index: u32 = 0;1280 var group_index: u32 = 0;
947 var segment_offset: u32 = 0;1281 var segment_offset: u32 = 0;
...@@ -976,7 +1310,11 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -976,7 +1310,11 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
976 try appendLeb128(gpa, binary_bytes, group_size);1310 try appendLeb128(gpa, binary_bytes, group_size);
977 }1311 }
978 if (segment_id.isEmpty(wasm)) {1312 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 }
980 continue;1318 continue;
981 }1319 }
9821320
...@@ -986,6 +1324,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -986,6 +1324,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
986 segment_offset = needed_offset;1324 segment_offset = needed_offset;
9871325
988 const code_start = binary_bytes.items.len;1326 const code_start = binary_bytes.items.len;
1327 const output_offset: u32 = @intCast(binary_bytes.items.len - section_offset);
989 append: {1328 append: {
990 const code = switch (segment_id.unpack(wasm)) {1329 const code = switch (segment_id.unpack(wasm)) {
991 .__heap_base => {1330 .__heap_base => {
...@@ -1001,12 +1340,19 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -1001,12 +1340,19 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
1001 break :append;1340 break :append;
1002 },1341 },
1003 .__zig_error_name_table => {1342 .__zig_error_name_table => {
1004 if (is_obj) @panic("TODO error name table reloc");1343 if (is_obj) {
1005 const base = f.data_segments.get(.__zig_error_names).?;1344 try emitRelocatableNameTable(
1006 if (!is64) {1345 wasm,
1007 try emitTagNameTable(gpa, binary_bytes, wasm.error_name_offs.items, wasm.error_name_bytes.items, base, u32);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 );
1008 } else {1353 } 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);
1010 }1356 }
1011 break :append;1357 break :append;
1012 },1358 },
...@@ -1015,22 +1361,51 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -1015,22 +1361,51 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
1015 break :append;1361 break :append;
1016 },1362 },
1017 .__zig_tag_name_table => {1363 .__zig_tag_name_table => {
1018 if (is_obj) @panic("TODO tag name table reloc");1364 if (is_obj) {
1019 const base = f.data_segments.get(.__zig_tag_names).?;1365 try emitRelocatableNameTable(
1020 if (!is64) {1366 wasm,
1021 try emitTagNameTable(gpa, binary_bytes, wasm.tag_name_offs.items, wasm.tag_name_bytes.items, base, u32);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 );
1022 } else {1374 } 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);
1024 }1377 }
1025 break :append;1378 break :append;
1026 },1379 },
1027 .object => |i| {1380 .object => |i| {
1028 const ptr = i.ptr(wasm);1381 const ptr = i.ptr(wasm);
1029 try binary_bytes.appendSlice(gpa, ptr.payload.slice(wasm));1382 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 }
1031 break :append;1394 break :append;
1032 },1395 },
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,
1034 };1409 };
1035 try binary_bytes.appendSlice(gpa, code.slice(wasm));1410 try binary_bytes.appendSlice(gpa, code.slice(wasm));
1036 }1411 }
...@@ -1043,7 +1418,274 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -1043,7 +1418,274 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
1043 }1418 }
10441419
1045 if (is_obj) {1420 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 );
1047 } else if (comp.config.debug_format != .strip) {1689 } else if (comp.config.debug_format != .strip) {
1048 try emitNameSection(wasm, f.data_segment_groups.items, binary_bytes);1690 try emitNameSection(wasm, f.data_segment_groups.items, binary_bytes);
1049 }1691 }
...@@ -1121,7 +1763,10 @@ fn emitNameSection(...@@ -1121,7 +1763,10 @@ fn emitNameSection(
1121 const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes);1763 const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes);
1122 defer replaceHeader(binary_bytes, sub_offset, @backingInt(std.wasm.NameSubsection.function));1764 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 );
1125 try appendLeb128(gpa, binary_bytes, total_functions);1770 try appendLeb128(gpa, binary_bytes, total_functions);
11261771
1127 for (f.function_imports.keys(), 0..) |name_index, function_index| {1772 for (f.function_imports.keys(), 0..) |name_index, function_index| {
...@@ -1130,7 +1775,16 @@ fn emitNameSection(...@@ -1130,7 +1775,16 @@ fn emitNameSection(
1130 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));1775 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));
1131 try binary_bytes.appendSlice(gpa, name);1776 try binary_bytes.appendSlice(gpa, name);
1132 }1777 }
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| {
1134 const name = resolution.name(wasm).?;1788 const name = resolution.name(wasm).?;
1135 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(function_index)));1789 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(function_index)));
1136 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));1790 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));
...@@ -1152,7 +1806,8 @@ fn emitNameSection(...@@ -1152,7 +1806,8 @@ fn emitNameSection(
1152 try binary_bytes.appendSlice(gpa, name);1806 try binary_bytes.appendSlice(gpa, name);
1153 }1807 }
1154 for (wasm.globals.keys(), f.global_imports.entries.len..) |resolution, global_index| {1808 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).?;
1156 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(global_index)));1811 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(global_index)));
1157 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));1812 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len)));
1158 try binary_bytes.appendSlice(gpa, name);1813 try binary_bytes.appendSlice(gpa, name);
...@@ -1270,7 +1925,7 @@ fn emitProducerSection(gpa: Allocator, binary_bytes: *ArrayList(u8)) !void {...@@ -1270,7 +1925,7 @@ fn emitProducerSection(gpa: Allocator, binary_bytes: *ArrayList(u8)) !void {
12701925
1271fn splitSegmentName(name: []const u8) struct { []const u8, []const u8 } {1926fn splitSegmentName(name: []const u8) struct { []const u8, []const u8 } {
1272 const start = @intFromBool(name.len >= 1 and name[0] == '.');1927 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;
1274 return .{ name[0..pivot], name[pivot..] };1929 return .{ name[0..pivot], name[pivot..] };
1275}1930}
12761931
...@@ -1418,29 +2073,6 @@ pub fn emitExpr(wasm: *const Wasm, binary_bytes: *ArrayList(u8), expr: Wasm.Expr...@@ -1418,29 +2073,6 @@ pub fn emitExpr(wasm: *const Wasm, binary_bytes: *ArrayList(u8), expr: Wasm.Expr
1418 try binary_bytes.appendSlice(gpa, slice[0 .. slice.len + 1]); // +1 to include end opcode2073 try binary_bytes.appendSlice(gpa, slice[0 .. slice.len + 1]); // +1 to include end opcode
1419}2074}
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
1444fn uleb128size(x: u32) u32 {2076fn uleb128size(x: u32) u32 {
1445 var value = x;2077 var value = x;
1446 var size: u32 = 0;2078 var size: u32 = 0;
...@@ -1449,22 +2081,395 @@ fn uleb128size(x: u32) u32 {...@@ -1449,22 +2081,395 @@ fn uleb128size(x: u32) u32 {
1449}2081}
14502082
1451fn emitTagNameTable(2083fn emitTagNameTable(
1452 gpa: Allocator,2084 wasm: *const Wasm,
1453 code: *ArrayList(u8),2085 code: *ArrayList(u8),
1454 tag_name_offs: []const u32,2086 tag_name_offs: []const u32,
1455 tag_name_bytes: []const u8,2087 tag_name_bytes: []const u8,
1456 base: u32,2088 base: u32,
1457 comptime Int: type,2089 is64: bool,
1458) error{OutOfMemory}!void {2090) 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;
1460 try code.ensureUnusedCapacity(gpa, ptr_size_bytes * 2 * tag_name_offs.len);2093 try code.ensureUnusedCapacity(gpa, ptr_size_bytes * 2 * tag_name_offs.len);
1461 for (tag_name_offs) |off| {2094 for (tag_name_offs) |off| {
1462 const name_len: u32 = @intCast(mem.indexOfScalar(u8, tag_name_bytes[off..], 0).?);2095 const name_len: u32 = @intCast(mem.findScalar(u8, tag_name_bytes[off..], 0).?);
1463 mem.writeInt(Int, code.addManyAsArrayAssumeCapacity(ptr_size_bytes), base + off, .little);2096 if (is64) {
1464 mem.writeInt(Int, code.addManyAsArrayAssumeCapacity(ptr_size_bytes), name_len, .little);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 });
1465 }2266 }
1466}2267}
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
1468fn applyRelocs(code: []u8, code_offset: u32, relocs: Wasm.ObjectRelocation.IterableSlice, wasm: *const Wasm) void {2473fn applyRelocs(code: []u8, code_offset: u32, relocs: Wasm.ObjectRelocation.IterableSlice, wasm: *const Wasm) void {
1469 for (2474 for (
1470 relocs.slice.tags(wasm),2475 relocs.slice.tags(wasm),
...@@ -1579,12 +2584,17 @@ const RelocAddr = struct {...@@ -1579,12 +2584,17 @@ const RelocAddr = struct {
1579 fn fromSymbolName(wasm: *const Wasm, name: String, addend: i32) RelocAddr {2584 fn fromSymbolName(wasm: *const Wasm, name: String, addend: i32) RelocAddr {
1580 const flush = &wasm.flush_buffer;2585 const flush = &wasm.flush_buffer;
1581 if (wasm.object_data_imports.getPtr(name)) |import| {2586 if (wasm.object_data_imports.getPtr(name)) |import| {
1582 return fromDataLoc(flush, import.resolution.dataLoc(wasm), addend);2587 if (import.resolution != .unresolved) {
1583 } else if (wasm.data_imports.get(name)) |id| {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| {
1584 return fromDataLoc(flush, .fromDataImportId(wasm, id), addend);2595 return fromDataLoc(flush, .fromDataImportId(wasm, id), addend);
1585 } else {
1586 unreachable;
1587 }2596 }
2597 unreachable;
1588 }2598 }
15892599
1590 fn fromDataLoc(flush: *const Flush, data_loc: Wasm.DataLoc, addend: i32) RelocAddr {2600 fn fromDataLoc(flush: *const Flush, data_loc: Wasm.DataLoc, addend: i32) RelocAddr {
...@@ -1702,13 +2712,11 @@ fn emitInitMemoryFunction(...@@ -1702,13 +2712,11 @@ fn emitInitMemoryFunction(
1702 }2712 }
17032713
1704 const segment_groups = wasm.flush_buffer.data_segment_groups.items;2714 const segment_groups = wasm.flush_buffer.data_segment_groups.items;
1705 var prev_end: u32 = 0;
1706 for (segment_groups, 0..) |group, segment_index| {2715 for (segment_groups, 0..) |group, segment_index| {
1707 defer prev_end = group.end_addr;
1708 const segment = group.first_segment;2716 const segment = group.first_segment;
1709 if (!segment.isPassive(wasm)) continue;2717 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).?;
1712 const segment_size: u32 = group.end_addr - start_addr;2720 const segment_size: u32 = group.end_addr - start_addr;
17132721
1714 try binary_bytes.ensureUnusedCapacity(gpa, 6 + 6 + 1 + 5 + 6 + 6 + 1 + 6 * 2 + 1 + 1);2722 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 {...@@ -2028,12 +3036,15 @@ fn appendReservedUleb32(bytes: *ArrayList(u8), val: u32) void {
2028 };3036 };
2029}3037}
20303038
2031fn appendGlobal(gpa: Allocator, bytes: *ArrayList(u8), mutable: u8, val: u32) Allocator.Error!void {3039fn appendGlobal(gpa: Allocator, bytes: *ArrayList(u8), mutable: u8, val: u64, is64: bool) Allocator.Error!void {
2032 try bytes.ensureUnusedCapacity(gpa, 9);3040 try bytes.ensureUnusedCapacity(gpa, if (is64) 14 else 9);
2033 bytes.appendAssumeCapacity(@backingInt(std.wasm.Valtype.i32));3041 bytes.appendAssumeCapacity(@backingInt(@as(std.wasm.Valtype, if (is64) .i64 else .i32)));
2034 bytes.appendAssumeCapacity(mutable);3042 bytes.appendAssumeCapacity(mutable);
2035 bytes.appendAssumeCapacity(@backingInt(std.wasm.Opcode.i32_const));3043 if (is64) {
2036 appendReservedUleb32(bytes, val);3044 appendReservedI64Const(bytes, val);
3045 } else {
3046 appendReservedI32Const(bytes, @intCast(val));
3047 }
2037 bytes.appendAssumeCapacity(@backingInt(std.wasm.Opcode.end));3048 bytes.appendAssumeCapacity(@backingInt(std.wasm.Opcode.end));
2038}3049}
20393050
src/link/Wasm/Object.zig+2-2
...@@ -146,7 +146,7 @@ pub const Symbol = struct {...@@ -146,7 +146,7 @@ pub const Symbol = struct {
146 pointee: Pointee,146 pointee: Pointee,
147147
148 /// https://github.com/WebAssembly/tool-conventions/blob/df8d737539eb8a8f446ba5eab9dc670c40dfb81e/Linking.md#symbol-table-subsection148 /// https://github.com/WebAssembly/tool-conventions/blob/df8d737539eb8a8f446ba5eab9dc670c40dfb81e/Linking.md#symbol-table-subsection
149 const Tag = enum(u8) {149 pub const Tag = enum(u8) {
150 function,150 function,
151 data,151 data,
152 global,152 global,
...@@ -856,7 +856,7 @@ pub fn parse(...@@ -856,7 +856,7 @@ pub fn parse(
856 start_function = @fromBackingInt(@intCast(functions_start + index));856 start_function = @fromBackingInt(@intCast(functions_start + index));
857 },857 },
858 .element => {858 .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
860 pos = section_end;860 pos = section_end;
861 },861 },
862 .code => {862 .code => {
src/main.zig+40-54
...@@ -44,9 +44,9 @@ pub const std_options: std.Options = .{...@@ -44,9 +44,9 @@ pub const std_options: std.Options = .{
44 .logFn = log,44 .logFn = log,
4545
46 .log_level = switch (builtin.mode) {46 .log_level = switch (builtin.mode) {
47 .Debug => .debug,47 .debug => .debug,
48 .ReleaseSafe, .ReleaseFast => .info,48 .safe, .fast => .info,
49 .ReleaseSmall => .err,49 .small => .err,
50 },50 },
51};51};
52pub const std_options_cwd = if (native_os == .wasi) wasi_cwd else null;52pub const std_options_cwd = if (native_os == .wasi) wasi_cwd else null;
...@@ -158,8 +158,8 @@ pub fn log(...@@ -158,8 +158,8 @@ pub fn log(
158158
159const use_safe_allocator = build_options.debug_gpa or159const use_safe_allocator = build_options.debug_gpa or
160 (native_os != .wasi and !builtin.link_libc and switch (builtin.mode) {160 (native_os != .wasi and !builtin.link_libc and switch (builtin.mode) {
161 .Debug, .ReleaseSafe => true,161 .debug, .safe => true,
162 .ReleaseFast, .ReleaseSmall => false,162 .fast, .small => false,
163 });163 });
164164
165var safe_allocator: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{165var safe_allocator: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{
...@@ -359,8 +359,7 @@ fn mainArgs(...@@ -359,8 +359,7 @@ fn mainArgs(
359 .prepend_global_cache_path = true,359 .prepend_global_cache_path = true,
360 .prepend_zig_exe_path = true,360 .prepend_zig_exe_path = true,
361 .prepend_seed = true,361 .prepend_seed = true,
362 .debug_env_var = .ZIG_DEBUG_MAKER,362 .release_mode = .safe,
363 .release_mode = .ReleaseSafe,
364 });363 });
365 },364 },
366 .clang, .@"-cc1", .@"-cc1as" => {365 .clang, .@"-cc1", .@"-cc1as" => {
...@@ -557,10 +556,6 @@ const usage_build_generic =...@@ -557,10 +556,6 @@ const usage_build_generic =
557 \\ -fno-function-sections All functions go into same section556 \\ -fno-function-sections All functions go into same section
558 \\ -fdata-sections Places each data in a separate section557 \\ -fdata-sections Places each data in a separate section
559 \\ -fno-data-sections All data go into same section558 \\ -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
564 \\ -mexec-model=[value] (WASI) Execution model559 \\ -mexec-model=[value] (WASI) Execution model
565 \\ -municode (Windows) Use wmain/wWinMain as entry point560 \\ -municode (Windows) Use wmain/wWinMain as entry point
566 \\ --time-report Send timing diagnostics to '--listen' clients561 \\ --time-report Send timing diagnostics to '--listen' clients
...@@ -568,10 +563,10 @@ const usage_build_generic =...@@ -568,10 +563,10 @@ const usage_build_generic =
568 \\Per-Module Compile Options:563 \\Per-Module Compile Options:
569 \\ -target [name] <arch><sub>-<os>-<abi> see the targets command564 \\ -target [name] <arch><sub>-<os>-<abi> see the targets command
570 \\ -O [mode] Choose what to optimize for565 \\ -O [mode] Choose what to optimize for
571 \\ Debug (default) Optimizations off, safety on566 \\ debug (default) Prioritize bug detection, accurate debug info, compilation speed
572 \\ ReleaseFast Optimize for performance, safety off567 \\ fast Prioritize runtime performance. Safety checks off.
573 \\ ReleaseSafe Optimize for performance, safety on568 \\ safe Enable both safety checks and machine code optimizations
574 \\ ReleaseSmall Optimize for small binary, safety off569 \\ small Prioritize small binary size. Safety checks off.
575 \\ -ofmt=[fmt] Override target object format570 \\ -ofmt=[fmt] Override target object format
576 \\ elf Executable and Linking Format571 \\ elf Executable and Linking Format
577 \\ c C source code572 \\ c C source code
...@@ -994,7 +989,7 @@ fn buildOutputType(...@@ -994,7 +989,7 @@ fn buildOutputType(
994 var minor_subsystem_version: ?u16 = null;989 var minor_subsystem_version: ?u16 = null;
995 var mingw_unicode_entry_point: bool = false;990 var mingw_unicode_entry_point: bool = false;
996 var enable_link_snapshots: bool = false;991 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;
998 var install_name: ?[]const u8 = null;993 var install_name: ?[]const u8 = null;
999 var hash_style: link.File.Lld.Elf.HashStyle = .both;994 var hash_style: link.File.Lld.Elf.HashStyle = .both;
1000 var entitlements: ?[]const u8 = null;995 var entitlements: ?[]const u8 = null;
...@@ -1200,10 +1195,6 @@ fn buildOutputType(...@@ -1200,10 +1195,6 @@ fn buildOutputType(
1200 if (mem.eql(u8, next_arg, "--")) break;1195 if (mem.eql(u8, next_arg, "--")) break;
1201 try extra_rcflags.append(arena, next_arg);1196 try extra_rcflags.append(arena, next_arg);
1202 }1197 }
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;
1207 } else if (mem.eql(u8, arg, "--color")) {1198 } else if (mem.eql(u8, arg, "--color")) {
1208 const next_arg = args_iter.next() orelse {1199 const next_arg = args_iter.next() orelse {
1209 fatal("expected [auto|on|off] after --color", .{});1200 fatal("expected [auto|on|off] after --color", .{});
...@@ -1433,7 +1424,7 @@ fn buildOutputType(...@@ -1433,7 +1424,7 @@ fn buildOutputType(
1433 enable_link_snapshots = true;1424 enable_link_snapshots = true;
1434 }1425 }
1435 } else if (mem.eql(u8, arg, "--debug-rt")) {1426 } else if (mem.eql(u8, arg, "--debug-rt")) {
1436 debug_compiler_runtime_libs = .Debug;1427 debug_compiler_runtime_libs = .debug;
1437 } else if (mem.cutPrefix(u8, arg, "--debug-rt=")) |rest| {1428 } else if (mem.cutPrefix(u8, arg, "--debug-rt=")) |rest| {
1438 debug_compiler_runtime_libs = parseOptimizeMode(rest);1429 debug_compiler_runtime_libs = parseOptimizeMode(rest);
1439 } else if (mem.eql(u8, arg, "--debug-incremental")) {1430 } else if (mem.eql(u8, arg, "--debug-incremental")) {
...@@ -1650,12 +1641,6 @@ fn buildOutputType(...@@ -1650,12 +1641,6 @@ fn buildOutputType(
1650 create_module.opts.debug_format = .{ .dwarf = .@"32" };1641 create_module.opts.debug_format = .{ .dwarf = .@"32" };
1651 } else if (mem.eql(u8, arg, "-gdwarf64")) {1642 } else if (mem.eql(u8, arg, "-gdwarf64")) {
1652 create_module.opts.debug_format = .{ .dwarf = .@"64" };1643 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", .{});
1659 } else if (mem.eql(u8, arg, "-fsingle-threaded")) {1644 } else if (mem.eql(u8, arg, "-fsingle-threaded")) {
1660 mod_opts.single_threaded = true;1645 mod_opts.single_threaded = true;
1661 } else if (mem.eql(u8, arg, "-fno-single-threaded")) {1646 } else if (mem.eql(u8, arg, "-fno-single-threaded")) {
...@@ -2162,7 +2147,7 @@ fn buildOutputType(...@@ -2162,7 +2147,7 @@ fn buildOutputType(
2162 preprocessor_arg[0] == '-' and2147 preprocessor_arg[0] == '-' and
2163 preprocessor_arg[2] != '-')2148 preprocessor_arg[2] != '-')
2164 {2149 {
2165 if (mem.indexOfScalar(u8, preprocessor_arg, '=')) |equals_pos| {2150 if (mem.findScalar(u8, preprocessor_arg, '=')) |equals_pos| {
2166 const key = preprocessor_arg[0..equals_pos];2151 const key = preprocessor_arg[0..equals_pos];
2167 const value = preprocessor_arg[equals_pos + 1 ..];2152 const value = preprocessor_arg[equals_pos + 1 ..];
2168 try preprocessor_args.append(key);2153 try preprocessor_args.append(key);
...@@ -2184,7 +2169,7 @@ fn buildOutputType(...@@ -2184,7 +2169,7 @@ fn buildOutputType(
2184 linker_arg[0] == '-' and2169 linker_arg[0] == '-' and
2185 linker_arg[2] != '-')2170 linker_arg[2] != '-')
2186 {2171 {
2187 if (mem.indexOfScalar(u8, linker_arg, '=')) |equals_pos| {2172 if (mem.findScalar(u8, linker_arg, '=')) |equals_pos| {
2188 const key = linker_arg[0..equals_pos];2173 const key = linker_arg[0..equals_pos];
2189 const value = linker_arg[equals_pos + 1 ..];2174 const value = linker_arg[equals_pos + 1 ..];
21902175
...@@ -2271,18 +2256,18 @@ fn buildOutputType(...@@ -2271,18 +2256,18 @@ fn buildOutputType(
2271 if (mem.eql(u8, level, "s") or2256 if (mem.eql(u8, level, "s") or
2272 mem.eql(u8, level, "z"))2257 mem.eql(u8, level, "z"))
2273 {2258 {
2274 mod_opts.optimize_mode = .ReleaseSmall;2259 mod_opts.optimize_mode = .small;
2275 } else if (mem.eql(u8, level, "1") or2260 } else if (mem.eql(u8, level, "1") or
2276 mem.eql(u8, level, "2") or2261 mem.eql(u8, level, "2") or
2277 mem.eql(u8, level, "3") or2262 mem.eql(u8, level, "3") or
2278 mem.eql(u8, level, "4") or2263 mem.eql(u8, level, "4") or
2279 mem.eql(u8, level, "fast"))2264 mem.eql(u8, level, "fast"))
2280 {2265 {
2281 mod_opts.optimize_mode = .ReleaseFast;2266 mod_opts.optimize_mode = .fast;
2282 } else if (mem.eql(u8, level, "g") or2267 } else if (mem.eql(u8, level, "g") or
2283 mem.eql(u8, level, "0"))2268 mem.eql(u8, level, "0"))
2284 {2269 {
2285 mod_opts.optimize_mode = .Debug;2270 mod_opts.optimize_mode = .debug;
2286 } else {2271 } else {
2287 try cc_argv.appendSlice(arena, it.other_args);2272 try cc_argv.appendSlice(arena, it.other_args);
2288 }2273 }
...@@ -2356,9 +2341,9 @@ fn buildOutputType(...@@ -2356,9 +2341,9 @@ fn buildOutputType(
2356 // `sanitize_c` will resolve to! So we either have to pick `off` or `full`.2341 // `sanitize_c` will resolve to! So we either have to pick `off` or `full`.
2357 //2342 //
2358 // `full` has the potential to be problematic if `optimize_mode` turns out to2343 // `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 larger2344 // be `fast`/`small` because the user will get a slower and larger
2360 // binary than expected. On the other hand, if `optimize_mode` turns out to be2345 // 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.
2362 //2347 //
2363 // `off` seems very slightly less bad, so let's go with that.2348 // `off` seems very slightly less bad, so let's go with that.
2364 mod_opts.sanitize_c = .off;2349 mod_opts.sanitize_c = .off;
...@@ -2392,7 +2377,7 @@ fn buildOutputType(...@@ -2392,7 +2377,7 @@ fn buildOutputType(
2392 // Handle joined args like `--dependency-file=foo.d`.2377 // Handle joined args like `--dependency-file=foo.d`.
2393 // Must be prefixed with 1 or 2 dashes.2378 // Must be prefixed with 1 or 2 dashes.
2394 if (it.only_arg.len >= 3 and it.only_arg[0] == '-' and it.only_arg[2] != '-') {2379 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| {
2396 const key = it.only_arg[0..equals_pos];2381 const key = it.only_arg[0..equals_pos];
2397 const value = it.only_arg[equals_pos + 1 ..];2382 const value = it.only_arg[equals_pos + 1 ..];
23982383
...@@ -2972,8 +2957,8 @@ fn buildOutputType(...@@ -2972,8 +2957,8 @@ fn buildOutputType(
2972 }2957 }
29732958
2974 if (mod_opts.sanitize_c) |wsc| {2959 if (mod_opts.sanitize_c) |wsc| {
2975 if (wsc != .off and mod_opts.optimize_mode == .ReleaseFast) {2960 if (wsc != .off and mod_opts.optimize_mode == .fast) {
2976 mod_opts.optimize_mode = .ReleaseSafe;2961 mod_opts.optimize_mode = .safe;
2977 }2962 }
2978 }2963 }
29792964
...@@ -3835,11 +3820,17 @@ fn buildOutputType(...@@ -3835,11 +3820,17 @@ fn buildOutputType(
38353820
3836 var prev_has_cflags = false;3821 var prev_has_cflags = false;
3837 var prev_has_rcflags = false;3822 var prev_has_rcflags = false;
3838 if (dirs.zig_lib.path) |zig_lib_path| {3823 {
3839 try test_exec_args.appendSlice(arena, &.{ "-cflags", "-I", zig_lib_path, "--" });3824 if (dirs.zig_lib.path) |zig_lib_path| {
3840 prev_has_cflags = true;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" });
3841 }3833 }
3842 try test_exec_args.append(arena, null);
3843 for (create_module.modules.keys(), create_module.modules.values()) |mod_name, mod| {3834 for (create_module.modules.keys(), create_module.modules.values()) |mod_name, mod| {
3844 for (create_module.c_source_files.items[mod.c_source_files_start..mod.c_source_files_end]) |c_source_file| {3835 for (create_module.c_source_files.items[mod.c_source_files_start..mod.c_source_files_end]) |c_source_file| {
3845 const cflags_len = c_source_file.extra_flags.len + c_source_file.cache_exempt_flags.len;3836 const cflags_len = c_source_file.extra_flags.len + c_source_file.cache_exempt_flags.len;
...@@ -4305,11 +4296,8 @@ fn serve(...@@ -4305,11 +4296,8 @@ fn serve(
4305 const gpa = comp.gpa;4296 const gpa = comp.gpa;
4306 const io = comp.io;4297 const io = comp.io;
43074298
4308 var server = try Server.init(.{4299 var server: Server = .{ .in = in, .out = out };
4309 .in = in,4300 try server.serveStringMessage(.zig_version, build_options.version);
4310 .out = out,
4311 .zig_version = build_options.version,
4312 });
43134301
4314 var child_pid: ?std.process.Child.Id = null;4302 var child_pid: ?std.process.Child.Id = null;
43154303
...@@ -4874,8 +4862,7 @@ const JitCmdOptions = struct {...@@ -4874,8 +4862,7 @@ const JitCmdOptions = struct {
4874 capture: ?*[]u8 = null,4862 capture: ?*[]u8 = null,
4875 /// Send error bundles via std.zig.Server over stdout4863 /// Send error bundles via std.zig.Server over stdout
4876 server: bool = false,4864 server: bool = false,
4877 debug_env_var: EnvVar = .ZIG_DEBUG_CMD,4865 release_mode: std.lang.Optimize = .fast,
4878 release_mode: std.lang.OptimizeMode = .ReleaseFast,
4879};4866};
48804867
4881fn jitCmd(4868fn jitCmd(
...@@ -4926,11 +4913,11 @@ fn jitCmdInner(...@@ -4926,11 +4913,11 @@ fn jitCmdInner(
4926 const self_exe_path = process.executablePathAlloc(io, arena) catch |err|4913 const self_exe_path = process.executablePathAlloc(io, arena) catch |err|
4927 fatal("unable to find self exe path: {t}", .{err});4914 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))4916 const optimize_mode: std.lang.Optimize = if (EnvVar.ZIG_DEBUG_CMD.isSet(environ_map))
4930 .Debug4917 .debug
4931 else4918 else
4932 options.release_mode;4919 options.release_mode;
4933 const strip = optimize_mode != .Debug;4920 const strip = optimize_mode != .debug;
4934 var override_lib_dir: ?[]const u8 = EnvVar.ZIG_LIB_DIR.get(environ_map);4921 var override_lib_dir: ?[]const u8 = EnvVar.ZIG_LIB_DIR.get(environ_map);
4935 const override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map);4922 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 {...@@ -6008,9 +5995,8 @@ fn parseRcIncludes(arg: []const u8) std.zig.RcIncludes {
6008 fatal("unsupported rc includes type: {q}", .{arg});5995 fatal("unsupported rc includes type: {q}", .{arg});
6009}5996}
60105997
6011fn parseOptimizeMode(s: []const u8) std.lang.OptimizeMode {5998fn parseOptimizeMode(s: []const u8) std.lang.Optimize {
6012 return stringToEnum(std.lang.OptimizeMode, s) orelse5999 return std.lang.Optimize.fromString(s) orelse fatal("unrecognized optimization mode: {q}", .{s});
6013 fatal("unrecognized optimization mode: {q}", .{s});
6014}6000}
60156001
6016fn parseWasiExecModel(s: []const u8) std.lang.WasiExecModel {6002fn parseWasiExecModel(s: []const u8) std.lang.WasiExecModel {
src/print_targets.zig+3-3
...@@ -43,9 +43,9 @@ pub fn cmdTargets(...@@ -43,9 +43,9 @@ pub fn cmdTargets(
43 {43 {
44 var root_obj = try serializer.beginStruct(.{});44 var root_obj = try serializer.beginStruct(.{});
4545
46 try root_obj.field("arch", meta.fieldNames(Target.Cpu.Arch), .{});46 try root_obj.field("arch", @typeInfo(Target.Cpu.Arch).@"enum".field_names, .{});
47 try root_obj.field("os", meta.fieldNames(Target.Os.Tag), .{});47 try root_obj.field("os", @typeInfo(Target.Os.Tag).@"enum".field_names, .{});
48 try root_obj.field("abi", meta.fieldNames(Target.Abi), .{});48 try root_obj.field("abi", @typeInfo(Target.Abi).@"enum".field_names, .{});
4949
50 {50 {
51 var libc_obj = try root_obj.beginTupleField("libc", .{});51 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;...@@ -12,7 +12,6 @@ pub const default_stack_protector_buffer_size = 4;
1212
13pub fn canDynamicLink(target: *const std.Target) bool {13pub fn canDynamicLink(target: *const std.Target) bool {
14 return switch (target.cpu.arch) {14 return switch (target.cpu.arch) {
15 .amdgcn,
16 .bpfeb,15 .bpfeb,
17 .bpfel,16 .bpfel,
18 .nvptx,17 .nvptx,
...@@ -119,10 +118,6 @@ pub fn defaultSingleThreaded(target: *const std.Target) bool {...@@ -119,10 +118,6 @@ pub fn defaultSingleThreaded(target: *const std.Target) bool {
119 .wasm32, .wasm64 => return true,118 .wasm32, .wasm64 => return true,
120 else => {},119 else => {},
121 }120 }
122 switch (target.os.tag) {
123 .haiku => return true,
124 else => {},
125 }
126 return false;121 return false;
127}122}
128123
...@@ -357,12 +352,12 @@ pub fn libcProvidesStackProtector(target: *const std.Target) bool {...@@ -357,12 +352,12 @@ pub fn libcProvidesStackProtector(target: *const std.Target) bool {
357352
358/// Returns true if `@returnAddress()` is supported by the target and has a353/// Returns true if `@returnAddress()` is supported by the target and has a
359/// reasonably performant implementation for the requested optimization mode.354/// 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 {
361 return switch (target.cpu.arch) {356 return switch (target.cpu.arch) {
362 // Emscripten currently implements `emscripten_return_address()` by calling357 // Emscripten currently implements `emscripten_return_address()` by calling
363 // out into JavaScript and parsing a stack trace, which introduces significant358 // out into JavaScript and parsing a stack trace, which introduces significant
364 // overhead that we would prefer to avoid in release builds.359 // 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,
366 .bpfel, .bpfeb => false,361 .bpfel, .bpfeb => false,
367 .spirv32, .spirv64 => false,362 .spirv32, .spirv64 => false,
368 else => true,363 else => true,
...@@ -417,11 +412,11 @@ pub fn hasDebugInfo(target: *const std.Target) bool {...@@ -417,11 +412,11 @@ pub fn hasDebugInfo(target: *const std.Target) bool {
417 };412 };
418}413}
419414
420pub fn defaultCompilerRtOptimizeMode(target: *const std.Target) std.lang.OptimizeMode {415pub fn defaultCompilerRtOptimizeMode(target: *const std.Target) std.lang.Optimize {
421 if (target.cpu.arch.isWasm() and target.os.tag == .freestanding) {416 if (target.cpu.arch.isWasm() and target.os.tag == .freestanding) {
422 return .ReleaseSmall;417 return .small;
423 } else {418 } else {
424 return .ReleaseFast;419 return .fast;
425 }420 }
426}421}
427422
...@@ -437,7 +432,7 @@ pub fn canBuildLibCompilerRt(target: *const std.Target) enum { no, yes, llvm_onl...@@ -437,7 +432,7 @@ pub fn canBuildLibCompilerRt(target: *const std.Target) enum { no, yes, llvm_onl
437 else => {},432 else => {},
438 }433 }
439 return switch (zigBackend(target, false)) {434 return switch (zigBackend(target, false)) {
440 .stage2_aarch64, .stage2_x86_64 => .yes,435 .stage2_aarch64, .stage2_wasm, .stage2_x86_64 => .yes,
441 else => .llvm_only,436 else => .llvm_only,
442 };437 };
443}438}
...@@ -450,7 +445,7 @@ pub fn canBuildLibUbsanRt(target: *const std.Target) enum { no, yes, llvm_only,...@@ -450,7 +445,7 @@ pub fn canBuildLibUbsanRt(target: *const std.Target) enum { no, yes, llvm_only,
450 else => {},445 else => {},
451 }446 }
452 return switch (zigBackend(target, false)) {447 return switch (zigBackend(target, false)) {
453 .stage2_wasm => .llvm_lld_only,448 .stage2_wasm => .yes,
454 .stage2_x86_64 => .yes,449 .stage2_x86_64 => .yes,
455 else => .llvm_only,450 else => .llvm_only,
456 };451 };
...@@ -681,14 +676,14 @@ pub fn isDynamicAMDGCNFeature(target: *const std.Target, feature: std.Target.Cpu...@@ -681,14 +676,14 @@ pub fn isDynamicAMDGCNFeature(target: *const std.Target, feature: std.Target.Cpu
681 const feature_tag: std.Target.amdgcn.Feature = @fromBackingInt(@intCast(feature.index));676 const feature_tag: std.Target.amdgcn.Feature = @fromBackingInt(@intCast(feature.index));
682677
683 if (feature_tag == .sramecc) {678 if (feature_tag == .sramecc) {
684 if (std.mem.indexOfScalar(679 if (std.mem.findScalar(
685 *const std.Target.Cpu.Model,680 *const std.Target.Cpu.Model,
686 sramecc_only ++ xnack_or_sramecc,681 sramecc_only ++ xnack_or_sramecc,
687 target.cpu.model,682 target.cpu.model,
688 )) |_| return true;683 )) |_| return true;
689 }684 }
690 if (feature_tag == .xnack) {685 if (feature_tag == .xnack) {
691 if (std.mem.indexOfScalar(686 if (std.mem.findScalar(
692 *const std.Target.Cpu.Model,687 *const std.Target.Cpu.Model,
693 xnack_or_sramecc,688 xnack_or_sramecc,
694 target.cpu.model,689 target.cpu.model,
...@@ -876,18 +871,18 @@ pub fn libcFloatSuffix(float_bits: u16) []const u8 {...@@ -876,18 +871,18 @@ pub fn libcFloatSuffix(float_bits: u16) []const u8 {
876 32 => "f",871 32 => "f",
877 64 => "",872 64 => "",
878 80 => "x", // Non-standard873 80 => "x", // Non-standard
879 128 => "q", // Non-standard (mimics convention in GCC libquadmath)874 128 => "f128",
880 else => unreachable,875 else => unreachable,
881 };876 };
882}877}
883878
884pub fn compilerRtFloatAbbrev(float_bits: u16) []const u8 {879pub fn compilerRtFloatAbbrev(target: *const std.Target, float_bits: u16) []const u8 {
885 return switch (float_bits) {880 return switch (float_bits) {
886 16 => "h",881 16 => "h",
887 32 => "s",882 32 => "s",
888 64 => "d",883 64 => "d",
889 80 => "x",884 80 => "x",
890 128 => "t",885 128 => if (target.cpu.arch.isPowerPC()) "k" else "t",
891 else => unreachable,886 else => unreachable,
892 };887 };
893}888}
src/zig_llvm.cpp+16-3
...@@ -473,19 +473,32 @@ void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) {...@@ -473,19 +473,32 @@ void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) {
473}473}
474474
475bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count,475bool 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)
477{477{
478 SmallVector<NewArchiveMember, 4> new_members;478 SmallVector<NewArchiveMember, 4> new_members;
479 for (size_t i = 0; i < file_name_count; i += 1) {479 for (size_t i = 0; i < file_name_count; i += 1) {
480 Expected<NewArchiveMember> new_member = NewArchiveMember::getFile(file_names[i], true);480 Expected<NewArchiveMember> new_member = NewArchiveMember::getFile(file_names[i], true);
481 Error err = new_member.takeError();481 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 }
483 new_members.push_back(std::move(*new_member));489 new_members.push_back(std::move(*new_member));
484 }490 }
485 Error err = writeArchive(archive_name, new_members,491 Error err = writeArchive(archive_name, new_members,
486 SymtabWritingMode::NormalSymtab, static_cast<object::Archive::Kind>(archive_kind), true, false, nullptr);492 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
489 return false;502 return false;
490}503}
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...@@ -121,7 +121,12 @@ ZIG_EXTERN_C bool ZigLLDLinkCOFF(int argc, const char **argv, bool can_exit_earl
121ZIG_EXTERN_C bool ZigLLDLinkELF(int argc, const char **argv, bool can_exit_early, bool disable_output);121ZIG_EXTERN_C bool ZigLLDLinkELF(int argc, const char **argv, bool can_exit_early, bool disable_output);
122ZIG_EXTERN_C bool ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early, bool disable_output);122ZIG_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`.
124ZIG_EXTERN_C bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count,129ZIG_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
127#endif132#endif
stage1/FuncGen.h+3-3
...@@ -52,17 +52,17 @@ static void FuncGen_free(struct FuncGen *self) {...@@ -52,17 +52,17 @@ static void FuncGen_free(struct FuncGen *self) {
52}52}
5353
54static void FuncGen_outdent(struct FuncGen *self, FILE *out) {54static 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);
56}56}
5757
58static void FuncGen_indent(struct FuncGen *self, FILE *out) {58static void FuncGen_indent(struct FuncGen *self, FILE *out) {
59 FuncGen_outdent(self, out);59 FuncGen_outdent(self, out);
60 fputs(" ", out);60 fputs(" ", out);
61}61}
6262
63static void FuncGen_cont(struct FuncGen *self, FILE *out) {63static void FuncGen_cont(struct FuncGen *self, FILE *out) {
64 FuncGen_indent(self, out);64 FuncGen_indent(self, out);
65 fputs(" ", out);65 fputs(" ", out);
66}66}
6767
68static uint32_t FuncGen_localAlloc(struct FuncGen *self, int8_t type) {68static 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) {...@@ -518,8 +518,8 @@ int main(int argc, char **argv) {
518 }518 }
519 fprintf(out,519 fprintf(out,
520 ") {\n"520 ") {\n"
521 " init();\n"521 " init();\n"
522 " %sf%" PRIu32 "(",522 " %sf%" PRIu32 "(",
523 func_type->result->len > 0 ? "return " : "", idx - imports_len);523 func_type->result->len > 0 ? "return " : "", idx - imports_len);
524 for (uint32_t param_i = 0; param_i < func_type->param->len; param_i += 1) {524 for (uint32_t param_i = 0; param_i < func_type->param->len; param_i += 1) {
525 if (param_i > 0) fputs(", ", out);525 if (param_i > 0) fputs(", ", out);
...@@ -552,7 +552,7 @@ int main(int argc, char **argv) {...@@ -552,7 +552,7 @@ int main(int argc, char **argv) {
552 uint32_t segment_len = InputStream_readLeb128_u32(&in);552 uint32_t segment_len = InputStream_readLeb128_u32(&in);
553 for (uint32_t i = 0; i < segment_len; i += 1) {553 for (uint32_t i = 0; i < segment_len; i += 1) {
554 uint32_t func_id = InputStream_readLeb128_u32(&in);554 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))&",
556 table_idx, offset + i);556 table_idx, offset + i);
557 if (func_id < imports_len)557 if (func_id < imports_len)
558 fprintf(out, "%s_%s", imports[func_id].mod, imports[func_id].name);558 fprintf(out, "%s_%s", imports[func_id].mod, imports[func_id].name);
...@@ -2260,9 +2260,9 @@ int main(int argc, char **argv) {...@@ -2260,9 +2260,9 @@ int main(int argc, char **argv) {
2260 uint32_t len = InputStream_readLeb128_u32(&in);2260 uint32_t len = InputStream_readLeb128_u32(&in);
2261 fputs("static void init_data(void) {\n", out);2261 fputs("static void init_data(void) {\n", out);
2262 for (uint32_t i = 0; i < mems_len; i += 1)2262 for (uint32_t i = 0; i < mems_len; i += 1)
2263 fprintf(out, " p%" PRIu32 " = UINT32_C(%" PRIu32 ");\n"2263 fprintf(out, " p%" PRIu32 " = UINT32_C(%" PRIu32 ");\n"
2264 " c%" PRIu32 " = p%" PRIu32 ";\n"2264 " c%" PRIu32 " = p%" PRIu32 ";\n"
2265 " m%" PRIu32 " = calloc(c%" PRIu32 ", UINT32_C(1) << 16);\n",2265 " m%" PRIu32 " = calloc(c%" PRIu32 ", UINT32_C(1) << 16);\n",
2266 i, mems[i].limits.min, i, i, i, i);2266 i, mems[i].limits.min, i, i, i, i);
2267 for (uint32_t segment_i = 0; segment_i < len; segment_i += 1) {2267 for (uint32_t segment_i = 0; segment_i < len; segment_i += 1) {
2268 uint32_t mem_idx;2268 uint32_t mem_idx;
...@@ -2280,15 +2280,15 @@ int main(int argc, char **argv) {...@@ -2280,15 +2280,15 @@ int main(int argc, char **argv) {
2280 uint32_t offset = evalExpr(&in);2280 uint32_t offset = evalExpr(&in);
2281 uint32_t segment_len = InputStream_readLeb128_u32(&in);2281 uint32_t segment_len = InputStream_readLeb128_u32(&in);
2282 fputc('\n', out);2282 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 ")] = {",
2284 segment_i, segment_len);2284 segment_i, segment_len);
2285 for (uint32_t i = 0; i < segment_len; i += 1) {2285 for (uint32_t i = 0; i < segment_len; i += 1) {
2286 if (i % 32 == 0) fputs("\n ", out);2286 if (i % 32 == 0) fputs("\n ", out);
2287 fprintf(out, " 0x%02hhX,", InputStream_readByte(&in));2287 fprintf(out, " 0x%02hhX,", InputStream_readByte(&in));
2288 }2288 }
2289 fprintf(out, "\n"2289 fprintf(out, "\n"
2290 " };\n"2290 " };\n"
2291 " memcpy(&m%" PRIu32 "[UINT32_C(0x%" PRIX32 ")], s%" PRIu32 ", UINT32_C(%" PRIu32 "));\n",2291 " memcpy(&m%" PRIu32 "[UINT32_C(0x%" PRIX32 ")], s%" PRIu32 ", UINT32_C(%" PRIu32 "));\n",
2292 mem_idx, offset, segment_i, segment_len);2292 mem_idx, offset, segment_i, segment_len);
2293 }2293 }
2294 fputs("}\n", out);2294 fputs("}\n", out);
stage1/zig.h+3079-991
...@@ -166,6 +166,12 @@...@@ -166,6 +166,12 @@
166#endif166#endif
167#define zig_expand_has_builtin(b) zig_has_builtin(b)167#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
169#if defined(__has_attribute)175#if defined(__has_attribute)
170#define zig_has_attribute(attribute) __has_attribute(attribute)176#define zig_has_attribute(attribute) __has_attribute(attribute)
171#else177#else
...@@ -175,9 +181,9 @@...@@ -175,9 +181,9 @@
175#if __STDC_VERSION__ >= 201112L181#if __STDC_VERSION__ >= 201112L
176#define zig_static_assert(cond, msg) _Static_assert(cond, msg)182#define zig_static_assert(cond, msg) _Static_assert(cond, msg)
177#elif zig_has_attribute(unused)183#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))
179#else185#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]
181#endif187#endif
182188
183#if __STDC_VERSION__ >= 202311L189#if __STDC_VERSION__ >= 202311L
...@@ -193,10 +199,8 @@...@@ -193,10 +199,8 @@
193#endif199#endif
194200
195#if defined(zig_msvc)201#if defined(zig_msvc)
196#define zig_const_arr
197#define zig_callconv(c) __##c202#define zig_callconv(c) __##c
198#else203#else
199#define zig_const_arr static const
200#define zig_callconv(c) __attribute__((c))204#define zig_callconv(c) __attribute__((c))
201#endif205#endif
202206
...@@ -267,12 +271,20 @@...@@ -267,12 +271,20 @@
267271
268#if __STDC_VERSION__ >= 202311L272#if __STDC_VERSION__ >= 202311L
269#define zig_align(alignment) alignas(alignment)273#define zig_align(alignment) alignas(alignment)
270#elif __STDC_VERSION__ >= 201112L274#elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignas)
271#define zig_align(alignment) _Alignas(alignment)275#define zig_align(alignment) _Alignas(alignment)
272#else276#else
273#define zig_align(alignment) zig_under_align(alignment)277#define zig_align(alignment) zig_under_align(alignment)
274#endif278#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
276#if zig_has_attribute(aligned) || defined(zig_tinyc)288#if zig_has_attribute(aligned) || defined(zig_tinyc)
277#define zig_align_fn(alignment) __attribute__((aligned(alignment)))289#define zig_align_fn(alignment) __attribute__((aligned(alignment)))
278#elif defined(zig_msvc)290#elif defined(zig_msvc)
...@@ -350,11 +362,9 @@...@@ -350,11 +362,9 @@
350#define zig_export(symbol, name) __attribute__((alias(symbol)))362#define zig_export(symbol, name) __attribute__((alias(symbol)))
351#else363#else
352#define zig_export(symbol, name) ; \364#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))
354#endif366#endif
355367
356#define zig_mangled_tentative zig_mangled
357#define zig_mangled_final zig_mangled
358#if defined(zig_msvc)368#if defined(zig_msvc)
359#define zig_mangled(mangled, unmangled) ; \369#define zig_mangled(mangled, unmangled) ; \
360 zig_export(#mangled, unmangled)370 zig_export(#mangled, unmangled)
...@@ -364,7 +374,7 @@...@@ -364,7 +374,7 @@
364#else /* zig_msvc */374#else /* zig_msvc */
365#define zig_mangled(mangled, unmangled) __asm(zig_mangle_c(unmangled))375#define zig_mangled(mangled, unmangled) __asm(zig_mangle_c(unmangled))
366#define zig_mangled_export(mangled, unmangled, symbol) \376#define zig_mangled_export(mangled, unmangled, symbol) \
367 zig_mangled_final(mangled, unmangled) \377 zig_mangled(mangled, unmangled) \
368 zig_export(symbol, unmangled)378 zig_export(symbol, unmangled)
369#endif /* zig_msvc */379#endif /* zig_msvc */
370380
...@@ -550,6 +560,9 @@...@@ -550,6 +560,9 @@
550#define zig_noreturn560#define zig_noreturn
551#endif561#endif
552562
563#define zig_has_always 1
564#define zig_has_never 0
565
553#define zig_compiler_rt_abbrev_uint32_t si566#define zig_compiler_rt_abbrev_uint32_t si
554#define zig_compiler_rt_abbrev_int32_t si567#define zig_compiler_rt_abbrev_int32_t si
555#define zig_compiler_rt_abbrev_uint64_t di568#define zig_compiler_rt_abbrev_uint64_t di
...@@ -560,7 +573,11 @@...@@ -560,7 +573,11 @@
560#define zig_compiler_rt_abbrev_zig_f32 sf573#define zig_compiler_rt_abbrev_zig_f32 sf
561#define zig_compiler_rt_abbrev_zig_f64 df574#define zig_compiler_rt_abbrev_zig_f64 df
562#define zig_compiler_rt_abbrev_zig_f80 xf575#define zig_compiler_rt_abbrev_zig_f80 xf
576#ifdef zig_powerpc
577#define zig_compiler_rt_abbrev_zig_f128 kf
578#else
563#define zig_compiler_rt_abbrev_zig_f128 tf579#define zig_compiler_rt_abbrev_zig_f128 tf
580#endif
564581
565zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t);582zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t);
566zig_extern void *memset (void *, int, size_t);583zig_extern void *memset (void *, int, size_t);
...@@ -645,16 +662,6 @@ typedef signed long long int16_t;...@@ -645,16 +662,6 @@ typedef signed long long int16_t;
645#define INT16_MAX ( INT16_C(0x7FFF))662#define INT16_MAX ( INT16_C(0x7FFF))
646#define UINT16_MAX ( INT16_C(0xFFFF))663#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
658#if SCHAR_MIN == ~0x7FFFFFFF && SCHAR_MAX == 0x7FFFFFFF && UCHAR_MAX == 0xFFFFFFFF665#if SCHAR_MIN == ~0x7FFFFFFF && SCHAR_MAX == 0x7FFFFFFF && UCHAR_MAX == 0xFFFFFFFF
659typedef unsigned char uint32_t;666typedef unsigned char uint32_t;
660typedef signed char int32_t;667typedef signed char int32_t;
...@@ -685,17 +692,6 @@ typedef signed long long int32_t;...@@ -685,17 +692,6 @@ typedef signed long long int32_t;
685#define INT32_MAX ( INT32_C(0x7FFFFFFF))692#define INT32_MAX ( INT32_C(0x7FFFFFFF))
686#define UINT32_MAX ( INT32_C(0xFFFFFFFF))693#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
699#if SCHAR_MIN == ~0x7FFFFFFFFFFFFFFF && SCHAR_MAX == 0x7FFFFFFFFFFFFFFF && UCHAR_MAX == 0xFFFFFFFFFFFFFFFF695#if SCHAR_MIN == ~0x7FFFFFFFFFFFFFFF && SCHAR_MAX == 0x7FFFFFFFFFFFFFFF && UCHAR_MAX == 0xFFFFFFFFFFFFFFFF
700typedef unsigned char uint64_t;696typedef unsigned char uint64_t;
701typedef signed char int64_t;697typedef signed char int64_t;
...@@ -726,6 +722,27 @@ typedef signed long long int64_t;...@@ -726,6 +722,27 @@ typedef signed long long int64_t;
726#define INT64_MAX ( INT64_C(0x7FFFFFFFFFFFFFFF))722#define INT64_MAX ( INT64_C(0x7FFFFFFFFFFFFFFF))
727#define UINT64_MAX ( INT64_C(0xFFFFFFFFFFFFFFFF))723#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
729typedef size_t uintptr_t;746typedef size_t uintptr_t;
730typedef ptrdiff_t intptr_t;747typedef ptrdiff_t intptr_t;
731748
...@@ -739,23 +756,145 @@ typedef ptrdiff_t intptr_t;...@@ -739,23 +756,145 @@ typedef ptrdiff_t intptr_t;
739#define zig_maxInt_i16 INT16_MAX756#define zig_maxInt_i16 INT16_MAX
740#define zig_minInt_u16 UINT16_C(0)757#define zig_minInt_u16 UINT16_C(0)
741#define zig_maxInt_u16 UINT16_MAX758#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
746#define zig_minInt_i32 INT32_MIN759#define zig_minInt_i32 INT32_MIN
747#define zig_maxInt_i32 INT32_MAX760#define zig_maxInt_i32 INT32_MAX
748#define zig_minInt_u32 UINT32_C(0)761#define zig_minInt_u32 UINT32_C(0)
749#define zig_maxInt_u32 UINT32_MAX762#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
754#define zig_minInt_i64 INT64_MIN763#define zig_minInt_i64 INT64_MIN
755#define zig_maxInt_i64 INT64_MAX764#define zig_maxInt_i64 INT64_MAX
756#define zig_minInt_u64 UINT64_C(0)765#define zig_minInt_u64 UINT64_C(0)
757#define zig_maxInt_u64 UINT64_MAX766#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
759#define zig_intLimit(s, w, limit, bits) zig_shr_##s##w(zig_##limit##Int_##s##w, w - (bits))898#define zig_intLimit(s, w, limit, bits) zig_shr_##s##w(zig_##limit##Int_##s##w, w - (bits))
760#define zig_minInt_i(w, bits) zig_intLimit(i, w, min, bits)899#define zig_minInt_i(w, bits) zig_intLimit(i, w, min, bits)
761#define zig_maxInt_i(w, bits) zig_intLimit(i, w, max, bits)900#define zig_maxInt_i(w, bits) zig_intLimit(i, w, max, bits)
...@@ -770,7 +909,33 @@ typedef ptrdiff_t intptr_t;...@@ -770,7 +909,33 @@ typedef ptrdiff_t intptr_t;
770 zig_operator(Type, Type, operation, operator)909 zig_operator(Type, Type, operation, operator)
771#define zig_shift_operator(Type, operation, operator) \910#define zig_shift_operator(Type, operation, operator) \
772 zig_operator(Type, uint8_t, operation, operator)911 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) \
774 zig_basic_operator(uint##w##_t, and_u##w, &) \939 zig_basic_operator(uint##w##_t, and_u##w, &) \
775 zig_basic_operator( int##w##_t, and_i##w, &) \940 zig_basic_operator( int##w##_t, and_i##w, &) \
776 zig_basic_operator(uint##w##_t, or_u##w, |) \941 zig_basic_operator(uint##w##_t, or_u##w, |) \
...@@ -786,44 +951,48 @@ typedef ptrdiff_t intptr_t;...@@ -786,44 +951,48 @@ typedef ptrdiff_t intptr_t;
786 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \951 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \
787 } \952 } \
788\953\
789 static inline uint##w##_t zig_not_u##w(uint##w##_t val, uint8_t bits) { \954 static inline uint##w##_t zig_not_u##w(uint##w##_t arg, uint8_t bits) { \
790 return val ^ zig_maxInt_u(w, bits); \955 return arg ^ zig_maxInt_u(w, bits); \
791 } \956 } \
792\957\
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) { \
794 (void)bits; \959 (void)bits; \
795 return ~val; \960 return ~arg; \
796 } \961 } \
797\962\
798 static inline uint##w##_t zig_wrap_u##w(uint##w##_t val, uint8_t bits) { \963 zig_basic_operator(uint##w##_t, divFloor_u##w, /) \
799 return val & zig_maxInt_u(w, bits); \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)); \
800 } \967 } \
801\968\
802 static inline int##w##_t zig_wrap_i##w(int##w##_t val, uint8_t bits) { \969 static inline uint##w##_t zig_divCeil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \
803 return (val & UINT##w##_C(1) << (bits - UINT8_C(1))) != 0 \970 return lhs / rhs + (lhs % rhs != UINT##w##_C(0) ? UINT##w##_C(1) : UINT##w##_C(0)); \
804 ? val | zig_minInt_i(w, bits) : val & zig_maxInt_i(w, bits); \
805 } \971 } \
806\972\
807 static inline uint##w##_t zig_abs_i##w(int##w##_t val) { \973 static inline int##w##_t zig_divCeil_i##w(int##w##_t lhs, int##w##_t rhs) { \
808 return (val < 0) ? -(uint##w##_t)val : (uint##w##_t)val; \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)); \
809 } \976 } \
810\977\
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) \
812\980\
813 static inline int##w##_t zig_div_floor_i##w(int##w##_t lhs, int##w##_t rhs) { \981 static inline uint##w##_t zig_u##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \
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)); \982 return zig_u##w##_truncate_u##w(arg, bits); \
815 } \983 } \
816\984\
817 static inline uint##w##_t zig_div_ceil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \985 static inline uint##w##_t zig_u##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \
818 return lhs / rhs + (lhs % rhs != UINT##w##_C(0) ? UINT##w##_C(1) : UINT##w##_C(0)); \986 return zig_u##w##_bitCast_u##w((uint##w##_t)arg, bits); \
819 } \987 } \
820\988\
821 static inline int##w##_t zig_div_ceil_i##w(int##w##_t lhs, int##w##_t rhs) { \989 static inline int##w##_t zig_i##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \
822 return lhs / rhs + (lhs % rhs != INT##w##_C(0) \990 return zig_i##w##_truncate_i##w(arg, bits); \
823 ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) + INT##w##_C(1) : INT##w##_C(0)); \
824 } \991 } \
825\992\
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 } \
827\996\
828 static inline int##w##_t zig_mod_i##w(int##w##_t lhs, int##w##_t rhs) { \997 static inline int##w##_t zig_mod_i##w(int##w##_t lhs, int##w##_t rhs) { \
829 int##w##_t rem = lhs % rhs; \998 int##w##_t rem = lhs % rhs; \
...@@ -831,100 +1000,102 @@ typedef ptrdiff_t intptr_t;...@@ -831,100 +1000,102 @@ typedef ptrdiff_t intptr_t;
831 } \1000 } \
832\1001\
833 static inline uint##w##_t zig_shlw_u##w(uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \1002 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); \
835 } \1004 } \
836\1005\
837 static inline int##w##_t zig_shlw_i##w(int##w##_t lhs, uint8_t rhs, uint8_t bits) { \1006 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); \
839 } \1008 } \
840\1009\
841 static inline uint##w##_t zig_addw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \1010 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); \
843 } \1012 } \
844\1013\
845 static inline int##w##_t zig_addw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \1014 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); \
847 } \1016 } \
848\1017\
849 static inline uint##w##_t zig_subw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \1018 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); \
851 } \1020 } \
852\1021\
853 static inline int##w##_t zig_subw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \1022 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); \
855 } \1024 } \
856\1025\
857 static inline uint##w##_t zig_mulw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \1026 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); \
859 } \1028 } \
860\1029\
861 static inline int##w##_t zig_mulw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \1030 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; \
863 }1053 }
864#if UINT8_MAX <= UINT_MAX1054zig_int_operators(8)
865zig_int_helpers(8, unsigned int)1055zig_int_operators(16)
866#elif UINT8_MAX <= ULONG_MAX1056zig_int_operators(32)
867zig_int_helpers(8, unsigned long)1057zig_int_operators(64)
868#elif UINT8_MAX <= ULLONG_MAX1058#ifdef zig_ez80
869zig_int_helpers(8, unsigned long long)1059zig_int_operators(24)
870#else1060zig_int_operators(48)
871zig_int_helpers(8, uint8_t)1061#endif
872#endif1062
873#if UINT16_MAX <= UINT_MAX1063#define zig_int_casts(bw, sw) \
874zig_int_helpers(16, unsigned int)1064 static inline uint##sw##_t zig_u##sw##_intCast_u##bw(uint##bw##_t arg) { \
875#elif UINT16_MAX <= ULONG_MAX1065 return (uint##sw##_t)arg; \
876zig_int_helpers(16, unsigned long)1066 } \
877#elif UINT16_MAX <= ULLONG_MAX1067\
878zig_int_helpers(16, unsigned long long)1068 static inline uint##sw##_t zig_u##sw##_intCast_i##bw(int##bw##_t arg) { \
879#else1069 return (uint##sw##_t)arg; \
880zig_int_helpers(16, uint16_t)1070 } \
881#endif1071\
882#if defined(zig_ez80)1072 static inline int##sw##_t zig_i##sw##_intCast_u##bw(uint##bw##_t arg) { \
883#if UINT24_MAX <= UINT_MAX1073 return (int##sw##_t)arg; \
884zig_int_helpers(24, unsigned int)1074 } \
885#elif UINT24_MAX <= ULONG_MAX1075\
886zig_int_helpers(24, unsigned long)1076 static inline int##sw##_t zig_i##sw##_intCast_i##bw(int##bw##_t arg) { \
887#elif UINT24_MAX <= ULLONG_MAX1077 return (int##sw##_t)arg; \
888zig_int_helpers(24, unsigned long long)1078 } \
889#else1079\
890zig_int_helpers(24, uint24_t)1080 zig_int_casts_common(bw, sw)
891#endif1081zig_int_casts(16, 8)
892#endif1082zig_int_casts(32, 8)
893#if UINT32_MAX <= UINT_MAX1083zig_int_casts(64, 8)
894zig_int_helpers(32, unsigned int)1084zig_int_casts(32, 16)
895#elif UINT32_MAX <= ULONG_MAX1085zig_int_casts(64, 16)
896zig_int_helpers(32, unsigned long)1086zig_int_casts(64, 32)
897#elif UINT32_MAX <= ULLONG_MAX1087#ifdef zig_ez80
898zig_int_helpers(32, unsigned long long)1088zig_int_casts(32, 24)
899#else1089zig_int_casts(48, 24)
900zig_int_helpers(32, uint32_t)1090zig_int_casts(64, 24)
901#endif1091zig_int_casts(64, 48)
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)
921#endif1092#endif
9221093
923static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {1094static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
924#if zig_has_builtin(add_overflow) || defined(zig_gcc)1095#if zig_has_builtin(add_overflow) || defined(zig_gcc)
925 uint32_t full_res;1096 uint32_t full_res;
926 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1097 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);
928 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);1099 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
929#else1100#else
930 *res = zig_addw_u32(lhs, rhs, bits);1101 *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...@@ -936,19 +1107,19 @@ static inline bool zig_addo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t
936#if zig_has_builtin(add_overflow) || defined(zig_gcc)1107#if zig_has_builtin(add_overflow) || defined(zig_gcc)
937 int32_t full_res;1108 int32_t full_res;
938 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1109 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);
939#else1112#else
940 int32_t full_res = (int32_t)((uint32_t)lhs + (uint32_t)rhs);1113 *res = zig_addw_i32(lhs, rhs, bits);
941 bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0;1114 return ((*res ^ lhs) & (*res ^ rhs)) < INT32_C(0);
942#endif1115#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);
945}1116}
9461117
947static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {1118static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
948#if zig_has_builtin(add_overflow) || defined(zig_gcc)1119#if zig_has_builtin(add_overflow) || defined(zig_gcc)
949 uint64_t full_res;1120 uint64_t full_res;
950 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1121 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);
952 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);1123 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
953#else1124#else
954 *res = zig_addw_u64(lhs, rhs, bits);1125 *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...@@ -960,24 +1131,24 @@ static inline bool zig_addo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t
960#if zig_has_builtin(add_overflow) || defined(zig_gcc)1131#if zig_has_builtin(add_overflow) || defined(zig_gcc)
961 int64_t full_res;1132 int64_t full_res;
962 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1133 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);
963#else1136#else
964 int64_t full_res = (int64_t)((uint64_t)lhs + (uint64_t)rhs);1137 *res = zig_addw_i64(lhs, rhs, bits);
965 bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0;1138 return ((*res ^ lhs) & (*res ^ rhs)) < INT64_C(0);
966#endif1139#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);
969}1140}
9701141
971static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {1142static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
972#if zig_has_builtin(add_overflow) || defined(zig_gcc)1143#if zig_has_builtin(add_overflow) || defined(zig_gcc)
973 uint8_t full_res;1144 uint8_t full_res;
974 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1145 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);
976 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);1147 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
977#else1148#else
978 uint32_t full_res;1149 uint32_t full_res;
979 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);1150 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
980 *res = (uint8_t)full_res;1151 *res = zig_u8_intCast_u32(full_res);
981 return overflow;1152 return overflow;
982#endif1153#endif
983}1154}
...@@ -986,12 +1157,12 @@ static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits...@@ -986,12 +1157,12 @@ static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
986#if zig_has_builtin(add_overflow) || defined(zig_gcc)1157#if zig_has_builtin(add_overflow) || defined(zig_gcc)
987 int8_t full_res;1158 int8_t full_res;
988 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1159 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);
990 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);1161 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
991#else1162#else
992 int32_t full_res;1163 int32_t full_res;
993 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);1164 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
994 *res = (int8_t)full_res;1165 *res = zig_i8_intCast_i32(full_res);
995 return overflow;1166 return overflow;
996#endif1167#endif
997}1168}
...@@ -1000,12 +1171,12 @@ static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8...@@ -1000,12 +1171,12 @@ static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
1000#if zig_has_builtin(add_overflow) || defined(zig_gcc)1171#if zig_has_builtin(add_overflow) || defined(zig_gcc)
1001 uint16_t full_res;1172 uint16_t full_res;
1002 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1173 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);
1004 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);1175 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
1005#else1176#else
1006 uint32_t full_res;1177 uint32_t full_res;
1007 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);1178 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
1008 *res = (uint16_t)full_res;1179 *res = zig_u16_intCast_u32(full_res);
1009 return overflow;1180 return overflow;
1010#endif1181#endif
1011}1182}
...@@ -1014,27 +1185,28 @@ static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t...@@ -1014,27 +1185,28 @@ static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
1014#if zig_has_builtin(add_overflow) || defined(zig_gcc)1185#if zig_has_builtin(add_overflow) || defined(zig_gcc)
1015 int16_t full_res;1186 int16_t full_res;
1016 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1187 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);
1018 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);1189 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
1019#else1190#else
1020 int32_t full_res;1191 int32_t full_res;
1021 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);1192 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
1022 *res = (int16_t)full_res;1193 *res = zig_i16_intCast_i32(full_res);
1023 return overflow;1194 return overflow;
1024#endif1195#endif
1025}1196}
10261197
1027#if defined(zig_ez80)1198#if defined(zig_ez80)
1199
1028static inline bool zig_addo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {1200static inline bool zig_addo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {
1029#if zig_has_builtin(add_overflow) || defined(zig_gcc)1201#if zig_has_builtin(add_overflow) || defined(zig_gcc)
1030 uint24_t full_res;1202 uint24_t full_res;
1031 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1203 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);
1033 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);1205 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);
1034#else1206#else
1035 uint32_t full_res;1207 uint32_t full_res;
1036 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);1208 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
1037 *res = (uint24_t)full_res;1209 *res = zig_u24_intCast_u32(full_res);
1038 return overflow;1210 return overflow;
1039#endif1211#endif
1040}1212}
...@@ -1043,28 +1215,26 @@ static inline bool zig_addo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t...@@ -1043,28 +1215,26 @@ static inline bool zig_addo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t
1043#if zig_has_builtin(add_overflow) || defined(zig_gcc)1215#if zig_has_builtin(add_overflow) || defined(zig_gcc)
1044 int24_t full_res;1216 int24_t full_res;
1045 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1217 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);
1047 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);1219 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);
1048#else1220#else
1049 int32_t full_res;1221 int32_t full_res;
1050 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);1222 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
1051 *res = (int24_t)full_res;1223 *res = zig_i24_intCast_i32(full_res);
1052 return overflow;1224 return overflow;
1053#endif1225#endif
1054}1226}
1055#endif
10561227
1057#if defined(zig_ez80)
1058static inline bool zig_addo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {1228static inline bool zig_addo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {
1059#if zig_has_builtin(add_overflow) || defined(zig_gcc)1229#if zig_has_builtin(add_overflow) || defined(zig_gcc)
1060 uint48_t full_res;1230 uint48_t full_res;
1061 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1231 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);
1063 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);1233 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);
1064#else1234#else
1065 uint64_t full_res;1235 uint64_t full_res;
1066 bool overflow = zig_addo_u64(&full_res, lhs, rhs, bits);1236 bool overflow = zig_addo_u64(&full_res, lhs, rhs, bits);
1067 *res = (uint48_t)full_res;1237 *res = zig_u48_intCast_u64(full_res);
1068 return overflow;1238 return overflow;
1069#endif1239#endif
1070}1240}
...@@ -1073,22 +1243,23 @@ static inline bool zig_addo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t...@@ -1073,22 +1243,23 @@ static inline bool zig_addo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
1073#if zig_has_builtin(add_overflow) || defined(zig_gcc)1243#if zig_has_builtin(add_overflow) || defined(zig_gcc)
1074 int48_t full_res;1244 int48_t full_res;
1075 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1245 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);
1077 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);1247 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);
1078#else1248#else
1079 int64_t full_res;1249 int64_t full_res;
1080 bool overflow = zig_addo_i64(&full_res, lhs, rhs, bits);1250 bool overflow = zig_addo_i64(&full_res, lhs, rhs, bits);
1081 *res = (int48_t)full_res;1251 *res = zig_i48_intCast_i64(full_res);
1082 return overflow;1252 return overflow;
1083#endif1253#endif
1084}1254}
1255
1085#endif1256#endif
10861257
1087static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {1258static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
1088#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1259#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1089 uint32_t full_res;1260 uint32_t full_res;
1090 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1261 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);
1092 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);1263 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
1093#else1264#else
1094 *res = zig_subw_u32(lhs, rhs, bits);1265 *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...@@ -1100,20 +1271,19 @@ static inline bool zig_subo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t
1100#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1271#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1101 int32_t full_res;1272 int32_t full_res;
1102 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1273 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);
1103#else1276#else
1104 int32_t full_res = (int32_t)((uint32_t)lhs - (uint32_t)rhs);1277 *res = zig_subw_i32(lhs, rhs, bits);
1105 bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0;1278 return ((lhs ^ rhs) & (*res ^ lhs)) < INT32_C(0);
1106#endif1279#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);
1109}1280}
11101281
1111
1112static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {1282static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
1113#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1283#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1114 uint64_t full_res;1284 uint64_t full_res;
1115 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1285 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);
1117 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);1287 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
1118#else1288#else
1119 *res = zig_subw_u64(lhs, rhs, bits);1289 *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...@@ -1125,24 +1295,24 @@ static inline bool zig_subo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t
1125#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1295#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1126 int64_t full_res;1296 int64_t full_res;
1127 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1297 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);
1128#else1300#else
1129 int64_t full_res = (int64_t)((uint64_t)lhs - (uint64_t)rhs);1301 *res = zig_subw_i64(lhs, rhs, bits);
1130 bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0;1302 return ((lhs ^ rhs) & (*res ^ lhs)) < INT64_C(0);
1131#endif1303#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);
1134}1304}
11351305
1136static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {1306static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
1137#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1307#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1138 uint8_t full_res;1308 uint8_t full_res;
1139 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1309 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);
1141 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);1311 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
1142#else1312#else
1143 uint32_t full_res;1313 uint32_t full_res;
1144 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);1314 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
1145 *res = (uint8_t)full_res;1315 *res = zig_u8_intCast_u32(full_res);
1146 return overflow;1316 return overflow;
1147#endif1317#endif
1148}1318}
...@@ -1151,12 +1321,12 @@ static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits...@@ -1151,12 +1321,12 @@ static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
1151#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1321#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1152 int8_t full_res;1322 int8_t full_res;
1153 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1323 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);
1155 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);1325 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
1156#else1326#else
1157 int32_t full_res;1327 int32_t full_res;
1158 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);1328 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
1159 *res = (int8_t)full_res;1329 *res = zig_i8_intCast_i32(full_res);
1160 return overflow;1330 return overflow;
1161#endif1331#endif
1162}1332}
...@@ -1165,12 +1335,12 @@ static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8...@@ -1165,12 +1335,12 @@ static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
1165#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1335#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1166 uint16_t full_res;1336 uint16_t full_res;
1167 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1337 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);
1169 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);1339 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
1170#else1340#else
1171 uint32_t full_res;1341 uint32_t full_res;
1172 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);1342 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
1173 *res = (uint16_t)full_res;1343 *res = zig_u16_intCast_u32(full_res);
1174 return overflow;1344 return overflow;
1175#endif1345#endif
1176}1346}
...@@ -1179,27 +1349,28 @@ static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t...@@ -1179,27 +1349,28 @@ static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
1179#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1349#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1180 int16_t full_res;1350 int16_t full_res;
1181 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1351 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);
1183 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);1353 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
1184#else1354#else
1185 int32_t full_res;1355 int32_t full_res;
1186 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);1356 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
1187 *res = (int16_t)full_res;1357 *res = zig_i16_intCast_i32(full_res);
1188 return overflow;1358 return overflow;
1189#endif1359#endif
1190}1360}
11911361
1192#if defined(zig_ez80)1362#if defined(zig_ez80)
1363
1193static inline bool zig_subo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {1364static inline bool zig_subo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {
1194#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1365#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1195 uint24_t full_res;1366 uint24_t full_res;
1196 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1367 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);
1198 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);1369 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);
1199#else1370#else
1200 uint32_t full_res;1371 uint32_t full_res;
1201 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);1372 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
1202 *res = (uint24_t)full_res;1373 *res = zig_u24_intCast_u32(full_res);
1203 return overflow;1374 return overflow;
1204#endif1375#endif
1205}1376}
...@@ -1208,28 +1379,26 @@ static inline bool zig_subo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t...@@ -1208,28 +1379,26 @@ static inline bool zig_subo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t
1208#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1379#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1209 int24_t full_res;1380 int24_t full_res;
1210 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1381 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);
1212 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);1383 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);
1213#else1384#else
1214 int32_t full_res;1385 int32_t full_res;
1215 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);1386 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
1216 *res = (int24_t)full_res;1387 *res = zig_i24_intCast_i32(full_res);
1217 return overflow;1388 return overflow;
1218#endif1389#endif
1219}1390}
1220#endif
12211391
1222#if defined(zig_ez80)
1223static inline bool zig_subo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {1392static inline bool zig_subo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {
1224#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1393#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1225 uint48_t full_res;1394 uint48_t full_res;
1226 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1395 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);
1228 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);1397 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);
1229#else1398#else
1230 uint64_t full_res;1399 uint64_t full_res;
1231 bool overflow = zig_subo_u64(&full_res, lhs, rhs, bits);1400 bool overflow = zig_subo_u64(&full_res, lhs, rhs, bits);
1232 *res = (uint48_t)full_res;1401 *res = zig_u48_intCast_u64(full_res);
1233 return overflow;1402 return overflow;
1234#endif1403#endif
1235}1404}
...@@ -1238,22 +1407,23 @@ static inline bool zig_subo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t...@@ -1238,22 +1407,23 @@ static inline bool zig_subo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
1238#if zig_has_builtin(sub_overflow) || defined(zig_gcc)1407#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
1239 int48_t full_res;1408 int48_t full_res;
1240 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1409 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);
1242 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);1411 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);
1243#else1412#else
1244 int64_t full_res;1413 int64_t full_res;
1245 bool overflow = zig_subo_i64(&full_res, lhs, rhs, bits);1414 bool overflow = zig_subo_i64(&full_res, lhs, rhs, bits);
1246 *res = (int48_t)full_res;1415 *res = zig_i48_intCast_i64(full_res);
1247 return overflow;1416 return overflow;
1248#endif1417#endif
1249}1418}
1419
1250#endif1420#endif
12511421
1252static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {1422static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
1253#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1423#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1254 uint32_t full_res;1424 uint32_t full_res;
1255 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1425 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);
1257 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);1427 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
1258#else1428#else
1259 *res = zig_mulw_u32(lhs, rhs, bits);1429 *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...@@ -1261,8 +1431,8 @@ static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8
1261#endif1431#endif
1262}1432}
12631433
1264zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow);
1265static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) {1434static 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);
1266#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1436#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1267 int32_t full_res;1437 int32_t full_res;
1268 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1438 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...@@ -1271,7 +1441,7 @@ static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t
1271 int32_t full_res = __mulosi4(lhs, rhs, &overflow_int);1441 int32_t full_res = __mulosi4(lhs, rhs, &overflow_int);
1272 bool overflow = overflow_int != 0;1442 bool overflow = overflow_int != 0;
1273#endif1443#endif
1274 *res = zig_wrap_i32(full_res, bits);1444 *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);1445 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
1276}1446}
12771447
...@@ -1279,7 +1449,7 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8...@@ -1279,7 +1449,7 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8
1279#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1449#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1280 uint64_t full_res;1450 uint64_t full_res;
1281 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1451 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);
1283 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);1453 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
1284#else1454#else
1285 *res = zig_mulw_u64(lhs, rhs, bits);1455 *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...@@ -1287,8 +1457,8 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8
1287#endif1457#endif
1288}1458}
12891459
1290zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow);
1291static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) {1460static 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);
1292#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1462#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1293 int64_t full_res;1463 int64_t full_res;
1294 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1464 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...@@ -1297,7 +1467,7 @@ static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t
1297 int64_t full_res = __mulodi4(lhs, rhs, &overflow_int);1467 int64_t full_res = __mulodi4(lhs, rhs, &overflow_int);
1298 bool overflow = overflow_int != 0;1468 bool overflow = overflow_int != 0;
1299#endif1469#endif
1300 *res = zig_wrap_i64(full_res, bits);1470 *res = zig_i64_truncate_i64(full_res, bits);
1301 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);1471 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
1302}1472}
13031473
...@@ -1305,12 +1475,12 @@ static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b...@@ -1305,12 +1475,12 @@ static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b
1305#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1475#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1306 uint8_t full_res;1476 uint8_t full_res;
1307 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1477 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);
1309 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);1479 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
1310#else1480#else
1311 uint32_t full_res;1481 uint32_t full_res;
1312 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);1482 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
1313 *res = (uint8_t)full_res;1483 *res = zig_u8_intCast_u32(full_res);
1314 return overflow;1484 return overflow;
1315#endif1485#endif
1316}1486}
...@@ -1319,12 +1489,12 @@ static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits...@@ -1319,12 +1489,12 @@ static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
1319#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1489#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1320 int8_t full_res;1490 int8_t full_res;
1321 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1491 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);
1323 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);1493 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
1324#else1494#else
1325 int32_t full_res;1495 int32_t full_res;
1326 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);1496 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
1327 *res = (int8_t)full_res;1497 *res = zig_i8_intCast_i32(full_res);
1328 return overflow;1498 return overflow;
1329#endif1499#endif
1330}1500}
...@@ -1333,12 +1503,12 @@ static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8...@@ -1333,12 +1503,12 @@ static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
1333#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1503#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1334 uint16_t full_res;1504 uint16_t full_res;
1335 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1505 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);
1337 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);1507 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
1338#else1508#else
1339 uint32_t full_res;1509 uint32_t full_res;
1340 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);1510 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
1341 *res = (uint16_t)full_res;1511 *res = zig_u16_intCast_u32(full_res);
1342 return overflow;1512 return overflow;
1343#endif1513#endif
1344}1514}
...@@ -1347,27 +1517,28 @@ static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t...@@ -1347,27 +1517,28 @@ static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
1347#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1517#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1348 int16_t full_res;1518 int16_t full_res;
1349 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1519 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);
1351 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);1521 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
1352#else1522#else
1353 int32_t full_res;1523 int32_t full_res;
1354 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);1524 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
1355 *res = (int16_t)full_res;1525 *res = zig_i16_intCast_i32(full_res);
1356 return overflow;1526 return overflow;
1357#endif1527#endif
1358}1528}
13591529
1360#if defined(zig_ez80)1530#if defined(zig_ez80)
1531
1361static inline bool zig_mulo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {1532static inline bool zig_mulo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {
1362#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1533#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1363 uint24_t full_res;1534 uint24_t full_res;
1364 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1535 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);
1366 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);1537 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);
1367#else1538#else
1368 uint32_t full_res;1539 uint32_t full_res;
1369 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);1540 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
1370 *res = (uint24_t)full_res;1541 *res = zig_u24_intCast_u32(full_res);
1371 return overflow;1542 return overflow;
1372#endif1543#endif
1373}1544}
...@@ -1376,28 +1547,26 @@ static inline bool zig_mulo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t...@@ -1376,28 +1547,26 @@ static inline bool zig_mulo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t
1376#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1547#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1377 int24_t full_res;1548 int24_t full_res;
1378 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1549 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);
1380 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);1551 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);
1381#else1552#else
1382 int32_t full_res;1553 int32_t full_res;
1383 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);1554 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
1384 *res = (int24_t)full_res;1555 *res = zig_i24_intCast_i32(full_res);
1385 return overflow;1556 return overflow;
1386#endif1557#endif
1387}1558}
1388#endif
13891559
1390#if defined(zig_ez80)
1391static inline bool zig_mulo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {1560static inline bool zig_mulo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {
1392#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1561#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1393 uint48_t full_res;1562 uint48_t full_res;
1394 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1563 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);
1396 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);1565 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);
1397#else1566#else
1398 uint64_t full_res;1567 uint64_t full_res;
1399 bool overflow = zig_mulo_u64(&full_res, lhs, rhs, bits);1568 bool overflow = zig_mulo_u64(&full_res, lhs, rhs, bits);
1400 *res = (uint48_t)full_res;1569 *res = zig_u48_intCast_u64(full_res);
1401 return overflow;1570 return overflow;
1402#endif1571#endif
1403}1572}
...@@ -1406,18 +1575,32 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t...@@ -1406,18 +1575,32 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
1406#if zig_has_builtin(mul_overflow) || defined(zig_gcc)1575#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
1407 int48_t full_res;1576 int48_t full_res;
1408 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1577 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);
1410 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);1579 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);
1411#else1580#else
1412 int64_t full_res;1581 int64_t full_res;
1413 bool overflow = zig_mulo_i64(&full_res, lhs, rhs, bits);1582 bool overflow = zig_mulo_i64(&full_res, lhs, rhs, bits);
1414 *res = (int48_t)full_res;1583 *res = zig_i48_intCast_i64(full_res);
1415 return overflow;1584 return overflow;
1416#endif1585#endif
1417}1586}
1587
1418#endif1588#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) \
1421 static inline bool zig_shlo_u##w(uint##w##_t *res, uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \1604 static inline bool zig_shlo_u##w(uint##w##_t *res, uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \
1422 *res = zig_shlw_u##w(lhs, rhs, bits); \1605 *res = zig_shlw_u##w(lhs, rhs, bits); \
1423 return lhs > zig_maxInt_u(w, bits) >> rhs; \1606 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...@@ -1429,18 +1612,10 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
1429 return (lhs & mask) != INT##w##_C(0) && (lhs & mask) != mask; \1612 return (lhs & mask) != INT##w##_C(0) && (lhs & mask) != mask; \
1430 } \1613 } \
1431\1614\
1432 static inline uint##w##_t zig_shls_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \1615 zig_shls_builtins(w, 8) \
1433 uint##w##_t res; \1616 zig_shls_builtins(w, 16) \
1434 if (rhs < bits && !zig_shlo_u##w(&res, lhs, rhs, bits)) return res; \1617 zig_shls_builtins(w, 32) \
1435 return lhs == INT##w##_C(0) ? INT##w##_C(0) : zig_maxInt_u(w, bits); \1618 zig_shls_builtins(w, 64) \
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 } \
1444\1619\
1445 static inline uint##w##_t zig_adds_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \1620 static inline uint##w##_t zig_adds_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
1446 uint##w##_t res; \1621 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...@@ -1474,332 +1649,321 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
1474 if (!zig_mulo_i##w(&res, lhs, rhs, bits)) return res; \1649 if (!zig_mulo_i##w(&res, lhs, rhs, bits)) return res; \
1475 return (lhs ^ rhs) < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \1650 return (lhs ^ rhs) < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \
1476 }1651 }
1477zig_int_builtins(8)1652zig_int_sat_builtins(8)
1478zig_int_builtins(16)1653zig_int_sat_builtins(16)
1479#if defined(zig_ez80)1654zig_int_sat_builtins(32)
1480zig_int_builtins(24)1655zig_int_sat_builtins(64)
1481#endif
1482zig_int_builtins(32)
1483#if defined(zig_ez80)1656#if defined(zig_ez80)
1484zig_int_builtins(48)1657zig_int_sat_builtins(24)
1658zig_int_sat_builtins(48)
1485#endif1659#endif
1486zig_int_builtins(64)
14871660
1488#define zig_builtin8(name, val) __builtin_##name(val)1661#define zig_builtin8(name, arg) __builtin_##name(arg)
1489typedef unsigned int zig_Builtin8;1662typedef unsigned int zig_Builtin8;
14901663
1491#define zig_builtin16(name, val) __builtin_##name(val)1664#define zig_builtin16(name, arg) __builtin_##name(arg)
1492typedef unsigned int zig_Builtin16;1665typedef 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
1499#if INT_MIN <= INT32_MIN1667#if INT_MIN <= INT32_MIN
1500#define zig_builtin32(name, val) __builtin_##name(val)1668#define zig_builtin32(name, arg) __builtin_##name(arg)
1501typedef unsigned int zig_Builtin32;1669typedef unsigned int zig_Builtin32;
1502#elif LONG_MIN <= INT32_MIN1670#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)
1504typedef unsigned long zig_Builtin32;1672typedef unsigned long zig_Builtin32;
1505#endif1673#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
1512#if INT_MIN <= INT64_MIN1675#if INT_MIN <= INT64_MIN
1513#define zig_builtin64(name, val) __builtin_##name(val)1676#define zig_builtin64(name, arg) __builtin_##name(arg)
1514typedef unsigned int zig_Builtin64;1677typedef unsigned int zig_Builtin64;
1515#elif LONG_MIN <= INT64_MIN1678#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)
1517typedef unsigned long zig_Builtin64;1680typedef unsigned long zig_Builtin64;
1518#elif LLONG_MIN <= INT64_MIN1681#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)
1520typedef unsigned long long zig_Builtin64;1683typedef unsigned long long zig_Builtin64;
1521#endif1684#endif
15221685
1523static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) {1686#if defined(zig_ez80)
1524 return zig_wrap_u8(val >> (8 - bits), bits);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);
1525}1695}
15261696
1527static inline int8_t zig_byte_swap_i8(int8_t val, uint8_t bits) {1697static inline int8_t zig_byteSwap_i8(int8_t arg, uint8_t bits) {
1528 return zig_wrap_i8((int8_t)zig_byte_swap_u8((uint8_t)val, bits), bits);1698 return zig_i8_truncate_i8((int8_t)zig_byteSwap_u8((uint8_t)arg, bits), bits);
1529}1699}
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) {
1532 uint16_t full_res;1702 uint16_t full_res;
1533#if zig_has_builtin(bswap16) || defined(zig_gcc)1703#if zig_has_builtin(bswap16) || defined(zig_gcc)
1534 full_res = __builtin_bswap16(val);1704 full_res = __builtin_bswap16(arg);
1535#else1705#else
1536 full_res = (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 8 |1706 full_res = (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 8 |
1537 (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 8), 8) >> 0;1707 (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 8), 8) >> 0;
1538#endif1708#endif
1539 return zig_wrap_u16(full_res >> (16 - bits), bits);1709 return zig_u16_truncate_u16(full_res >> (16 - bits), bits);
1540}1710}
15411711
1542static inline int16_t zig_byte_swap_i16(int16_t val, uint8_t bits) {1712static inline int16_t zig_byteSwap_i16(int16_t arg, uint8_t bits) {
1543 return zig_wrap_i16((int16_t)zig_byte_swap_u16((uint16_t)val, bits), bits);1713 return zig_i16_truncate_i16((int16_t)zig_byteSwap_u16((uint16_t)arg, bits), bits);
1544}1714}
15451715
1546#if defined(zig_ez80)1716#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) {
1548 uint24_t full_res;1718 uint24_t full_res;
1549#if zig_has_builtin(bswap24) || defined(zig_gcc)1719#if zig_has_builtin(bswap24) || defined(zig_gcc)
1550 full_res = __builtin_bswap24(val);1720 full_res = __builtin_bswap24(arg);
1551#else1721#else
1552 full_res = (uint24_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 16 |1722 full_res = (uint24_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 16 |
1553 (uint24_t)zig_byte_swap_u16((uint16_t)(val >> 8), 16) >> 0;1723 (uint24_t)zig_byteSwap_u16((uint16_t)(arg >> 8), 16) >> 0;
1554#endif1724#endif
1555 return zig_wrap_u24(full_res >> (24 - bits), bits);1725 return zig_u24_truncate_u24(full_res >> (24 - bits), bits);
1556}1726}
15571727
1558static inline int16_t zig_byte_swap_i24(int24_t val, uint8_t bits) {1728static inline int16_t zig_byteSwap_i24(int24_t arg, uint8_t bits) {
1559 return zig_wrap_i24((int24_t)zig_byte_swap_u24((uint24_t)val, bits), bits);1729 return zig_i24_truncate_i24((int24_t)zig_byteSwap_u24((uint24_t)arg, bits), bits);
1560}1730}
1561#endif1731#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) {
1564 uint32_t full_res;1734 uint32_t full_res;
1565#if zig_has_builtin(bswap32) || defined(zig_gcc)1735#if zig_has_builtin(bswap32) || defined(zig_gcc)
1566 full_res = __builtin_bswap32(val);1736 full_res = __builtin_bswap32(arg);
1567#else1737#else
1568 full_res = (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 0), 16) << 16 |1738 full_res = (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 0), 16) << 16 |
1569 (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 16), 16) >> 0;1739 (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 16), 16) >> 0;
1570#endif1740#endif
1571 return zig_wrap_u32(full_res >> (32 - bits), bits);1741 return zig_u32_truncate_u32(full_res >> (32 - bits), bits);
1572}1742}
15731743
1574static inline int32_t zig_byte_swap_i32(int32_t val, uint8_t bits) {1744static inline int32_t zig_byteSwap_i32(int32_t arg, uint8_t bits) {
1575 return zig_wrap_i32((int32_t)zig_byte_swap_u32((uint32_t)val, bits), bits);1745 return zig_i32_truncate_i32((int32_t)zig_byteSwap_u32((uint32_t)arg, bits), bits);
1576}1746}
15771747
1578#if defined(zig_ez80)1748#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) {
1580 uint48_t full_res;1750 uint48_t full_res;
1581#if zig_has_builtin(bswap48) || defined(zig_gcc)1751#if zig_has_builtin(bswap48) || defined(zig_gcc)
1582 full_res = __builtin_bswap48(val);1752 full_res = __builtin_bswap48(arg);
1583#else1753#else
1584 full_res = (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 0), 24) << 24 |1754 full_res = (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 0), 24) << 24 |
1585 (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 24), 24) >> 0;1755 (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 24), 24) >> 0;
1586#endif1756#endif
1587 return zig_wrap_u48(full_res >> (48 - bits), bits);1757 return zig_u48_truncate_u48(full_res >> (48 - bits), bits);
1588}1758}
15891759
1590static inline int32_t zig_byte_swap_i48(int48_t val, uint8_t bits) {1760static inline int32_t zig_byteSwap_i48(int48_t arg, uint8_t bits) {
1591 return zig_wrap_i48((int48_t)zig_byte_swap_u48((uint48_t)val, bits), bits);1761 return zig_i48_truncate_i48((int48_t)zig_byteSwap_u48((uint48_t)arg, bits), bits);
1592}1762}
1593#endif1763#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) {
1596 uint64_t full_res;1766 uint64_t full_res;
1597#if zig_has_builtin(bswap64) || defined(zig_gcc)1767#if zig_has_builtin(bswap64) || defined(zig_gcc)
1598 full_res = __builtin_bswap64(val);1768 full_res = __builtin_bswap64(arg);
1599#else1769#else
1600 full_res = (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 0), 32) << 32 |1770 full_res = (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 0), 32) << 32 |
1601 (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 32), 32) >> 0;1771 (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 32), 32) >> 0;
1602#endif1772#endif
1603 return zig_wrap_u64(full_res >> (64 - bits), bits);1773 return zig_u64_truncate_u64(full_res >> (64 - bits), bits);
1604}1774}
16051775
1606static inline int64_t zig_byte_swap_i64(int64_t val, uint8_t bits) {1776static inline int64_t zig_byteSwap_i64(int64_t arg, uint8_t bits) {
1607 return zig_wrap_i64((int64_t)zig_byte_swap_u64((uint64_t)val, bits), bits);1777 return zig_i64_truncate_i64((int64_t)zig_byteSwap_u64((uint64_t)arg, bits), bits);
1608}1778}
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) {
1611 uint8_t full_res;1781 uint8_t full_res;
1612#if zig_has_builtin(bitreverse8)1782#if zig_has_builtin(bitreverse8)
1613 full_res = __builtin_bitreverse8(val);1783 full_res = __builtin_bitreverse8(arg);
1614#else1784#else
1615 static uint8_t const lut[0x10] = {1785 static uint8_t const lut[0x10] = {
1616 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,1786 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
1617 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf1787 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
1618 };1788 };
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;
1620#endif1790#endif
1621 return zig_wrap_u8(full_res >> (8 - bits), bits);1791 return zig_u8_truncate_u8(full_res >> (8 - bits), bits);
1622}1792}
16231793
1624static inline int8_t zig_bit_reverse_i8(int8_t val, uint8_t bits) {1794static inline int8_t zig_bitReverse_i8(int8_t arg, uint8_t bits) {
1625 return zig_wrap_i8((int8_t)zig_bit_reverse_u8((uint8_t)val, bits), bits);1795 return zig_i8_truncate_i8((int8_t)zig_bitReverse_u8((uint8_t)arg, bits), bits);
1626}1796}
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) {
1629 uint16_t full_res;1799 uint16_t full_res;
1630#if zig_has_builtin(bitreverse16)1800#if zig_has_builtin(bitreverse16)
1631 full_res = __builtin_bitreverse16(val);1801 full_res = __builtin_bitreverse16(arg);
1632#else1802#else
1633 full_res = (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 8 |1803 full_res = (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 8 |
1634 (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 8), 8) >> 0;1804 (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 8), 8) >> 0;
1635#endif1805#endif
1636 return zig_wrap_u16(full_res >> (16 - bits), bits);1806 return zig_u16_truncate_u16(full_res >> (16 - bits), bits);
1637}1807}
16381808
1639static inline int16_t zig_bit_reverse_i16(int16_t val, uint8_t bits) {1809static inline int16_t zig_bitReverse_i16(int16_t arg, uint8_t bits) {
1640 return zig_wrap_i16((int16_t)zig_bit_reverse_u16((uint16_t)val, bits), bits);1810 return zig_i16_truncate_i16((int16_t)zig_bitReverse_u16((uint16_t)arg, bits), bits);
1641}1811}
16421812
1643#if defined(zig_ez80)1813#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) {
1645 uint24_t full_res;1815 uint24_t full_res;
1646#if zig_has_builtin(bitreverse24)1816#if zig_has_builtin(bitreverse24)
1647 full_res = __builtin_bitreverse24(val);1817 full_res = __builtin_bitreverse24(arg);
1648#else1818#else
1649 full_res = (uint24_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 16 |1819 full_res = (uint24_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 16 |
1650 (uint24_t)zig_bit_reverse_u16((uint16_t)(val >> 8), 16) >> 0;1820 (uint24_t)zig_bitReverse_u16((uint16_t)(arg >> 8), 16) >> 0;
1651#endif1821#endif
1652 return zig_wrap_u24(full_res >> (24 - bits), bits);1822 return zig_u24_truncate_u24(full_res >> (24 - bits), bits);
1653}1823}
16541824
1655static inline int24_t zig_bit_reverse_i24(int24_t val, uint8_t bits) {1825static inline int24_t zig_bitReverse_i24(int24_t arg, uint8_t bits) {
1656 return zig_wrap_i24((int24_t)zig_bit_reverse_u24((uint24_t)val, bits), bits);1826 return zig_i24_truncate_i24((int24_t)zig_bitReverse_u24((uint24_t)arg, bits), bits);
1657}1827}
1658#endif1828#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) {
1661 uint32_t full_res;1831 uint32_t full_res;
1662#if zig_has_builtin(bitreverse32)1832#if zig_has_builtin(bitreverse32)
1663 full_res = __builtin_bitreverse32(val);1833 full_res = __builtin_bitreverse32(arg);
1664#else1834#else
1665 full_res = (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 0), 16) << 16 |1835 full_res = (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 0), 16) << 16 |
1666 (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 16), 16) >> 0;1836 (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 16), 16) >> 0;
1667#endif1837#endif
1668 return zig_wrap_u32(full_res >> (32 - bits), bits);1838 return zig_u32_truncate_u32(full_res >> (32 - bits), bits);
1669}1839}
16701840
1671static inline int32_t zig_bit_reverse_i32(int32_t val, uint8_t bits) {1841static inline int32_t zig_bitReverse_i32(int32_t arg, uint8_t bits) {
1672 return zig_wrap_i32((int32_t)zig_bit_reverse_u32((uint32_t)val, bits), bits);1842 return zig_i32_truncate_i32((int32_t)zig_bitReverse_u32((uint32_t)arg, bits), bits);
1673}1843}
16741844
1675#if defined(zig_ez80)1845#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) {
1677 uint48_t full_res;1847 uint48_t full_res;
1678#if zig_has_builtin(bitreverse48)1848#if zig_has_builtin(bitreverse48)
1679 full_res = __builtin_bitreverse48(val);1849 full_res = __builtin_bitreverse48(arg);
1680#else1850#else
1681 full_res = (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 0), 24) << 24 |1851 full_res = (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 0), 24) << 24 |
1682 (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 24), 24) >> 0;1852 (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 24), 24) >> 0;
1683#endif1853#endif
1684 return zig_wrap_u32(full_res >> (48 - bits), bits);1854 return zig_u48_truncate_u48(full_res >> (48 - bits), bits);
1685}1855}
16861856
1687static inline int32_t zig_bit_reverse_i48(int48_t val, uint8_t bits) {1857static inline int32_t zig_bitReverse_i48(int48_t arg, uint8_t bits) {
1688 return zig_wrap_i48((int48_t)zig_bit_reverse_u48((uint48_t)val, bits), bits);1858 return zig_i48_truncate_i48((int48_t)zig_bitReverse_u48((uint48_t)arg, bits), bits);
1689}1859}
1690#endif1860#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) {
1693 uint64_t full_res;1863 uint64_t full_res;
1694#if zig_has_builtin(bitreverse64)1864#if zig_has_builtin(bitreverse64)
1695 full_res = __builtin_bitreverse64(val);1865 full_res = __builtin_bitreverse64(arg);
1696#else1866#else
1697 full_res = (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 0), 32) << 32 |1867 full_res = (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 0), 32) << 32 |
1698 (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 32), 32) >> 0;1868 (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 32), 32) >> 0;
1699#endif1869#endif
1700 return zig_wrap_u64(full_res >> (64 - bits), bits);1870 return zig_u64_truncate_u64(full_res >> (64 - bits), bits);
1701}1871}
17021872
1703static inline int64_t zig_bit_reverse_i64(int64_t val, uint8_t bits) {1873static inline int64_t zig_bitReverse_i64(int64_t arg, uint8_t bits) {
1704 return zig_wrap_i64((int64_t)zig_bit_reverse_u64((uint64_t)val, bits), bits);1874 return zig_i64_truncate_i64((int64_t)zig_bitReverse_u64((uint64_t)arg, bits), bits);
1705}1875}
17061876
1707#define zig_builtin_popcount_common(w) \1877#define zig_builtin_popCount_common(w) \
1708 static inline uint8_t zig_popcount_i##w(int##w##_t val, uint8_t bits) { \1878 static inline uint8_t zig_popCount_i##w(int##w##_t arg, uint8_t bits) { \
1709 return zig_popcount_u##w((uint##w##_t)val, bits); \1879 return zig_popCount_u##w((uint##w##_t)arg, bits); \
1710 }1880 }
1711#if zig_has_builtin(popcount) || defined(zig_gcc) || defined(zig_tinyc)1881#if zig_has_builtin(popCount) || defined(zig_gcc) || defined(zig_tinyc)
1712#define zig_builtin_popcount(w) \1882#define zig_builtin_popCount(w) \
1713 static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \1883 static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \
1714 (void)bits; \1884 (void)bits; \
1715 return zig_builtin##w(popcount, val); \1885 return zig_builtin##w(popcount, arg); \
1716 } \1886 } \
1717\1887\
1718 zig_builtin_popcount_common(w)1888 zig_builtin_popCount_common(w)
1719#else1889#else
1720#define zig_builtin_popcount(w) \1890#define zig_builtin_popCount(w) \
1721 static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \1891 static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \
1722 (void)bits; \1892 (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)); \
1724 temp = (temp & (UINT##w##_MAX / 5)) + ((temp >> 2) & (UINT##w##_MAX / 5)); \1894 temp = (temp & (UINT##w##_MAX / 5)) + ((temp >> 2) & (UINT##w##_MAX / 5)); \
1725 temp = (temp + (temp >> 4)) & (UINT##w##_MAX / 17); \1895 temp = (temp + (temp >> 4)) & (UINT##w##_MAX / 17); \
1726 return temp * (UINT##w##_MAX / 255) >> (UINT8_C(w) - UINT8_C(8)); \1896 return temp * (UINT##w##_MAX / 255) >> (UINT8_C(w) - UINT8_C(8)); \
1727 } \1897 } \
1728\1898\
1729 zig_builtin_popcount_common(w)1899 zig_builtin_popCount_common(w)
1730#endif
1731zig_builtin_popcount(8)
1732zig_builtin_popcount(16)
1733#if defined(zig_ez80)
1734zig_builtin_popcount(24)
1735#endif1900#endif
1736zig_builtin_popcount(32)1901zig_builtin_popCount(8)
1902zig_builtin_popCount(16)
1903zig_builtin_popCount(32)
1904zig_builtin_popCount(64)
1737#if defined(zig_ez80)1905#if defined(zig_ez80)
1738zig_builtin_popcount(48)1906zig_builtin_popCount(24)
1907zig_builtin_popCount(48)
1739#endif1908#endif
1740zig_builtin_popcount(64)
17411909
1742#define zig_builtin_ctz_common(w) \1910#define zig_builtin_ctz_common(w) \
1743 static inline uint8_t zig_ctz_i##w(int##w##_t val, uint8_t bits) { \1911 static inline uint8_t zig_ctz_i##w(int##w##_t arg, uint8_t bits) { \
1744 return zig_ctz_u##w((uint##w##_t)val, bits); \1912 return zig_ctz_u##w((uint##w##_t)arg, bits); \
1745 }1913 }
1746#if zig_has_builtin(ctz) || defined(zig_gcc) || defined(zig_tinyc)1914#if zig_has_builtin(ctz) || defined(zig_gcc) || defined(zig_tinyc)
1747#define zig_builtin_ctz(w) \1915#define zig_builtin_ctz(w) \
1748 static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \1916 static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \
1749 if (val == 0) return bits; \1917 if (arg == 0) return bits; \
1750 return zig_builtin##w(ctz, val); \1918 return zig_builtin##w(ctz, arg); \
1751 } \1919 } \
1752\1920\
1753 zig_builtin_ctz_common(w)1921 zig_builtin_ctz_common(w)
1754#else1922#else
1755#define zig_builtin_ctz(w) \1923#define zig_builtin_ctz(w) \
1756 static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \1924 static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \
1757 return zig_popcount_u##w(zig_not_u##w(val, bits) & zig_subw_u##w(val, 1, bits), bits); \1925 return zig_popCount_u##w(zig_not_u##w(arg, bits) & zig_subw_u##w(arg, 1, bits), bits); \
1758 } \1926 } \
1759\1927\
1760 zig_builtin_ctz_common(w)1928 zig_builtin_ctz_common(w)
1761#endif1929#endif
1762zig_builtin_ctz(8)1930zig_builtin_ctz(8)
1763zig_builtin_ctz(16)1931zig_builtin_ctz(16)
1764#if defined(zig_ez80)
1765zig_builtin_ctz(24)
1766#endif
1767zig_builtin_ctz(32)1932zig_builtin_ctz(32)
1933zig_builtin_ctz(64)
1768#if defined(zig_ez80)1934#if defined(zig_ez80)
1935zig_builtin_ctz(24)
1769zig_builtin_ctz(48)1936zig_builtin_ctz(48)
1770#endif1937#endif
1771zig_builtin_ctz(64)
17721938
1773#define zig_builtin_clz_common(w) \1939#define zig_builtin_clz_common(w) \
1774 static inline uint8_t zig_clz_i##w(int##w##_t val, uint8_t bits) { \1940 static inline uint8_t zig_clz_i##w(int##w##_t arg, uint8_t bits) { \
1775 return zig_clz_u##w((uint##w##_t)val, bits); \1941 return zig_clz_u##w((uint##w##_t)arg, bits); \
1776 }1942 }
1777#if zig_has_builtin(clz) || defined(zig_gcc) || defined(zig_tinyc)1943#if zig_has_builtin(clz) || defined(zig_gcc) || defined(zig_tinyc)
1778#define zig_builtin_clz(w) \1944#define zig_builtin_clz(w) \
1779 static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \1945 static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \
1780 if (val == 0) return bits; \1946 if (arg == 0) return bits; \
1781 return zig_builtin##w(clz, val) - (zig_bitSizeOf(zig_Builtin##w) - bits); \1947 return zig_builtin##w(clz, arg) - (zig_bitSizeOf(zig_Builtin##w) - bits); \
1782 } \1948 } \
1783\1949\
1784 zig_builtin_clz_common(w)1950 zig_builtin_clz_common(w)
1785#else1951#else
1786#define zig_builtin_clz(w) \1952#define zig_builtin_clz(w) \
1787 static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \1953 static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \
1788 return zig_ctz_u##w(zig_bit_reverse_u##w(val, bits), bits); \1954 return zig_ctz_u##w(zig_bitReverse_u##w(arg, bits), bits); \
1789 } \1955 } \
1790\1956\
1791 zig_builtin_clz_common(w)1957 zig_builtin_clz_common(w)
1792#endif1958#endif
1793zig_builtin_clz(8)1959zig_builtin_clz(8)
1794zig_builtin_clz(16)1960zig_builtin_clz(16)
1795#if defined(zig_ez80)
1796zig_builtin_clz(24)
1797#endif
1798zig_builtin_clz(32)1961zig_builtin_clz(32)
1962zig_builtin_clz(64)
1799#if defined(zig_ez80)1963#if defined(zig_ez80)
1964zig_builtin_clz(24)
1800zig_builtin_clz(48)1965zig_builtin_clz(48)
1801#endif1966#endif
1802zig_builtin_clz(64)
18031967
1804/* ======================== 128-bit Integer Support ========================= */1968/* ======================== 128-bit Integer Support ========================= */
18051969
...@@ -1816,16 +1980,14 @@ zig_builtin_clz(64)...@@ -1816,16 +1980,14 @@ zig_builtin_clz(64)
1816typedef unsigned __int128 zig_u128;1980typedef unsigned __int128 zig_u128;
1817typedef signed __int128 zig_i128;1981typedef signed __int128 zig_i128;
18181982
1819#define zig_make_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))1983#define zig_init_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))
1820#define zig_make_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo))1984#define zig_init_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo))
1821#define zig_init_u128(hi, lo) zig_make_u128(hi, lo)1985#define zig_make_u128(hi, lo) zig_init_u128(hi, lo)
1822#define zig_init_i128(hi, lo) zig_make_i128(hi, lo)1986#define zig_make_i128(hi, lo) zig_init_i128(hi, lo)
1823#define zig_hi_u128(val) ((uint64_t)((val) >> 64))1987#define zig_hi_u128(arg) ((uint64_t)((arg) >> 64))
1824#define zig_lo_u128(val) ((uint64_t)((val) >> 0))1988#define zig_lo_u128(arg) ((uint64_t)((arg) >> 0))
1825#define zig_hi_i128(val) (( int64_t)((val) >> 64))1989#define zig_hi_i128(arg) (( int64_t)((arg) >> 64))
1826#define zig_lo_i128(val) ((uint64_t)((val) >> 0))1990#define zig_lo_i128(arg) ((uint64_t)((arg) >> 0))
1827#define zig_bitCast_u128(val) ((zig_u128)(val))
1828#define zig_bitCast_i128(val) ((zig_i128)(val))
1829#define zig_cmp_int128(Type) \1991#define zig_cmp_int128(Type) \
1830 static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \1992 static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
1831 return (lhs > rhs) - (lhs < rhs); \1993 return (lhs > rhs) - (lhs < rhs); \
...@@ -1835,32 +1997,49 @@ typedef signed __int128 zig_i128;...@@ -1835,32 +1997,49 @@ typedef signed __int128 zig_i128;
1835 return lhs operator rhs; \1997 return lhs operator rhs; \
1836 }1998 }
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_endian2004static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
1841typedef struct { zig_align(16) uint64_t lo; uint64_t hi; } zig_u128;2005 return lhs >> rhs;
1842typedef struct { zig_align(16) uint64_t lo; int64_t hi; } zig_i128;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;
1843#else2019#else
1844typedef struct { zig_align(16) uint64_t hi; uint64_t lo; } zig_u128;2020 zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0);
1845typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;2021 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask;
1846#endif2022#endif
2023}
18472024
1848#define zig_make_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) })2025#else /* zig_has_int128 */
1849#define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) })
18502026
1851#if defined(zig_msvc) /* MSVC doesn't allow struct literals in constant expressions */2027#if zig_little_endian
1852#define zig_init_u128(hi, lo) { .h##i = (hi), .l##o = (lo) }2028typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; uint64_t hi; } zig_u128;
1853#define zig_init_i128(hi, lo) { .h##i = (hi), .l##o = (lo) }2029typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; int64_t hi; } zig_i128;
1854#else /* But non-MSVC doesn't like the unprotected commas */2030#else
1855#define zig_init_u128(hi, lo) zig_make_u128(hi, lo)2031typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t hi; uint64_t lo; } zig_u128;
1856#define zig_init_i128(hi, lo) zig_make_i128(hi, lo)2032typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) int64_t hi; uint64_t lo; } zig_i128;
1857#endif2033#endif
1858#define zig_hi_u128(val) ((val).hi)2034
1859#define zig_lo_u128(val) ((val).lo)2035#define zig_init_u128(hi, lo) { .h##i = hi, .l##o = lo }
1860#define zig_hi_i128(val) ((val).hi)2036#define zig_init_i128(hi, lo) { .h##i = hi, .l##o = lo }
1861#define zig_lo_i128(val) ((val).lo)2037#define zig_make_u128(hi, lo) (zig_u128)zig_init_u128(hi, lo)
1862#define zig_bitCast_u128(val) zig_make_u128((uint64_t)(val).hi, (val).lo)2038#define zig_make_i128(hi, lo) (zig_i128)zig_init_i128(hi, lo)
1863#define zig_bitCast_i128(val) zig_make_i128(( int64_t)(val).hi, (val).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
1864#define zig_cmp_int128(Type) \2043#define zig_cmp_int128(Type) \
1865 static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \2044 static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
1866 return (lhs.hi == rhs.hi) \2045 return (lhs.hi == rhs.hi) \
...@@ -1872,6 +2051,30 @@ typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;...@@ -1872,6 +2051,30 @@ typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;
1872 return (zig_##Type){ .hi = lhs.hi operator rhs.hi, .lo = lhs.lo operator rhs.lo }; \2051 return (zig_##Type){ .hi = lhs.hi operator rhs.hi, .lo = lhs.lo operator rhs.lo }; \
1873 }2052 }
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
1875#endif /* zig_has_int128 */2078#endif /* zig_has_int128 */
18762079
1877#define zig_minInt_u128 zig_make_u128(zig_minInt_u64, zig_minInt_u64)2080#define zig_minInt_u128 zig_make_u128(zig_minInt_u64, zig_minInt_u64)
...@@ -1891,42 +2094,177 @@ zig_bit_int128(i128, or, |)...@@ -1891,42 +2094,177 @@ zig_bit_int128(i128, or, |)
1891zig_bit_int128(u128, xor, ^)2094zig_bit_int128(u128, xor, ^)
1892zig_bit_int128(i128, xor, ^)2095zig_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_int1282110static 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) {2123static inline uint32_t zig_u32_intCast_u128(zig_u128 arg) {
1899 return val ^ zig_maxInt_u(128, bits);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);
1900}2134}
19012135
1902static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) {2136static inline uint64_t zig_u64_intCast_u128(zig_u128 arg) {
1903 (void)bits;2137 return zig_lo_u128(arg);
1904 return ~val;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);
1905}2147}
19062148
1907static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {2149static inline zig_u128 zig_u128_intCast_u8(uint8_t arg) {
1908 return lhs >> rhs;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);
1909}2160}
19102161
1911static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {2162static inline zig_u128 zig_u128_intCast_u16(uint16_t arg) {
1912 return lhs << rhs;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);
1913}2173}
19142174
1915static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {2175static inline zig_u128 zig_u128_intCast_u32(uint32_t arg) {
1916 // This works around a GCC miscompilation, but it has the side benefit of2176 return zig_make_u128(UINT32_C(0), arg);
1917 // emitting better code. It is behind the `#if` because it depends on2177}
1918 // arithmetic right shift, which is implementation-defined in C, but should2178static inline zig_u128 zig_u128_intCast_i32(int32_t arg) {
1919 // be guaranteed on any GCC-compatible compiler.2179 return zig_make_u128(UINT32_C(0), (uint32_t)arg);
1920#if defined(zig_gnuc)2180}
1921 return lhs >> rhs;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;
1922#else2207#else
1923 zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0);2208 return zig_make_u128(zig_u64_bitCast_i64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg));
1924 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask;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));
1925#endif2219#endif
1926}2220}
19272221
1928static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {2222#define zig_int128_cast_builtins(w) \
1929 return lhs << rhs;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;
1930}2268}
19312269
1932static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) {2270static 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) {...@@ -1953,11 +2291,11 @@ static inline zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {
1953 return lhs * rhs;2291 return lhs * rhs;
1954}2292}
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) {
1957 return lhs / rhs;2295 return lhs / rhs;
1958}2296}
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) {
1961 return lhs / rhs;2299 return lhs / rhs;
1962}2300}
19632301
...@@ -1971,36 +2309,14 @@ static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {...@@ -1971,36 +2309,14 @@ static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
19712309
1972#else /* zig_has_int128 */2310#else /* zig_has_int128 */
19732311
1974static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) {2312static inline zig_u128 zig_not_u128(zig_u128 arg, 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)) };2313 if (bits <= UINT8_C(64)) return (zig_u128){ .hi = UINT64_C(0), .lo = zig_not_u64(arg.lo, bits) };
1976}2314 return (zig_u128){ .hi = zig_not_u64(arg.hi, bits - UINT8_C(64)), .lo = zig_not_u64(arg.lo, UINT8_C(64)) };
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) };
1998}2315}
19992316
2000static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {2317static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) {
2001 if (rhs == UINT8_C(0)) return lhs;2318 (void)bits;
2002 if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };2319 return (zig_i128){ .hi = ~arg.hi, .lo = ~arg.lo };
2003 return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
2004}2320}
20052321
2006static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) {2322static 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) {...@@ -2027,59 +2343,59 @@ static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) {
2027 return res;2343 return res;
2028}2344}
20292345
2030zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs);
2031static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {2346static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {
2347 zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs);
2032 return __multi3(lhs, rhs);2348 return __multi3(lhs, rhs);
2033}2349}
20342350
2035static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) {2351static 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));
2037}2353}
20382354
2039zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs);2355static zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) {
2040static zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) {2356 zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs);
2041 return __udivti3(lhs, rhs);2357 return __udivti3(lhs, rhs);
2042}2358}
20432359
2044zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs);2360static zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) {
2045static zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) {2361 zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs);
2046 return __divti3(lhs, rhs);2362 return __divti3(lhs, rhs);
2047}2363}
20482364
2049zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs);
2050static zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) {2365static zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) {
2366 zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs);
2051 return __umodti3(lhs, rhs);2367 return __umodti3(lhs, rhs);
2052}2368}
20532369
2054zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs);
2055static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {2370static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
2371 zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs);
2056 return __modti3(lhs, rhs);2372 return __modti3(lhs, rhs);
2057}2373}
20582374
2059#endif /* zig_has_int128 */2375#endif /* zig_has_int128 */
20602376
2061#define zig_div_floor_u128 zig_div_trunc_u1282377#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) {
2064 zig_i128 rem = zig_rem_i128(lhs, rhs);2380 zig_i128 rem = zig_rem_i128(lhs, rhs);
2065 int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0)2381 int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0)
2066 ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) : INT64_C(0);2382 ? 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));
2068}2384}
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) {
2071 zig_u128 rem = zig_rem_u128(lhs, rhs);2387 zig_u128 rem = zig_rem_u128(lhs, rhs);
2072 uint64_t mask = zig_or_u64(zig_hi_u128(rem), zig_lo_u128(rem)) != UINT64_C(0)2388 uint64_t mask = zig_or_u64(zig_hi_u128(rem), zig_lo_u128(rem)) != UINT64_C(0)
2073 ? UINT64_C(1) : UINT64_C(0);2389 ? 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));
2075}2391}
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) {
2078 zig_i128 rem = zig_rem_i128(lhs, rhs);2394 zig_i128 rem = zig_rem_i128(lhs, rhs);
2079 int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0)2395 int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0)
2080 ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) + INT64_C(1)2396 ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) + INT64_C(1)
2081 : INT64_C(0);2397 : 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));
2083}2399}
20842400
2085#define zig_mod_u128 zig_rem_u1282401#define zig_mod_u128 zig_rem_u128
...@@ -2107,51 +2423,41 @@ static inline zig_i128 zig_max_i128(zig_i128 lhs, zig_i128 rhs) {...@@ -2107,51 +2423,41 @@ static inline zig_i128 zig_max_i128(zig_i128 lhs, zig_i128 rhs) {
2107 return zig_cmp_i128(lhs, rhs) > INT32_C(0) ? lhs : rhs;2423 return zig_cmp_i128(lhs, rhs) > INT32_C(0) ? lhs : rhs;
2108}2424}
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
2120static inline zig_u128 zig_shlw_u128(zig_u128 lhs, uint8_t rhs, uint8_t bits) {2426static 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);
2122}2428}
21232429
2124static inline zig_i128 zig_shlw_i128(zig_i128 lhs, uint8_t rhs, uint8_t bits) {2430static 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);
2126}2432}
21272433
2128static inline zig_u128 zig_addw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {2434static 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);
2130}2436}
21312437
2132static inline zig_i128 zig_addw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {2438static 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);
2134}2440}
21352441
2136static inline zig_u128 zig_subw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {2442static 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);
2138}2444}
21392445
2140static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {2446static 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);
2142}2448}
21432449
2144static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {2450static 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);
2146}2452}
21472453
2148static inline zig_i128 zig_mulw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {2454static 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);
2150}2456}
21512457
2152static inline zig_u128 zig_abs_i128(zig_i128 val) {2458static inline zig_u128 zig_abs_i128(zig_i128 arg) {
2153 zig_i128 tmp = zig_shr_i128(val, 127);2459 zig_u128 tmp = zig_u128_bitCast_i128(zig_shr_i128(arg, 127), UINT8_C(128));
2154 return zig_bitCast_u128(zig_sub_i128(zig_xor_i128(val, tmp), tmp));2460 return zig_sub_u128(zig_xor_u128(zig_u128_bitCast_i128(arg, UINT8_C(128)), tmp), tmp);
2155}2461}
21562462
2157#if zig_has_int1282463#if zig_has_int128
...@@ -2160,7 +2466,7 @@ static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint...@@ -2160,7 +2466,7 @@ static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
2160#if zig_has_builtin(add_overflow)2466#if zig_has_builtin(add_overflow)
2161 zig_u128 full_res;2467 zig_u128 full_res;
2162 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);2468 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);
2164 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);2470 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
2165#else2471#else
2166 *res = zig_addw_u128(lhs, rhs, bits);2472 *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...@@ -2176,7 +2482,7 @@ static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint
2176 zig_i128 full_res = (zig_i128)((zig_u128)lhs + (zig_u128)rhs);2482 zig_i128 full_res = (zig_i128)((zig_u128)lhs + (zig_u128)rhs);
2177 bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0;2483 bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0;
2178#endif2484#endif
2179 *res = zig_wrap_i128(full_res, bits);2485 *res = zig_i128_truncate_i128(full_res, bits);
2180 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);2486 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
2181}2487}
21822488
...@@ -2184,7 +2490,7 @@ static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint...@@ -2184,7 +2490,7 @@ static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
2184#if zig_has_builtin(sub_overflow)2490#if zig_has_builtin(sub_overflow)
2185 zig_u128 full_res;2491 zig_u128 full_res;
2186 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);2492 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);
2188 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);2494 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
2189#else2495#else
2190 *res = zig_subw_u128(lhs, rhs, bits);2496 *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...@@ -2200,7 +2506,7 @@ static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint
2200 zig_i128 full_res = (zig_i128)((zig_u128)lhs - (zig_u128)rhs);2506 zig_i128 full_res = (zig_i128)((zig_u128)lhs - (zig_u128)rhs);
2201 bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0;2507 bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0;
2202#endif2508#endif
2203 *res = zig_wrap_i128(full_res, bits);2509 *res = zig_i128_truncate_i128(full_res, bits);
2204 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);2510 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
2205}2511}
22062512
...@@ -2208,7 +2514,7 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint...@@ -2208,7 +2514,7 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
2208#if zig_has_builtin(mul_overflow)2514#if zig_has_builtin(mul_overflow)
2209 zig_u128 full_res;2515 zig_u128 full_res;
2210 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);2516 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);
2212 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);2518 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
2213#else2519#else
2214 *res = zig_mulw_u128(lhs, rhs, bits);2520 *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...@@ -2216,8 +2522,8 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
2216#endif2522#endif
2217}2523}
22182524
2219zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
2220static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {2525static 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);
2221#if zig_has_builtin(mul_overflow)2527#if zig_has_builtin(mul_overflow)
2222 zig_i128 full_res;2528 zig_i128 full_res;
2223 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);2529 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...@@ -2226,50 +2532,78 @@ static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint
2226 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);2532 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);
2227 bool overflow = overflow_int != 0;2533 bool overflow = overflow_int != 0;
2228#endif2534#endif
2229 *res = zig_wrap_i128(full_res, bits);2535 *res = zig_i128_truncate_i128(full_res, bits);
2230 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);2536 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
2231}2537}
22322538
2233#else /* zig_has_int128 */2539#else /* zig_has_int128 */
22342540
2235static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {2541static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2236 uint64_t hi;2542 if (bits <= UINT8_C(64)) {
2237 bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - 64);2543 uint64_t lo;
2238 return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);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 }
2239}2552}
22402553
2241static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {2554static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2242 int64_t hi;2555 if (bits <= UINT8_C(64)) {
2243 bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - 64);2556 int64_t lo;
2244 return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);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 }
2245}2565}
22462566
2247static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {2567static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2248 uint64_t hi;2568 if (bits <= UINT8_C(64)) {
2249 bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - 64);2569 uint64_t lo;
2250 return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);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 }
2251}2578}
22522579
2253static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {2580static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2254 int64_t hi;2581 if (bits <= UINT8_C(64)) {
2255 bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - 64);2582 int64_t lo;
2256 return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);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 }
2257}2591}
22582592
2259static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {2593static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2260 *res = zig_mulw_u128(lhs, rhs, bits);2594 *res = zig_mulw_u128(lhs, rhs, bits);
2261 return zig_cmp_u128(*res, zig_make_u128(0, 0)) != INT32_C(0) &&2595 return zig_cmp_u128(rhs, 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);2596 zig_cmp_u128(lhs, zig_divTrunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0);
2263}2597}
22642598
2265zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
2266static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {2599static 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);
2267 int overflow_int;2601 int overflow_int;
2268 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);2602 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);
2269 bool overflow = overflow_int != 0 ||2603 bool overflow = overflow_int != 0 ||
2270 zig_cmp_i128(full_res, zig_minInt_i(128, bits)) < INT32_C(0) ||2604 zig_cmp_i128(full_res, zig_minInt_i(128, bits)) < INT32_C(0) ||
2271 zig_cmp_i128(full_res, zig_maxInt_i(128, bits)) > INT32_C(0);2605 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);
2273 return overflow;2607 return overflow;
2274}2608}
22752609
...@@ -2282,28 +2616,54 @@ static inline bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, uint8_t rhs, uint8...@@ -2282,28 +2616,54 @@ static inline bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, uint8_t rhs, uint8
22822616
2283static inline bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, uint8_t rhs, uint8_t bits) {2617static inline bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, uint8_t rhs, uint8_t bits) {
2284 *res = zig_shlw_i128(lhs, rhs, bits);2618 *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);
2286 return zig_cmp_i128(zig_and_i128(lhs, mask), zig_make_i128(0, 0)) != INT32_C(0) &&2620 return zig_cmp_i128(zig_and_i128(lhs, mask), zig_make_i128(0, 0)) != INT32_C(0) &&
2287 zig_cmp_i128(zig_and_i128(lhs, mask), mask) != INT32_C(0);2621 zig_cmp_i128(zig_and_i128(lhs, mask), mask) != INT32_C(0);
2288}2622}
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) {
2291 zig_u128 res;2651 zig_u128 res;
2292 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;2652 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;
2293 switch (zig_cmp_u128(lhs, zig_make_u128(0, 0))) {2653 switch (zig_cmp_u128(lhs, zig_make_u128(0, 0))) {
2294 case 0: return zig_make_u128(0, 0);2654 case INT32_C(0): return zig_make_u128(0, 0);
2295 case 1: return zig_maxInt_u(128, bits);2655 case INT32_C(1): return zig_maxInt_u(128, bits);
2296 default: zig_unreachable();2656 default: zig_unreachable();
2297 }2657 }
2298}2658}
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) {
2301 zig_i128 res;2661 zig_i128 res;
2302 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;2662 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;
2303 switch (zig_cmp_i128(lhs, zig_make_i128(0, 0))) {2663 switch (zig_cmp_i128(lhs, zig_make_i128(0, 0))) {
2304 case -1: return zig_minInt_i(128, bits);2664 case -INT32_C(1): return zig_minInt_i(128, bits);
2305 case 0: return zig_make_i128(0, 0);2665 case INT32_C(0): return zig_make_i128(0, 0);
2306 case 1: return zig_maxInt_i(128, bits);2666 case INT32_C(1): return zig_maxInt_i(128, bits);
2307 default: zig_unreachable();2667 default: zig_unreachable();
2308 }2668 }
2309}2669}
...@@ -2341,57 +2701,60 @@ static inline zig_i128 zig_muls_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {...@@ -2341,57 +2701,60 @@ static inline zig_i128 zig_muls_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2341 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);2701 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);
2342}2702}
23432703
2344static inline uint8_t zig_clz_u128(zig_u128 val, uint8_t bits) {2704static inline uint8_t zig_clz_u128(zig_u128 arg, uint8_t bits) {
2345 if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(val), bits);2705 if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(arg), bits);
2346 if (zig_hi_u128(val) != 0) return zig_clz_u64(zig_hi_u128(val), bits - UINT8_C(64));2706 if (zig_hi_u128(arg) != 0) return zig_clz_u64(zig_hi_u128(arg), bits - UINT8_C(64));
2347 return zig_clz_u64(zig_lo_u128(val), UINT8_C(64)) + (bits - UINT8_C(64));2707 return zig_clz_u64(zig_lo_u128(arg), UINT8_C(64)) + (bits - UINT8_C(64));
2348}2708}
23492709
2350static inline uint8_t zig_clz_i128(zig_i128 val, uint8_t bits) {2710static inline uint8_t zig_clz_i128(zig_i128 arg, uint8_t bits) {
2351 return zig_clz_u128(zig_bitCast_u128(val), bits);2711 return zig_clz_u128(zig_u128_bitCast_i128(arg, bits), bits);
2352}2712}
23532713
2354static inline uint8_t zig_ctz_u128(zig_u128 val, uint8_t bits) {2714static inline uint8_t zig_ctz_u128(zig_u128 arg, uint8_t bits) {
2355 if (zig_lo_u128(val) != 0) return zig_ctz_u64(zig_lo_u128(val), UINT8_C(64));2715 if (zig_lo_u128(arg) != 0) return zig_ctz_u64(zig_lo_u128(arg), UINT8_C(64));
2356 return zig_ctz_u64(zig_hi_u128(val), bits - UINT8_C(64)) + UINT8_C(64);2716 return zig_ctz_u64(zig_hi_u128(arg), bits - UINT8_C(64)) + UINT8_C(64);
2357}2717}
23582718
2359static inline uint8_t zig_ctz_i128(zig_i128 val, uint8_t bits) {2719static inline uint8_t zig_ctz_i128(zig_i128 arg, uint8_t bits) {
2360 return zig_ctz_u128(zig_bitCast_u128(val), bits);2720 return zig_ctz_u128(zig_u128_bitCast_i128(arg, bits), bits);
2361}2721}
23622722
2363static inline uint8_t zig_popcount_u128(zig_u128 val, uint8_t bits) {2723static inline uint8_t zig_popCount_u128(zig_u128 arg, uint8_t bits) {
2364 return zig_popcount_u64(zig_hi_u128(val), bits - UINT8_C(64)) +2724 return (bits > UINT8_C(64) ? zig_popCount_u64(zig_hi_u128(arg), bits - UINT8_C(64)) : UINT8_C(0)) +
2365 zig_popcount_u64(zig_lo_u128(val), UINT8_C(64));2725 zig_popCount_u64(zig_lo_u128(arg), UINT8_C(64));
2366}2726}
23672727
2368static inline uint8_t zig_popcount_i128(zig_i128 val, uint8_t bits) {2728static inline uint8_t zig_popCount_i128(zig_i128 arg, uint8_t bits) {
2369 return zig_popcount_u128(zig_bitCast_u128(val), bits);2729 return zig_popCount_u128(zig_u128_bitCast_i128(arg, bits), bits);
2370}2730}
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) {
2373 zig_u128 full_res;2733 zig_u128 full_res;
2374#if zig_has_builtin(bswap128)2734#if zig_has_builtin(bswap128)
2375 full_res = __builtin_bswap128(val);2735 full_res = __builtin_bswap128(arg);
2376#else2736#else
2377 full_res = zig_make_u128(zig_byte_swap_u64(zig_lo_u128(val), UINT8_C(64)),2737 full_res = zig_make_u128(
2378 zig_byte_swap_u64(zig_hi_u128(val), UINT8_C(64)));2738 zig_byteSwap_u64(zig_lo_u128(arg), UINT8_C(64)),
2739 zig_byteSwap_u64(zig_hi_u128(arg), UINT8_C(64))
2740 );
2379#endif2741#endif
2380 return zig_shr_u128(full_res, UINT8_C(128) - bits);2742 return zig_shr_u128(full_res, UINT8_C(128) - bits);
2381}2743}
23822744
2383static inline zig_i128 zig_byte_swap_i128(zig_i128 val, uint8_t bits) {2745static inline zig_i128 zig_byteSwap_i128(zig_i128 arg, uint8_t bits) {
2384 return zig_bitCast_i128(zig_byte_swap_u128(zig_bitCast_u128(val), bits));2746 return zig_i128_bitCast_u128(zig_byteSwap_u128(zig_u128_bitCast_i128(arg, bits), bits), bits);
2385}2747}
23862748
2387static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, uint8_t bits) {2749static inline zig_u128 zig_bitReverse_u128(zig_u128 arg, uint8_t bits) {
2388 return zig_shr_u128(zig_make_u128(zig_bit_reverse_u64(zig_lo_u128(val), UINT8_C(64)),2750 return zig_shr_u128(zig_make_u128(
2389 zig_bit_reverse_u64(zig_hi_u128(val), UINT8_C(64))),2751 zig_bitReverse_u64(zig_lo_u128(arg), UINT8_C(64)),
2390 UINT8_C(128) - bits);2752 zig_bitReverse_u64(zig_hi_u128(arg), UINT8_C(64))
2753 ), UINT8_C(128) - bits);
2391}2754}
23922755
2393static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) {2756static inline zig_i128 zig_bitReverse_i128(zig_i128 arg, uint8_t bits) {
2394 return zig_bitCast_i128(zig_bit_reverse_u128(zig_bitCast_u128(val), bits));2757 return zig_i128_bitCast_u128(zig_bitReverse_u128(zig_u128_bitCast_i128(arg, bits), bits), bits);
2395}2758}
23962759
2397#if zig_has_int1282760#if zig_has_int128
...@@ -2411,15 +2774,218 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) {...@@ -2411,15 +2774,218 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) {
2411/* ========================== Big Integer Support =========================== */2774/* ========================== Big Integer Support =========================== */
24122775
2413static inline uint16_t zig_int_bytes(uint16_t bits) {2776static 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);
2415 uint16_t alignment = ZIG_TARGET_MAX_INT_ALIGNMENT;2778 uint16_t alignment = ZIG_TARGET_MAX_INT_ALIGNMENT;
2779
2416 while (alignment / 2 >= bytes) alignment /= 2;2780 while (alignment / 2 >= bytes) alignment /= 2;
2417 return (bytes + alignment - 1) / alignment * alignment;2781 return (bytes + alignment - 1) / alignment * alignment;
2418}2782}
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) {
2421 const uint8_t *lhs_bytes = lhs;2988 const uint8_t *lhs_bytes = lhs;
2422 const uint8_t *rhs_bytes = rhs;
2423 uint16_t byte_offset = 0;2989 uint16_t byte_offset = 0;
2424 bool do_signed = is_signed;2990 bool do_signed = is_signed;
2425 uint16_t remaining_bytes = zig_int_bytes(bits);2991 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...@@ -2429,6 +2995,7 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
2429#endif2995#endif
24302996
2431 while (remaining_bytes >= 128 / CHAR_BIT) {2997 while (remaining_bytes >= 128 / CHAR_BIT) {
2998 uint8_t rhs_byte = remaining_bytes == 128 / CHAR_BIT ? rhs : UINT8_C(0);
2432 int32_t limb_cmp;2999 int32_t limb_cmp;
24333000
2434#if zig_little_endian3001#if zig_little_endian
...@@ -2437,18 +3004,16 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign...@@ -2437,18 +3004,16 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
24373004
2438 if (do_signed) {3005 if (do_signed) {
2439 zig_i128 lhs_limb;3006 zig_i128 lhs_limb;
2440 zig_i128 rhs_limb;3007 zig_i128 rhs_limb = zig_i128_intCast_u8(rhs_byte);
24413008
2442 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3009 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2443 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2444 limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb);3010 limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb);
2445 do_signed = false;3011 do_signed = false;
2446 } else {3012 } else {
2447 zig_u128 lhs_limb;3013 zig_u128 lhs_limb;
2448 zig_u128 rhs_limb;3014 zig_u128 rhs_limb = zig_u128_intCast_u8(rhs_byte);
24493015
2450 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3016 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2451 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2452 limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb);3017 limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb);
2453 }3018 }
24543019
...@@ -2461,24 +3026,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign...@@ -2461,24 +3026,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
2461 }3026 }
24623027
2463 while (remaining_bytes >= 64 / CHAR_BIT) {3028 while (remaining_bytes >= 64 / CHAR_BIT) {
3029 uint8_t rhs_byte = remaining_bytes == 64 / CHAR_BIT ? rhs : UINT8_C(0);
3030
2464#if zig_little_endian3031#if zig_little_endian
2465 byte_offset -= 64 / CHAR_BIT;3032 byte_offset -= 64 / CHAR_BIT;
2466#endif3033#endif
24673034
2468 if (do_signed) {3035 if (do_signed) {
2469 int64_t lhs_limb;3036 int64_t lhs_limb;
2470 int64_t rhs_limb;3037 int64_t rhs_limb = zig_i64_intCast_u8(rhs_byte);
24713038
2472 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3039 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2473 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2474 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);3040 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
2475 do_signed = false;3041 do_signed = false;
2476 } else {3042 } else {
2477 uint64_t lhs_limb;3043 uint64_t lhs_limb;
2478 uint64_t rhs_limb;3044 uint64_t rhs_limb = zig_u64_intCast_u8(rhs_byte);
24793045
2480 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3046 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2481 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2482 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);3047 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
2483 }3048 }
24843049
...@@ -2490,24 +3055,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign...@@ -2490,24 +3055,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
2490 }3055 }
24913056
2492 while (remaining_bytes >= 32 / CHAR_BIT) {3057 while (remaining_bytes >= 32 / CHAR_BIT) {
3058 uint8_t rhs_byte = remaining_bytes == 32 / CHAR_BIT ? rhs : UINT8_C(0);
3059
2493#if zig_little_endian3060#if zig_little_endian
2494 byte_offset -= 32 / CHAR_BIT;3061 byte_offset -= 32 / CHAR_BIT;
2495#endif3062#endif
24963063
2497 if (do_signed) {3064 if (do_signed) {
2498 int32_t lhs_limb;3065 int32_t lhs_limb;
2499 int32_t rhs_limb;3066 int32_t rhs_limb = zig_i32_intCast_u8(rhs_byte);
25003067
2501 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3068 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2502 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2503 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);3069 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
2504 do_signed = false;3070 do_signed = false;
2505 } else {3071 } else {
2506 uint32_t lhs_limb;3072 uint32_t lhs_limb;
2507 uint32_t rhs_limb;3073 uint32_t rhs_limb = zig_u32_intCast_u8(rhs_byte);
25083074
2509 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3075 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2510 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2511 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);3076 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
2512 }3077 }
25133078
...@@ -2519,24 +3084,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign...@@ -2519,24 +3084,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
2519 }3084 }
25203085
2521 while (remaining_bytes >= 16 / CHAR_BIT) {3086 while (remaining_bytes >= 16 / CHAR_BIT) {
3087 uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0);
3088
2522#if zig_little_endian3089#if zig_little_endian
2523 byte_offset -= 16 / CHAR_BIT;3090 byte_offset -= 16 / CHAR_BIT;
2524#endif3091#endif
25253092
2526 if (do_signed) {3093 if (do_signed) {
2527 int16_t lhs_limb;3094 int16_t lhs_limb;
2528 int16_t rhs_limb;3095 int16_t rhs_limb = zig_i16_intCast_u8(rhs_byte);
25293096
2530 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3097 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2531 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2532 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);3098 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
2533 do_signed = false;3099 do_signed = false;
2534 } else {3100 } else {
2535 uint16_t lhs_limb;3101 uint16_t lhs_limb;
2536 uint16_t rhs_limb;3102 uint16_t rhs_limb = zig_u16_intCast_u8(rhs_byte);
25373103
2538 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3104 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2539 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2540 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);3105 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
2541 }3106 }
25423107
...@@ -2548,24 +3113,26 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign...@@ -2548,24 +3113,26 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
2548 }3113 }
25493114
2550 while (remaining_bytes >= 8 / CHAR_BIT) {3115 while (remaining_bytes >= 8 / CHAR_BIT) {
3116 uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0);
3117
2551#if zig_little_endian3118#if zig_little_endian
2552 byte_offset -= 8 / CHAR_BIT;3119 byte_offset -= 8 / CHAR_BIT;
2553#endif3120#endif
25543121
2555 if (do_signed) {3122 if (do_signed) {
2556 int8_t lhs_limb;3123 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
2559 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3127 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2560 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));3128 lhs_cmp_limb = zig_i16_intCast_i8(lhs_limb);
2561 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);3129 if (lhs_cmp_limb != rhs_cmp_limb) return (lhs_cmp_limb > rhs_cmp_limb) - (lhs_cmp_limb < rhs_cmp_limb);
2562 do_signed = false;3130 do_signed = false;
2563 } else {3131 } else {
2564 uint8_t lhs_limb;3132 uint8_t lhs_limb;
2565 uint8_t rhs_limb;3133 uint8_t rhs_limb = rhs_byte;
25663134
2567 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3135 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2568 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2569 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);3136 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
2570 }3137 }
25713138
...@@ -2579,148 +3146,472 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign...@@ -2579,148 +3146,472 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
2579 return 0;3146 return 0;
2580}3147}
25813148
2582static inline void zig_and_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {3149static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2583 uint8_t *res_bytes = res;
2584 const uint8_t *lhs_bytes = lhs;3150 const uint8_t *lhs_bytes = lhs;
2585 const uint8_t *rhs_bytes = rhs;3151 const uint8_t *rhs_bytes = rhs;
2586 uint16_t byte_offset = 0;3152 uint16_t byte_offset = 0;
3153 bool do_signed = is_signed;
2587 uint16_t remaining_bytes = zig_int_bytes(bits);3154 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
2590 while (remaining_bytes >= 128 / CHAR_BIT) {3160 while (remaining_bytes >= 128 / CHAR_BIT) {
2591 zig_u128 res_limb;3161 int32_t limb_cmp;
2592 zig_u128 lhs_limb;
2593 zig_u128 rhs_limb;
25943162
2595 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3163#if zig_little_endian
2596 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));3164 byte_offset -= 128 / CHAR_BIT;
2597 res_limb = zig_and_u128(lhs_limb, rhs_limb);3165#endif
2598 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));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;
2600 remaining_bytes -= 128 / CHAR_BIT;3185 remaining_bytes -= 128 / CHAR_BIT;
3186
3187#if zig_big_endian
2601 byte_offset += 128 / CHAR_BIT;3188 byte_offset += 128 / CHAR_BIT;
3189#endif
2602 }3190 }
26033191
2604 while (remaining_bytes >= 64 / CHAR_BIT) {3192 while (remaining_bytes >= 64 / CHAR_BIT) {
2605 uint64_t res_limb;3193#if zig_little_endian
2606 uint64_t lhs_limb;3194 byte_offset -= 64 / CHAR_BIT;
2607 uint64_t rhs_limb;3195#endif
26083196
2609 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3197 if (do_signed) {
2610 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));3198 int64_t lhs_limb;
2611 res_limb = zig_and_u64(lhs_limb, rhs_limb);3199 int64_t rhs_limb;
2612 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_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
2614 remaining_bytes -= 64 / CHAR_BIT;3214 remaining_bytes -= 64 / CHAR_BIT;
3215
3216#if zig_big_endian
2615 byte_offset += 64 / CHAR_BIT;3217 byte_offset += 64 / CHAR_BIT;
3218#endif
2616 }3219 }
26173220
2618 while (remaining_bytes >= 32 / CHAR_BIT) {3221 while (remaining_bytes >= 32 / CHAR_BIT) {
2619 uint32_t res_limb;3222#if zig_little_endian
2620 uint32_t lhs_limb;3223 byte_offset -= 32 / CHAR_BIT;
2621 uint32_t rhs_limb;3224#endif
26223225
2623 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3226 if (do_signed) {
2624 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));3227 int32_t lhs_limb;
2625 res_limb = zig_and_u32(lhs_limb, rhs_limb);3228 int32_t rhs_limb;
2626 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_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
2628 remaining_bytes -= 32 / CHAR_BIT;3243 remaining_bytes -= 32 / CHAR_BIT;
3244
3245#if zig_big_endian
2629 byte_offset += 32 / CHAR_BIT;3246 byte_offset += 32 / CHAR_BIT;
3247#endif
2630 }3248 }
26313249
2632 while (remaining_bytes >= 16 / CHAR_BIT) {3250 while (remaining_bytes >= 16 / CHAR_BIT) {
2633 uint16_t res_limb;3251#if zig_little_endian
2634 uint16_t lhs_limb;3252 byte_offset -= 16 / CHAR_BIT;
2635 uint16_t rhs_limb;3253#endif
26363254
2637 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3255 if (do_signed) {
2638 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));3256 int16_t lhs_limb;
2639 res_limb = zig_and_u16(lhs_limb, rhs_limb);3257 int16_t rhs_limb;
2640 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_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
2642 remaining_bytes -= 16 / CHAR_BIT;3272 remaining_bytes -= 16 / CHAR_BIT;
3273
3274#if zig_big_endian
2643 byte_offset += 16 / CHAR_BIT;3275 byte_offset += 16 / CHAR_BIT;
3276#endif
2644 }3277 }
26453278
2646 while (remaining_bytes >= 8 / CHAR_BIT) {3279 while (remaining_bytes >= 8 / CHAR_BIT) {
2647 uint8_t res_limb;3280#if zig_little_endian
2648 uint8_t lhs_limb;3281 byte_offset -= 8 / CHAR_BIT;
2649 uint8_t rhs_limb;3282#endif
26503283
2651 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3284 if (do_signed) {
2652 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));3285 int8_t lhs_limb;
2653 res_limb = zig_and_u8(lhs_limb, rhs_limb);3286 int8_t rhs_limb;
2654 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_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
2656 remaining_bytes -= 8 / CHAR_BIT;3301 remaining_bytes -= 8 / CHAR_BIT;
3302
3303#if zig_big_endian
2657 byte_offset += 8 / CHAR_BIT;3304 byte_offset += 8 / CHAR_BIT;
3305#endif
2658 }3306 }
3307
3308 return 0;
2659}3309}
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) {
2662 uint8_t *res_bytes = res;3312 uint8_t *res_bytes = res;
2663 const uint8_t *lhs_bytes = lhs;3313 const uint8_t *arg_bytes = arg;
2664 const uint8_t *rhs_bytes = rhs;
2665 uint16_t byte_offset = 0;3314 uint16_t byte_offset = 0;
2666 uint16_t remaining_bytes = zig_int_bytes(bits);3315 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
2669 while (remaining_bytes >= 128 / CHAR_BIT) {3322 while (remaining_bytes >= 128 / CHAR_BIT) {
2670 zig_u128 res_limb;3323 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
2671 zig_u128 lhs_limb;
2672 zig_u128 rhs_limb;
26733324
2674 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3325#if zig_big_endian
2675 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));3326 byte_offset -= 128 / CHAR_BIT;
2676 res_limb = zig_or_u128(lhs_limb, rhs_limb);3327#endif
2677 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));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
2679 remaining_bytes -= 128 / CHAR_BIT;3345 remaining_bytes -= 128 / CHAR_BIT;
3346
3347#if zig_little_endian
2680 byte_offset += 128 / CHAR_BIT;3348 byte_offset += 128 / CHAR_BIT;
3349#endif
2681 }3350 }
26823351
2683 while (remaining_bytes >= 64 / CHAR_BIT) {3352 while (remaining_bytes >= 64 / CHAR_BIT) {
2684 uint64_t res_limb;3353 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
2685 uint64_t lhs_limb;
2686 uint64_t rhs_limb;
26873354
2688 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3355#if zig_big_endian
2689 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));3356 byte_offset -= 64 / CHAR_BIT;
2690 res_limb = zig_or_u64(lhs_limb, rhs_limb);3357#endif
2691 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));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
2693 remaining_bytes -= 64 / CHAR_BIT;3375 remaining_bytes -= 64 / CHAR_BIT;
3376
3377#if zig_little_endian
2694 byte_offset += 64 / CHAR_BIT;3378 byte_offset += 64 / CHAR_BIT;
3379#endif
2695 }3380 }
26963381
2697 while (remaining_bytes >= 32 / CHAR_BIT) {3382 while (remaining_bytes >= 32 / CHAR_BIT) {
2698 uint32_t res_limb;3383 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
2699 uint32_t lhs_limb;
2700 uint32_t rhs_limb;
27013384
2702 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3385#if zig_big_endian
2703 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));3386 byte_offset -= 32 / CHAR_BIT;
2704 res_limb = zig_or_u32(lhs_limb, rhs_limb);3387#endif
2705 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));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
2707 remaining_bytes -= 32 / CHAR_BIT;3405 remaining_bytes -= 32 / CHAR_BIT;
3406
3407#if zig_little_endian
2708 byte_offset += 32 / CHAR_BIT;3408 byte_offset += 32 / CHAR_BIT;
3409#endif
2709 }3410 }
27103411
2711 while (remaining_bytes >= 16 / CHAR_BIT) {3412 while (remaining_bytes >= 16 / CHAR_BIT) {
2712 uint16_t res_limb;3413 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
2713 uint16_t lhs_limb;
2714 uint16_t rhs_limb;
27153414
2716 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));3415#if zig_big_endian
2717 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));3416 byte_offset -= 16 / CHAR_BIT;
2718 res_limb = zig_or_u16(lhs_limb, rhs_limb);3417#endif
2719 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
27203418
2721 remaining_bytes -= 16 / CHAR_BIT;3419 if (remaining_bytes != 16 / CHAR_BIT || is_signed) {
2722 byte_offset += 16 / CHAR_BIT;3420 int16_t res_limb;
2723 }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
2725 while (remaining_bytes >= 8 / CHAR_BIT) {3616 while (remaining_bytes >= 8 / CHAR_BIT) {
2726 uint8_t res_limb;3617 uint8_t res_limb;
...@@ -2816,13 +3707,415 @@ static inline void zig_xor_big(void *res, const void *lhs, const void *rhs, bool...@@ -2816,13 +3707,415 @@ static inline void zig_xor_big(void *res, const void *lhs, const void *rhs, bool
2816 }3707 }
2817}3708}
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
2819static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {4112static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2820 uint8_t *res_bytes = res;4113 uint8_t *res_bytes = res;
2821 const uint8_t *lhs_bytes = lhs;4114 const uint8_t *lhs_bytes = lhs;
2822 const uint8_t *rhs_bytes = rhs;4115 const uint8_t *rhs_bytes = rhs;
2823 uint16_t byte_offset = 0;4116 uint16_t byte_offset = 0;
2824 uint16_t remaining_bytes = zig_int_bytes(bits);4117 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);
2826 bool overflow = false;4119 bool overflow = false;
28274120
2828#if zig_big_endian4121#if zig_big_endian
...@@ -3038,7 +4331,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo...@@ -3038,7 +4331,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
3038 const uint8_t *rhs_bytes = rhs;4331 const uint8_t *rhs_bytes = rhs;
3039 uint16_t byte_offset = 0;4332 uint16_t byte_offset = 0;
3040 uint16_t remaining_bytes = zig_int_bytes(bits);4333 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);
3042 bool overflow = false;4335 bool overflow = false;
30434336
3044#if zig_big_endian4337#if zig_big_endian
...@@ -3238,218 +4531,890 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo...@@ -3238,218 +4531,890 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
3238 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));4531 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3239 }4532 }
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
3243#if zig_little_endian5160#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);
3245#endif5164#endif
3246 }5165 }
32475166
3248 return overflow;5167 {
3249}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) {5174 {
3252 (void)zig_addo_big(res, lhs, rhs, is_signed, bits);5175 uint8_t byte = arg_bytes[arg_byte_offset];
3253}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) {5180 res_bytes[res_byte_offset] = byte;
3256 (void)zig_subo_big(res, lhs, rhs, is_signed, bits);
3257}
32585181
3259zig_extern void __udivei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits);5182#if zig_little_endian
3260static inline void zig_div_trunc_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {5183 res_byte_offset += UINT16_C(1);
3261 if (!is_signed) {5184 memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset);
3262 __udivei4(res, lhs, rhs, bits);5185#else
3263 return;5186 memset(&res_bytes[0], fill, res_byte_offset);
5187#endif
5188 }
3264 }5189 }
3265
3266 zig_trap();
3267}5190}
32685191
3269static inline void zig_div_floor_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {5192static inline void zig_bitReverse_big(void *res, const void *arg, bool is_signed, uint16_t bits) {
3270 if (!is_signed) {5193 uint8_t *res_bytes = res;
3271 zig_div_trunc_big(res, lhs, rhs, is_signed, bits);5194 const uint8_t *arg_bytes = arg;
3272 return;5195 uint16_t size = zig_int_bytes(bits);
3273 }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();5202#if zig_big_endian
3276}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) {5208 {
3279 zig_trap();5209#if zig_little_endian
3280}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);5213 arg_prev_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8));
3283static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {5214
3284 if (!is_signed) {5215#if zig_big_endian
3285 __umodei4(res, lhs, rhs, bits);5216 arg_byte_offset += UINT16_C(1);
3286 return;5217#endif
3287 }5218 }
32885219
3289 zig_trap();5220 while (arg_byte_offset != end_byte_offset) {
3290}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) {5227 {
3293 if (!is_signed) {5228 uint8_t arg_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8));
3294 zig_rem_big(res, lhs, rhs, is_signed, bits);5229
3295 return;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
3296 }5242 }
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 }
3299}5267}
33005268
3301static inline uint16_t zig_clz_big(const void *val, bool is_signed, uint16_t bits) {5269static inline uint16_t zig_popCount_big(const void *arg, bool is_signed, uint16_t bits) {
3302 const uint8_t *val_bytes = val;5270 const uint8_t *arg_bytes = arg;
3303 uint16_t byte_offset = 0;5271 uint16_t byte_offset = 0;
3304 uint16_t remaining_bytes = zig_int_bytes(bits);5272 uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
3305 uint16_t skip_bits = remaining_bytes * 8 - bits;5273 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
3306 uint16_t total_lz = 0;5274 uint16_t total_pc = 0;
3307 uint16_t limb_lz;
3308 (void)is_signed;5275 (void)is_signed;
33095276
3310#if zig_little_endian5277#if zig_big_endian
3311 byte_offset = remaining_bytes;5278 byte_offset = zig_int_bytes(bits);
3312#endif5279#endif
33135280
3314 while (remaining_bytes >= 128 / CHAR_BIT) {5281 while (remaining_bytes >= 128 / CHAR_BIT) {
3315#if zig_little_endian5282 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
5283
5284#if zig_big_endian
3316 byte_offset -= 128 / CHAR_BIT;5285 byte_offset -= 128 / CHAR_BIT;
3317#endif5286#endif
33185287
3319 {5288 {
3320 zig_u128 val_limb;5289 zig_u128 arg_limb;
33215290
3322 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5291 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3323 limb_lz = zig_clz_u128(val_limb, 128 - skip_bits);5292 total_pc += zig_popCount_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits);
3324 }5293 }
33255294
3326 total_lz += limb_lz;
3327 if (limb_lz < 128 - skip_bits) return total_lz;
3328 skip_bits = 0;
3329 remaining_bytes -= 128 / CHAR_BIT;5295 remaining_bytes -= 128 / CHAR_BIT;
33305296
3331#if zig_big_endian5297#if zig_little_endian
3332 byte_offset += 128 / CHAR_BIT;5298 byte_offset += 128 / CHAR_BIT;
3333#endif5299#endif
3334 }5300 }
33355301
3336 while (remaining_bytes >= 64 / CHAR_BIT) {5302 while (remaining_bytes >= 64 / CHAR_BIT) {
3337#if zig_little_endian5303 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
5304
5305#if zig_big_endian
3338 byte_offset -= 64 / CHAR_BIT;5306 byte_offset -= 64 / CHAR_BIT;
3339#endif5307#endif
33405308
3341 {5309 {
3342 uint64_t val_limb;5310 uint64_t arg_limb;
33435311
3344 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5312 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3345 limb_lz = zig_clz_u64(val_limb, 64 - skip_bits);5313 total_pc += zig_popCount_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits);
3346 }5314 }
33475315
3348 total_lz += limb_lz;
3349 if (limb_lz < 64 - skip_bits) return total_lz;
3350 skip_bits = 0;
3351 remaining_bytes -= 64 / CHAR_BIT;5316 remaining_bytes -= 64 / CHAR_BIT;
33525317
3353#if zig_big_endian5318#if zig_little_endian
3354 byte_offset += 64 / CHAR_BIT;5319 byte_offset += 64 / CHAR_BIT;
3355#endif5320#endif
3356 }5321 }
33575322
3358 while (remaining_bytes >= 32 / CHAR_BIT) {5323 while (remaining_bytes >= 32 / CHAR_BIT) {
3359#if zig_little_endian5324 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
5325
5326#if zig_big_endian
3360 byte_offset -= 32 / CHAR_BIT;5327 byte_offset -= 32 / CHAR_BIT;
3361#endif5328#endif
33625329
3363 {5330 {
3364 uint32_t val_limb;5331 uint32_t arg_limb;
33655332
3366 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5333 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3367 limb_lz = zig_clz_u32(val_limb, 32 - skip_bits);5334 total_pc += zig_popCount_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits);
3368 }5335 }
33695336
3370 total_lz += limb_lz;
3371 if (limb_lz < 32 - skip_bits) return total_lz;
3372 skip_bits = 0;
3373 remaining_bytes -= 32 / CHAR_BIT;5337 remaining_bytes -= 32 / CHAR_BIT;
33745338
3375#if zig_big_endian5339#if zig_little_endian
3376 byte_offset += 32 / CHAR_BIT;5340 byte_offset += 32 / CHAR_BIT;
3377#endif5341#endif
3378 }5342 }
33795343
3380 while (remaining_bytes >= 16 / CHAR_BIT) {5344 while (remaining_bytes >= 16 / CHAR_BIT) {
3381#if zig_little_endian5345 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
5346
5347#if zig_big_endian
3382 byte_offset -= 16 / CHAR_BIT;5348 byte_offset -= 16 / CHAR_BIT;
3383#endif5349#endif
33845350
3385 {5351 {
3386 uint16_t val_limb;5352 uint16_t arg_limb;
33875353
3388 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5354 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3389 limb_lz = zig_clz_u16(val_limb, 16 - skip_bits);5355 total_pc += zig_popCount_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits);
3390 }5356 }
33915357
3392 total_lz += limb_lz;
3393 if (limb_lz < 16 - skip_bits) return total_lz;
3394 skip_bits = 0;
3395 remaining_bytes -= 16 / CHAR_BIT;5358 remaining_bytes -= 16 / CHAR_BIT;
33965359
3397#if zig_big_endian5360#if zig_little_endian
3398 byte_offset += 16 / CHAR_BIT;5361 byte_offset += 16 / CHAR_BIT;
3399#endif5362#endif
3400 }5363 }
34015364
3402 while (remaining_bytes >= 8 / CHAR_BIT) {5365 while (remaining_bytes >= 8 / CHAR_BIT) {
3403#if zig_little_endian5366 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
5367
5368#if zig_big_endian
3404 byte_offset -= 8 / CHAR_BIT;5369 byte_offset -= 8 / CHAR_BIT;
3405#endif5370#endif
34065371
3407 {5372 {
3408 uint8_t val_limb;5373 uint8_t arg_limb;
34095374
3410 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5375 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3411 limb_lz = zig_clz_u8(val_limb, 8 - skip_bits);5376 total_pc += zig_popCount_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits);
3412 }5377 }
34135378
3414 total_lz += limb_lz;
3415 if (limb_lz < 8 - skip_bits) return total_lz;
3416 skip_bits = 0;
3417 remaining_bytes -= 8 / CHAR_BIT;5379 remaining_bytes -= 8 / CHAR_BIT;
34185380
3419#if zig_big_endian5381#if zig_little_endian
3420 byte_offset += 8 / CHAR_BIT;5382 byte_offset += 8 / CHAR_BIT;
3421#endif5383#endif
3422 }5384 }
34235385
3424 return total_lz;5386 return total_pc;
3425}5387}
34265388
3427static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bits) {5389static inline uint16_t zig_ctz_big(const void *arg, bool is_signed, uint16_t bits) {
3428 const uint8_t *val_bytes = val;5390 const uint8_t *arg_bytes = arg;
3429 uint16_t byte_offset = 0;5391 uint16_t byte_offset = UINT16_C(0);
3430 uint16_t remaining_bytes = zig_int_bytes(bits);5392 uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
3431 uint16_t total_tz = 0;5393 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
5394 uint16_t total_tz = UINT16_C(0);
3432 uint16_t limb_tz;5395 uint16_t limb_tz;
3433 (void)is_signed;5396 (void)is_signed;
34345397
3435#if zig_big_endian5398#if zig_big_endian
3436 byte_offset = remaining_bytes;5399 byte_offset = zig_int_bytes(bits);
3437#endif5400#endif
34385401
3439 while (remaining_bytes >= 128 / CHAR_BIT) {5402 while (remaining_bytes >= 128 / CHAR_BIT) {
5403 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
5404
3440#if zig_big_endian5405#if zig_big_endian
3441 byte_offset -= 128 / CHAR_BIT;5406 byte_offset -= 128 / CHAR_BIT;
3442#endif5407#endif
34435408
3444 {5409 {
3445 zig_u128 val_limb;5410 zig_u128 arg_limb;
34465411
3447 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5412 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3448 limb_tz = zig_ctz_u128(val_limb, 128);5413 limb_tz = zig_ctz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits);
3449 }5414 }
34505415
3451 total_tz += limb_tz;5416 total_tz += limb_tz;
3452 if (limb_tz < 128) return total_tz;5417 if (limb_tz < limb_bits) return total_tz;
3453 remaining_bytes -= 128 / CHAR_BIT;5418 remaining_bytes -= 128 / CHAR_BIT;
34545419
3455#if zig_little_endian5420#if zig_little_endian
...@@ -3458,19 +5423,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit...@@ -3458,19 +5423,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
3458 }5423 }
34595424
3460 while (remaining_bytes >= 64 / CHAR_BIT) {5425 while (remaining_bytes >= 64 / CHAR_BIT) {
5426 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
5427
3461#if zig_big_endian5428#if zig_big_endian
3462 byte_offset -= 64 / CHAR_BIT;5429 byte_offset -= 64 / CHAR_BIT;
3463#endif5430#endif
34645431
3465 {5432 {
3466 uint64_t val_limb;5433 uint64_t arg_limb;
34675434
3468 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5435 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3469 limb_tz = zig_ctz_u64(val_limb, 64);5436 limb_tz = zig_ctz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits);
3470 }5437 }
34715438
3472 total_tz += limb_tz;5439 total_tz += limb_tz;
3473 if (limb_tz < 64) return total_tz;5440 if (limb_tz < limb_bits) return total_tz;
3474 remaining_bytes -= 64 / CHAR_BIT;5441 remaining_bytes -= 64 / CHAR_BIT;
34755442
3476#if zig_little_endian5443#if zig_little_endian
...@@ -3479,19 +5446,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit...@@ -3479,19 +5446,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
3479 }5446 }
34805447
3481 while (remaining_bytes >= 32 / CHAR_BIT) {5448 while (remaining_bytes >= 32 / CHAR_BIT) {
5449 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
5450
3482#if zig_big_endian5451#if zig_big_endian
3483 byte_offset -= 32 / CHAR_BIT;5452 byte_offset -= 32 / CHAR_BIT;
3484#endif5453#endif
34855454
3486 {5455 {
3487 uint32_t val_limb;5456 uint32_t arg_limb;
34885457
3489 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5458 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3490 limb_tz = zig_ctz_u32(val_limb, 32);5459 limb_tz = zig_ctz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits);
3491 }5460 }
34925461
3493 total_tz += limb_tz;5462 total_tz += limb_tz;
3494 if (limb_tz < 32) return total_tz;5463 if (limb_tz < limb_bits) return total_tz;
3495 remaining_bytes -= 32 / CHAR_BIT;5464 remaining_bytes -= 32 / CHAR_BIT;
34965465
3497#if zig_little_endian5466#if zig_little_endian
...@@ -3500,19 +5469,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit...@@ -3500,19 +5469,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
3500 }5469 }
35015470
3502 while (remaining_bytes >= 16 / CHAR_BIT) {5471 while (remaining_bytes >= 16 / CHAR_BIT) {
5472 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
5473
3503#if zig_big_endian5474#if zig_big_endian
3504 byte_offset -= 16 / CHAR_BIT;5475 byte_offset -= 16 / CHAR_BIT;
3505#endif5476#endif
35065477
3507 {5478 {
3508 uint16_t val_limb;5479 uint16_t arg_limb;
35095480
3510 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5481 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3511 limb_tz = zig_ctz_u16(val_limb, 16);5482 limb_tz = zig_ctz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits);
3512 }5483 }
35135484
3514 total_tz += limb_tz;5485 total_tz += limb_tz;
3515 if (limb_tz < 16) return total_tz;5486 if (limb_tz < limb_bits) return total_tz;
3516 remaining_bytes -= 16 / CHAR_BIT;5487 remaining_bytes -= 16 / CHAR_BIT;
35175488
3518#if zig_little_endian5489#if zig_little_endian
...@@ -3521,19 +5492,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit...@@ -3521,19 +5492,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
3521 }5492 }
35225493
3523 while (remaining_bytes >= 8 / CHAR_BIT) {5494 while (remaining_bytes >= 8 / CHAR_BIT) {
5495 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
5496
3524#if zig_big_endian5497#if zig_big_endian
3525 byte_offset -= 8 / CHAR_BIT;5498 byte_offset -= 8 / CHAR_BIT;
3526#endif5499#endif
35275500
3528 {5501 {
3529 uint8_t val_limb;5502 uint8_t arg_limb;
35305503
3531 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5504 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3532 limb_tz = zig_ctz_u8(val_limb, 8);5505 limb_tz = zig_ctz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits);
3533 }5506 }
35345507
3535 total_tz += limb_tz;5508 total_tz += limb_tz;
3536 if (limb_tz < 8) return total_tz;5509 if (limb_tz < limb_bits) return total_tz;
3537 remaining_bytes -= 8 / CHAR_BIT;5510 remaining_bytes -= 8 / CHAR_BIT;
35385511
3539#if zig_little_endian5512#if zig_little_endian
...@@ -3544,113 +5517,141 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit...@@ -3544,113 +5517,141 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
3544 return total_tz;5517 return total_tz;
3545}5518}
35465519
3547static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_t bits) {5520static inline uint16_t zig_clz_big(const void *arg, bool is_signed, uint16_t bits) {
3548 const uint8_t *val_bytes = val;5521 const uint8_t *arg_bytes = arg;
3549 uint16_t byte_offset = 0;5522 uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
3550 uint16_t remaining_bytes = zig_int_bytes(bits);5523 uint16_t remaining_bytes = byte_offset;
3551 uint16_t total_pc = 0;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;
3552 (void)is_signed;5528 (void)is_signed;
35535529
3554#if zig_big_endian5530#if zig_big_endian
3555 byte_offset = remaining_bytes;5531 byte_offset = zig_int_bytes(bits) - remaining_bytes;
3556#endif5532#endif
35575533
3558 while (remaining_bytes >= 128 / CHAR_BIT) {5534 while (remaining_bytes >= 128 / CHAR_BIT) {
3559#if zig_big_endian5535 uint8_t limb_bits = UINT8_C(128) - (sign_limb ? top_bits : UINT8_C(0));
5536
5537#if zig_little_endian
3560 byte_offset -= 128 / CHAR_BIT;5538 byte_offset -= 128 / CHAR_BIT;
3561#endif5539#endif
35625540
3563 {5541 {
3564 zig_u128 val_limb;5542 zig_u128 arg_limb;
35655543
3566 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5544 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3567 total_pc += zig_popcount_u128(val_limb, 128);5545 limb_lz = zig_clz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits);
3568 }5546 }
35695547
5548 total_lz += limb_lz;
5549 if (limb_lz < limb_bits) return total_lz;
5550 sign_limb = false;
3570 remaining_bytes -= 128 / CHAR_BIT;5551 remaining_bytes -= 128 / CHAR_BIT;
35715552
3572#if zig_little_endian5553#if zig_big_endian
3573 byte_offset += 128 / CHAR_BIT;5554 byte_offset += 128 / CHAR_BIT;
3574#endif5555#endif
3575 }5556 }
35765557
3577 while (remaining_bytes >= 64 / CHAR_BIT) {5558 while (remaining_bytes >= 64 / CHAR_BIT) {
3578#if zig_big_endian5559 uint8_t limb_bits = UINT8_C(64) - (sign_limb ? top_bits : UINT8_C(0));
5560
5561#if zig_little_endian
3579 byte_offset -= 64 / CHAR_BIT;5562 byte_offset -= 64 / CHAR_BIT;
3580#endif5563#endif
35815564
3582 {5565 {
3583 uint64_t val_limb;5566 uint64_t arg_limb;
35845567
3585 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5568 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3586 total_pc += zig_popcount_u64(val_limb, 64);5569 limb_lz = zig_clz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits);
3587 }5570 }
35885571
5572 total_lz += limb_lz;
5573 if (limb_lz < limb_bits) return total_lz;
5574 sign_limb = false;
3589 remaining_bytes -= 64 / CHAR_BIT;5575 remaining_bytes -= 64 / CHAR_BIT;
35905576
3591#if zig_little_endian5577#if zig_big_endian
3592 byte_offset += 64 / CHAR_BIT;5578 byte_offset += 64 / CHAR_BIT;
3593#endif5579#endif
3594 }5580 }
35955581
3596 while (remaining_bytes >= 32 / CHAR_BIT) {5582 while (remaining_bytes >= 32 / CHAR_BIT) {
3597#if zig_big_endian5583 uint8_t limb_bits = UINT8_C(32) - (sign_limb ? top_bits : UINT8_C(0));
5584
5585#if zig_little_endian
3598 byte_offset -= 32 / CHAR_BIT;5586 byte_offset -= 32 / CHAR_BIT;
3599#endif5587#endif
36005588
3601 {5589 {
3602 uint32_t val_limb;5590 uint32_t arg_limb;
36035591
3604 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5592 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3605 total_pc += zig_popcount_u32(val_limb, 32);5593 limb_lz = zig_clz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits);
3606 }5594 }
36075595
5596 total_lz += limb_lz;
5597 if (limb_lz < limb_bits) return total_lz;
5598 sign_limb = false;
3608 remaining_bytes -= 32 / CHAR_BIT;5599 remaining_bytes -= 32 / CHAR_BIT;
36095600
3610#if zig_little_endian5601#if zig_big_endian
3611 byte_offset += 32 / CHAR_BIT;5602 byte_offset += 32 / CHAR_BIT;
3612#endif5603#endif
3613 }5604 }
36145605
3615 while (remaining_bytes >= 16 / CHAR_BIT) {5606 while (remaining_bytes >= 16 / CHAR_BIT) {
3616#if zig_big_endian5607 uint8_t limb_bits = UINT8_C(16) - (sign_limb ? top_bits : UINT8_C(0));
5608
5609#if zig_little_endian
3617 byte_offset -= 16 / CHAR_BIT;5610 byte_offset -= 16 / CHAR_BIT;
3618#endif5611#endif
36195612
3620 {5613 {
3621 uint16_t val_limb;5614 uint16_t arg_limb;
36225615
3623 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5616 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3624 total_pc = zig_popcount_u16(val_limb, 16);5617 limb_lz = zig_clz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits);
3625 }5618 }
36265619
5620 total_lz += limb_lz;
5621 if (limb_lz < limb_bits) return total_lz;
5622 sign_limb = false;
3627 remaining_bytes -= 16 / CHAR_BIT;5623 remaining_bytes -= 16 / CHAR_BIT;
36285624
3629#if zig_little_endian5625#if zig_big_endian
3630 byte_offset += 16 / CHAR_BIT;5626 byte_offset += 16 / CHAR_BIT;
3631#endif5627#endif
3632 }5628 }
36335629
3634 while (remaining_bytes >= 8 / CHAR_BIT) {5630 while (remaining_bytes >= 8 / CHAR_BIT) {
3635#if zig_big_endian5631 uint8_t limb_bits = UINT8_C(8) - (sign_limb ? top_bits : UINT8_C(0));
5632
5633#if zig_little_endian
3636 byte_offset -= 8 / CHAR_BIT;5634 byte_offset -= 8 / CHAR_BIT;
3637#endif5635#endif
36385636
3639 {5637 {
3640 uint8_t val_limb;5638 uint8_t arg_limb;
36415639
3642 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));5640 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3643 total_pc = zig_popcount_u8(val_limb, 8);5641 limb_lz = zig_clz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits);
3644 }5642 }
36455643
5644 total_lz += limb_lz;
5645 if (limb_lz < limb_bits) return total_lz;
5646 sign_limb = false;
3646 remaining_bytes -= 8 / CHAR_BIT;5647 remaining_bytes -= 8 / CHAR_BIT;
36475648
3648#if zig_little_endian5649#if zig_big_endian
3649 byte_offset += 8 / CHAR_BIT;5650 byte_offset += 8 / CHAR_BIT;
3650#endif5651#endif
3651 }5652 }
36525653
3653 return total_pc;5654 return total_lz;
3654}5655}
36555656
3656/* ========================= Floating Point Support ========================= */5657/* ========================= Floating Point Support ========================= */
...@@ -3687,29 +5688,29 @@ long double __cdecl nanl(char const* input);...@@ -3687,29 +5688,29 @@ long double __cdecl nanl(char const* input);
3687#define zig_make_special_f80(sign, name, arg, repr) sign zig_make_f80 (__builtin_##name, )(arg)5688#define zig_make_special_f80(sign, name, arg, repr) sign zig_make_f80 (__builtin_##name, )(arg)
3688#define zig_make_special_f128(sign, name, arg, repr) sign zig_make_f128(__builtin_##name, )(arg)5689#define zig_make_special_f128(sign, name, arg, repr) sign zig_make_f128(__builtin_##name, )(arg)
3689#else5690#else
3690#define zig_make_special_f16(sign, name, arg, repr) zig_bitCast_f16 (repr)5691#define zig_make_special_f16(sign, name, arg, repr) zig_f16_bitCast_u16 (repr)
3691#define zig_make_special_f32(sign, name, arg, repr) zig_bitCast_f32 (repr)5692#define zig_make_special_f32(sign, name, arg, repr) zig_f32_bitCast_u32 (repr)
3692#define zig_make_special_f64(sign, name, arg, repr) zig_bitCast_f64 (repr)5693#define zig_make_special_f64(sign, name, arg, repr) zig_f64_bitCast_u64 (repr)
3693#define zig_make_special_f80(sign, name, arg, repr) zig_bitCast_f80 (repr)5694#define zig_make_special_f80(sign, name, arg, repr) zig_f80_bitCast_u128(repr)
3694#define zig_make_special_f128(sign, name, arg, repr) zig_bitCast_f128(repr)5695#define zig_make_special_f128(sign, name, arg, repr) zig_f128_bitCast_u128(repr)
3695#endif5696#endif
36965697
3697#define zig_has_f16 15698#define zig_has_f16 1
3698#define zig_libc_name_f16(name) __##name##h5699#define zig_libc_name_f16(name) __##name##h
3699#define zig_init_special_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr)5700#define zig_init_special_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr)
3700#if FLT_MANT_DIG == 115701#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT_MANT_DIG == 11
3701typedef float zig_f16;5702typedef float zig_f16;
3702#define zig_make_f16(fp, repr) fp##f5703#define zig_make_f16(fp, repr) fp##f
3703#elif DBL_MANT_DIG == 115704#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && DBL_MANT_DIG == 11
3704typedef double zig_f16;5705typedef double zig_f16;
3705#define zig_make_f16(fp, repr) fp5706#define zig_make_f16(fp, repr) fp
3706#elif LDBL_MANT_DIG == 115707#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && LDBL_MANT_DIG == 11
3707typedef long double zig_f16;5708typedef long double zig_f16;
3708#define zig_make_f16(fp, repr) fp##l5709#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))
3710typedef _Float16 zig_f16;5711typedef _Float16 zig_f16;
3711#define zig_make_f16(fp, repr) fp##f165712#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__)
3713typedef __fp16 zig_f16;5714typedef __fp16 zig_f16;
3714#define zig_make_f16(fp, repr) fp##f165715#define zig_make_f16(fp, repr) fp##f16
3715#else5716#else
...@@ -3723,11 +5724,6 @@ typedef uint16_t zig_f16;...@@ -3723,11 +5724,6 @@ typedef uint16_t zig_f16;
3723#undef zig_init_special_f165724#undef zig_init_special_f16
3724#define zig_init_special_f16(sign, name, arg, repr) repr5725#define zig_init_special_f16(sign, name, arg, repr) repr
3725#endif5726#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
3732#define zig_has_f32 15728#define zig_has_f32 1
3733#define zig_libc_name_f32(name) name##f5729#define zig_libc_name_f32(name) name##f
...@@ -3736,16 +5732,16 @@ typedef zig_f16 zig_compiler_rt_f16;...@@ -3736,16 +5732,16 @@ typedef zig_f16 zig_compiler_rt_f16;
3736#else5732#else
3737#define zig_init_special_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr)5733#define zig_init_special_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr)
3738#endif5734#endif
3739#if FLT_MANT_DIG == 245735#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT_MANT_DIG == 24
3740typedef float zig_f32;5736typedef float zig_f32;
3741#define zig_make_f32(fp, repr) fp##f5737#define zig_make_f32(fp, repr) fp##f
3742#elif DBL_MANT_DIG == 245738#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && DBL_MANT_DIG == 24
3743typedef double zig_f32;5739typedef double zig_f32;
3744#define zig_make_f32(fp, repr) fp5740#define zig_make_f32(fp, repr) fp
3745#elif LDBL_MANT_DIG == 245741#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && LDBL_MANT_DIG == 24
3746typedef long double zig_f32;5742typedef long double zig_f32;
3747#define zig_make_f32(fp, repr) fp##l5743#define zig_make_f32(fp, repr) fp##l
3748#elif FLT32_MANT_DIG == 245744#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT32_MANT_DIG == 24
3749typedef _Float32 zig_f32;5745typedef _Float32 zig_f32;
3750#define zig_make_f32(fp, repr) fp##f325746#define zig_make_f32(fp, repr) fp##f32
3751#else5747#else
...@@ -3768,19 +5764,19 @@ typedef uint32_t zig_f32;...@@ -3768,19 +5764,19 @@ typedef uint32_t zig_f32;
3768#else5764#else
3769#define zig_init_special_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr)5765#define zig_init_special_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr)
3770#endif5766#endif
3771#if FLT_MANT_DIG == 535767#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT_MANT_DIG == 53
3772typedef float zig_f64;5768typedef float zig_f64;
3773#define zig_make_f64(fp, repr) fp##f5769#define zig_make_f64(fp, repr) fp##f
3774#elif DBL_MANT_DIG == 535770#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && DBL_MANT_DIG == 53
3775typedef double zig_f64;5771typedef double zig_f64;
3776#define zig_make_f64(fp, repr) fp5772#define zig_make_f64(fp, repr) fp
3777#elif LDBL_MANT_DIG == 535773#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && LDBL_MANT_DIG == 53
3778typedef long double zig_f64;5774typedef long double zig_f64;
3779#define zig_make_f64(fp, repr) fp##l5775#define zig_make_f64(fp, repr) fp##l
3780#elif FLT64_MANT_DIG == 535776#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT64_MANT_DIG == 53
3781typedef _Float64 zig_f64;5777typedef _Float64 zig_f64;
3782#define zig_make_f64(fp, repr) fp##f645778#define zig_make_f64(fp, repr) fp##f64
3783#elif FLT32X_MANT_DIG == 535779#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT32X_MANT_DIG == 53
3784typedef _Float32x zig_f64;5780typedef _Float32x zig_f64;
3785#define zig_make_f64(fp, repr) fp##f32x5781#define zig_make_f64(fp, repr) fp##f32x
3786#else5782#else
...@@ -3798,7 +5794,14 @@ typedef uint64_t zig_f64;...@@ -3798,7 +5794,14 @@ typedef uint64_t zig_f64;
3798#define zig_has_f80 15794#define zig_has_f80 1
3799#define zig_libc_name_f80(name) __##name##x5795#define zig_libc_name_f80(name) __##name##x
3800#define zig_init_special_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr)5796#define zig_init_special_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr)
3801#if FLT_MANT_DIG == 645797#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
3802typedef float zig_f80;5805typedef float zig_f80;
3803#define zig_make_f80(fp, repr) fp##f5806#define zig_make_f80(fp, repr) fp##f
3804#elif DBL_MANT_DIG == 645807#elif DBL_MANT_DIG == 64
...@@ -3818,68 +5821,91 @@ typedef __float80 zig_f80;...@@ -3818,68 +5821,91 @@ typedef __float80 zig_f80;
3818#define zig_make_f80(fp, repr) fp##l5821#define zig_make_f80(fp, repr) fp##l
3819#else5822#else
3820#undef zig_has_f805823#undef zig_has_f80
3821#define zig_has_f80 0
3822#define zig_repr_f80 u128
3823typedef zig_u128 zig_f80;5824typedef 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
3824#define zig_make_f80(fp, repr) repr5832#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
3825#undef zig_make_special_f805836#undef zig_make_special_f80
3826#define zig_make_special_f80(sign, name, arg, repr) repr5837#define zig_make_special_f80(sign, name, arg, repr) repr
3827#undef zig_init_special_f805838#undef zig_init_special_f80
3828#define zig_init_special_f80(sign, name, arg, repr) repr5839#define zig_init_special_f80(sign, name, arg, repr) repr
3829#endif5840#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
3837#define zig_has_f128 15842#define zig_has_f128 1
3838#define zig_libc_name_f128(name) name##q5843#define zig_libc_name_f128(name) name##f128
3839#define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr)5844#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 == 1135845#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
3841typedef float zig_f128;5856typedef float zig_f128;
3842#define zig_make_f128(fp, repr) fp##f5857#define zig_make_f128(fp, repr) fp##f
3843#elif !zig_f128_has_miscompilations && DBL_MANT_DIG == 1135858#elif DBL_MANT_DIG == 113
3844typedef double zig_f128;5859typedef double zig_f128;
3845#define zig_make_f128(fp, repr) fp5860#define zig_make_f128(fp, repr) fp
3846#elif !zig_f128_has_miscompilations && LDBL_MANT_DIG == 1135861#elif LDBL_MANT_DIG == 113
3847typedef long double zig_f128;5862typedef long double zig_f128;
3848#define zig_make_f128(fp, repr) fp##l5863#define zig_make_f128(fp, repr) fp##l
3849#elif !zig_f128_has_miscompilations && FLT128_MANT_DIG == 1135864#elif FLT128_MANT_DIG == 113
3850typedef _Float128 zig_f128;5865typedef _Float128 zig_f128;
3851#define zig_make_f128(fp, repr) fp##f1285866#define zig_make_f128(fp, repr) fp##f128
3852#elif !zig_f128_has_miscompilations && FLT64X_MANT_DIG == 1135867#elif FLT64X_MANT_DIG == 113
3853typedef _Float64x zig_f128;5868typedef _Float64x zig_f128;
3854#define zig_make_f128(fp, repr) fp##f64x5869#define zig_make_f128(fp, repr) fp##f64x
3855#elif !zig_f128_has_miscompilations && defined(__SIZEOF_FLOAT128__)5870#elif defined(__SIZEOF_FLOAT128__)
3856typedef __float128 zig_f128;5871typedef __float128 zig_f128;
3857#define zig_make_f128(fp, repr) fp##q5872#define zig_make_f128(fp, repr) fp##q
3858#undef zig_make_special_f1285873#undef zig_make_special_f128
3859#define zig_make_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg)5874#define zig_make_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg)
3860#else5875#else
3861#undef zig_has_f1285876#undef zig_has_f128
3862#define zig_has_f128 05877#if defined(zig_x86_64) && defined(ZIG_TARGET_ABI_MSVC)
3863#undef zig_make_special_f1285878#if defined(zig_msvc) && !defined(__clang__)
3864#undef zig_init_special_f1285879#include <emmintrin.h>
3865#if defined(zig_darwin) || defined(zig_aarch64)5880typedef __m128i zig_f128;
3866typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_v2u64;5881#define zig_init_repr_f128(hi, lo) { .m128i_u64 = { lo, hi } }
3867zig_basic_operator(zig_v2u64, xor_v2u64, ^)5882#define zig_lo_repr_f128(arg) (arg).m128i_u64[0]
3868#define zig_repr_f128 v2u645883#define zig_hi_repr_f128(arg) (arg).m128i_u64[1]
3869typedef zig_v2u64 zig_f128;5884#else
3870#define zig_make_f128_zig_make_u128(hi, lo) (zig_f128){ lo, hi }5885typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_f128;
3871#define zig_make_f128_zig_init_u128 zig_make_f128_zig_make_u1285886#define zig_init_repr_f128(hi, lo) { lo, hi }
3872#define zig_make_f128(fp, repr) zig_make_f128_##repr5887#define zig_lo_repr_f128(arg) (arg)[0]
3873#define zig_make_special_f128(sign, name, arg, repr) zig_make_f128_##repr5888#define zig_hi_repr_f128(arg) (arg)[1]
3874#define zig_init_special_f128(sign, name, arg, repr) zig_make_f128_##repr5889#endif
3875#else5890#else
3876#define zig_repr_f128 u128
3877typedef zig_u128 zig_f128;5891typedef 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
3878#define zig_make_f128(fp, repr) repr5900#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
3879#define zig_make_special_f128(sign, name, arg, repr) repr5905#define zig_make_special_f128(sign, name, arg, repr) repr
5906#undef zig_init_special_f128
3880#define zig_init_special_f128(sign, name, arg, repr) repr5907#define zig_init_special_f128(sign, name, arg, repr) repr
3881#endif5908#endif
3882#endif
38835909
3884#if !defined(zig_msvc) && defined(ZIG_TARGET_ABI_MSVC)5910#if !defined(zig_msvc) && defined(ZIG_TARGET_ABI_MSVC)
3885/* Emulate msvc abi on a gnu compiler */5911/* Emulate msvc abi on a gnu compiler */
...@@ -3892,84 +5918,141 @@ typedef zig_f128 zig_c_longdouble;...@@ -3892,84 +5918,141 @@ typedef zig_f128 zig_c_longdouble;
3892typedef long double zig_c_longdouble;5918typedef long double zig_c_longdouble;
3893#endif5919#endif
38945920
3895#define zig_bitCast_float(Type, ReprType) \5921#if __AVR__
3896 static inline zig_##Type zig_bitCast_##Type(ReprType repr) { \5922typedef signed char zig_FloatCompareResult;
3897 zig_##Type result; \5923#elif defined(zig_aarch64)
3898 memcpy(&result, &repr, sizeof(result)); \5924typedef signed int zig_FloatCompareResult;
3899 return result; \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); \
3900 }5951 }
3901zig_bitCast_float(f16, uint16_t)5952zig_bitCast_float(16, 16, uint16_t, int16_t)
3902zig_bitCast_float(f32, uint32_t)5953zig_bitCast_float(32, 32, uint32_t, int32_t)
3903zig_bitCast_float(f64, uint64_t)5954zig_bitCast_float(64, 64, uint64_t, int64_t)
3904zig_bitCast_float(f80, zig_u128)5955#if zig_has_f80
3905zig_bitCast_float(f128, zig_u128)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) \5998#define zig_convert_float_00(ResType, operation, ArgType, version) \
3908 zig_extern ExternResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \5999 zig_extern ResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
3909 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ExternArgType); \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) \
3910 static inline ResType zig_expand_concat(zig_expand_concat(zig_##operation, \6010 static inline ResType zig_expand_concat(zig_expand_concat(zig_##operation, \
3911 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType)(ArgType arg) { \6011 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType)(ArgType arg) { \
3912 ResType res; \6012 zig_expand_concat(zig_expand_concat(zig_convert_float_, zig_has_##res_when), \
3913 ExternResType extern_res; \6013 zig_has_##arg_when)(ResType, operation, ArgType, version); \
3914 ExternArgType extern_arg; \6014 }
3915 memcpy(&extern_arg, &arg, sizeof(extern_arg)); \6015
3916 extern_res = zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \6016#define zig_convert_floats(SmallType, BigType) \
3917 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(extern_arg); \6017 zig_convert_float(SmallType, zig_##SmallType, trunc, BigType, zig_##BigType, 2) \
3918 memcpy(&res, &extern_res, sizeof(res)); \6018 zig_convert_float(BigType, zig_##BigType, extend, SmallType, zig_##SmallType, 2)
3919 return extern_res; \6019zig_convert_floats(f16, f32)
3920 }6020zig_convert_floats(f16, f64)
3921zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f32, zig_f32, 2)6021zig_convert_floats(f16, f80)
3922zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f64, zig_f64, 2)6022zig_convert_floats(f16, f128)
3923zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f80, zig_f80, 2)6023zig_convert_floats(f32, f64)
3924zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f128, zig_f128, 2)6024zig_convert_floats(f32, f80)
3925zig_convert_builtin(zig_f32, zig_f32, extend, zig_compiler_rt_f16, zig_f16, 2)6025zig_convert_floats(f32, f128)
3926zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f80, zig_f80, 2)6026zig_convert_floats(f64, f80)
3927zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f128, zig_f128, 2)6027zig_convert_floats(f64, f128)
3928zig_convert_builtin(zig_f64, zig_f64, extend, zig_compiler_rt_f16, zig_f16, 2)6028zig_convert_floats(f80, f128)
3929zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f80, zig_f80, 2)6029
3930zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f128, zig_f128, 2)6030#define zig_float_negate_builtin_0(w, sb) \
3931zig_convert_builtin(zig_f80, zig_f80, extend, zig_f16, zig_f16, 2)6031 zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, sb))
3932zig_convert_builtin(zig_f80, zig_f80, extend, zig_f32, zig_f32, 2)6032#define zig_float_negate_builtin_1(w, sb) -arg
3933zig_convert_builtin(zig_f80, zig_f80, extend, zig_f64, zig_f64, 2)6033#define zig_float_negate_builtin(w, sb) \
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) \
3959 static inline zig_f##w zig_neg_f##w(zig_f##w arg) { \6034 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); \
3961 }6036 }
3962zig_float_negate_builtin(16, , UINT16_C(1) << 15 )6037zig_float_negate_builtin(16, UINT16_C(1) << 15)
3963zig_float_negate_builtin(32, , UINT32_C(1) << 31 )6038zig_float_negate_builtin(32, UINT32_C(1) << 31)
3964zig_float_negate_builtin(64, , UINT64_C(1) << 63 )6039zig_float_negate_builtin(64, UINT64_C(1) << 63)
3965zig_float_negate_builtin(80, zig_make_u128, (UINT64_C(1) << 15, UINT64_C(0)))6040
3966zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))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
3968#define zig_float_less_builtin_0(Type, operation) \6051#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, \
3970 zig_compiler_rt_abbrev_zig_##Type), 2)(zig_##Type, zig_##Type); \6053 zig_compiler_rt_abbrev_zig_##Type), 2)(zig_##Type, zig_##Type); \
3971 static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \6054 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); \
3973 }6056 }
3974#define zig_float_less_builtin_1(Type, operation) \6057#define zig_float_less_builtin_1(Type, operation) \
3975 static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \6058 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)))...@@ -3994,13 +6077,52 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))
3994 return lhs operator rhs; \6077 return lhs operator rhs; \
3995 }6078 }
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, )
3997#define zig_common_float_builtins(w) \6084#define zig_common_float_builtins(w) \
3998 zig_convert_builtin( int64_t, int64_t, fix, zig_f##w, zig_f##w, ) \6085 zig_convert_float(always, int32_t, fix, f##w, zig_f##w, ) \
3999 zig_convert_builtin(zig_i128, zig_i128, fix, zig_f##w, zig_f##w, ) \6086 zig_convert_float(always, int64_t, fix, f##w, zig_f##w, ) \
4000 zig_convert_builtin(zig_u128, zig_u128, fixuns, zig_f##w, zig_f##w, ) \6087 zig_convert_float(int128, zig_i128, fix, f##w, zig_f##w, ) \
4001 zig_convert_builtin(zig_f##w, zig_f##w, float, int64_t, int64_t, ) \6088 zig_convert_float(always, uint32_t, fixuns, f##w, zig_f##w, ) \
4002 zig_convert_builtin(zig_f##w, zig_f##w, float, zig_i128, zig_i128, ) \6089 zig_convert_float(always, uint64_t, fixuns, f##w, zig_f##w, ) \
4003 zig_convert_builtin(zig_f##w, zig_f##w, floatun, zig_u128, zig_u128, ) \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\
4004 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, cmp) \6126 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, cmp) \
4005 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, ne) \6127 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, ne) \
4006 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, eq) \6128 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)))...@@ -4031,82 +6153,48 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))
4031 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)) \6153 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)) \
4032 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)) \6154 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)) \
4033\6155\
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) { \
4035 return zig_trunc_f##w(zig_div_f##w(lhs, rhs)); \6157 return zig_trunc_f##w(zig_div_f##w(lhs, rhs)); \
4036 } \6158 } \
4037\6159\
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) { \
4039 return zig_floor_f##w(zig_div_f##w(lhs, rhs)); \6161 return zig_floor_f##w(zig_div_f##w(lhs, rhs)); \
4040 } \6162 } \
4041\6163\
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) { \
4043 return zig_ceil_f##w(zig_div_f##w(lhs, rhs)); \6165 return zig_ceil_f##w(zig_div_f##w(lhs, rhs)); \
4044 } \6166 } \
4045\6167\
4046 static inline zig_f##w zig_mod_f##w(zig_f##w lhs, zig_f##w rhs) { \6168 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)); \
4048 }6170 }
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, )
4062zig_float_builtins(16)6171zig_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
4106zig_float_builtins(32)6172zig_float_builtins(32)
4107zig_float_builtins(64)6173zig_float_builtins(64)
41086174zig_float_builtins(80)
4109#endif /* __ARM_EABI__ */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
4111/* ============================ Atomics Support ============================= */6199/* ============================ Atomics Support ============================= */
41126200
...@@ -4410,19 +6498,19 @@ typedef int zig_memory_order;...@@ -4410,19 +6498,19 @@ typedef int zig_memory_order;
4410 } \6498 } \
4411 static inline void zig_msvc_atomic_store_##ZigType(Type volatile* obj, Type value) { \6499 static inline void zig_msvc_atomic_store_##ZigType(Type volatile* obj, Type value) { \
4412 (void)_InterlockedExchange##suffix((SigType volatile*)obj, (SigType)value); \6500 (void)_InterlockedExchange##suffix((SigType volatile*)obj, (SigType)value); \
4413 } \6501 } \
4414 static inline Type zig_msvc_atomic_load_zig_memory_order_relaxed_##ZigType(Type volatile* obj) { \6502 static inline Type zig_msvc_atomic_load_zig_memory_order_relaxed_##ZigType(Type volatile* obj) { \
4415 return __iso_volatile_load##iso_suffix((SigType volatile*)obj); \6503 return __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
4416 } \6504 } \
4417 static inline Type zig_msvc_atomic_load_zig_memory_order_acquire_##ZigType(Type volatile* obj) { \6505 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); \
4419 _ReadWriteBarrier(); \6507 _ReadWriteBarrier(); \
4420 return val; \6508 return value; \
4421 } \6509 } \
4422 static inline Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##ZigType(Type volatile* obj) { \6510 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); \
4424 _ReadWriteBarrier(); \6512 _ReadWriteBarrier(); \
4425 return val; \6513 return value; \
4426 }6514 }
44276515
4428zig_msvc_atomics( u8, uint8_t, char, 8, 8)6516zig_msvc_atomics( u8, uint8_t, char, 8, 8)
...@@ -4465,14 +6553,14 @@ zig_msvc_atomics(i64, int64_t, __int64, 64, 64)...@@ -4465,14 +6553,14 @@ zig_msvc_atomics(i64, int64_t, __int64, 64, 64)
4465 zig_##Type result; \6553 zig_##Type result; \
4466 SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \6554 SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
4467 _ReadWriteBarrier(); \6555 _ReadWriteBarrier(); \
4468 memcpy(&result, &initial, sizeof(result)); \6556 memcpy(&result, &initial, sizeof(result)); \
4469 return result; \6557 return result; \
4470 } \6558 } \
4471 static inline zig_##Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##Type(zig_##Type volatile* obj) { \6559 static inline zig_##Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##Type(zig_##Type volatile* obj) { \
4472 zig_##Type result; \6560 zig_##Type result; \
4473 SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \6561 SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
4474 _ReadWriteBarrier(); \6562 _ReadWriteBarrier(); \
4475 memcpy(&result, &initial, sizeof(result)); \6563 memcpy(&result, &initial, sizeof(result)); \
4476 return result; \6564 return result; \
4477 }6565 }
44786566
...@@ -4502,9 +6590,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p32(void volat...@@ -4502,9 +6590,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p32(void volat
4502}6590}
45036591
4504static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p32(void volatile* obj) {6592static 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);
4506 _ReadWriteBarrier();6594 _ReadWriteBarrier();
4507 return val;6595 return value;
4508}6596}
45096597
4510static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p32(void volatile* obj) {6598static 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...@@ -4532,9 +6620,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p64(void volat
4532}6620}
45336621
4534static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p64(void volatile* obj) {6622static 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);
4536 _ReadWriteBarrier();6624 _ReadWriteBarrier();
4537 return val;6625 return value;
4538}6626}
45396627
4540static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p64(void volatile* obj) {6628static 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" {...@@ -144,7 +144,6 @@ test "@abs big int <= 128 bits" {
144 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO144 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
145 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO145 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
146 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO146 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
147 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
148147
149 try comptime testAbsSignedBigInt();148 try comptime testAbsSignedBigInt();
150 try testAbsSignedBigInt();149 try testAbsSignedBigInt();
...@@ -256,7 +255,6 @@ fn testAbsFloats(comptime T: type) !void {...@@ -256,7 +255,6 @@ fn testAbsFloats(comptime T: type) !void {
256255
257test "@abs int vectors" {256test "@abs int vectors" {
258 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;257 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
259 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
260 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO258 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
261 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO259 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
262 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;260 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" {...@@ -129,8 +129,7 @@ test "alignment and size of structs with 128-bit fields" {
129 y: u8,129 y: u8,
130 };130 };
131 const expected = switch (builtin.cpu.arch) {131 const expected = switch (builtin.cpu.arch) {
132 .s390x,132 .s390x => .{
133 => .{
134 .a_align = 8,133 .a_align = 8,
135 .a_size = 16,134 .a_size = 16,
136135
...@@ -142,7 +141,32 @@ test "alignment and size of structs with 128-bit fields" {...@@ -142,7 +141,32 @@ test "alignment and size of structs with 128-bit fields" {
142 .u129_align = 8,141 .u129_align = 8,
143 .u129_size = 24,142 .u129_size = 24,
144 },143 },
145144 .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 },
146 .amdgcn,170 .amdgcn,
147 .arm,171 .arm,
148 .armeb,172 .armeb,
...@@ -155,12 +179,13 @@ test "alignment and size of structs with 128-bit fields" {...@@ -155,12 +179,13 @@ test "alignment and size of structs with 128-bit fields" {
155 .powerpc,179 .powerpc,
156 .powerpcle,180 .powerpcle,
157 .riscv32,181 .riscv32,
182 .sparc,
158 => .{183 => .{
159 .a_align = 8,184 .a_align = 8,
160 .a_size = 16,185 .a_size = 16,
161186
162 .b_align = 16,187 .b_align = 8,
163 .b_size = 32,188 .b_size = 24,
164189
165 .u128_align = 8,190 .u128_align = 8,
166 .u128_size = 16,191 .u128_size = 16,
...@@ -178,12 +203,10 @@ test "alignment and size of structs with 128-bit fields" {...@@ -178,12 +203,10 @@ test "alignment and size of structs with 128-bit fields" {
178 .nvptx64,203 .nvptx64,
179 .powerpc64,204 .powerpc64,
180 .powerpc64le,205 .powerpc64le,
181 .sparc,
182 .sparc64,206 .sparc64,
183 .riscv64,207 .riscv64,
184 .wasm32,208 .wasm32,
185 .wasm64,209 .wasm64,
186 .x86,
187 .x86_64,210 .x86_64,
188 => .{211 => .{
189 .a_align = 16,212 .a_align = 16,
...@@ -200,12 +223,11 @@ test "alignment and size of structs with 128-bit fields" {...@@ -200,12 +223,11 @@ test "alignment and size of structs with 128-bit fields" {
200223
201 else => return error.SkipZigTest,224 else => return error.SkipZigTest,
202 };225 };
203 const min_struct_align = if (builtin.zig_backend == .stage2_c) if (builtin.cpu.arch == .s390x) 8 else 16 else 0;
204 comptime {226 comptime {
205 assert(@alignOf(A) == @max(expected.a_align, min_struct_align));227 assert(@alignOf(A) == expected.a_align);
206 assert(@sizeOf(A) == expected.a_size);228 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);
209 assert(@sizeOf(B) == expected.b_size);231 assert(@sizeOf(B) == expected.b_size);
210232
211 assert(@alignOf(u128) == expected.u128_align);233 assert(@alignOf(u128) == expected.u128_align);
...@@ -547,8 +569,6 @@ test "sub-aligned pointer field access" {...@@ -547,8 +569,6 @@ test "sub-aligned pointer field access" {
547}569}
548570
549test "alignment of zero-bit types is respected" {571test "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;
552 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;572 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
553 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO573 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" {...@@ -582,7 +602,6 @@ test "zero-bit fields in extern struct pad fields appropriately" {
582 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;602 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
583 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;603 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
584 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;604 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
585 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
586605
587 const S = extern struct {606 const S = extern struct {
588 x: u8,607 x: u8,
test/behavior/basic.zig-3
...@@ -797,10 +797,8 @@ test "auto created variables have correct alignment" {...@@ -797,10 +797,8 @@ test "auto created variables have correct alignment" {
797}797}
798798
799test "extern variable with non-pointer opaque type" {799test "extern variable with non-pointer opaque type" {
800 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
801 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO800 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
802 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO801 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
803 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
804 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO802 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
805803
806 @export(&var_to_export, .{ .name = "opaque_extern_var" });804 @export(&var_to_export, .{ .name = "opaque_extern_var" });
...@@ -1398,7 +1396,6 @@ test "allocation and looping over 3-byte integer" {...@@ -1398,7 +1396,6 @@ test "allocation and looping over 3-byte integer" {
1398 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1396 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1399 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1397 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1400 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1398 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
1403 try expect(@sizeOf(u24) == 4);1400 try expect(@sizeOf(u24) == 4);
1404 try expect(@sizeOf([1]u24) == 4);1401 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" {...@@ -147,7 +147,6 @@ test "Saturating Shift Left where lhs is of a computed type" {
147147
148test "Saturating Shift Left" {148test "Saturating Shift Left" {
149 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;149 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
150 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
151 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;150 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
152 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;151 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
153 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;152 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...@@ -210,7 +210,6 @@ test "triple level result location with bitcast sandwich passed as tuple element
210210
211test "@bitCast packed struct of floats" {211test "@bitCast packed struct of floats" {
212 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;212 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
213 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
214 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;213 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
215 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO214 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
216 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;215 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -247,7 +246,6 @@ test "@bitCast packed struct of floats" {...@@ -247,7 +246,6 @@ test "@bitCast packed struct of floats" {
247246
248test "comptime @bitCast packed struct to int and back" {247test "comptime @bitCast packed struct to int and back" {
249 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;248 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
250 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
251 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;249 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
252 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO250 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
253 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;251 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -283,7 +281,6 @@ test "comptime @bitCast packed struct to int and back" {...@@ -283,7 +281,6 @@ test "comptime @bitCast packed struct to int and back" {
283test "bitcast vector to integer and back" {281test "bitcast vector to integer and back" {
284 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;282 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
285 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO283 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
286 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
287 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;284 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
288 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;285 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
289286
...@@ -329,10 +326,10 @@ fn bitCastWrapper128(x: f128) u128 {...@@ -329,10 +326,10 @@ fn bitCastWrapper128(x: f128) u128 {
329}326}
330test "bitcast nan float does not modify signaling bit" {327test "bitcast nan float does not modify signaling bit" {
331 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO328 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
332 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
333 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;329 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
334 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;330 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
335 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;331 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
337 const snan_u16: u16 = 0x7D00;334 const snan_u16: u16 = 0x7D00;
338 const snan_u32: u32 = 0x7FA00000;335 const snan_u32: u32 = 0x7FA00000;
...@@ -383,7 +380,6 @@ test "bitcast nan float does not modify signaling bit" {...@@ -383,7 +380,6 @@ test "bitcast nan float does not modify signaling bit" {
383test "@bitCast of packed struct of bools all true" {380test "@bitCast of packed struct of bools all true" {
384 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;381 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
385 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO382 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
386 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
387 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO383 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
388 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO384 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
389385
...@@ -404,7 +400,6 @@ test "@bitCast of packed struct of bools all true" {...@@ -404,7 +400,6 @@ test "@bitCast of packed struct of bools all true" {
404test "@bitCast of packed struct of bools all false" {400test "@bitCast of packed struct of bools all false" {
405 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;401 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
406 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO402 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
407 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
408 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO403 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
409404
410 const P = packed struct {405 const P = packed struct {
...@@ -437,6 +432,22 @@ test "@bitCast of packed struct with void field to integer" {...@@ -437,6 +432,22 @@ test "@bitCast of packed struct with void field to integer" {
437 try comptime S.doTheTest(123);432 try comptime S.doTheTest(123);
438}433}
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
440test "@bitCast vector to array with different element size" {451test "@bitCast vector to array with different element size" {
441 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;452 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;...@@ -6,7 +6,6 @@ var x: u8 = 1;
66
7// This excludes builtin functions that return void or noreturn that cannot be tested.7// This excludes builtin functions that return void or noreturn that cannot be tested.
8test {8test {
9 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;11 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/call.zig-1
...@@ -21,7 +21,6 @@ test "super basic invocations" {...@@ -21,7 +21,6 @@ test "super basic invocations" {
2121
22test "basic invocations" {22test "basic invocations" {
23 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;23 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
24 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
25 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO24 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
26 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO25 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
27 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;26 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/cast.zig+7-19
...@@ -120,6 +120,7 @@ test "@floatFromInt" {...@@ -120,6 +120,7 @@ test "@floatFromInt" {
120 try expect(@as(i32, @floor(f)) == k);120 try expect(@as(i32, @floor(f)) == k);
121 try expect(@as(i32, @ceil(f)) == k);121 try expect(@as(i32, @ceil(f)) == k);
122 try expect(@as(i32, @trunc(f)) == k);122 try expect(@as(i32, @trunc(f)) == k);
123 try expect(@as(i32, @trunc(@floor(f))) == k);
123 }124 }
124 };125 };
125 try S.doTheTest();126 try S.doTheTest();
...@@ -134,7 +135,6 @@ test "@intFromFloat > 128 bits" {...@@ -134,7 +135,6 @@ test "@intFromFloat > 128 bits" {
134 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;135 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
135 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;136 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
136 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;137 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
137 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
138138
139 try testIntFromFloat(f16, 1024, u140, 1024);139 try testIntFromFloat(f16, 1024, u140, 1024);
140 try testIntFromFloat(f16, -1024, i140, -1024);140 try testIntFromFloat(f16, -1024, i140, -1024);
...@@ -160,7 +160,6 @@ test "@floatFromInt > 128 bits" {...@@ -160,7 +160,6 @@ test "@floatFromInt > 128 bits" {
160 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;160 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
161 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;161 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
162 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;162 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
163 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
164163
165 try testFloatFromInt(u140, 1024, f16, 1024);164 try testFloatFromInt(u140, 1024, f16, 1024);
166 try testFloatFromInt(i140, -1024, f16, -1024);165 try testFloatFromInt(i140, -1024, f16, -1024);
...@@ -182,8 +181,8 @@ test "@floatFromInt(f80)" {...@@ -182,8 +181,8 @@ test "@floatFromInt(f80)" {
182 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO181 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
183 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO182 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
184 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;183 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
185 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
186 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;184 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
185 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
187186
188 const S = struct {187 const S = struct {
189 fn doTheTest(comptime Int: type) !void {188 fn doTheTest(comptime Int: type) !void {
...@@ -199,6 +198,7 @@ test "@floatFromInt(f80)" {...@@ -199,6 +198,7 @@ test "@floatFromInt(f80)" {
199 try expect(@as(Int, @floor(f)) == k);198 try expect(@as(Int, @floor(f)) == k);
200 try expect(@as(Int, @ceil(f)) == k);199 try expect(@as(Int, @ceil(f)) == k);
201 try expect(@as(Int, @trunc(f)) == k);200 try expect(@as(Int, @trunc(f)) == k);
201 try expect(@as(Int, @trunc(@floor(f))) == k);
202 }202 }
203 };203 };
204 try S.doTheTest(i31);204 try S.doTheTest(i31);
...@@ -207,7 +207,7 @@ test "@floatFromInt(f80)" {...@@ -207,7 +207,7 @@ test "@floatFromInt(f80)" {
207 try S.doTheTest(i64);207 try S.doTheTest(i64);
208 try S.doTheTest(i80);208 try S.doTheTest(i80);
209 try S.doTheTest(i128);209 try S.doTheTest(i128);
210 // try S.doTheTest(i256); // TODO missing compiler_rt symbols210 try S.doTheTest(i256);
211 try comptime S.doTheTest(i31);211 try comptime S.doTheTest(i31);
212 try comptime S.doTheTest(i32);212 try comptime S.doTheTest(i32);
213 try comptime S.doTheTest(i45);213 try comptime S.doTheTest(i45);
...@@ -281,6 +281,7 @@ test "type coercion from int to float" {...@@ -281,6 +281,7 @@ test "type coercion from int to float" {
281test "@intFromFloat" {281test "@intFromFloat" {
282 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO282 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
283 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO283 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
284
284 try testIntFromFloats();285 try testIntFromFloats();
285 try comptime testIntFromFloats();286 try comptime testIntFromFloats();
286}287}
...@@ -498,7 +499,7 @@ test "array coercion to undefined at runtime" {...@@ -498,7 +499,7 @@ test "array coercion to undefined at runtime" {
498499
499 @setRuntimeSafety(true);500 @setRuntimeSafety(true);
500501
501 if (builtin.mode != .Debug and builtin.mode != .ReleaseSafe) {502 if (builtin.mode != .debug and builtin.mode != .safe) {
502 return error.SkipZigTest;503 return error.SkipZigTest;
503 }504 }
504505
...@@ -1473,11 +1474,6 @@ fn foobar(func: PFN_void) !void {...@@ -1473,11 +1474,6 @@ fn foobar(func: PFN_void) !void {
1473test "cast function with an opaque parameter" {1474test "cast function with an opaque parameter" {
1474 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1475 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
1481 const Container = struct {1477 const Container = struct {
1482 const Ctx = opaque {};1478 const Ctx = opaque {};
1483 ctx: *Ctx,1479 ctx: *Ctx,
...@@ -1724,9 +1720,7 @@ test "cast f16 to wider types" {...@@ -1724,9 +1720,7 @@ test "cast f16 to wider types" {
1724 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1720 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1725 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1721 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1726 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1722 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1727 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
1728 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1723 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
1731 const S = struct {1725 const S = struct {
1732 fn doTheTest() !void {1726 fn doTheTest() !void {
...@@ -1831,21 +1825,15 @@ test "pointer to empty struct literal to mutable slice" {...@@ -1831,21 +1825,15 @@ test "pointer to empty struct literal to mutable slice" {
18311825
1832test "coerce between pointers of compatible differently-named floats" {1826test "coerce between pointers of compatible differently-named floats" {
1833 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1827 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;
1835 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1828 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1836 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1829 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1837 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1830 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
1844 const F = switch (@typeInfo(c_longdouble).float.bits) {1832 const F = switch (@typeInfo(c_longdouble).float.bits) {
1845 64 => f64,1833 64 => f64,
1846 80 => f80,1834 80 => f80,
1847 128 => f128,1835 128 => f128,
1848 else => @compileError("unreachable"),1836 else => comptime unreachable,
1849 };1837 };
1850 var f1: F = 12.34;1838 var f1: F = 12.34;
1851 const f2: *c_longdouble = &f1;1839 const f2: *c_longdouble = &f1;
test/behavior/cast_int.zig-1
...@@ -168,7 +168,6 @@ test "@intCast <= 64 bits" {...@@ -168,7 +168,6 @@ test "@intCast <= 64 bits" {
168168
169test "@intCast > 128 bits" {169test "@intCast > 128 bits" {
170 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;170 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
171 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
172 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;171 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
173172
174 try testIntCast(u8, 123, u140, 123);173 try testIntCast(u8, 123, u140, 123);
test/behavior/eval.zig-1
...@@ -513,7 +513,6 @@ test "runtime 128 bit integer division" {...@@ -513,7 +513,6 @@ test "runtime 128 bit integer division" {
513 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO513 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
514 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO514 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
515 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;515 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
516 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
517 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;516 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
518517
519 var a: u128 = 152313999999999991610955792383;518 var a: u128 = 152313999999999991610955792383;
test/behavior/export_builtin.zig-15
...@@ -5,11 +5,6 @@ const expect = std.testing.expect;...@@ -5,11 +5,6 @@ const expect = std.testing.expect;
5test "exporting enum value" {5test "exporting enum value" {
6 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;6 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
13 const S = struct {8 const S = struct {
14 const E = enum(c_int) { one, two };9 const E = enum(c_int) { one, two };
15 const e: E = .two;10 const e: E = .two;
...@@ -35,11 +30,6 @@ test "exporting with internal linkage" {...@@ -35,11 +30,6 @@ test "exporting with internal linkage" {
35test "exporting using namespace access" {30test "exporting using namespace access" {
36 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;31 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
43 const S = struct {33 const S = struct {
44 const Inner = struct {34 const Inner = struct {
45 const x: u32 = 5;35 const x: u32 = 5;
...@@ -57,11 +47,6 @@ test "exporting comptime-known value" {...@@ -57,11 +47,6 @@ test "exporting comptime-known value" {
57 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;47 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
58 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;48 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
65 const x: u32 = 10;50 const x: u32 = 10;
66 @export(&x, .{ .name = "exporting_comptime_known_value_foo" });51 @export(&x, .{ .name = "exporting_comptime_known_value_foo" });
67 const S = struct {52 const S = struct {
test/behavior/extern.zig-1
...@@ -3,7 +3,6 @@ const std = @import("std");...@@ -3,7 +3,6 @@ const std = @import("std");
3const expect = std.testing.expect;3const expect = std.testing.expect;
44
5test "anyopaque extern symbol" {5test "anyopaque extern symbol" {
6 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
7 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;6 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;7 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" {...@@ -586,7 +586,6 @@ test "@fieldParentPtr extern struct last zero-bit field" {
586}586}
587587
588test "@fieldParentPtr unaligned packed struct" {588test "@fieldParentPtr unaligned packed struct" {
589 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
590 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;589 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
591 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;590 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
592 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;591 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -725,7 +724,6 @@ test "@fieldParentPtr unaligned packed struct" {...@@ -725,7 +724,6 @@ test "@fieldParentPtr unaligned packed struct" {
725}724}
726725
727test "@fieldParentPtr aligned packed struct" {726test "@fieldParentPtr aligned packed struct" {
728 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
729 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;727 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
730 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;728 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
731 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;729 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1897,7 +1895,6 @@ test "@fieldParentPtr packed union" {...@@ -1897,7 +1895,6 @@ test "@fieldParentPtr packed union" {
1897}1895}
18981896
1899test "@fieldParentPtr tagged union all zero-bit fields" {1897test "@fieldParentPtr tagged union all zero-bit fields" {
1900 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
1901 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1898 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1902 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1899 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 {...@@ -118,7 +118,6 @@ fn testMul(comptime T: type) !void {
118test "cmp f16" {118test "cmp f16" {
119 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO119 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
120 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;120 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
123 try testCmp(f16);122 try testCmp(f16);
124 try comptime testCmp(f16);123 try comptime testCmp(f16);
...@@ -127,7 +126,6 @@ test "cmp f16" {...@@ -127,7 +126,6 @@ test "cmp f16" {
127test "cmp f32" {126test "cmp f32" {
128 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;127 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
129 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO128 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
132 try testCmp(f32);130 try testCmp(f32);
133 try comptime testCmp(f32);131 try comptime testCmp(f32);
...@@ -142,7 +140,6 @@ test "cmp f64" {...@@ -142,7 +140,6 @@ test "cmp f64" {
142140
143test "cmp f128" {141test "cmp f128" {
144 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO142 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;
146 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;143 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
147 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;144 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
148145
...@@ -152,7 +149,6 @@ test "cmp f128" {...@@ -152,7 +149,6 @@ test "cmp f128" {
152149
153test "cmp f80/c_longdouble" {150test "cmp f80/c_longdouble" {
154 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO151 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;
156 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;152 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
157 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;153 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
158154
...@@ -220,7 +216,6 @@ test "vector cmp f16" {...@@ -220,7 +216,6 @@ test "vector cmp f16" {
220 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;216 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
221 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO217 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
222 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;218 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
223 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isArm()) return error.SkipZigTest;
224 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;219 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
225220
226 try testCmpVector(f16);221 try testCmpVector(f16);
...@@ -233,7 +228,7 @@ test "vector cmp f32" {...@@ -233,7 +228,7 @@ test "vector cmp f32" {
233 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO228 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
234 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;229 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
235 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isArm()) return error.SkipZigTest;230 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
237 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;232 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
238233
239 try testCmpVector(f32);234 try testCmpVector(f32);
...@@ -253,10 +248,9 @@ test "vector cmp f64" {...@@ -253,10 +248,9 @@ test "vector cmp f64" {
253test "vector cmp f128" {248test "vector cmp f128" {
254 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;249 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
255 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO250 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;
257 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;251 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
258 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;252 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
260 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;254 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
261255
262 try testCmpVector(f128);256 try testCmpVector(f128);
...@@ -266,7 +260,7 @@ test "vector cmp f128" {...@@ -266,7 +260,7 @@ test "vector cmp f128" {
266test "vector cmp f80/c_longdouble" {260test "vector cmp f80/c_longdouble" {
267 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;261 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
268 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;262 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
270 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;264 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
271 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;265 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
272266
...@@ -381,11 +375,7 @@ test "@sqrt f80/f128/c_longdouble" {...@@ -381,11 +375,7 @@ test "@sqrt f80/f128/c_longdouble" {
381 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO375 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
382 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;376 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
383 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;377 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
384378 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
385 if (builtin.os.tag == .freebsd) {
386 // TODO https://github.com/ziglang/zig/issues/10875
387 return error.SkipZigTest;
388 }
389379
390 try testSqrt(f80);380 try testSqrt(f80);
391 try comptime testSqrt(f80);381 try comptime testSqrt(f80);
...@@ -431,9 +421,9 @@ fn testSqrt(comptime T: type) !void {...@@ -431,9 +421,9 @@ fn testSqrt(comptime T: type) !void {
431 var inf: T = math.inf(T);421 var inf: T = math.inf(T);
432 try expect(math.isPositiveInf(@sqrt(inf)));422 try expect(math.isPositiveInf(@sqrt(inf)));
433 var zero: T = 0.0;423 var zero: T = 0.0;
434 try expect(@sqrt(zero) == 0.0);424 try expect(math.isPositiveZero(@sqrt(zero)));
435 var neg_zero: T = -0.0;425 var neg_zero: T = -0.0;
436 try expect(@sqrt(neg_zero) == 0.0);426 try expect(math.isNegativeZero(@sqrt(neg_zero)));
437 var neg_one: T = -1.0;427 var neg_one: T = -1.0;
438 try expect(math.isNan(@sqrt(neg_one)));428 try expect(math.isNan(@sqrt(neg_one)));
439 var nan: T = math.nan(T);429 var nan: T = math.nan(T);
...@@ -947,7 +937,7 @@ test "@log2 with vectors" {...@@ -947,7 +937,7 @@ test "@log2 with vectors" {
947 builtin.cpu.arch == .aarch64 and937 builtin.cpu.arch == .aarch64 and
948 builtin.os.tag == .windows) return error.SkipZigTest;938 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) {
951 // https://codeberg.org/ziglang/zig/issues/35518941 // https://codeberg.org/ziglang/zig/issues/35518
952 return error.SkipZigTest;942 return error.SkipZigTest;
953 }943 }
...@@ -1054,7 +1044,6 @@ test "@abs f32/f64" {...@@ -1054,7 +1044,6 @@ test "@abs f32/f64" {
10541044
1055test "@abs f80/f128/c_longdouble" {1045test "@abs f80/f128/c_longdouble" {
1056 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1046 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;
1058 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1047 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1059 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1048 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1060 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1049 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1172,16 +1161,10 @@ test "@floor f32/f64" {...@@ -1172,16 +1161,10 @@ test "@floor f32/f64" {
11721161
1173test "@floor f80/f128/c_longdouble" {1162test "@floor f80/f128/c_longdouble" {
1174 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1163 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;
1176 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1164 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1177 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1165 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1178 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1166 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
1185 try testFloor(f80);1168 try testFloor(f80);
1186 try comptime testFloor(f80);1169 try comptime testFloor(f80);
1187 try testFloor(f128);1170 try testFloor(f128);
...@@ -1261,16 +1244,10 @@ test "@ceil f32/f64" {...@@ -1261,16 +1244,10 @@ test "@ceil f32/f64" {
12611244
1262test "@ceil f80/f128/c_longdouble" {1245test "@ceil f80/f128/c_longdouble" {
1263 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1246 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;
1265 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1247 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1266 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1248 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1267 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1249 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
1274 try testCeil(f80);1251 try testCeil(f80);
1275 try comptime testCeil(f80);1252 try comptime testCeil(f80);
1276 try testCeil(f128);1253 try testCeil(f128);
...@@ -1281,16 +1258,10 @@ test "@ceil f80/f128/c_longdouble" {...@@ -1281,16 +1258,10 @@ test "@ceil f80/f128/c_longdouble" {
12811258
1282test "@ceil f80 maxInt(u64)" {1259test "@ceil f80 maxInt(u64)" {
1283 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1260 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;
1285 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1261 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1286 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1262 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1287 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1263 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
1294 var x: u64 = std.math.maxInt(u64);1265 var x: u64 = std.math.maxInt(u64);
1295 x = x;1266 x = x;
1296 const float: f80 = @floatFromInt(x);1267 const float: f80 = @floatFromInt(x);
...@@ -1368,16 +1339,10 @@ test "@trunc f32/f64" {...@@ -1368,16 +1339,10 @@ test "@trunc f32/f64" {
13681339
1369test "@trunc f80/f128/c_longdouble" {1340test "@trunc f80/f128/c_longdouble" {
1370 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1341 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;
1372 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1342 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1373 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1343 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1374 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1344 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
1381 try testTrunc(f80);1346 try testTrunc(f80);
1382 try comptime testTrunc(f80);1347 try comptime testTrunc(f80);
1383 try testTrunc(f128);1348 try testTrunc(f128);
...@@ -1440,11 +1405,6 @@ test "neg f16" {...@@ -1440,11 +1405,6 @@ test "neg f16" {
1440 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1405 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1441 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1406 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
1448 try testNeg(f16);1408 try testNeg(f16);
1449 try comptime testNeg(f16);1409 try comptime testNeg(f16);
1450}1410}
...@@ -1501,9 +1461,9 @@ fn testNeg(comptime T: type) !void {...@@ -1501,9 +1461,9 @@ fn testNeg(comptime T: type) !void {
15011461
1502 // subnormals1462 // subnormals
1503 var zero: T = 0.0;1463 var zero: T = 0.0;
1504 try expect(-zero == -0.0);1464 try expect(math.isNegativeZero(-zero));
1505 var neg_zero: T = -0.0;1465 var neg_zero: T = -0.0;
1506 try expect(-neg_zero == 0.0);1466 try expect(math.isPositiveZero(-neg_zero));
1507 var true_min: T = math.floatTrueMin(T);1467 var true_min: T = math.floatTrueMin(T);
1508 try expect(-true_min == -math.floatTrueMin(T));1468 try expect(-true_min == -math.floatTrueMin(T));
1509 var neg_true_min: T = -math.floatTrueMin(T);1469 var neg_true_min: T = -math.floatTrueMin(T);
...@@ -1678,7 +1638,7 @@ test "runtime isNan(inf * 0)" {...@@ -1678,7 +1638,7 @@ test "runtime isNan(inf * 0)" {
16781638
1679test "optimized float mode" {1639test "optimized float mode" {
1680 if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest;1640 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
1683 const big = 0x1p40;1643 const big = 0x1p40;
1684 const small = 0.001;1644 const small = 0.001;
test/behavior/fn.zig-2
...@@ -147,7 +147,6 @@ fn fnWithUnreachable() noreturn {...@@ -147,7 +147,6 @@ fn fnWithUnreachable() noreturn {
147147
148test "extern struct with stdcallcc fn pointer" {148test "extern struct with stdcallcc fn pointer" {
149 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;149 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
150 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .x86) return error.SkipZigTest;
151 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;150 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
152151
153 const S = extern struct {152 const S = extern struct {
...@@ -419,7 +418,6 @@ test "import passed byref to function in return type" {...@@ -419,7 +418,6 @@ test "import passed byref to function in return type" {
419418
420test "implicit cast function to function ptr" {419test "implicit cast function to function ptr" {
421 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO420 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
422 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
423 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;421 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
424422
425 const S1 = struct {423 const S1 = struct {
test/behavior/int128.zig+1-1
...@@ -31,7 +31,7 @@ test "undefined 128 bit int" {...@@ -31,7 +31,7 @@ test "undefined 128 bit int" {
31 @setRuntimeSafety(true);31 @setRuntimeSafety(true);
3232
33 // TODO implement @setRuntimeSafety33 // TODO implement @setRuntimeSafety
34 if (builtin.mode != .Debug and builtin.mode != .ReleaseSafe) {34 if (builtin.mode != .debug and builtin.mode != .safe) {
35 return error.SkipZigTest;35 return error.SkipZigTest;
36 }36 }
3737
test/behavior/math.zig-35
...@@ -873,7 +873,6 @@ test "umax wrapped squaring" {...@@ -873,7 +873,6 @@ test "umax wrapped squaring" {
873test "128-bit multiplication" {873test "128-bit multiplication" {
874 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO874 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
875 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO875 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;
877 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;876 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
878877
879 {878 {
...@@ -968,7 +967,6 @@ test "@addWithOverflow > 128 bits" {...@@ -968,7 +967,6 @@ test "@addWithOverflow > 128 bits" {
968 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO967 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
969 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;968 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
970 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO969 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
973 try testAddWithOverflow(u129, 4, 105, 109, 0);971 try testAddWithOverflow(u129, 4, 105, 109, 0);
974 try testAddWithOverflow(u129, 1000, 100, 1100, 0);972 try testAddWithOverflow(u129, 1000, 100, 1100, 0);
...@@ -1136,7 +1134,6 @@ test "Multiply unwrap error * immediate" {...@@ -1136,7 +1134,6 @@ test "Multiply unwrap error * immediate" {
11361134
1137test "@mulWithOverflow bitsize 128 bits" {1135test "@mulWithOverflow bitsize 128 bits" {
1138 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1136 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1139 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1140 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1137 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1141 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1138 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1142 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1139 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1163,7 +1160,6 @@ test "@mulWithOverflow bitsize 128 bits" {...@@ -1163,7 +1160,6 @@ test "@mulWithOverflow bitsize 128 bits" {
11631160
1164test "@mulWithOverflow > 128 bits" {1161test "@mulWithOverflow > 128 bits" {
1165 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1162 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1166 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1167 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1163 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
11681164
1169 try testMulWithOverflow(u140, 0, maxInt(u140), 0, 0);1165 try testMulWithOverflow(u140, 0, maxInt(u140), 0, 0);
...@@ -1193,7 +1189,6 @@ test "@mulWithOverflow > 128 bits" {...@@ -1193,7 +1189,6 @@ test "@mulWithOverflow > 128 bits" {
11931189
1194test "@mulWithOverflow bitsize 256 bits" {1190test "@mulWithOverflow bitsize 256 bits" {
1195 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1191 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1196 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1197 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1192 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1198 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1193 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11991194
...@@ -1298,7 +1293,6 @@ test "@subWithOverflow > 128 bits" {...@@ -1298,7 +1293,6 @@ test "@subWithOverflow > 128 bits" {
1298 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1293 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1299 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1294 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1300 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO1295 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
1303 try testSubWithOverflow(u129, 4, 105, maxInt(u129) - 100, 1);1297 try testSubWithOverflow(u129, 4, 105, maxInt(u129) - 100, 1);
1304 try testSubWithOverflow(u129, 1000, 100, 900, 0);1298 try testSubWithOverflow(u129, 1000, 100, 900, 0);
...@@ -1389,7 +1383,6 @@ test "@shlWithOverflow > 64 bits" {...@@ -1389,7 +1383,6 @@ test "@shlWithOverflow > 64 bits" {
13891383
1390test "@shlWithOverflow > 128 bits" {1384test "@shlWithOverflow > 128 bits" {
1391 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1385 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1392 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1393 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1386 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
13941387
1395 try testShlWithOverflow(u140, 1 << 100, 20, 1 << 120, 0);1388 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 {...@@ -1419,7 +1412,6 @@ fn testAnd(comptime T: type, a: T, b: T, expected: T) !void {
14191412
1420test "and > 128 bits" {1413test "and > 128 bits" {
1421 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1414 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1422 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
14231415
1424 try testAnd(u140, (1 << 139) | (1 << 70) | 0xaa, (1 << 139) | (1 << 69) | 0xcc, (1 << 139) | 0x88);1416 try testAnd(u140, (1 << 139) | (1 << 70) | 0xaa, (1 << 139) | (1 << 69) | 0xcc, (1 << 139) | 0x88);
1425 try testAnd(u140, maxInt(u140), 1 << 100, 1 << 100);1417 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 {...@@ -1448,7 +1440,6 @@ fn testOr(comptime T: type, a: T, b: T, expected: T) !void {
14481440
1449test "or > 128 bits" {1441test "or > 128 bits" {
1450 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1442 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1451 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
14521443
1453 try testOr(u140, 0, 1 << 139, 1 << 139);1444 try testOr(u140, 0, 1 << 139, 1 << 139);
1454 try testOr(u140, (1 << 70) | 0xa, (1 << 69) | 0x5, (1 << 70) | (1 << 69) | 0xf);1445 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 {...@@ -1477,7 +1468,6 @@ fn testXor(comptime T: type, a: T, b: T, expected: T) !void {
14771468
1478test "xor > 128 bits" {1469test "xor > 128 bits" {
1479 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1470 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1480 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
14811471
1482 try testXor(u140, 0, maxInt(u140), maxInt(u140));1472 try testXor(u140, 0, maxInt(u140), maxInt(u140));
1483 try testXor(u140, 1 << 139, 1 << 139, 0);1473 try testXor(u140, 1 << 139, 1 << 139, 0);
...@@ -1506,7 +1496,6 @@ fn testNot(comptime T: type, a: T, expected: T) !void {...@@ -1506,7 +1496,6 @@ fn testNot(comptime T: type, a: T, expected: T) !void {
15061496
1507test "not > 128 bits" {1497test "not > 128 bits" {
1508 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1498 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1509 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
15101499
1511 try testNot(u140, 0, maxInt(u140));1500 try testNot(u140, 0, maxInt(u140));
1512 try testNot(u140, maxInt(u140), 0);1501 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 {...@@ -1535,7 +1524,6 @@ fn testShl(comptime T: type, a: T, b: std.math.Log2Int(T), expected: T) !void {
15351524
1536test "shl > 128 bits" {1525test "shl > 128 bits" {
1537 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1526 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1538 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
15391527
1540 try testShl(u140, 1 << 5, 10, 1 << 15);1528 try testShl(u140, 1 << 5, 10, 1 << 15);
1541 try testShl(u140, 3, 138, (1 << 139) | (1 << 138));1529 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 {...@@ -1564,7 +1552,6 @@ fn testShr(comptime T: type, a: T, b: std.math.Log2Int(T), expected: T) !void {
15641552
1565test "shr > 128 bits" {1553test "shr > 128 bits" {
1566 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1554 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1567 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
15681555
1569 try testShr(u140, 1 << 139, 39, 1 << 100);1556 try testShr(u140, 1 << 139, 39, 1 << 100);
1570 try testShr(u140, (1 << 70) | 8, 3, (1 << 67) | 1);1557 try testShr(u140, (1 << 70) | 8, 3, (1 << 67) | 1);
...@@ -1593,7 +1580,6 @@ fn testClz(comptime T: type, a: T, expected: u16) !void {...@@ -1593,7 +1580,6 @@ fn testClz(comptime T: type, a: T, expected: u16) !void {
15931580
1594test "@clz > 128 bits" {1581test "@clz > 128 bits" {
1595 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1582 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1596 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1597 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1583 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
15981584
1599 try testClz(u140, 0, 140);1585 try testClz(u140, 0, 140);
...@@ -1623,7 +1609,6 @@ fn testCtz(comptime T: type, a: T, expected: u16) !void {...@@ -1623,7 +1609,6 @@ fn testCtz(comptime T: type, a: T, expected: u16) !void {
16231609
1624test "@ctz > 128 bits" {1610test "@ctz > 128 bits" {
1625 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1611 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1626 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1627 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1612 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
16281613
1629 try testCtz(u140, 0, 140);1614 try testCtz(u140, 0, 140);
...@@ -1653,7 +1638,6 @@ fn testPopCount(comptime T: type, a: T, expected: u16) !void {...@@ -1653,7 +1638,6 @@ fn testPopCount(comptime T: type, a: T, expected: u16) !void {
16531638
1654test "@popCount > 128 bits" {1639test "@popCount > 128 bits" {
1655 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1640 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1656 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1657 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1641 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
16581642
1659 try testPopCount(u140, 0, 0);1643 try testPopCount(u140, 0, 0);
...@@ -1683,7 +1667,6 @@ fn testBitReverse(comptime T: type, a: T, expected: T) !void {...@@ -1683,7 +1667,6 @@ fn testBitReverse(comptime T: type, a: T, expected: T) !void {
16831667
1684test "@bitReverse > 128 bits" {1668test "@bitReverse > 128 bits" {
1685 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1669 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1686 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1687 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1670 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
16881671
1689 try testBitReverse(u140, 1 << 139, 1);1672 try testBitReverse(u140, 1 << 139, 1);
...@@ -1713,7 +1696,6 @@ fn testByteSwap(comptime T: type, a: T, expected: T) !void {...@@ -1713,7 +1696,6 @@ fn testByteSwap(comptime T: type, a: T, expected: T) !void {
17131696
1714test "@byteSwap > 128 bits" {1697test "@byteSwap > 128 bits" {
1715 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1698 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1716 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1717 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1699 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
17181700
1719 try testByteSwap(u144, 1 << 136, 1);1701 try testByteSwap(u144, 1 << 136, 1);
...@@ -1743,7 +1725,6 @@ fn testMax(comptime T: type, a: T, b: T, expected: T) !void {...@@ -1743,7 +1725,6 @@ fn testMax(comptime T: type, a: T, b: T, expected: T) !void {
17431725
1744test "@max > 128 bits" {1726test "@max > 128 bits" {
1745 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1727 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1746 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1747 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1728 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
17481729
1749 try testMax(u140, 0, maxInt(u140), maxInt(u140));1730 try testMax(u140, 0, maxInt(u140), maxInt(u140));
...@@ -1773,7 +1754,6 @@ fn testMin(comptime T: type, a: T, b: T, expected: T) !void {...@@ -1773,7 +1754,6 @@ fn testMin(comptime T: type, a: T, b: T, expected: T) !void {
17731754
1774test "@min > 128 bits" {1755test "@min > 128 bits" {
1775 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1756 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1776 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1777 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1757 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
17781758
1779 try testMin(u140, 0, maxInt(u140), 0);1759 try testMin(u140, 0, maxInt(u140), 0);
...@@ -1803,7 +1783,6 @@ fn testAbs(comptime T: type, a: T, expected: anytype) !void {...@@ -1803,7 +1783,6 @@ fn testAbs(comptime T: type, a: T, expected: anytype) !void {
18031783
1804test "@abs > 128 bits" {1784test "@abs > 128 bits" {
1805 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1785 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1806 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
18071786
1808 try testAbs(u140, 0, 0);1787 try testAbs(u140, 0, 0);
1809 try testAbs(u140, 1 << 139, 1 << 139);1788 try testAbs(u140, 1 << 139, 1 << 139);
...@@ -1827,7 +1806,6 @@ fn testRem(comptime T: type, numerator: T, denominator: T, expected: T) !void {...@@ -1827,7 +1806,6 @@ fn testRem(comptime T: type, numerator: T, denominator: T, expected: T) !void {
18271806
1828test "@rem > 128 bits" {1807test "@rem > 128 bits" {
1829 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1808 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1830 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1831 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1809 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
18321810
1833 try testRem(u140, 0, maxInt(u140), 0);1811 try testRem(u140, 0, maxInt(u140), 0);
...@@ -1855,7 +1833,6 @@ fn testMod(comptime T: type, numerator: T, denominator: T, expected: T) !void {...@@ -1855,7 +1833,6 @@ fn testMod(comptime T: type, numerator: T, denominator: T, expected: T) !void {
18551833
1856test "@mod > 128 bits" {1834test "@mod > 128 bits" {
1857 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1835 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1858 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1859 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1836 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
18601837
1861 try testMod(u140, 0, maxInt(u140), 0);1838 try testMod(u140, 0, maxInt(u140), 0);
...@@ -1883,7 +1860,6 @@ fn testDivFloor(comptime T: type, numerator: T, denominator: T, expected: T) !vo...@@ -1883,7 +1860,6 @@ fn testDivFloor(comptime T: type, numerator: T, denominator: T, expected: T) !vo
18831860
1884test "@divFloor > 128 bits" {1861test "@divFloor > 128 bits" {
1885 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1862 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1886 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1887 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1863 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
18881864
1889 try testDivFloor(u140, 0, maxInt(u140), 0);1865 try testDivFloor(u140, 0, maxInt(u140), 0);
...@@ -1912,7 +1888,6 @@ fn testDivCeil(comptime T: type, numerator: T, denominator: T, expected: T) !voi...@@ -1912,7 +1888,6 @@ fn testDivCeil(comptime T: type, numerator: T, denominator: T, expected: T) !voi
19121888
1913test "@divCeil > 128 bits" {1889test "@divCeil > 128 bits" {
1914 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1890 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1915 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1916 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1891 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
19171892
1918 try testDivCeil(u140, 0, maxInt(u140), 0);1893 try testDivCeil(u140, 0, maxInt(u140), 0);
...@@ -1941,7 +1916,6 @@ fn testDivTrunc(comptime T: type, numerator: T, denominator: T, expected: T) !vo...@@ -1941,7 +1916,6 @@ fn testDivTrunc(comptime T: type, numerator: T, denominator: T, expected: T) !vo
19411916
1942test "@divTrunc > 128 bits" {1917test "@divTrunc > 128 bits" {
1943 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1918 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1944 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1945 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1919 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
19461920
1947 try testDivTrunc(u140, 0, maxInt(u140), 0);1921 try testDivTrunc(u140, 0, maxInt(u140), 0);
...@@ -2166,14 +2140,8 @@ test "remainder division" {...@@ -2166,14 +2140,8 @@ test "remainder division" {
2166 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2140 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2167 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2141 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2168 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2142 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2169 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
2170 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;2143 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
2177 if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff and builtin.abi != .gnu) return error.SkipZigTest;2145 if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff and builtin.abi != .gnu) return error.SkipZigTest;
21782146
2179 try comptime remdiv(f16);2147 try comptime remdiv(f16);
...@@ -2315,7 +2283,6 @@ test "@round f80" {...@@ -2315,7 +2283,6 @@ test "@round f80" {
2315 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2283 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2316 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2284 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2317 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2285 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2318 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
2319 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;2286 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
23202287
2321 try testRound(f80, 12.0);2288 try testRound(f80, 12.0);
...@@ -2326,7 +2293,6 @@ test "@round f128" {...@@ -2326,7 +2293,6 @@ test "@round f128" {
2326 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2293 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2327 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2294 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2328 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2295 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2329 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
2330 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;2296 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
23312297
2332 try testRound(f128, 12.0);2298 try testRound(f128, 12.0);
...@@ -2366,7 +2332,6 @@ test "NaN comparison" {...@@ -2366,7 +2332,6 @@ test "NaN comparison" {
2366 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2332 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2367 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2333 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2368 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;2334 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
2371 try testNanEqNan(f16);2336 try testNanEqNan(f16);
2372 try testNanEqNan(f32);2337 try testNanEqNan(f32);
test/behavior/maximum_minimum.zig-1
...@@ -115,7 +115,6 @@ test "@min/max for floats" {...@@ -115,7 +115,6 @@ test "@min/max for floats" {
115 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO115 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
116 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO116 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
117 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;117 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
118 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
119 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;118 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
120119
121 const S = struct {120 const S = struct {
test/behavior/muladd.zig-4
...@@ -49,7 +49,6 @@ test "@mulAdd f80" {...@@ -49,7 +49,6 @@ test "@mulAdd f80" {
49 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO49 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
50 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO50 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
51 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;51 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
53 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;52 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
5453
55 try comptime testMulAdd80();54 try comptime testMulAdd80();
...@@ -68,7 +67,6 @@ test "@mulAdd f128" {...@@ -68,7 +67,6 @@ test "@mulAdd f128" {
68 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO67 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
69 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO68 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
70 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;69 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
71 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
72 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;70 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
7371
74 try comptime testMulAdd128();72 try comptime testMulAdd128();
...@@ -169,7 +167,6 @@ test "vector f80" {...@@ -169,7 +167,6 @@ test "vector f80" {
169 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO167 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
170 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO168 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
171 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;169 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
172 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
173 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;170 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
174171
175 try comptime vector80();172 try comptime vector80();
...@@ -194,7 +191,6 @@ test "vector f128" {...@@ -194,7 +191,6 @@ test "vector f128" {
194 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO191 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
195 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO192 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
196 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;193 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
197 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
198 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;194 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
199195
200 try comptime vector128();196 try comptime vector128();
test/behavior/packed-struct.zig-4
...@@ -404,7 +404,6 @@ test "nested packed struct field pointers" {...@@ -404,7 +404,6 @@ test "nested packed struct field pointers" {
404 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;404 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
405 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO405 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
406 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;406 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
407 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // ubsan unaligned pointer access
408 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO407 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
409 const S2 = packed struct {408 const S2 = packed struct {
410 base: u8,409 base: u8,
...@@ -579,7 +578,6 @@ test "packed struct fields modification" {...@@ -579,7 +578,6 @@ test "packed struct fields modification" {
579}578}
580579
581test "nested packed struct field access test" {580test "nested packed struct field access test" {
582 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
583 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO581 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
584 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO582 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
585 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;583 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -733,7 +731,6 @@ test "nested packed struct at non-zero offset 2" {...@@ -733,7 +731,6 @@ test "nested packed struct at non-zero offset 2" {
733 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;731 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
734 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO732 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
735 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;733 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
736 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
737 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;734 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
738735
739 const S = struct {736 const S = struct {
...@@ -1171,7 +1168,6 @@ test "packed struct equality" {...@@ -1171,7 +1168,6 @@ test "packed struct equality" {
11711168
1172test "packed struct equality ignores padding bits" {1169test "packed struct equality ignores padding bits" {
1173 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1170 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1174 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1175 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1171 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
11761172
1177 const S = packed struct { b: bool };1173 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" {...@@ -275,7 +275,7 @@ test "compare equality of optional and non-optional pointer" {
275}275}
276276
277test "allowzero pointer and slice" {277test "allowzero pointer and slice" {
278 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO278 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
279 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;279 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
280 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO280 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
281 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;281 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/saturating_arithmetic.zig-7
...@@ -144,7 +144,6 @@ test "saturating multiplication <= 32 bits" {...@@ -144,7 +144,6 @@ test "saturating multiplication <= 32 bits" {
144 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO144 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
145 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO145 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
146 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;146 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
147 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
148 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;147 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
149148
150 try testSatMul(u8, 0, maxInt(u8), 0);149 try testSatMul(u8, 0, maxInt(u8), 0);
...@@ -238,7 +237,6 @@ test "saturating multiplication" {...@@ -238,7 +237,6 @@ test "saturating multiplication" {
238 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO237 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
239 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO238 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
240 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;239 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
241 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
242 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;240 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
243241
244 const S = struct {242 const S = struct {
...@@ -313,7 +311,6 @@ test "saturating shift-left" {...@@ -313,7 +311,6 @@ test "saturating shift-left" {
313311
314test "saturating shift-left large rhs" {312test "saturating shift-left large rhs" {
315 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;313 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
316 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
317 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;314 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
318 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;315 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
319 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;316 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
...@@ -361,7 +358,6 @@ test "saturating shl uses the LHS type" {...@@ -361,7 +358,6 @@ test "saturating shl uses the LHS type" {
361358
362test "sat add > 128 bits" {359test "sat add > 128 bits" {
363 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;360 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
364 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
365 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;361 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
366362
367 try testSatAdd(u140, 0, 0, 0);363 try testSatAdd(u140, 0, 0, 0);
...@@ -377,7 +373,6 @@ test "sat add > 128 bits" {...@@ -377,7 +373,6 @@ test "sat add > 128 bits" {
377373
378test "sat sub > 128 bits" {374test "sat sub > 128 bits" {
379 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;375 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
380 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
381 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;376 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
382377
383 try testSatSub(u140, 0, 1, 0);378 try testSatSub(u140, 0, 1, 0);
...@@ -393,7 +388,6 @@ test "sat sub > 128 bits" {...@@ -393,7 +388,6 @@ test "sat sub > 128 bits" {
393388
394test "sat mul > 128 bits" {389test "sat mul > 128 bits" {
395 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;390 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
396 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
397 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;391 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
398392
399 try testSatMul(u140, 0, maxInt(u140), 0);393 try testSatMul(u140, 0, maxInt(u140), 0);
...@@ -409,7 +403,6 @@ test "sat mul > 128 bits" {...@@ -409,7 +403,6 @@ test "sat mul > 128 bits" {
409403
410test "sat shl > 128 bits" {404test "sat shl > 128 bits" {
411 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;405 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
412 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
413 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;406 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
414407
415 try testSatShl(u140, 0, u8, 17, 0);408 try testSatShl(u140, 0, u8, 17, 0);
test/behavior/select.zig+14
...@@ -31,6 +31,20 @@ fn selectVectors() !void {...@@ -31,6 +31,20 @@ fn selectVectors() !void {
31 _ = .{ &x, &y, &z };31 _ = .{ &x, &y, &z };
32 const xyz = @select(f32, x, y, z);32 const xyz = @select(f32, x, y, z);
33 try expect(mem.eql(f32, &@as([4]f32, xyz), &[4]f32{ 0.0, 312.1, -145.9, -3381.233 }));33 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;
34}48}
3549
36test "@select arrays" {50test "@select arrays" {
test/behavior/shuffle.zig+20
...@@ -170,3 +170,23 @@ test "@shuffle bool 2" {...@@ -170,3 +170,23 @@ test "@shuffle bool 2" {
170 try S.doTheTest();170 try S.doTheTest();
171 try comptime S.doTheTest();171 try comptime S.doTheTest();
172}172}
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" {...@@ -1089,3 +1089,85 @@ test "slice field alignment" {
1089 var arr: [10]u8 = @splat(0);1089 var arr: [10]u8 = @splat(0);
1090 try S.doTheTest(&&arr);1090 try S.doTheTest(&&arr);
1091}1091}
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" {...@@ -535,7 +535,6 @@ test "zero-bit field in packed struct" {
535test "packed struct with non-ABI-aligned field" {535test "packed struct with non-ABI-aligned field" {
536 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;536 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
537 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO537 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
538 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
539 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO538 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
540 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;539 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
541 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;540 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -792,7 +791,6 @@ test "non-packed struct with u128 entry in union" {...@@ -792,7 +791,6 @@ test "non-packed struct with u128 entry in union" {
792 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO791 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
793 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO792 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
794 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;793 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
795 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
796 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;794 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
797795
798 const U = union(enum) {796 const U = union(enum) {
...@@ -1539,7 +1537,6 @@ test "instantiate struct with comptime field" {...@@ -1539,7 +1537,6 @@ test "instantiate struct with comptime field" {
1539}1537}
15401538
1541test "struct field pointer has correct alignment" {1539test "struct field pointer has correct alignment" {
1542 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1543 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1540 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1544 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1541 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1545 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1542 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1569,7 +1566,6 @@ test "struct field pointer has correct alignment" {...@@ -1569,7 +1566,6 @@ test "struct field pointer has correct alignment" {
1569}1566}
15701567
1571test "extern struct field pointer has correct alignment" {1568test "extern struct field pointer has correct alignment" {
1572 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1573 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1569 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1574 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1570 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1575 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1571 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -2007,7 +2003,6 @@ test "initiate global variable with runtime value" {...@@ -2007,7 +2003,6 @@ test "initiate global variable with runtime value" {
2007}2003}
20082004
2009test "struct containing optional pointer to array of @This()" {2005test "struct containing optional pointer to array of @This()" {
2010 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2011 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2006 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
20122007
2013 const S = struct {2008 const S = struct {
...@@ -2266,7 +2261,8 @@ test "struct contains aligned pointer to itself through type decl" {...@@ -2266,7 +2261,8 @@ test "struct contains aligned pointer to itself through type decl" {
22662261
2267test "struct contains underaligned field with overaligned pointer to itself" {2262test "struct contains underaligned field with overaligned pointer to itself" {
2268 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2263 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2269 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO2264 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2265
2270 const S = struct {2266 const S = struct {
2271 ptr: *align(8) @This() align(1),2267 ptr: *align(8) @This() align(1),
2272 };2268 };
test/behavior/switch.zig+1-1
...@@ -1267,7 +1267,7 @@ test "switch with complex item expressions" {...@@ -1267,7 +1267,7 @@ test "switch with complex item expressions" {
1267test "switch evaluation order" {1267test "switch evaluation order" {
1268 const eu: anyerror!u32 = 0;1268 const eu: anyerror!u32 = 0;
1269 _ = eu catch |err| switch (err) {1269 _ = eu catch |err| switch (err) {
1270 if (true) @compileError("unreachable") => unreachable,1270 if (true) comptime unreachable => unreachable,
1271 else => unreachable,1271 else => unreachable,
1272 };1272 };
1273}1273}
test/behavior/switch_loop.zig+1-2
...@@ -223,7 +223,6 @@ test "unanalyzed continue with operand" {...@@ -223,7 +223,6 @@ test "unanalyzed continue with operand" {
223223
224test "switch loop on larger than pointer integer" {224test "switch loop on larger than pointer integer" {
225 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;225 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
226 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
227 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;226 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
228227
229 var entry: @Int(.unsigned, @bitSizeOf(usize) + 1) = undefined;228 var entry: @Int(.unsigned, @bitSizeOf(usize) + 1) = undefined;
...@@ -268,7 +267,7 @@ test "switch loop on non-exhaustive enum" {...@@ -268,7 +267,7 @@ test "switch loop on non-exhaustive enum" {
268267
269test "switch loop with discarded tag capture" {268test "switch loop with discarded tag capture" {
270 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;269 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
271 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;270
272 const S = struct {271 const S = struct {
273 const U = union(enum) {272 const U = union(enum) {
274 a: u32,273 a: u32,
test/behavior/switch_on_captured_error.zig+3-3
...@@ -243,7 +243,7 @@ test "switch on error union catch capture" {...@@ -243,7 +243,7 @@ test "switch on error union catch capture" {
243 var a: error{}!u64 = 0;243 var a: error{}!u64 = 0;
244 _ = &a;244 _ = &a;
245 const b = a catch |err| switch (err) {245 const b = a catch |err| switch (err) {
246 undefined => @compileError("unreachable"),246 undefined => comptime unreachable,
247 };247 };
248 try expectEqual(@as(u64, 0), b);248 try expectEqual(@as(u64, 0), b);
249 }249 }
...@@ -829,7 +829,7 @@ test "switch on error union if else capture" {...@@ -829,7 +829,7 @@ test "switch on error union if else capture" {
829 var a: error{}!u64 = 0;829 var a: error{}!u64 = 0;
830 _ = &a;830 _ = &a;
831 const b = if (a) |x| x else |err| switch (err) {831 const b = if (a) |x| x else |err| switch (err) {
832 undefined => @compileError("unreachable"),832 undefined => comptime unreachable,
833 };833 };
834 try expectEqual(@as(u64, 0), b);834 try expectEqual(@as(u64, 0), b);
835 }835 }
...@@ -840,7 +840,7 @@ test "switch on error union if else capture" {...@@ -840,7 +840,7 @@ test "switch on error union if else capture" {
840 var a: error{}!u64 = 0;840 var a: error{}!u64 = 0;
841 _ = &a;841 _ = &a;
842 const b = if (a) |*x| x.* else |err| switch (err) {842 const b = if (a) |*x| x.* else |err| switch (err) {
843 undefined => @compileError("unreachable"),843 undefined => comptime unreachable,
844 };844 };
845 try expectEqual(@as(u64, 0), b);845 try expectEqual(@as(u64, 0), b);
846 }846 }
test/behavior/threadlocal.zig-5
...@@ -9,11 +9,6 @@ test "thread local variable" {...@@ -9,11 +9,6 @@ test "thread local variable" {
9 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO10 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
17 const S = struct {12 const S = struct {
18 threadlocal var t: i32 = 1234;13 threadlocal var t: i32 = 1234;
19 };14 };
test/behavior/truncate.zig-1
...@@ -49,7 +49,6 @@ fn testTruncate(comptime S: type, a: S, comptime D: type, expected: D) !void {...@@ -49,7 +49,6 @@ fn testTruncate(comptime S: type, a: S, comptime D: type, expected: D) !void {
4949
50test "@truncate > 128 bits" {50test "@truncate > 128 bits" {
51 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;51 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
53 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;52 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
5453
55 try testTruncate(u140, 0, u128, 0);54 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" {...@@ -1437,7 +1437,6 @@ test "coerce enum literal to union in result loc" {
1437}1437}
14381438
1439test "defined-layout union field pointer has correct alignment" {1439test "defined-layout union field pointer has correct alignment" {
1440 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1441 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1440 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1442 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1441 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1443 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1442 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1472,7 +1471,6 @@ test "defined-layout union field pointer has correct alignment" {...@@ -1472,7 +1471,6 @@ test "defined-layout union field pointer has correct alignment" {
1472}1471}
14731472
1474test "undefined-layout union field pointer has correct alignment" {1473test "undefined-layout union field pointer has correct alignment" {
1475 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1476 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1474 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1477 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1475 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1478 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1476 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1611,6 +1609,10 @@ fn littleToNativeEndian(comptime T: type, v: T) T {...@@ -1611,6 +1609,10 @@ fn littleToNativeEndian(comptime T: type, v: T) T {
1611}1609}
16121610
1613test "reinterpret extern union" {1611test "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
1614 if (true) {1616 if (true) {
1615 // https://github.com/ziglang/zig/issues/193891617 // https://github.com/ziglang/zig/issues/19389
1616 return error.SkipZigTest;1618 return error.SkipZigTest;
...@@ -1678,8 +1680,6 @@ test "reinterpret extern union" {...@@ -1678,8 +1680,6 @@ test "reinterpret extern union" {
1678 };1680 };
16791681
1680 try comptime S.doTheTest();1682 try comptime S.doTheTest();
1681
1682 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
1683 try S.doTheTest();1683 try S.doTheTest();
1684}1684}
16851685
...@@ -1758,8 +1758,6 @@ test "reinterpret packed union" {...@@ -1758,8 +1758,6 @@ test "reinterpret packed union" {
1758 };1758 };
17591759
1760 try comptime S.doTheTest();1760 try comptime S.doTheTest();
1761
1762 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1763 try S.doTheTest();1761 try S.doTheTest();
1764}1762}
17651763
...@@ -1800,8 +1798,6 @@ test "reinterpret packed union inside packed struct" {...@@ -1800,8 +1798,6 @@ test "reinterpret packed union inside packed struct" {
1800 };1798 };
18011799
1802 try comptime S.doTheTest();1800 try comptime S.doTheTest();
1803
1804 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1805 try S.doTheTest();1801 try S.doTheTest();
1806}1802}
18071803
test/behavior/vector.zig+19-18
...@@ -128,13 +128,6 @@ test "vector float operators" {...@@ -128,13 +128,6 @@ test "vector float operators" {
128 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO128 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
129 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO129 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
130 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;130 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
139 const S = struct {132 const S = struct {
140 fn doTheTest(T: type) !void {133 fn doTheTest(T: type) !void {
...@@ -280,7 +273,6 @@ test "array to vector with element type coercion" {...@@ -280,7 +273,6 @@ test "array to vector with element type coercion" {
280 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO273 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
281 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;274 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
282 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;275 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
285 const S = struct {277 const S = struct {
286 fn doTheTest() !void {278 fn doTheTest() !void {
...@@ -736,9 +728,7 @@ test "vector reduce operation" {...@@ -736,9 +728,7 @@ test "vector reduce operation" {
736 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO728 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
737 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO729 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
738 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;730 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
739 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
740 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;731 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
743 const S = struct {733 const S = struct {
744 fn testReduce(comptime op: std.builtin.ReduceOp, x: anytype, expected: anytype) !void {734 fn testReduce(comptime op: std.builtin.ReduceOp, x: anytype, expected: anytype) !void {
...@@ -776,6 +766,8 @@ test "vector reduce operation" {...@@ -776,6 +766,8 @@ test "vector reduce operation" {
776 try testReduce(.Add, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 42.9));766 try testReduce(.Add, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 42.9));
777 try testReduce(.Add, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 42.9));767 try testReduce(.Add, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 42.9));
778 try testReduce(.Add, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 42.9));768 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
780 try testReduce(.And, [4]bool{ true, false, true, true }, @as(bool, false));772 try testReduce(.And, [4]bool{ true, false, true, true }, @as(bool, false));
781 try testReduce(.And, [4]u1{ 1, 0, 1, 1 }, @as(u1, 0));773 try testReduce(.And, [4]u1{ 1, 0, 1, 1 }, @as(u1, 0));
...@@ -794,6 +786,8 @@ test "vector reduce operation" {...@@ -794,6 +786,8 @@ test "vector reduce operation" {
794 try testReduce(.Min, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, -100.0));786 try testReduce(.Min, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, -100.0));
795 try testReduce(.Min, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, -100.0));787 try testReduce(.Min, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, -100.0));
796 try testReduce(.Min, [4]f64{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f64, -100.0));788 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
798 try testReduce(.Max, [4]i16{ -1, 2, 3, 4 }, @as(i16, 4));792 try testReduce(.Max, [4]i16{ -1, 2, 3, 4 }, @as(i16, 4));
799 try testReduce(.Max, [4]u16{ 1, 2, 3, 4 }, @as(u16, 4));793 try testReduce(.Max, [4]u16{ 1, 2, 3, 4 }, @as(u16, 4));
...@@ -806,6 +800,8 @@ test "vector reduce operation" {...@@ -806,6 +800,8 @@ test "vector reduce operation" {
806 try testReduce(.Max, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, 10.0e9));800 try testReduce(.Max, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, 10.0e9));
807 try testReduce(.Max, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, 10.0e9));801 try testReduce(.Max, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, 10.0e9));
808 try testReduce(.Max, [4]f64{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f64, 10.0e9));802 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
810 try testReduce(.Mul, [4]i16{ -1, 2, 3, 4 }, @as(i16, -24));806 try testReduce(.Mul, [4]i16{ -1, 2, 3, 4 }, @as(i16, -24));
811 try testReduce(.Mul, [4]u16{ 1, 2, 3, 4 }, @as(u16, 24));807 try testReduce(.Mul, [4]u16{ 1, 2, 3, 4 }, @as(u16, 24));
...@@ -818,6 +814,8 @@ test "vector reduce operation" {...@@ -818,6 +814,8 @@ test "vector reduce operation" {
818 try testReduce(.Mul, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 58430.7));814 try testReduce(.Mul, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 58430.7));
819 try testReduce(.Mul, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 58430.7));815 try testReduce(.Mul, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 58430.7));
820 try testReduce(.Mul, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 58430.7));816 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
822 try testReduce(.Or, [4]bool{ false, true, false, false }, @as(bool, true));820 try testReduce(.Or, [4]bool{ false, true, false, false }, @as(bool, true));
823 try testReduce(.Or, [4]u1{ 0, 1, 0, 0 }, @as(u1, 1));821 try testReduce(.Or, [4]u1{ 0, 1, 0, 0 }, @as(u1, 1));
...@@ -825,6 +823,7 @@ test "vector reduce operation" {...@@ -825,6 +823,7 @@ test "vector reduce operation" {
825 try testReduce(.Or, [4]u32{ 0xffff0000, 0xff00, 0xf0, 0xf }, ~@as(u32, 0));823 try testReduce(.Or, [4]u32{ 0xffff0000, 0xff00, 0xf0, 0xf }, ~@as(u32, 0));
826 try testReduce(.Or, [4]u64{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u64, 0xffffffff));824 try testReduce(.Or, [4]u64{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u64, 0xffffffff));
827 try testReduce(.Or, [4]u128{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u128, 0xffffffff));825 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
829 try testReduce(.Xor, [4]bool{ true, true, true, false }, @as(bool, true));828 try testReduce(.Xor, [4]bool{ true, true, true, false }, @as(bool, true));
830 try testReduce(.Xor, [4]u1{ 1, 1, 1, 0 }, @as(u1, 1));829 try testReduce(.Xor, [4]u1{ 1, 1, 1, 0 }, @as(u1, 1));
...@@ -837,22 +836,32 @@ test "vector reduce operation" {...@@ -837,22 +836,32 @@ test "vector reduce operation" {
837 const f16_nan = math.nan(f16);836 const f16_nan = math.nan(f16);
838 const f32_nan = math.nan(f32);837 const f32_nan = math.nan(f32);
839 const f64_nan = math.nan(f64);838 const f64_nan = math.nan(f64);
839 const f80_nan = math.nan(f80);
840 const f128_nan = math.nan(f128);
840841
841 try testReduce(.Add, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);842 try testReduce(.Add, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
842 try testReduce(.Add, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);843 try testReduce(.Add, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);
843 try testReduce(.Add, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan);844 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
845 try testReduce(.Min, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, @as(f16, -1.9));848 try testReduce(.Min, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, @as(f16, -1.9));
846 try testReduce(.Min, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, @as(f32, -1.9));849 try testReduce(.Min, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, @as(f32, -1.9));
847 try testReduce(.Min, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, @as(f64, -1.9));850 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
849 try testReduce(.Max, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, @as(f16, 100.0));854 try testReduce(.Max, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, @as(f16, 100.0));
850 try testReduce(.Max, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, @as(f32, 100.0));855 try testReduce(.Max, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, @as(f32, 100.0));
851 try testReduce(.Max, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, @as(f64, 100.0));856 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
853 try testReduce(.Mul, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);860 try testReduce(.Mul, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
854 try testReduce(.Mul, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);861 try testReduce(.Mul, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);
855 try testReduce(.Mul, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan);862 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);
856 }865 }
857 };866 };
858867
...@@ -1321,11 +1330,6 @@ test "byte vector initialized in inline function" {...@@ -1321,11 +1330,6 @@ test "byte vector initialized in inline function" {
1321 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1330 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1322 if (builtin.cpu.arch == .hexagon and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;1331 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
1329 const S = struct {1333 const S = struct {
1330 fn boolx4(e0: bool, e1: bool, e2: bool, e3: bool) @Vector(4, bool) {1334 fn boolx4(e0: bool, e1: bool, e2: bool, e3: bool) @Vector(4, bool) {
1331 return .{ e0, e1, e2, e3 };1335 return .{ e0, e1, e2, e3 };
...@@ -1437,7 +1441,6 @@ test "store packed vector element" {...@@ -1437,7 +1441,6 @@ test "store packed vector element" {
1437 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1441 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1438 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1442 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1439 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1443 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1440 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1441 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1444 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
14421445
1443 var v = @Vector(4, u1){ 1, 1, 1, 1 };1446 var v = @Vector(4, u1){ 1, 1, 1, 1 };
...@@ -1469,7 +1472,6 @@ test "store vector with memset" {...@@ -1469,7 +1472,6 @@ test "store vector with memset" {
1469 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1472 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1470 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1473 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1471 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO1474 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
1472 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1473 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1475 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
14741476
1475 var a: [5]@Vector(2, i1) = undefined;1477 var a: [5]@Vector(2, i1) = undefined;
...@@ -1610,7 +1612,6 @@ test "bitcast vector to array of smaller vectors" {...@@ -1610,7 +1612,6 @@ test "bitcast vector to array of smaller vectors" {
1610 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1612 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1611 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1613 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1612 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1614 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1613 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
16141615
1615 const u8x32 = @Vector(32, u8);1616 const u8x32 = @Vector(32, u8);
1616 const u8x64 = @Vector(64, u8);1617 const u8x64 = @Vector(64, u8);
test/behavior/widening.zig-1
...@@ -41,7 +41,6 @@ test "float widening" {...@@ -41,7 +41,6 @@ test "float widening" {
41 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO41 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
42 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;42 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
43 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;43 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
46 var a: f16 = 12.34;45 var a: f16 = 12.34;
47 var b: f32 = a;46 var b: f32 = a;
test/behavior/x86_64/unary.zig+1-1
...@@ -56,7 +56,7 @@ fn unary(comptime op: anytype, comptime opts: struct {...@@ -56,7 +56,7 @@ fn unary(comptime op: anytype, comptime opts: struct {
56 f32 => libc_name ++ "f",56 f32 => libc_name ++ "f",
57 f64 => libc_name,57 f64 => libc_name,
58 f80 => "__" ++ libc_name ++ "x",58 f80 => "__" ++ libc_name ++ "x",
59 f128 => libc_name ++ "q",59 f128 => libc_name ++ "f128",
60 else => break :libc,60 else => break :libc,
61 },61 },
62 .library_name = switch (@import("builtin").object_format) {62 .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) {...@@ -77,7 +77,7 @@ static void assert_or_panic(bool ok) {
77# define ZIG_NO_COMPLEX77# define ZIG_NO_COMPLEX
78#endif78#endif
7979
80#ifdef ZIG_PPC3280#ifdef __powerpc__
81# define ZIG_NO_COMPLEX81# define ZIG_NO_COMPLEX
82#endif82#endif
8383
...@@ -191,9 +191,6 @@ void zig_struct_i128(struct i128);...@@ -191,9 +191,6 @@ void zig_struct_i128(struct i128);
191#endif191#endif
192void zig_five_integers(int32_t, int32_t, int32_t, int32_t, int32_t);192void 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);
197void zig_five_floats(float, float, float, float, float);194void zig_five_floats(float, float, float, float, float);
198195
199bool zig_ret_bool();196bool zig_ret_bool();
...@@ -219,7 +216,203 @@ float complex zig_cmultf(float complex a, float complex b);...@@ -219,7 +216,203 @@ float complex zig_cmultf(float complex a, float complex b);
219double complex zig_cmultd(double complex a, double complex b);216double complex zig_cmultd(double complex a, double complex b);
220#endif217#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
224typedef bool Vector_2_bool __attribute__((ext_vector_type(2)));417typedef bool Vector_2_bool __attribute__((ext_vector_type(2)));
225418
...@@ -4468,6 +4661,10 @@ void c_test_vector_512_bool(void) {...@@ -4468,6 +4661,10 @@ void c_test_vector_512_bool(void) {
4468 });4661 });
4469}4662}
44704663
4664#endif
4665#endif
4666#endif
4667#endif
4471#endif4668#endif
44724669
4473typedef uint8_t Vector_1_u8 __attribute__((vector_size(1 * sizeof(uint8_t))));4670typedef 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) {...@@ -14997,6 +15194,242 @@ void c_test_struct_f32_f32_f32_f32_f32(void) {
14997 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);15194 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);
14998}15195}
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
15000struct Struct_f32a8 {15433struct Struct_f32a8 {
15001 alignas(8) float a;15434 alignas(8) float a;
15002};15435};
...@@ -15212,6 +15645,146 @@ void c_test_struct_f64_f64_f64_f64_f64(void) {...@@ -15212,6 +15645,146 @@ void c_test_struct_f64_f64_f64_f64_f64(void) {
15212 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);15645 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);
15213}15646}
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
15215struct Struct_u32_Union_u32_u32u32 {15788struct Struct_u32_Union_u32_u32u32 {
15216 uint32_t a;15789 uint32_t a;
15217 union {15790 union {
...@@ -15326,9 +15899,6 @@ void run_c_tests(void) {...@@ -15326,9 +15899,6 @@ void run_c_tests(void) {
1532615899
15327 zig_five_integers(12, 34, 56, 78, 90);15900 zig_five_integers(12, 34, 56, 78, 90);
1532815901
15329 zig_f32(12.34f);
15330 zig_f64(56.78);
15331 zig_longdouble(12.34l);
15332 zig_five_floats(1.0f, 2.0f, 3.0f, 4.0f, 5.0f);15902 zig_five_floats(1.0f, 2.0f, 3.0f, 4.0f, 5.0f);
1533315903
15334 zig_ptr((void *)0xdeadbeefL);15904 zig_ptr((void *)0xdeadbeefL);
...@@ -15377,8 +15947,7 @@ void run_c_tests(void) {...@@ -15377,8 +15947,7 @@ void run_c_tests(void) {
15377#if !(defined(__i386__) && defined(_WIN32))15947#if !(defined(__i386__) && defined(_WIN32))
15378#ifndef __loongarch__15948#ifndef __loongarch__
15379#ifndef ZIG_MIPS6415949#ifndef ZIG_MIPS64
15380#ifndef __powerpc__15950#ifndef ZIG_PPC32
15381#ifndef __s390x__
15382 {15951 {
15383 struct Struct_i32_i32 s = {1, 2};15952 struct Struct_i32_i32 s = {1, 2};
15384 zig_struct_i32_i32(s);15953 zig_struct_i32_i32(s);
...@@ -15387,13 +15956,11 @@ void run_c_tests(void) {...@@ -15387,13 +15956,11 @@ void run_c_tests(void) {
15387#endif15956#endif
15388#endif15957#endif
15389#endif15958#endif
15390#endif
1539115959
15392#ifndef __hexagon__15960#ifndef __hexagon__
15393#ifndef __loongarch__15961#ifndef __loongarch__
15394#ifndef ZIG_MIPS6415962#ifndef ZIG_MIPS64
15395#ifndef __powerpc__15963#ifndef ZIG_PPC32
15396#ifndef __s390x__
15397 {15964 {
15398 struct BigStruct s = {1, 2, 3, 4, 5};15965 struct BigStruct s = {1, 2, 3, 4, 5};
15399 zig_big_struct(s);15966 zig_big_struct(s);
...@@ -15402,7 +15969,6 @@ void run_c_tests(void) {...@@ -15402,7 +15969,6 @@ void run_c_tests(void) {
15402#endif15969#endif
15403#endif15970#endif
15404#endif15971#endif
15405#endif
1540615972
15407#ifndef ZIG_NO_I12815973#ifndef ZIG_NO_I128
15408 {15974 {
...@@ -15426,8 +15992,7 @@ void run_c_tests(void) {...@@ -15426,8 +15992,7 @@ void run_c_tests(void) {
15426#ifndef __i386__15992#ifndef __i386__
15427#ifndef __loongarch__15993#ifndef __loongarch__
15428#ifndef ZIG_MIPS6415994#ifndef ZIG_MIPS64
15429#ifndef __powerpc__15995#ifndef ZIG_PPC32
15430#ifndef __s390x__
15431 {15996 {
15432 struct SplitStructInts s = {1234, 100, 1337};15997 struct SplitStructInts s = {1234, 100, 1337};
15433 zig_split_struct_ints(s);15998 zig_split_struct_ints(s);
...@@ -15437,13 +16002,11 @@ void run_c_tests(void) {...@@ -15437,13 +16002,11 @@ void run_c_tests(void) {
15437#endif16002#endif
15438#endif16003#endif
15439#endif16004#endif
15440#endif
1544116005
15442#ifndef __hexagon__16006#ifndef __hexagon__
15443#ifndef __loongarch__16007#ifndef __loongarch__
15444#ifndef ZIG_MIPS6416008#ifndef ZIG_MIPS64
15445#ifndef __powerpc__16009#ifndef ZIG_PPC32
15446#ifndef __s390x__
15447 {16010 {
15448 struct MedStructMixed s = {1234, 100.0f, 1337.0f};16011 struct MedStructMixed s = {1234, 100.0f, 1337.0f};
15449 zig_med_struct_mixed(s);16012 zig_med_struct_mixed(s);
...@@ -15452,14 +16015,12 @@ void run_c_tests(void) {...@@ -15452,14 +16015,12 @@ void run_c_tests(void) {
15452#endif16015#endif
15453#endif16016#endif
15454#endif16017#endif
15455#endif
1545616018
15457#ifndef __hexagon__16019#ifndef __hexagon__
15458#ifndef __i386__16020#ifndef __i386__
15459#ifndef __loongarch__16021#ifndef __loongarch__
15460#ifndef ZIG_MIPS6416022#ifndef ZIG_MIPS64
15461#ifndef __powerpc__16023#ifndef ZIG_PPC32
15462#ifndef __s390x__
15463 {16024 {
15464 struct SplitStructMixed s = {1234, 100, 1337.0f};16025 struct SplitStructMixed s = {1234, 100, 1337.0f};
15465 zig_split_struct_mixed(s);16026 zig_split_struct_mixed(s);
...@@ -15469,13 +16030,11 @@ void run_c_tests(void) {...@@ -15469,13 +16030,11 @@ void run_c_tests(void) {
15469#endif16030#endif
15470#endif16031#endif
15471#endif16032#endif
15472#endif
1547316033
15474#ifndef __hexagon__16034#ifndef __hexagon__
15475#ifndef __loongarch__16035#ifndef __loongarch__
15476#ifndef ZIG_MIPS6416036#ifndef ZIG_MIPS64
15477#ifndef __powerpc__16037#ifndef ZIG_PPC32
15478#ifndef __s390x__
15479 {16038 {
15480 struct BigStruct s = {30, 31, 32, 33, 34};16039 struct BigStruct s = {30, 31, 32, 33, 34};
15481 struct BigStruct res = zig_big_struct_both(s);16040 struct BigStruct res = zig_big_struct_both(s);
...@@ -15488,7 +16047,6 @@ void run_c_tests(void) {...@@ -15488,7 +16047,6 @@ void run_c_tests(void) {
15488#endif16047#endif
15489#endif16048#endif
15490#endif16049#endif
15491#endif
15492#endif16050#endif
1549316051
15494 {16052 {
...@@ -15550,18 +16108,6 @@ void c_struct_i128(struct i128 x) {...@@ -15550,18 +16108,6 @@ void c_struct_i128(struct i128 x) {
15550}16108}
15551#endif16109#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
15565void c_ptr(void *x) {16111void c_ptr(void *x) {
15566 assert_or_panic(x == (void *)0xdeadbeefL);16112 assert_or_panic(x == (void *)0xdeadbeefL);
15567}16113}
...@@ -16078,6 +16624,16 @@ struct ByRef __attribute__((sysv_abi)) c_explict_sys_v(struct ByRef in) {...@@ -16078,6 +16624,16 @@ struct ByRef __attribute__((sysv_abi)) c_explict_sys_v(struct ByRef in) {
16078}16624}
16079#endif16625#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
16081struct byval_tail_callsite_attr_Point {16637struct byval_tail_callsite_attr_Point {
16082 double x;16638 double x;
16083 double y;16639 double y;
...@@ -16212,7 +16768,13 @@ void __attribute__((vectorcall)) c_vectorcall_check(int a, float b, double c, vo...@@ -16212,7 +16768,13 @@ void __attribute__((vectorcall)) c_vectorcall_check(int a, float b, double c, vo
16212}16768}
16213#endif16769#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
16216void c_win64_varargs_u64_f64_u64_f64(uint64_t a, double b, uint64_t c, double d) {16778void c_win64_varargs_u64_f64_u64_f64(uint64_t a, double b, uint64_t c, double d) {
16217 assert_or_panic(a == UINT64_C(0x3ff0000000000000));16779 assert_or_panic(a == UINT64_C(0x3ff0000000000000));
16218 assert_or_panic(b == 2.0);16780 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)...@@ -16225,4 +16787,3 @@ void c_win64_varargs_f64_u64_f64_u64(double a, uint64_t b, double c, uint64_t d)
16225 assert_or_panic(c == 7.0);16787 assert_or_panic(c == 7.0);
16226 assert_or_panic(d == UINT64_C(0x4020000000000000));16788 assert_or_panic(d == UINT64_C(0x4020000000000000));
16227}16789}
16228#endif
test/c_abi/main.zig+1049-286
...@@ -13,7 +13,7 @@ const expectEqual = std.testing.expectEqual;...@@ -13,7 +13,7 @@ const expectEqual = std.testing.expectEqual;
13const have_i128 = builtin.cpu.arch != .x86 and !builtin.cpu.arch.isArm() and13const have_i128 = builtin.cpu.arch != .x86 and !builtin.cpu.arch.isArm() and
14 !builtin.cpu.arch.isMIPS() and !builtin.cpu.arch.isPowerPC32() and builtin.cpu.arch != .riscv32 and14 !builtin.cpu.arch.isMIPS() and !builtin.cpu.arch.isPowerPC32() and builtin.cpu.arch != .riscv32 and
15 builtin.cpu.arch != .hexagon and15 builtin.cpu.arch != .hexagon and
16 builtin.cpu.arch != .s390x; // https://github.com/llvm/llvm-project/issues/16846016 builtin.cpu.arch != .s390x;
1717
18const have_f128 = builtin.cpu.arch.isWasm() or (builtin.cpu.arch.isX86() and !builtin.os.tag.isDarwin() and builtin.abi != .msvc);18const have_f128 = builtin.cpu.arch.isWasm() or (builtin.cpu.arch.isX86() and !builtin.os.tag.isDarwin() and builtin.abi != .msvc);
19const have_f80 = builtin.cpu.arch.isX86() and builtin.abi != .msvc;19const have_f80 = builtin.cpu.arch.isX86() and builtin.abi != .msvc;
...@@ -104,10 +104,6 @@ export fn zig_struct_u128(a: U128) void {...@@ -104,10 +104,6 @@ export fn zig_struct_u128(a: U128) void {
104 expect(a.value == 0xfffffffffffffffc) catch @panic("test failure: zig_struct_u128");104 expect(a.value == 0xfffffffffffffffc) catch @panic("test failure: zig_struct_u128");
105}105}
106106
107extern fn c_f32(f32) void;
108extern fn c_f64(f64) void;
109extern fn c_long_double(c_longdouble) void;
110
111// On windows x64, the first 4 are passed via registers, others on the stack.107// On windows x64, the first 4 are passed via registers, others on the stack.
112extern fn c_five_floats(f32, f32, f32, f32, f32) void;108extern 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 {...@@ -120,28 +116,9 @@ export fn zig_five_floats(a: f32, b: f32, c: f32, d: f32, e: f32) void {
120}116}
121117
122test "floats" {118test "floats" {
123 c_f32(12.34);
124 c_f64(56.78);
125 c_five_floats(1.0, 2.0, 3.0, 4.0, 5.0);119 c_five_floats(1.0, 2.0, 3.0, 4.0, 5.0);
126}120}
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
145extern fn c_ptr(*anyopaque) void;122extern fn c_ptr(*anyopaque) void;
146123
147test "pointer" {124test "pointer" {
...@@ -184,7 +161,7 @@ extern fn c_cmultf(a: ComplexFloat, b: ComplexFloat) ComplexFloat;...@@ -184,7 +161,7 @@ extern fn c_cmultf(a: ComplexFloat, b: ComplexFloat) ComplexFloat;
184extern fn c_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble;161extern fn c_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble;
185162
186const complex_abi_compatible = builtin.cpu.arch != .x86 and !builtin.cpu.arch.isMIPS() and163const 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() and164 !builtin.cpu.arch.isArm() and !builtin.cpu.arch.isPowerPC() and !builtin.cpu.arch.isRISCV() and
188 builtin.cpu.arch != .hexagon and165 builtin.cpu.arch != .hexagon and
189 builtin.cpu.arch != .s390x and166 builtin.cpu.arch != .s390x and
190 !(builtin.cpu.arch.isLoongArch() and builtin.abi.float() == .soft);167 !(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...@@ -269,10 +246,217 @@ export fn zig_cmultd_comp(a_r: f64, a_i: f64, b_r: f64, b_i: f64) ComplexDouble
269 return .{ .real = 1.5, .imag = 13.5 };246 return .{ .real = 1.5, .imag = 13.5 };
270}247}
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
272comptime {452comptime {
273 skip: {453 skip: {
274 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;454 if (builtin.zig_backend == .stage2_wasm) break :skip;
275 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) 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
277 _ = struct {461 _ = struct {
278 export fn zig_ret_vector_2_bool() @Vector(2, bool) {462 export fn zig_ret_vector_2_bool() @Vector(2, bool) {
...@@ -294,7 +478,14 @@ extern fn c_vector_2_bool(@Vector(2, bool)) void;...@@ -294,7 +478,14 @@ extern fn c_vector_2_bool(@Vector(2, bool)) void;
294extern fn c_test_vector_2_bool() void;478extern fn c_test_vector_2_bool() void;
295479
296test "@Vector(2, bool)" {480test "@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
299 const vec = c_ret_vector_2_bool();490 const vec = c_ret_vector_2_bool();
300 try expect(vec[0] == true);491 try expect(vec[0] == true);
...@@ -308,8 +499,12 @@ test "@Vector(2, bool)" {...@@ -308,8 +499,12 @@ test "@Vector(2, bool)" {
308499
309comptime {500comptime {
310 skip: {501 skip: {
311 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;502 if (builtin.zig_backend == .stage2_wasm) break :skip;
312 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) 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
314 _ = struct {509 _ = struct {
315 export fn zig_ret_vector_4_bool() @Vector(4, bool) {510 export fn zig_ret_vector_4_bool() @Vector(4, bool) {
...@@ -335,7 +530,14 @@ extern fn c_vector_4_bool(@Vector(4, bool)) void;...@@ -335,7 +530,14 @@ extern fn c_vector_4_bool(@Vector(4, bool)) void;
335extern fn c_test_vector_4_bool() void;530extern fn c_test_vector_4_bool() void;
336531
337test "@Vector(4, bool)" {532test "@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
340 const vec = c_ret_vector_4_bool();542 const vec = c_ret_vector_4_bool();
341 try expect(vec[0] == true);543 try expect(vec[0] == true);
...@@ -353,8 +555,12 @@ test "@Vector(4, bool)" {...@@ -353,8 +555,12 @@ test "@Vector(4, bool)" {
353555
354comptime {556comptime {
355 skip: {557 skip: {
356 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;558 if (builtin.zig_backend == .stage2_wasm) break :skip;
357 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) 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
359 _ = struct {565 _ = struct {
360 export fn zig_ret_vector_8_bool() @Vector(8, bool) {566 export fn zig_ret_vector_8_bool() @Vector(8, bool) {
...@@ -388,7 +594,14 @@ extern fn c_vector_8_bool(@Vector(8, bool)) void;...@@ -388,7 +594,14 @@ extern fn c_vector_8_bool(@Vector(8, bool)) void;
388extern fn c_test_vector_8_bool() void;594extern fn c_test_vector_8_bool() void;
389595
390test "@Vector(8, bool)" {596test "@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
393 const vec = c_ret_vector_8_bool();606 const vec = c_ret_vector_8_bool();
394 try expect(vec[0] == false);607 try expect(vec[0] == false);
...@@ -414,8 +627,12 @@ test "@Vector(8, bool)" {...@@ -414,8 +627,12 @@ test "@Vector(8, bool)" {
414627
415comptime {628comptime {
416 skip: {629 skip: {
417 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;630 if (builtin.zig_backend == .stage2_wasm) break :skip;
418 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) 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
420 _ = struct {637 _ = struct {
421 export fn zig_ret_vector_16_bool() @Vector(16, bool) {638 export fn zig_ret_vector_16_bool() @Vector(16, bool) {
...@@ -465,7 +682,14 @@ extern fn c_vector_16_bool(@Vector(16, bool)) void;...@@ -465,7 +682,14 @@ extern fn c_vector_16_bool(@Vector(16, bool)) void;
465extern fn c_test_vector_16_bool() void;682extern fn c_test_vector_16_bool() void;
466683
467test "@Vector(16, bool)" {684test "@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
470 const vec = c_ret_vector_16_bool();694 const vec = c_ret_vector_16_bool();
471 try expect(vec[0] == true);695 try expect(vec[0] == true);
...@@ -507,8 +731,12 @@ test "@Vector(16, bool)" {...@@ -507,8 +731,12 @@ test "@Vector(16, bool)" {
507731
508comptime {732comptime {
509 skip: {733 skip: {
510 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;734 if (builtin.zig_backend == .stage2_wasm) break :skip;
511 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) 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
513 _ = struct {741 _ = struct {
514 export fn zig_ret_vector_32_bool() @Vector(32, bool) {742 export fn zig_ret_vector_32_bool() @Vector(32, bool) {
...@@ -590,7 +818,14 @@ extern fn c_vector_32_bool(@Vector(32, bool)) void;...@@ -590,7 +818,14 @@ extern fn c_vector_32_bool(@Vector(32, bool)) void;
590extern fn c_test_vector_32_bool() void;818extern fn c_test_vector_32_bool() void;
591819
592test "@Vector(32, bool)" {820test "@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
595 const vec = c_ret_vector_32_bool();830 const vec = c_ret_vector_32_bool();
596 try expect(vec[0] == true);831 try expect(vec[0] == true);
...@@ -664,8 +899,12 @@ test "@Vector(32, bool)" {...@@ -664,8 +899,12 @@ test "@Vector(32, bool)" {
664899
665comptime {900comptime {
666 skip: {901 skip: {
667 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;902 if (builtin.zig_backend == .stage2_wasm) break :skip;
668 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) 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
670 _ = struct {909 _ = struct {
671 export fn zig_ret_vector_64_bool() @Vector(64, bool) {910 export fn zig_ret_vector_64_bool() @Vector(64, bool) {
...@@ -811,7 +1050,12 @@ extern fn c_vector_64_bool(@Vector(64, bool)) void;...@@ -811,7 +1050,12 @@ extern fn c_vector_64_bool(@Vector(64, bool)) void;
811extern fn c_test_vector_64_bool() void;1050extern fn c_test_vector_64_bool() void;
8121051
813test "@Vector(64, bool)" {1052test "@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
816 const vec = c_ret_vector_64_bool();1060 const vec = c_ret_vector_64_bool();
817 try expect(vec[0] == false);1061 try expect(vec[0] == false);
...@@ -949,8 +1193,12 @@ test "@Vector(64, bool)" {...@@ -949,8 +1193,12 @@ test "@Vector(64, bool)" {
9491193
950comptime {1194comptime {
951 skip: {1195 skip: {
952 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;1196 if (builtin.zig_backend == .stage2_wasm) break :skip;
953 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) 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
955 _ = struct {1203 _ = struct {
956 export fn zig_ret_vector_128_bool() @Vector(128, bool) {1204 export fn zig_ret_vector_128_bool() @Vector(128, bool) {
...@@ -1224,7 +1472,12 @@ extern fn c_vector_128_bool(@Vector(128, bool)) void;...@@ -1224,7 +1472,12 @@ extern fn c_vector_128_bool(@Vector(128, bool)) void;
1224extern fn c_test_vector_128_bool() void;1472extern fn c_test_vector_128_bool() void;
12251473
1226test "@Vector(128, bool)" {1474test "@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
1229 const vec = c_ret_vector_128_bool();1482 const vec = c_ret_vector_128_bool();
1230 try expect(vec[0] == false);1483 try expect(vec[0] == false);
...@@ -1490,8 +1743,12 @@ test "@Vector(128, bool)" {...@@ -1490,8 +1743,12 @@ test "@Vector(128, bool)" {
14901743
1491comptime {1744comptime {
1492 skip: {1745 skip: {
1493 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;1746 if (builtin.zig_backend == .stage2_wasm) break :skip;
1494 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) 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
1496 _ = struct {1753 _ = struct {
1497 export fn zig_ret_vector_256_bool() @Vector(256, bool) {1754 export fn zig_ret_vector_256_bool() @Vector(256, bool) {
...@@ -2021,7 +2278,12 @@ extern fn c_vector_256_bool(@Vector(256, bool)) void;...@@ -2021,7 +2278,12 @@ extern fn c_vector_256_bool(@Vector(256, bool)) void;
2021extern fn c_test_vector_256_bool() void;2278extern fn c_test_vector_256_bool() void;
20222279
2023test "@Vector(256, bool)" {2280test "@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
2026 const vec = c_ret_vector_256_bool();2288 const vec = c_ret_vector_256_bool();
2027 try expect(vec[0] == true);2289 try expect(vec[0] == true);
...@@ -2543,8 +2805,12 @@ test "@Vector(256, bool)" {...@@ -2543,8 +2805,12 @@ test "@Vector(256, bool)" {
25432805
2544comptime {2806comptime {
2545 skip: {2807 skip: {
2546 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;2808 if (builtin.zig_backend == .stage2_wasm) break :skip;
2547 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) 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
2549 _ = struct {2815 _ = struct {
2550 export fn zig_ret_vector_512_bool() @Vector(512, bool) {2816 export fn zig_ret_vector_512_bool() @Vector(512, bool) {
...@@ -3586,7 +3852,12 @@ extern fn c_vector_512_bool(@Vector(512, bool)) void;...@@ -3586,7 +3852,12 @@ extern fn c_vector_512_bool(@Vector(512, bool)) void;
3586extern fn c_test_vector_512_bool() void;3852extern fn c_test_vector_512_bool() void;
35873853
3588test "@Vector(512, bool)" {3854test "@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
3591 const vec = c_ret_vector_512_bool();3862 const vec = c_ret_vector_512_bool();
3592 try expect(vec[0] == false);3863 try expect(vec[0] == false);
...@@ -4660,7 +4931,7 @@ test "@Vector(2, u8)" {...@@ -4660,7 +4931,7 @@ test "@Vector(2, u8)" {
4660 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;4931 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
4661 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;4932 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
4662 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;4933 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
4665 const v = c_ret_vector_2_u8();4936 const v = c_ret_vector_2_u8();
4666 try expect(v[0] == 9);4937 try expect(v[0] == 9);
...@@ -4689,7 +4960,6 @@ test "@Vector(3, u8)" {...@@ -4689,7 +4960,6 @@ test "@Vector(3, u8)" {
4689 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;4960 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
4690 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;4961 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
4691 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;4962 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
4694 const v = c_ret_vector_3_u8();4964 const v = c_ret_vector_3_u8();
4695 try expect(v[0] == 19);4965 try expect(v[0] == 19);
...@@ -4732,7 +5002,7 @@ test "@Vector(4, u8)" {...@@ -4732,7 +5002,7 @@ test "@Vector(4, u8)" {
4732 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;5002 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
4733 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;5003 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
4734 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;5004 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
4737 const v = c_ret_vector_4_u8();5007 const v = c_ret_vector_4_u8();
4738 try expect(v[0] == 41);5008 try expect(v[0] == 41);
...@@ -4766,7 +5036,6 @@ test "@Vector(6, u8)" {...@@ -4766,7 +5036,6 @@ test "@Vector(6, u8)" {
4766 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;5036 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
4767 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;5037 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
4768 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;5038 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
4771 const v = c_ret_vector_6_u8();5040 const v = c_ret_vector_6_u8();
4772 try expect(v[0] == 53);5041 try expect(v[0] == 53);
...@@ -4956,7 +5225,6 @@ test "@Vector(24, u8)" {...@@ -4956,7 +5225,6 @@ test "@Vector(24, u8)" {
4956 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;5225 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
4957 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;5226 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
4958 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;5227 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
4959 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
49605228
4961 const v = c_ret_vector_24_u8();5229 const v = c_ret_vector_24_u8();
4962 try expect(v[0] == 57);5230 try expect(v[0] == 57);
...@@ -5040,7 +5308,6 @@ test "@Vector(32, u8)" {...@@ -5040,7 +5308,6 @@ test "@Vector(32, u8)" {
5040 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;5308 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
5041 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;5309 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
5042 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;5310 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
5043 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
50445311
5045 const v = c_ret_vector_32_u8();5312 const v = c_ret_vector_32_u8();
5046 try expect(v[0] == 69);5313 try expect(v[0] == 69);
...@@ -5150,7 +5417,6 @@ test "@Vector(48, u8)" {...@@ -5150,7 +5417,6 @@ test "@Vector(48, u8)" {
5150 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;5417 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
5151 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;5418 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
5152 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;5419 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
5153 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
51545420
5155 const v = c_ret_vector_48_u8();5421 const v = c_ret_vector_48_u8();
5156 try expect(v[0] == 29);5422 try expect(v[0] == 29);
...@@ -5293,7 +5559,6 @@ test "@Vector(64, u8)" {...@@ -5293,7 +5559,6 @@ test "@Vector(64, u8)" {
5293 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;5559 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
5294 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;5560 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
5295 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;5561 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
5296 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
52975562
5298 const v = c_ret_vector_64_u8();5563 const v = c_ret_vector_64_u8();
5299 try expect(v[0] == 53);5564 try expect(v[0] == 53);
...@@ -5488,7 +5753,6 @@ test "@Vector(96, u8)" {...@@ -5488,7 +5753,6 @@ test "@Vector(96, u8)" {
5488 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;5753 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
5489 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;5754 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
5490 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;5755 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
5491 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
54925756
5493 const v = c_ret_vector_96_u8();5757 const v = c_ret_vector_96_u8();
5494 try expect(v[0] == 82);5758 try expect(v[0] == 82);
...@@ -5751,7 +6015,6 @@ test "@Vector(128, u8)" {...@@ -5751,7 +6015,6 @@ test "@Vector(128, u8)" {
5751 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;6015 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
5752 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;6016 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
5753 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;6017 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
5754 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
57556018
5756 const v = c_ret_vector_128_u8();6019 const v = c_ret_vector_128_u8();
5757 try expect(v[0] == 30);6020 try expect(v[0] == 30);
...@@ -6116,7 +6379,6 @@ test "@Vector(192, u8)" {...@@ -6116,7 +6379,6 @@ test "@Vector(192, u8)" {
6116 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;6379 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
6117 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;6380 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
6118 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;6381 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
6119 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
61206382
6121 const v = c_ret_vector_192_u8();6383 const v = c_ret_vector_192_u8();
6122 try expect(v[0] == 70);6384 try expect(v[0] == 70);
...@@ -6617,7 +6879,6 @@ test "@Vector(256, u8)" {...@@ -6617,7 +6879,6 @@ test "@Vector(256, u8)" {
6617 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;6879 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
6618 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;6880 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
6619 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;6881 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
6620 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
66216882
6622 const v = c_ret_vector_256_u8();6883 const v = c_ret_vector_256_u8();
6623 try expect(v[0] == 66);6884 try expect(v[0] == 66);
...@@ -7322,7 +7583,6 @@ test "@Vector(384, u8)" {...@@ -7322,7 +7583,6 @@ test "@Vector(384, u8)" {
7322 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;7583 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
7323 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;7584 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
7324 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;7585 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
7325 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
73267586
7327 const v = c_ret_vector_384_u8();7587 const v = c_ret_vector_384_u8();
7328 try expect(v[0] == 46);7588 try expect(v[0] == 46);
...@@ -8299,7 +8559,6 @@ test "@Vector(512, u8)" {...@@ -8299,7 +8559,6 @@ test "@Vector(512, u8)" {
8299 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;8559 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
8300 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;8560 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
8301 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;8561 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
8302 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
83038562
8304 const v = c_ret_vector_512_u8();8563 const v = c_ret_vector_512_u8();
8305 try expect(v[0] == 38);8564 try expect(v[0] == 38);
...@@ -8893,7 +9152,7 @@ test "@Vector(2, u16)" {...@@ -8893,7 +9152,7 @@ test "@Vector(2, u16)" {
8893 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;9152 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
8894 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;9153 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
8895 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;9154 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
8898 const v = c_ret_vector_2_u16();9157 const v = c_ret_vector_2_u16();
8899 try expect(v[0] == 9);9158 try expect(v[0] == 9);
...@@ -8921,7 +9180,6 @@ test "@Vector(3, u16)" {...@@ -8921,7 +9180,6 @@ test "@Vector(3, u16)" {
8921 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;9180 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
8922 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;9181 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
8923 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;9182 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
8926 const v = c_ret_vector_3_u16();9184 const v = c_ret_vector_3_u16();
8927 try expect(v[0] == 19);9185 try expect(v[0] == 19);
...@@ -9070,7 +9328,6 @@ test "@Vector(12, u16)" {...@@ -9070,7 +9328,6 @@ test "@Vector(12, u16)" {
9070 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;9328 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
9071 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;9329 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
9072 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;9330 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9073 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
90749331
9075 const v = c_ret_vector_12_u16();9332 const v = c_ret_vector_12_u16();
9076 try expect(v[0] == 121);9333 try expect(v[0] == 121);
...@@ -9120,7 +9377,6 @@ test "@Vector(16, u16)" {...@@ -9120,7 +9377,6 @@ test "@Vector(16, u16)" {
9120 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;9377 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
9121 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;9378 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
9122 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;9379 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9123 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
91249380
9125 const v = c_ret_vector_16_u16();9381 const v = c_ret_vector_16_u16();
9126 try expect(v[0] == 177);9382 try expect(v[0] == 177);
...@@ -9186,7 +9442,6 @@ test "@Vector(24, u16)" {...@@ -9186,7 +9442,6 @@ test "@Vector(24, u16)" {
9186 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;9442 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
9187 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;9443 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
9188 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;9444 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9189 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
91909445
9191 const v = c_ret_vector_24_u16();9446 const v = c_ret_vector_24_u16();
9192 try expect(v[0] == 257);9447 try expect(v[0] == 257);
...@@ -9270,7 +9525,6 @@ test "@Vector(32, u16)" {...@@ -9270,7 +9525,6 @@ test "@Vector(32, u16)" {
9270 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;9525 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
9271 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;9526 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
9272 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;9527 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9273 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
92749528
9275 const v = c_ret_vector_32_u16();9529 const v = c_ret_vector_32_u16();
9276 try expect(v[0] == 369);9530 try expect(v[0] == 369);
...@@ -9380,7 +9634,6 @@ test "@Vector(48, u16)" {...@@ -9380,7 +9634,6 @@ test "@Vector(48, u16)" {
9380 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;9634 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
9381 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;9635 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
9382 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;9636 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9383 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
93849637
9385 const v = c_ret_vector_48_u16();9638 const v = c_ret_vector_48_u16();
9386 try expect(v[0] == 529);9639 try expect(v[0] == 529);
...@@ -9524,7 +9777,6 @@ test "@Vector(64, u16)" {...@@ -9524,7 +9777,6 @@ test "@Vector(64, u16)" {
9524 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;9777 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
9525 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;9778 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
9526 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;9779 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9527 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
95289780
9529 const v = c_ret_vector_64_u16();9781 const v = c_ret_vector_64_u16();
9530 try expect(v[0] == 753);9782 try expect(v[0] == 753);
...@@ -9719,7 +9971,6 @@ test "@Vector(96, u16)" {...@@ -9719,7 +9971,6 @@ test "@Vector(96, u16)" {
9719 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;9971 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
9720 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;9972 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
9721 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;9973 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9722 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
97239974
9724 const v = c_ret_vector_96_u16();9975 const v = c_ret_vector_96_u16();
9725 try expect(v[0] == 1082);9976 try expect(v[0] == 1082);
...@@ -9982,7 +10233,6 @@ test "@Vector(128, u16)" {...@@ -9982,7 +10233,6 @@ test "@Vector(128, u16)" {
9982 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;10233 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
9983 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;10234 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
9984 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;10235 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9985 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
998610236
9987 const v = c_ret_vector_128_u16();10237 const v = c_ret_vector_128_u16();
9988 try expect(v[0] == 1530);10238 try expect(v[0] == 1530);
...@@ -10347,7 +10597,6 @@ test "@Vector(192, u16)" {...@@ -10347,7 +10597,6 @@ test "@Vector(192, u16)" {
10347 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;10597 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
10348 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;10598 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
10349 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;10599 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
10350 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1035110600
10352 const v = c_ret_vector_192_u16();10601 const v = c_ret_vector_192_u16();
10353 try expect(v[0] == 2170);10602 try expect(v[0] == 2170);
...@@ -10848,7 +11097,6 @@ test "@Vector(256, u16)" {...@@ -10848,7 +11097,6 @@ test "@Vector(256, u16)" {
10848 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;11097 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
10849 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;11098 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
10850 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;11099 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
10851 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1085211100
10853 const v = c_ret_vector_256_u16();11101 const v = c_ret_vector_256_u16();
10854 try expect(v[0] == 3066);11102 try expect(v[0] == 3066);
...@@ -11265,7 +11513,6 @@ test "@Vector(6, u32)" {...@@ -11265,7 +11513,6 @@ test "@Vector(6, u32)" {
11265 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;11513 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
11266 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;11514 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
11267 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;11515 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11268 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1126911516
11270 const v = c_ret_vector_6_u32();11517 const v = c_ret_vector_6_u32();
11271 try expect(v[0] == 53);11518 try expect(v[0] == 53);
...@@ -11301,7 +11548,6 @@ test "@Vector(8, u32)" {...@@ -11301,7 +11548,6 @@ test "@Vector(8, u32)" {
11301 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;11548 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
11302 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;11549 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
11303 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;11550 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11304 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1130511551
11306 const v = c_ret_vector_8_u32();11552 const v = c_ret_vector_8_u32();
11307 try expect(v[0] == 81);11553 try expect(v[0] == 81);
...@@ -11344,7 +11590,6 @@ test "@Vector(12, u32)" {...@@ -11344,7 +11590,6 @@ test "@Vector(12, u32)" {
11344 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;11590 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
11345 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;11591 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
11346 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;11592 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11347 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1134811593
11349 const v = c_ret_vector_12_u32();11594 const v = c_ret_vector_12_u32();
11350 try expect(v[0] == 121);11595 try expect(v[0] == 121);
...@@ -11394,7 +11639,6 @@ test "@Vector(16, u32)" {...@@ -11394,7 +11639,6 @@ test "@Vector(16, u32)" {
11394 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;11639 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
11395 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;11640 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
11396 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;11641 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11397 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1139811642
11399 const v = c_ret_vector_16_u32();11643 const v = c_ret_vector_16_u32();
11400 try expect(v[0] == 177);11644 try expect(v[0] == 177);
...@@ -11460,7 +11704,6 @@ test "@Vector(24, u32)" {...@@ -11460,7 +11704,6 @@ test "@Vector(24, u32)" {
11460 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;11704 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
11461 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;11705 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
11462 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;11706 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11463 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1146411707
11465 const v = c_ret_vector_24_u32();11708 const v = c_ret_vector_24_u32();
11466 try expect(v[0] == 257);11709 try expect(v[0] == 257);
...@@ -11545,7 +11788,6 @@ test "@Vector(32, u32)" {...@@ -11545,7 +11788,6 @@ test "@Vector(32, u32)" {
11545 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;11788 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
11546 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;11789 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
11547 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;11790 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11548 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1154911791
11550 const v = c_ret_vector_32_u32();11792 const v = c_ret_vector_32_u32();
11551 try expect(v[0] == 369);11793 try expect(v[0] == 369);
...@@ -11655,7 +11897,6 @@ test "@Vector(48, u32)" {...@@ -11655,7 +11897,6 @@ test "@Vector(48, u32)" {
11655 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;11897 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
11656 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;11898 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
11657 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;11899 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11658 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1165911900
11660 const v = c_ret_vector_48_u32();11901 const v = c_ret_vector_48_u32();
11661 try expect(v[0] == 529);11902 try expect(v[0] == 529);
...@@ -11799,7 +12040,6 @@ test "@Vector(64, u32)" {...@@ -11799,7 +12040,6 @@ test "@Vector(64, u32)" {
11799 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;12040 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
11800 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;12041 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
11801 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;12042 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11802 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1180312043
11804 const v = c_ret_vector_64_u32();12044 const v = c_ret_vector_64_u32();
11805 try expect(v[0] == 753);12045 try expect(v[0] == 753);
...@@ -11994,7 +12234,6 @@ test "@Vector(96, u32)" {...@@ -11994,7 +12234,6 @@ test "@Vector(96, u32)" {
11994 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;12234 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
11995 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;12235 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
11996 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;12236 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11997 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1199812237
11999 const v = c_ret_vector_96_u32();12238 const v = c_ret_vector_96_u32();
12000 try expect(v[0] == 1082);12239 try expect(v[0] == 1082);
...@@ -12257,7 +12496,6 @@ test "@Vector(128, u32)" {...@@ -12257,7 +12496,6 @@ test "@Vector(128, u32)" {
12257 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;12496 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
12258 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;12497 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
12259 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;12498 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
12260 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1226112499
12262 const v = c_ret_vector_128_u32();12500 const v = c_ret_vector_128_u32();
12263 try expect(v[0] == 1530);12501 try expect(v[0] == 1530);
...@@ -12414,8 +12652,6 @@ extern fn c_vector_1_u64(@Vector(1, u64), usize) void;...@@ -12414,8 +12652,6 @@ extern fn c_vector_1_u64(@Vector(1, u64), usize) void;
12414extern fn c_test_vector_1_u64() void;12652extern fn c_test_vector_1_u64() void;
1241512653
12416test "@Vector(1, u64)" {12654test "@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
12419 const v = c_ret_vector_1_u64();12655 const v = c_ret_vector_1_u64();
12420 try expect(v[0] == 3);12656 try expect(v[0] == 3);
12421 c_vector_1_u64(.{4}, 1);12657 c_vector_1_u64(.{4}, 1);
...@@ -12464,7 +12700,6 @@ test "@Vector(3, u64)" {...@@ -12464,7 +12700,6 @@ test "@Vector(3, u64)" {
12464 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;12700 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
12465 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;12701 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
12466 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;12702 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
12467 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1246812703
12469 const v = c_ret_vector_3_u64();12704 const v = c_ret_vector_3_u64();
12470 try expect(v[0] == 19);12705 try expect(v[0] == 19);
...@@ -12493,7 +12728,6 @@ test "@Vector(4, u64)" {...@@ -12493,7 +12728,6 @@ test "@Vector(4, u64)" {
12493 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;12728 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
12494 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;12729 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
12495 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;12730 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
12496 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1249712731
12498 const v = c_ret_vector_4_u64();12732 const v = c_ret_vector_4_u64();
12499 try expect(v[0] == 33);12733 try expect(v[0] == 33);
...@@ -12560,7 +12794,6 @@ test "@Vector(8, u64)" {...@@ -12560,7 +12794,6 @@ test "@Vector(8, u64)" {
12560 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;12794 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
12561 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;12795 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
12562 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;12796 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
12563 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1256412797
12565 const v = c_ret_vector_8_u64();12798 const v = c_ret_vector_8_u64();
12566 try expect(v[0] == 81);12799 try expect(v[0] == 81);
...@@ -12652,7 +12885,6 @@ test "@Vector(16, u64)" {...@@ -12652,7 +12885,6 @@ test "@Vector(16, u64)" {
12652 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;12885 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
12653 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;12886 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
12654 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;12887 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
12655 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1265612888
12657 const v = c_ret_vector_16_u64();12889 const v = c_ret_vector_16_u64();
12658 try expect(v[0] == 177);12890 try expect(v[0] == 177);
...@@ -12801,7 +13033,6 @@ test "@Vector(32, u64)" {...@@ -12801,7 +13033,6 @@ test "@Vector(32, u64)" {
12801 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;13033 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
12802 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;13034 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
12803 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;13035 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
12804 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1280513036
12806 const v = c_ret_vector_32_u64();13037 const v = c_ret_vector_32_u64();
12807 try expect(v[0] == 369);13038 try expect(v[0] == 369);
...@@ -13053,7 +13284,6 @@ test "@Vector(64, u64)" {...@@ -13053,7 +13284,6 @@ test "@Vector(64, u64)" {
13053 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;13284 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
13054 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;13285 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
13055 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;13286 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13056 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1305713287
13058 const v = c_ret_vector_64_u64();13288 const v = c_ret_vector_64_u64();
13059 try expect(v[0] == 753);13289 try expect(v[0] == 753);
...@@ -13147,7 +13377,6 @@ test "@Vector(1, f32)" {...@@ -13147,7 +13377,6 @@ test "@Vector(1, f32)" {
13147 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;13377 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
13148 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;13378 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
13149 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;13379 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
13152 const v = c_ret_vector_1_f32();13381 const v = c_ret_vector_1_f32();
13153 try expect(v[0] == 3);13382 try expect(v[0] == 3);
...@@ -13269,7 +13498,6 @@ test "@Vector(6, f32)" {...@@ -13269,7 +13498,6 @@ test "@Vector(6, f32)" {
13269 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;13498 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
13270 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;13499 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
13271 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;13500 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13272 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1327313501
13274 const v = c_ret_vector_6_f32();13502 const v = c_ret_vector_6_f32();
13275 try expect(v[0] == 53);13503 try expect(v[0] == 53);
...@@ -13306,7 +13534,6 @@ test "@Vector(8, f32)" {...@@ -13306,7 +13534,6 @@ test "@Vector(8, f32)" {
13306 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;13534 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
13307 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;13535 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
13308 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;13536 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13309 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1331013537
13311 const v = c_ret_vector_8_f32();13538 const v = c_ret_vector_8_f32();
13312 try expect(v[0] == 81);13539 try expect(v[0] == 81);
...@@ -13349,7 +13576,6 @@ test "@Vector(12, f32)" {...@@ -13349,7 +13576,6 @@ test "@Vector(12, f32)" {
13349 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;13576 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
13350 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;13577 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
13351 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;13578 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13352 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1335313579
13354 const v = c_ret_vector_12_f32();13580 const v = c_ret_vector_12_f32();
13355 try expect(v[0] == 121);13581 try expect(v[0] == 121);
...@@ -13400,7 +13626,6 @@ test "@Vector(16, f32)" {...@@ -13400,7 +13626,6 @@ test "@Vector(16, f32)" {
13400 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;13626 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
13401 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;13627 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
13402 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;13628 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13403 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1340413629
13405 const v = c_ret_vector_16_f32();13630 const v = c_ret_vector_16_f32();
13406 try expect(v[0] == 177);13631 try expect(v[0] == 177);
...@@ -13466,7 +13691,6 @@ test "@Vector(24, f32)" {...@@ -13466,7 +13691,6 @@ test "@Vector(24, f32)" {
13466 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;13691 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
13467 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;13692 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
13468 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;13693 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13469 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1347013694
13471 const v = c_ret_vector_24_f32();13695 const v = c_ret_vector_24_f32();
13472 try expect(v[0] == 257);13696 try expect(v[0] == 257);
...@@ -13551,7 +13775,6 @@ test "@Vector(32, f32)" {...@@ -13551,7 +13775,6 @@ test "@Vector(32, f32)" {
13551 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;13775 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
13552 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;13776 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
13553 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;13777 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13554 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1355513778
13556 const v = c_ret_vector_32_f32();13779 const v = c_ret_vector_32_f32();
13557 try expect(v[0] == 369);13780 try expect(v[0] == 369);
...@@ -13661,7 +13884,6 @@ test "@Vector(48, f32)" {...@@ -13661,7 +13884,6 @@ test "@Vector(48, f32)" {
13661 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;13884 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
13662 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;13885 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
13663 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;13886 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13664 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1366513887
13666 const v = c_ret_vector_48_f32();13888 const v = c_ret_vector_48_f32();
13667 try expect(v[0] == 529);13889 try expect(v[0] == 529);
...@@ -13805,7 +14027,6 @@ test "@Vector(64, f32)" {...@@ -13805,7 +14027,6 @@ test "@Vector(64, f32)" {
13805 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;14027 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
13806 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;14028 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
13807 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;14029 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13808 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1380914030
13810 const v = c_ret_vector_64_f32();14031 const v = c_ret_vector_64_f32();
13811 try expect(v[0] == 753);14032 try expect(v[0] == 753);
...@@ -14000,7 +14221,6 @@ test "@Vector(96, f32)" {...@@ -14000,7 +14221,6 @@ test "@Vector(96, f32)" {
14000 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;14221 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
14001 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;14222 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
14002 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;14223 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14003 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1400414224
14005 const v = c_ret_vector_96_f32();14225 const v = c_ret_vector_96_f32();
14006 try expect(v[0] == 1082);14226 try expect(v[0] == 1082);
...@@ -14263,7 +14483,6 @@ test "@Vector(128, f32)" {...@@ -14263,7 +14483,6 @@ test "@Vector(128, f32)" {
14263 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;14483 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
14264 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;14484 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
14265 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;14485 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14266 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1426714486
14268 const v = c_ret_vector_128_f32();14487 const v = c_ret_vector_128_f32();
14269 try expect(v[0] == 1530);14488 try expect(v[0] == 1530);
...@@ -14471,7 +14690,6 @@ test "@Vector(3, f64)" {...@@ -14471,7 +14690,6 @@ test "@Vector(3, f64)" {
14471 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;14690 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
14472 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;14691 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
14473 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;14692 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14474 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1447514693
14476 const v = c_ret_vector_3_f64();14694 const v = c_ret_vector_3_f64();
14477 try expect(v[0] == 19);14695 try expect(v[0] == 19);
...@@ -14500,8 +14718,6 @@ test "@Vector(4, f64)" {...@@ -14500,8 +14718,6 @@ test "@Vector(4, f64)" {
14500 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;14718 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
14501 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;14719 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
14502 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;14720 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
14506 const v = c_ret_vector_4_f64();14722 const v = c_ret_vector_4_f64();
14507 try expect(v[0] == 33);14723 try expect(v[0] == 33);
...@@ -14534,7 +14750,6 @@ test "@Vector(6, f64)" {...@@ -14534,7 +14750,6 @@ test "@Vector(6, f64)" {
14534 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;14750 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
14535 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;14751 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
14536 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;14752 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14537 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1453814753
14539 const v = c_ret_vector_6_f64();14754 const v = c_ret_vector_6_f64();
14540 try expect(v[0] == 53);14755 try expect(v[0] == 53);
...@@ -14570,8 +14785,6 @@ test "@Vector(8, f64)" {...@@ -14570,8 +14785,6 @@ test "@Vector(8, f64)" {
14570 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;14785 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
14571 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;14786 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
14572 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;14787 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
14576 const v = c_ret_vector_8_f64();14789 const v = c_ret_vector_8_f64();
14577 try expect(v[0] == 81);14790 try expect(v[0] == 81);
...@@ -14614,7 +14827,6 @@ test "@Vector(12, f64)" {...@@ -14614,7 +14827,6 @@ test "@Vector(12, f64)" {
14614 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;14827 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
14615 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;14828 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
14616 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;14829 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14617 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1461814830
14619 const v = c_ret_vector_12_f64();14831 const v = c_ret_vector_12_f64();
14620 try expect(v[0] == 121);14832 try expect(v[0] == 121);
...@@ -14665,7 +14877,6 @@ test "@Vector(16, f64)" {...@@ -14665,7 +14877,6 @@ test "@Vector(16, f64)" {
14665 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;14877 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
14666 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;14878 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
14667 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;14879 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14668 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1466914880
14670 const v = c_ret_vector_16_f64();14881 const v = c_ret_vector_16_f64();
14671 try expect(v[0] == 177);14882 try expect(v[0] == 177);
...@@ -14731,7 +14942,6 @@ test "@Vector(24, f64)" {...@@ -14731,7 +14942,6 @@ test "@Vector(24, f64)" {
14731 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;14942 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
14732 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;14943 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
14733 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;14944 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14734 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1473514945
14736 const v = c_ret_vector_24_f64();14946 const v = c_ret_vector_24_f64();
14737 try expect(v[0] == 257);14947 try expect(v[0] == 257);
...@@ -14816,7 +15026,6 @@ test "@Vector(32, f64)" {...@@ -14816,7 +15026,6 @@ test "@Vector(32, f64)" {
14816 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;15026 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
14817 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;15027 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
14818 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;15028 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14819 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1482015029
14821 const v = c_ret_vector_32_f64();15030 const v = c_ret_vector_32_f64();
14822 try expect(v[0] == 369);15031 try expect(v[0] == 369);
...@@ -14926,7 +15135,6 @@ test "@Vector(48, f64)" {...@@ -14926,7 +15135,6 @@ test "@Vector(48, f64)" {
14926 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;15135 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
14927 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;15136 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
14928 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;15137 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14929 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1493015138
14931 const v = c_ret_vector_48_f64();15139 const v = c_ret_vector_48_f64();
14932 try expect(v[0] == 529);15140 try expect(v[0] == 529);
...@@ -15070,7 +15278,6 @@ test "@Vector(64, f64)" {...@@ -15070,7 +15278,6 @@ test "@Vector(64, f64)" {
15070 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;15278 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
15071 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;15279 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
15072 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;15280 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
15073 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1507415281
15075 const v = c_ret_vector_64_f64();15282 const v = c_ret_vector_64_f64();
15076 try expect(v[0] == 753);15283 try expect(v[0] == 753);
...@@ -15165,7 +15372,6 @@ extern fn c_test_struct_u8() void;...@@ -15165,7 +15372,6 @@ extern fn c_test_struct_u8() void;
15165test "struct u8" {15372test "struct u8" {
15166 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;15373 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15167 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;15374 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15168 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15169 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;15375 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1517015376
15171 const s = c_ret_struct_u8();15377 const s = c_ret_struct_u8();
...@@ -15196,8 +15402,7 @@ test "struct u8, u8" {...@@ -15196,8 +15402,7 @@ test "struct u8, u8" {
15196 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;15402 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
15197 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;15403 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
15198 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;15404 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15199 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;15405 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15200 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15201 if (builtin.cpu.arch == .x86) return error.SkipZigTest;15406 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1520215407
15203 const s = c_ret_struct_u8_u8();15408 const s = c_ret_struct_u8_u8();
...@@ -15231,8 +15436,7 @@ test "struct u8, u8, u8" {...@@ -15231,8 +15436,7 @@ test "struct u8, u8, u8" {
15231 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;15436 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
15232 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;15437 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
15233 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;15438 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15234 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;15439 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15235 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15236 if (builtin.cpu.arch == .x86) return error.SkipZigTest;15440 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1523715441
15238 const s = c_ret_struct_u8_u8_u8();15442 const s = c_ret_struct_u8_u8_u8();
...@@ -15269,8 +15473,7 @@ test "struct u8, u8, u8, u8" {...@@ -15269,8 +15473,7 @@ test "struct u8, u8, u8, u8" {
15269 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;15473 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
15270 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;15474 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
15271 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;15475 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15272 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;15476 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15273 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15274 if (builtin.cpu.arch == .x86) return error.SkipZigTest;15477 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1527515478
15276 const s = c_ret_struct_u8_u8_u8_u8();15479 const s = c_ret_struct_u8_u8_u8_u8();
...@@ -15301,7 +15504,6 @@ extern fn c_test_struct_u16() void;...@@ -15301,7 +15504,6 @@ extern fn c_test_struct_u16() void;
15301test "struct u16" {15504test "struct u16" {
15302 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;15505 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15303 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;15506 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15304 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15305 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;15507 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1530615508
15307 const s = c_ret_struct_u16();15509 const s = c_ret_struct_u16();
...@@ -15332,8 +15534,7 @@ test "struct u16, u16" {...@@ -15332,8 +15534,7 @@ test "struct u16, u16" {
15332 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;15534 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
15333 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;15535 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
15334 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;15536 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15335 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;15537 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15336 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15337 if (builtin.cpu.arch == .x86) return error.SkipZigTest;15538 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1533815539
15339 const s = c_ret_struct_u16_u16();15540 const s = c_ret_struct_u16_u16();
...@@ -15367,9 +15568,8 @@ test "struct u16, u16, u16" {...@@ -15367,9 +15568,8 @@ test "struct u16, u16, u16" {
15367 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;15568 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
15368 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;15569 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
15369 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;15570 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;
15371 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;15572 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
15372 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15373 if (builtin.cpu.arch == .x86) return error.SkipZigTest;15573 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1537415574
15375 const s = c_ret_struct_u16_u16_u16();15575 const s = c_ret_struct_u16_u16_u16();
...@@ -15406,9 +15606,8 @@ test "struct u16, u16, u16, u16" {...@@ -15406,9 +15606,8 @@ test "struct u16, u16, u16, u16" {
15406 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;15606 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
15407 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;15607 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
15408 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;15608 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;
15410 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;15610 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
15411 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15412 if (builtin.cpu.arch == .x86) return error.SkipZigTest;15611 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1541315612
15414 const s = c_ret_struct_u16_u16_u16_u16();15613 const s = c_ret_struct_u16_u16_u16_u16();
...@@ -15439,7 +15638,6 @@ extern fn c_test_struct_u32() void;...@@ -15439,7 +15638,6 @@ extern fn c_test_struct_u32() void;
15439test "struct u32" {15638test "struct u32" {
15440 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;15639 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15441 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;15640 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15442 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15443 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;15641 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1544415642
15445 const s = c_ret_struct_u32();15643 const s = c_ret_struct_u32();
...@@ -15469,9 +15667,8 @@ extern fn c_test_struct_u32_u32() void;...@@ -15469,9 +15667,8 @@ extern fn c_test_struct_u32_u32() void;
15469test "struct u32, u32" {15667test "struct u32, u32" {
15470 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;15668 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
15471 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;15669 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;
15473 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;15671 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
15474 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15475 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;15672 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1547615673
15477 const s = c_ret_struct_u32_u32();15674 const s = c_ret_struct_u32_u32();
...@@ -15505,8 +15702,7 @@ test "struct u32, u32, u32" {...@@ -15505,8 +15702,7 @@ test "struct u32, u32, u32" {
15505 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;15702 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
15506 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;15703 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
15507 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;15704 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15508 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;15705 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15509 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1551015706
15511 const s = c_ret_struct_u32_u32_u32();15707 const s = c_ret_struct_u32_u32_u32();
15512 try expect(s.a == 8);15708 try expect(s.a == 8);
...@@ -15542,8 +15738,7 @@ test "struct u32, u32, u32, u32" {...@@ -15542,8 +15738,7 @@ test "struct u32, u32, u32, u32" {
15542 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;15738 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
15543 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;15739 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
15544 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;15740 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15545 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;15741 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15546 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1554715742
15548 const s = c_ret_struct_u32_u32_u32_u32();15743 const s = c_ret_struct_u32_u32_u32_u32();
15549 try expect(s.a == 10);15744 try expect(s.a == 10);
...@@ -15573,7 +15768,6 @@ extern fn c_test_struct_u64() void;...@@ -15573,7 +15768,6 @@ extern fn c_test_struct_u64() void;
15573test "struct u64" {15768test "struct u64" {
15574 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;15769 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15575 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;15770 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
15576 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15577 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;15771 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1557815772
15579 const s = c_ret_struct_u64();15773 const s = c_ret_struct_u64();
...@@ -15651,7 +15845,6 @@ extern fn c_test_struct_u64_u64() void;...@@ -15651,7 +15845,6 @@ extern fn c_test_struct_u64_u64() void;
15651test "struct u64, u64" {15845test "struct u64, u64" {
15652 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;15846 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
15653 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;15847 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15654 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1565515848
15656 const s = c_ret_struct_u64_u64();15849 const s = c_ret_struct_u64_u64();
15657 try expect(s.a == 21);15850 try expect(s.a == 21);
...@@ -15691,8 +15884,7 @@ extern fn c_test_struct_u64_u64_u64() void;...@@ -15691,8 +15884,7 @@ extern fn c_test_struct_u64_u64_u64() void;
15691test "struct u64, u64, u64" {15884test "struct u64, u64, u64" {
15692 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;15885 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
15693 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;15886 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
15694 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;15887 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15695 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1569615888
15697 const s = c_ret_struct_u64_u64_u64();15889 const s = c_ret_struct_u64_u64_u64();
15698 try expect(s.a == 8);15890 try expect(s.a == 8);
...@@ -15727,8 +15919,7 @@ extern fn c_test_struct_u64_u64_u64_u64() void;...@@ -15727,8 +15919,7 @@ extern fn c_test_struct_u64_u64_u64_u64() void;
15727test "struct u64, u64, u64, u64" {15919test "struct u64, u64, u64, u64" {
15728 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;15920 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
15729 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;15921 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
15730 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;15922 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15731 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1573215923
15733 const s = c_ret_struct_u64_u64_u64_u64();15924 const s = c_ret_struct_u64_u64_u64_u64();
15734 try expect(s.a == 10);15925 try expect(s.a == 10);
...@@ -15757,8 +15948,7 @@ extern fn c_test_struct_f32() void;...@@ -15757,8 +15948,7 @@ extern fn c_test_struct_f32() void;
1575715948
15758test "struct f32" {15949test "struct f32" {
15759 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;15950 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15760 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;15951 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15761 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15762 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;15952 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1576315953
15764 const s = c_ret_struct_f32();15954 const s = c_ret_struct_f32();
...@@ -15791,7 +15981,6 @@ test "struct f32, f32" {...@@ -15791,7 +15981,6 @@ test "struct f32, f32" {
15791 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;15981 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15792 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;15982 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15793 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;15983 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
15794 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15795 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;15984 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1579615985
15797 const s = c_ret_struct_f32_f32();15986 const s = c_ret_struct_f32_f32();
...@@ -15827,7 +16016,6 @@ test "struct f32, f32, f32" {...@@ -15827,7 +16016,6 @@ test "struct f32, f32, f32" {
15827 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;16016 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
15828 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;16017 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15829 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;16018 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15830 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1583116019
15832 const s = c_ret_struct_f32_f32_f32();16020 const s = c_ret_struct_f32_f32_f32();
15833 try expect(s.a == 8);16021 try expect(s.a == 8);
...@@ -15865,7 +16053,6 @@ test "struct f32, f32, f32, f32" {...@@ -15865,7 +16053,6 @@ test "struct f32, f32, f32, f32" {
15865 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;16053 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
15866 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;16054 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15867 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;16055 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15868 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1586916056
15870 const s = c_ret_struct_f32_f32_f32_f32();16057 const s = c_ret_struct_f32_f32_f32_f32();
15871 try expect(s.a == 10);16058 try expect(s.a == 10);
...@@ -15905,7 +16092,6 @@ test "struct f32, f32, f32, f32, f32" {...@@ -15905,7 +16092,6 @@ test "struct f32, f32, f32, f32, f32" {
15905 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;16092 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
15906 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;16093 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15907 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;16094 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15908 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1590916095
15910 const s = c_ret_struct_f32_f32_f32_f32_f32();16096 const s = c_ret_struct_f32_f32_f32_f32_f32();
15911 try expect(s.a == 12);16097 try expect(s.a == 12);
...@@ -15917,31 +16103,408 @@ test "struct f32, f32, f32, f32, f32" {...@@ -15917,31 +16103,408 @@ test "struct f32, f32, f32, f32, f32" {
15917 c_test_struct_f32_f32_f32_f32_f32();16103 c_test_struct_f32_f32_f32_f32_f32();
15918}16104}
1591916105
15920const Struct_f32a8 = extern struct {16106const Struct_void_f32 = extern struct {
15921 a: f32 align(8),16107 _: void = {},
16108 a: f32,
15922};16109};
1592316110
15924export fn zig_ret_struct_f32a8() Struct_f32a8 {16111export fn zig_ret_struct_void_f32() Struct_void_f32 {
15925 return .{ .a = 1.25 };16112 return .{ .a = 1 };
15926}16113}
15927export fn zig_struct_f32a8(s: Struct_f32a8, f: f32) void {16114export fn zig_struct_void_f32(s: Struct_void_f32, i: usize) void {
15928 expect(s.a == 2.75) catch @panic("test failure");16115 expect(s.a == 2) catch @panic("test failure");
15929 expect(f == 3.5) catch @panic("test failure");16116 expect(i == 3) catch @panic("test failure");
15930}16117}
1593116118
15932extern fn c_ret_struct_f32a8() Struct_f32a8;16119extern fn c_ret_struct_void_f32() Struct_void_f32;
15933extern fn c_struct_f32a8(Struct_f32a8, f32) void;16120extern fn c_struct_void_f32(Struct_void_f32, usize) void;
15934extern fn c_test_struct_f32a8() void;16121extern fn c_test_struct_void_f32() void;
1593516122
15936test "struct f32 align(8)" {16123test "struct void, f32" {
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;
15940 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;16124 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15941 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;16125 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15942 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;16126 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
15943 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;16127
15944 if (builtin.cpu.arch == .x86) return error.SkipZigTest;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
15946 const s = c_ret_struct_f32a8();16509 const s = c_ret_struct_f32a8();
15947 try expect(s.a == 4.125);16510 try expect(s.a == 4.125);
...@@ -15974,7 +16537,6 @@ test "struct f32 align(8), f32 align(8)" {...@@ -15974,7 +16537,6 @@ test "struct f32 align(8), f32 align(8)" {
15974 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;16537 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15975 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;16538 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15976 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;16539 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
15977 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15978 if (builtin.cpu.arch == .x86) return error.SkipZigTest;16540 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1597916541
15980 const s = c_ret_struct_f32a8_f32a8();16542 const s = c_ret_struct_f32a8_f32a8();
...@@ -16007,8 +16569,7 @@ test "struct {f32, f32}, f32" {...@@ -16007,8 +16569,7 @@ test "struct {f32, f32}, f32" {
16007 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;16569 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16008 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;16570 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
16009 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;16571 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16010 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;16572 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16011 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1601216573
16013 const s = c_ret_struct_f32f32_f32();16574 const s = c_ret_struct_f32f32_f32();
16014 try expect(s.a.b == 1.0);16575 try expect(s.a.b == 1.0);
...@@ -16041,8 +16602,7 @@ test "struct f32, {f32, f32}" {...@@ -16041,8 +16602,7 @@ test "struct f32, {f32, f32}" {
16041 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;16602 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16042 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;16603 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
16043 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;16604 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16044 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;16605 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16045 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1604616606
16047 const s = c_ret_struct_f32_f32f32();16607 const s = c_ret_struct_f32_f32f32();
16048 try expect(s.a == 1.0);16608 try expect(s.a == 1.0);
...@@ -16070,9 +16630,8 @@ extern fn c_test_struct_f64() void;...@@ -16070,9 +16630,8 @@ extern fn c_test_struct_f64() void;
1607016630
16071test "struct f64" {16631test "struct f64" {
16072 if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;16632 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;
16074 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;16634 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
16075 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16076 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;16635 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1607716636
16078 const s = c_ret_struct_f64();16637 const s = c_ret_struct_f64();
...@@ -16102,8 +16661,7 @@ extern fn c_test_struct_f64_f64() void;...@@ -16102,8 +16661,7 @@ extern fn c_test_struct_f64_f64() void;
16102test "struct f64, f64" {16661test "struct f64, f64" {
16103 if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;16662 if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
16104 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;16663 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16105 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;16664 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16106 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1610716665
16108 const s = c_ret_struct_f64_f64();16666 const s = c_ret_struct_f64_f64();
16109 try expect(s.a == 6);16667 try expect(s.a == 6);
...@@ -16135,8 +16693,7 @@ extern fn c_test_struct_f64_f64_f64() void;...@@ -16135,8 +16693,7 @@ extern fn c_test_struct_f64_f64_f64() void;
16135test "struct f64, f64, f64" {16693test "struct f64, f64, f64" {
16136 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;16694 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16137 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;16695 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
16138 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;16696 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16139 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1614016697
16141 const s = c_ret_struct_f64_f64_f64();16698 const s = c_ret_struct_f64_f64_f64();
16142 try expect(s.a == 8);16699 try expect(s.a == 8);
...@@ -16171,8 +16728,7 @@ extern fn c_test_struct_f64_f64_f64_f64() void;...@@ -16171,8 +16728,7 @@ extern fn c_test_struct_f64_f64_f64_f64() void;
16171test "struct f64, f64, f64, f64" {16728test "struct f64, f64, f64, f64" {
16172 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;16729 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16173 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;16730 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
16174 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;16731 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16175 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1617616732
16177 const s = c_ret_struct_f64_f64_f64_f64();16733 const s = c_ret_struct_f64_f64_f64_f64();
16178 try expect(s.a == 10);16734 try expect(s.a == 10);
...@@ -16210,8 +16766,7 @@ extern fn c_test_struct_f64_f64_f64_f64_f64() void;...@@ -16210,8 +16766,7 @@ extern fn c_test_struct_f64_f64_f64_f64_f64() void;
16210test "struct f64, f64, f64, f64, f64" {16766test "struct f64, f64, f64, f64, f64" {
16211 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;16767 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16212 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;16768 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
16213 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;16769 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16214 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1621516770
16216 const s = c_ret_struct_f64_f64_f64_f64_f64();16771 const s = c_ret_struct_f64_f64_f64_f64_f64();
16217 try expect(s.a == 12);16772 try expect(s.a == 12);
...@@ -16223,6 +16778,201 @@ test "struct f64, f64, f64, f64, f64" {...@@ -16223,6 +16778,201 @@ test "struct f64, f64, f64, f64, f64" {
16223 c_test_struct_f64_f64_f64_f64_f64();16778 c_test_struct_f64_f64_f64_f64_f64();
16224}16779}
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
16226const Struct_u32_Union_u32_u32u32 = extern struct {16976const Struct_u32_Union_u32_u32u32 = extern struct {
16227 a: u32,16977 a: u32,
16228 b: extern union {16978 b: extern union {
...@@ -16250,8 +17000,7 @@ test "struct{u32,union{u32,struct{u32,u32}}}" {...@@ -16250,8 +17000,7 @@ test "struct{u32,union{u32,struct{u32,u32}}}" {
16250 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;17000 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16251 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;17001 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
16252 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;17002 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16253 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;17003 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16254 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1625517004
16256 const s = c_ret_struct_u32_union_u32_u32u32();17005 const s = c_ret_struct_u32_union_u32_u32u32();
16257 try expect(s.a == 1);17006 try expect(s.a == 1);
...@@ -16269,11 +17018,10 @@ extern fn c_mut_struct_i32_i32(Struct_i32_i32) Struct_i32_i32;...@@ -16269,11 +17018,10 @@ extern fn c_mut_struct_i32_i32(Struct_i32_i32) Struct_i32_i32;
16269extern fn c_struct_i32_i32(Struct_i32_i32) void;17018extern fn c_struct_i32_i32(Struct_i32_i32) void;
1627017019
16271test "struct i32 i32" {17020test "struct i32 i32" {
17021 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16272 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;17022 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;
16274 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;17024 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;
16277 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;17025 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1627817026
16279 const s: Struct_i32_i32 = .{17027 const s: Struct_i32_i32 = .{
...@@ -16303,11 +17051,10 @@ const BigStruct = extern struct {...@@ -16303,11 +17051,10 @@ const BigStruct = extern struct {
16303extern fn c_big_struct(BigStruct) void;17051extern fn c_big_struct(BigStruct) void;
1630417052
16305test "big struct" {17053test "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;
16309 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;17054 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
16312 const s = BigStruct{17059 const s = BigStruct{
16313 .a = 1,17060 .a = 1,
...@@ -16333,10 +17080,9 @@ const BigUnion = extern union {...@@ -16333,10 +17080,9 @@ const BigUnion = extern union {
16333extern fn c_big_union(BigUnion) void;17080extern fn c_big_union(BigUnion) void;
1633417081
16335test "big union" {17082test "big union" {
16336 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16337 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16338 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;17083 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
16341 const x = BigUnion{17087 const x = BigUnion{
16342 .a = BigStruct{17088 .a = BigStruct{
...@@ -16368,11 +17114,10 @@ extern fn c_med_struct_mixed(MedStructMixed) void;...@@ -16368,11 +17114,10 @@ extern fn c_med_struct_mixed(MedStructMixed) void;
16368extern fn c_ret_med_struct_mixed() MedStructMixed;17114extern fn c_ret_med_struct_mixed() MedStructMixed;
1636917115
16370test "medium struct of ints and floats" {17116test "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;
16374 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;17117 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
16377 const s = MedStructMixed{17122 const s = MedStructMixed{
16378 .a = 1234,17123 .a = 1234,
...@@ -16448,12 +17193,11 @@ const SplitStructInt = extern struct {...@@ -16448,12 +17193,11 @@ const SplitStructInt = extern struct {
16448extern fn c_split_struct_ints(SplitStructInt) void;17193extern fn c_split_struct_ints(SplitStructInt) void;
1644917194
16450test "split struct of ints" {17195test "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;
16455 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;17196 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
16458 const s = SplitStructInt{17202 const s = SplitStructInt{
16459 .a = 1234,17203 .a = 1234,
...@@ -16478,12 +17222,11 @@ extern fn c_split_struct_mixed(SplitStructMixed) void;...@@ -16478,12 +17222,11 @@ extern fn c_split_struct_mixed(SplitStructMixed) void;
16478extern fn c_ret_split_struct_mixed() SplitStructMixed;17222extern fn c_ret_split_struct_mixed() SplitStructMixed;
1647917223
16480test "split struct of ints and floats" {17224test "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;
16485 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;17225 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
16488 const s = SplitStructMixed{17231 const s = SplitStructMixed{
16489 .a = 1234,17232 .a = 1234,
...@@ -16506,11 +17249,10 @@ export fn zig_split_struct_mixed(x: SplitStructMixed) void {...@@ -16506,11 +17249,10 @@ export fn zig_split_struct_mixed(x: SplitStructMixed) void {
16506extern fn c_big_struct_both(BigStruct) BigStruct;17249extern fn c_big_struct_both(BigStruct) BigStruct;
1650717250
16508test "sret and byval together" {17251test "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;
16512 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;17252 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
16515 const s = BigStruct{17257 const s = BigStruct{
16516 .a = 1,17258 .a = 1,
...@@ -16620,12 +17362,11 @@ extern fn c_struct_with_array(StructWithArray) void;...@@ -16620,12 +17362,11 @@ extern fn c_struct_with_array(StructWithArray) void;
16620extern fn c_ret_struct_with_array() StructWithArray;17362extern fn c_ret_struct_with_array() StructWithArray;
1662117363
16622test "Struct with array as padding." {17364test "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;
16627 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;17365 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
16630 c_struct_with_array(.{ .a = 1, .padding = undefined, .b = 2 });17371 c_struct_with_array(.{ .a = 1, .padding = undefined, .b = 2 });
1663117372
...@@ -16649,11 +17390,10 @@ extern fn c_float_array_struct(FloatArrayStruct) void;...@@ -16649,11 +17390,10 @@ extern fn c_float_array_struct(FloatArrayStruct) void;
16649extern fn c_ret_float_array_struct() FloatArrayStruct;17390extern fn c_ret_float_array_struct() FloatArrayStruct;
1665017391
16651test "Float array like struct" {17392test "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;
16655 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;17393 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
16658 c_float_array_struct(.{17398 c_float_array_struct(.{
16659 .origin = .{17399 .origin = .{
...@@ -16684,37 +17424,37 @@ pub inline fn expectOk(c_err: c_int) !void {...@@ -16684,37 +17424,37 @@ pub inline fn expectOk(c_err: c_int) !void {
16684/// Tests for Double + Char struct17424/// Tests for Double + Char struct
16685const DC = extern struct { v1: f64, v2: u8 };17425const DC = extern struct { v1: f64, v2: u8 };
16686test "DC: Zig passes to C" {17426test "DC: Zig passes to C" {
17427 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
17428 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16687 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;17429 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17430 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16688 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;17431 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16689 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;17432
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;
16693 try expectOk(c_assert_DC(.{ .v1 = -0.25, .v2 = 15 }));17433 try expectOk(c_assert_DC(.{ .v1 = -0.25, .v2 = 15 }));
16694}17434}
16695test "DC: Zig returns to C" {17435test "DC: Zig returns to C" {
17436 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16696 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;17437 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17438 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16697 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;17439 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16698 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;17440
16699 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16700 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16701 try expectOk(c_assert_ret_DC());17441 try expectOk(c_assert_ret_DC());
16702}17442}
16703test "DC: C passes to Zig" {17443test "DC: C passes to Zig" {
17444 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
17445 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16704 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;17446 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17447 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16705 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;17448 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16706 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;17449
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;
16710 try expectOk(c_send_DC());17450 try expectOk(c_send_DC());
16711}17451}
16712test "DC: C returns to Zig" {17452test "DC: C returns to Zig" {
17453 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16713 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;17454 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17455 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16714 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;17456 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16715 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;17457
16716 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16717 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16718 try expectEqual(DC{ .v1 = -0.25, .v2 = 15 }, c_ret_DC());17458 try expectEqual(DC{ .v1 = -0.25, .v2 = 15 }, c_ret_DC());
16719}17459}
1672017460
...@@ -16739,36 +17479,35 @@ const CFF = extern struct { v1: u8, v2: f32, v3: f32 };...@@ -16739,36 +17479,35 @@ const CFF = extern struct { v1: u8, v2: f32, v3: f32 };
16739test "CFF: Zig passes to C" {17479test "CFF: Zig passes to C" {
16740 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;17480 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
16741 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;17481 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;
16743 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;17483 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16744 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;17484 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16745 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;17485
16746 try expectOk(c_assert_CFF(.{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 }));17486 try expectOk(c_assert_CFF(.{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 }));
16747}17487}
16748test "CFF: Zig returns to C" {17488test "CFF: Zig returns to C" {
16749 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;17489 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;
16751 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;17491 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16752 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;17492
16753 try expectOk(c_assert_ret_CFF());17493 try expectOk(c_assert_ret_CFF());
16754}17494}
16755test "CFF: C passes to Zig" {17495test "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;
16761 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;17496 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
16764 try expectOk(c_send_CFF());17503 try expectOk(c_send_CFF());
16765}17504}
16766test "CFF: C returns to Zig" {17505test "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;
16770 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;17506 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
16772 try expectEqual(CFF{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 }, c_ret_CFF());17511 try expectEqual(CFF{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 }, c_ret_CFF());
16773}17512}
16774pub extern fn c_assert_CFF(lv: CFF) c_int;17513pub extern fn c_assert_CFF(lv: CFF) c_int;
...@@ -16791,35 +17530,35 @@ pub export fn zig_ret_CFF() CFF {...@@ -16791,35 +17530,35 @@ pub export fn zig_ret_CFF() CFF {
16791const PD = extern struct { v1: ?*anyopaque, v2: f64 };17530const PD = extern struct { v1: ?*anyopaque, v2: f64 };
1679217531
16793test "PD: Zig passes to C" {17532test "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;
16797 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;17533 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;
16799 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;17537 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
17538
16800 try expectOk(c_assert_PD(.{ .v1 = null, .v2 = 0.5 }));17539 try expectOk(c_assert_PD(.{ .v1 = null, .v2 = 0.5 }));
16801}17540}
16802test "PD: Zig returns to C" {17541test "PD: Zig returns to C" {
16803 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16804 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16805 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;17542 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
16807 try expectOk(c_assert_ret_PD());17546 try expectOk(c_assert_ret_PD());
16808}17547}
16809test "PD: C passes to Zig" {17548test "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;
16813 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;17549 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;
16815 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;17553 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
17554
16816 try expectOk(c_send_PD());17555 try expectOk(c_send_PD());
16817}17556}
16818test "PD: C returns to Zig" {17557test "PD: C returns to Zig" {
16819 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16820 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16821 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;17558 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
16823 try expectEqual(PD{ .v1 = null, .v2 = 0.5 }, c_ret_PD());17562 try expectEqual(PD{ .v1 = null, .v2 = 0.5 }, c_ret_PD());
16824}17563}
16825pub extern fn c_assert_PD(lv: PD) c_int;17564pub extern fn c_assert_PD(lv: PD) c_int;
...@@ -16853,7 +17592,6 @@ extern fn c_modify_by_ref_param(ByRef) ByRef;...@@ -16853,7 +17592,6 @@ extern fn c_modify_by_ref_param(ByRef) ByRef;
16853test "C function modifies by ref param" {17592test "C function modifies by ref param" {
16854 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;17593 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16855 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;17594 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16856 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1685717595
16858 const res = c_modify_by_ref_param(.{ .val = 1, .arr = undefined });17596 const res = c_modify_by_ref_param(.{ .val = 1, .arr = undefined });
16859 try expect(res.val == 42);17597 try expect(res.val == 42);
...@@ -16874,11 +17612,10 @@ const ByVal = extern struct {...@@ -16874,11 +17612,10 @@ const ByVal = extern struct {
1687417612
16875extern fn c_func_ptr_byval(*anyopaque, *anyopaque, ByVal, c_ulong, *anyopaque, c_ulong) void;17613extern fn c_func_ptr_byval(*anyopaque, *anyopaque, ByVal, c_ulong, *anyopaque, c_ulong) void;
16876test "C function that takes byval struct called via function pointer" {17614test "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;
16877 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;17617 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16878 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;17618 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
16883 var fn_ptr = &c_func_ptr_byval;17620 var fn_ptr = &c_func_ptr_byval;
16884 _ = &fn_ptr;17621 _ = &fn_ptr;
...@@ -16897,17 +17634,16 @@ test "C function that takes byval struct called via function pointer" {...@@ -16897,17 +17634,16 @@ test "C function that takes byval struct called via function pointer" {
1689717634
16898extern fn c_f16(f16) f16;17635extern fn c_f16(f16) f16;
16899test "f16 bare" {17636test "f16 bare" {
16900 if (builtin.cpu.arch == .x86_64) return error.SkipZigTest;17637 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16901 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
16902 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;17638 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16903 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;17639 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16904 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;17640 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
17641 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16905 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;17642 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16906 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;17643 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16907 if (builtin.cpu.arch.isWasm()) return error.SkipZigTest;17644 if (builtin.cpu.arch.isWasm()) return error.SkipZigTest;
16908 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;17645 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1690917646 if (builtin.cpu.arch == .x86_64) return error.SkipZigTest;
16910 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
1691117647
16912 const a = c_f16(12);17648 const a = c_f16(12);
16913 try expect(a == 34);17649 try expect(a == 34);
...@@ -16918,9 +17654,9 @@ const f16_struct = extern struct {...@@ -16918,9 +17654,9 @@ const f16_struct = extern struct {
16918};17654};
16919extern fn c_f16_struct(f16_struct) f16_struct;17655extern fn c_f16_struct(f16_struct) f16_struct;
16920test "f16 struct" {17656test "f16 struct" {
17657 if (builtin.cpu.arch.isArm() and builtin.mode != .debug) return error.SkipZigTest;
16921 if (builtin.target.cpu.arch.isMIPS64()) return error.SkipZigTest;17658 if (builtin.target.cpu.arch.isMIPS64()) return error.SkipZigTest;
16922 if (builtin.target.cpu.arch.isPowerPC32()) return error.SkipZigTest;17659 if (builtin.target.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16923 if (builtin.cpu.arch.isArm() and builtin.mode != .Debug) return error.SkipZigTest;
16924 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;17660 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16925 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;17661 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1692617662
...@@ -17027,11 +17763,10 @@ const Coord2 = extern struct {...@@ -17027,11 +17763,10 @@ const Coord2 = extern struct {
1702717763
17028extern fn stdcall_coord2(Coord2, Coord2, Coord2) callconv(stdcall_callconv) Coord2;17764extern fn stdcall_coord2(Coord2, Coord2, Coord2) callconv(stdcall_callconv) Coord2;
17029test "Stdcall ABI structs" {17765test "Stdcall ABI structs" {
17766 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
17767 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17030 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;17768 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17031 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;17769 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;
17035 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;17770 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1703617771
17037 const res = stdcall_coord2(17772 const res = stdcall_coord2(
...@@ -17045,10 +17780,9 @@ test "Stdcall ABI structs" {...@@ -17045,10 +17780,9 @@ test "Stdcall ABI structs" {
1704517780
17046extern fn stdcall_big_union(BigUnion) callconv(stdcall_callconv) void;17781extern fn stdcall_big_union(BigUnion) callconv(stdcall_callconv) void;
17047test "Stdcall ABI big union" {17782test "Stdcall ABI big union" {
17048 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
17049 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17050 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;17783 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
17053 const x = BigUnion{17787 const x = BigUnion{
17054 .a = BigStruct{17788 .a = BigStruct{
...@@ -17120,11 +17854,10 @@ const byval_tail_callsite_attr = struct {...@@ -17120,11 +17854,10 @@ const byval_tail_callsite_attr = struct {
17120};17854};
1712117855
17122test "byval tail callsite attribute" {17856test "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;
17126 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;17857 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
17129 // Originally reported at https://github.com/ziglang/zig/issues/1629017862 // Originally reported at https://github.com/ziglang/zig/issues/16290
17130 // the bug was that the extern function had the byval attribute, but17863 // the bug was that the extern function had the byval attribute, but
...@@ -17268,11 +18001,19 @@ test "x86 vectorcall calling convention" {...@@ -17268,11 +18001,19 @@ test "x86 vectorcall calling convention" {
17268 static.c_vectorcall_check(1, 2.0, 3.0, @ptrFromInt(4), 5.0, 6.0, 7.0, 8.0, 9.0, 10);18001 static.c_vectorcall_check(1, 2.0, 3.0, @ptrFromInt(4), 5.0, 6.0, 7.0, 8.0, 9.0, 10);
17269}18002}
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
17271extern fn c_win64_varargs_u64_f64_u64_f64(...) void;18012extern fn c_win64_varargs_u64_f64_u64_f64(...) void;
17272extern fn c_win64_varargs_f64_u64_f64_u64(...) void;18013extern fn c_win64_varargs_f64_u64_f64_u64(...) void;
1727318014
17274test "win64 varargs" {18015test "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
17277 const Opv = extern struct {};18018 const Opv = extern struct {};
17278 c_win64_varargs_u64_f64_u64_f64(18019 c_win64_varargs_u64_f64_u64_f64(
...@@ -17298,3 +18039,25 @@ test "win64 varargs" {...@@ -17298,3 +18039,25 @@ test "win64 varargs" {
17298 @as(Opv, .{}),18039 @as(Opv, .{}),
17299 );18040 );
17300}18041}
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 {...@@ -15,6 +15,7 @@ pub const panic = struct {
15 pub const castToNull = simple_panic.castToNull;15 pub const castToNull = simple_panic.castToNull;
16 pub const incorrectAlignment = simple_panic.incorrectAlignment;16 pub const incorrectAlignment = simple_panic.incorrectAlignment;
17 pub const invalidErrorCode = simple_panic.invalidErrorCode;17 pub const invalidErrorCode = simple_panic.invalidErrorCode;
18 pub const unexpectedErrorCode = simple_panic.unexpectedErrorCode;
18 pub const integerOutOfBounds = simple_panic.integerOutOfBounds;19 pub const integerOutOfBounds = simple_panic.integerOutOfBounds;
19 pub const integerOverflow = simple_panic.integerOverflow;20 pub const integerOverflow = simple_panic.integerOverflow;
20 pub const shlOverflow = simple_panic.shlOverflow;21 pub const shlOverflow = simple_panic.shlOverflow;
test/cases/compile_errors/bad_panic_generic_signature.zig+1
...@@ -11,6 +11,7 @@ pub const panic = struct {...@@ -11,6 +11,7 @@ pub const panic = struct {
11 pub const castToNull = simple_panic.castToNull;11 pub const castToNull = simple_panic.castToNull;
12 pub const incorrectAlignment = simple_panic.incorrectAlignment;12 pub const incorrectAlignment = simple_panic.incorrectAlignment;
13 pub const invalidErrorCode = simple_panic.invalidErrorCode;13 pub const invalidErrorCode = simple_panic.invalidErrorCode;
14 pub const unexpectedErrorCode = simple_panic.unexpectedErrorCode;
14 pub const integerOutOfBounds = simple_panic.integerOutOfBounds;15 pub const integerOutOfBounds = simple_panic.integerOutOfBounds;
15 pub const integerOverflow = simple_panic.integerOverflow;16 pub const integerOverflow = simple_panic.integerOverflow;
16 pub const shlOverflow = simple_panic.shlOverflow;17 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 {...@@ -16,9 +16,14 @@ export fn d() void {
16 while (null) |*_| {}16 while (null) |*_| {}
17}17}
1818
19export fn e() void {
20 if (0) |*_| {} else |err| switch (err) {}
21}
22
19// error23// error
20//24//
21// :2:16: error: pointer modifier invalid on discard25// :2:16: error: pointer modifier invalid on discard
22// :7:18: error: pointer modifier invalid on discard26// :7:18: error: pointer modifier invalid on discard
23// :12:16: error: pointer modifier invalid on discard27// :12:16: error: pointer modifier invalid on discard
24// :16:19: error: pointer modifier invalid on discard28// :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 {...@@ -28,6 +28,16 @@ export fn entry5() void {
28 _ = q;28 _ = q;
29}29}
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
31// error41// error
32//42//
33// :3:22: error: expected type '**i32', found '**u32'43// :3:22: error: expected type '**i32', found '**u32'
...@@ -50,3 +60,7 @@ export fn entry5() void {...@@ -50,3 +60,7 @@ export fn entry5() void {
50// :27:24: note: pointer type child '*[1:42]u8' cannot cast into pointer type child '*[1]u8'60// :27:24: note: pointer type child '*[1:42]u8' cannot cast into pointer type child '*[1]u8'
51// :27:24: note: pointer type child '[1:42]u8' cannot cast into pointer type child '[1]u8'61// :27:24: note: pointer type child '[1:42]u8' cannot cast into pointer type child '[1]u8'
52// :27:24: note: source array cannot be guaranteed to maintain '42' sentinel62// :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 {...@@ -6,4 +6,4 @@ export fn entry() void {
66
7// error7// error
8//8//
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 {...@@ -7,4 +7,4 @@ comptime {
77
8// error8// error
9//9//
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 {...@@ -17,7 +17,7 @@ comptime {
1717
18// error18// error
19//19//
20// :5:9: error: duplicate switch value20// :5:9: error: duplicate switch value 'true'
21// :3:9: note: previous value here21// :3:9: note: previous value here
22// :13:9: error: duplicate switch value22// :13:9: error: duplicate switch value 'false'
23// :11:9: note: previous value here23// :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 {...@@ -16,5 +16,5 @@ fn foo(x: i32) !void {
1616
17// error17// error
18//18//
19// :5:9: error: duplicate switch value19// :5:9: error: duplicate switch value 'error.Foo'
20// :3:9: note: previous value here20// :3:9: note: previous value here
test/cases/compile_errors/ignored_deferred_function_call.zig+2-2
...@@ -14,6 +14,6 @@ fn bar2() anyerror {...@@ -14,6 +14,6 @@ fn bar2() anyerror {
1414
15// error15// error
16//16//
17// :2:14: error: error union is ignored17// :2:14: error: error union of type 'anyerror!i32' is ignored
18// :2:14: note: consider using 'try', 'catch', or 'if'18// :2:14: note: consider using 'try', 'catch', or 'if'
19// :9:15: error: error set is ignored19// :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 {...@@ -24,10 +24,10 @@ fn bad2() anyerror {
2424
25// error25// error
26//26//
27// :2:24: error: error union is ignored27// :2:24: error: error union of type 'anyerror!void' is ignored
28// :2:24: note: consider using 'try', 'catch', or 'if'28// :2:24: note: consider using 'try', 'catch', or 'if'
29// :7:25: error: error union is ignored29// :7:25: error: error union of type 'anyerror!void' is ignored
30// :7:25: note: consider using 'try', 'catch', or 'if'30// :7:25: note: consider using 'try', 'catch', or 'if'
31// :12:25: error: error union is ignored31// :12:25: error: error union of type 'anyerror!void' is ignored
32// :12:25: note: consider using 'try', 'catch', or 'if'32// :12:25: note: consider using 'try', 'catch', or 'if'
33// :19:25: error: error set is ignored33// :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 {...@@ -28,25 +28,6 @@ export fn init5() void {
28 _ = @as(U5, undefined);28 _ = @as(U5, undefined);
29}29}
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
50// error31// error
51//32//
52// :13:17: error: expected type 'tmp.U0', found '@TypeOf(undefined)'33// :13:17: error: expected type 'tmp.U0', found '@TypeOf(undefined)'
...@@ -67,15 +48,3 @@ export fn deref5(ptr: *const U5) void {...@@ -67,15 +48,3 @@ export fn deref5(ptr: *const U5) void {
67// :28:17: error: expected type 'tmp.U5', found '@TypeOf(undefined)'48// :28:17: error: expected type 'tmp.U5', found '@TypeOf(undefined)'
68// :28:17: note: cannot coerce to uninstantiable type 'tmp.U5'49// :28:17: note: cannot coerce to uninstantiable type 'tmp.U5'
69// :10:12: note: union declared here50// :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 {...@@ -22,6 +22,6 @@ export fn qux() void {
22// error22// error
23//23//
24// :4:40: error: unable to cast runtime value to 'comptime_float'24// :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'
26// :14:32: error: expected integer type, found 'f32'26// :14:32: error: expected integer type, found 'f32'
27// :19:29: error: expected float or vector type, found 'u32'27// :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 {...@@ -8,6 +8,9 @@ export fn bar() void {
8 _ = &a;8 _ = &a;
9 _ = @as(u32, @floatFromInt(a));9 _ = @as(u32, @floatFromInt(a));
10}10}
11export fn bar2() void {
12 _ = @as(comptime_int, @floatFromInt(2));
13}
11export fn baz() void {14export fn baz() void {
12 var a: u32 = 2;15 var a: u32 = 2;
13 _ = &a;16 _ = &a;
...@@ -22,6 +25,7 @@ export fn qux() void {...@@ -22,6 +25,7 @@ export fn qux() void {
22// error25// error
23//26//
24// :4:36: error: unable to cast runtime value to 'comptime_int'27// :4:36: error: unable to cast runtime value to 'comptime_int'
25// :9:18: error: expected float type, found 'u32'28// :9:18: error: expected float result type, found 'u32'
26// :14:32: error: expected float type, found 'u32'29// :12:27: error: expected float result type, found 'comptime_int'
27// :19:27: error: expected integer or vector, found 'f32'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 {...@@ -6,5 +6,5 @@ export fn entry() void {
66
7// error7// error
8//8//
9// :3:35: error: enum 'lang.OptimizeMode' has no member named 'x86'9// :3:35: error: enum 'lang.Optimize' has no member named 'x86'
10// : note: enum declared here10// : 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 {...@@ -20,5 +20,6 @@ export fn entry() usize {
2020
21// error21// error
22//22//
23// :13:15: error: duplicate switch value23// :13:15: error: duplicate switch value '.Two'
24// :10:15: note: previous value here24// :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 {...@@ -21,5 +21,6 @@ export fn entry() usize {
2121
22// error22// error
23//23//
24// :13:15: error: duplicate switch value24// :13:15: error: duplicate switch value '.Two'
25// :10:15: note: previous value here25// :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 {...@@ -25,7 +25,7 @@ export fn entry() usize {
2525
26// error26// error
27//27//
28// :8:9: error: duplicate switch value28// :8:9: error: duplicate switch value 'error.Foo'
29// :5:9: note: previous value here29// :5:9: note: previous value here
30// :16:9: error: duplicate switch value30// :16:9: error: duplicate switch value 'error.Foo'
31// :13:9: note: previous value here31// :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 {...@@ -27,7 +27,7 @@ export fn entry() usize {
2727
28// error28// error
29//29//
30// :8:9: error: duplicate switch value30// :8:9: error: duplicate switch value 'error.Foo'
31// :5:9: note: previous value here31// :5:9: note: previous value here
32// :17:9: error: duplicate switch value32// :17:9: error: duplicate switch value 'error.Foo'
33// :14:9: note: previous value here33// :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 {...@@ -13,5 +13,5 @@ export fn entry() usize {
1313
14// error14// error
15//15//
16// :6:9: error: duplicate switch value16// :6:9: error: duplicate switch value 'u32'
17// :4:9: note: previous value here17// :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 {...@@ -17,5 +17,6 @@ export fn entry() usize {
1717
18// error18// error
19//19//
20// :10:9: error: duplicate switch value20// :10:9: error: duplicate switch value 'tmp.Test'
21// :8:9: note: previous value here21// :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 {...@@ -28,13 +28,43 @@ export fn entry4(x: u8) void {
28 }28 }
29}29}
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
31// error52// error
32//53//
33// :4:10: error: duplicate switch value54// :4:10: error: duplicate switch ranges
34// :3:10: note: previous value here55// :3:10: note: overlaps with previous range here
35// :11:10: error: duplicate switch value56// :3:10: note: ranges overlap from '1' to '2'
36// :10:13: note: previous value here57// :11:10: error: duplicate switch value '5'
37// :17:10: error: duplicate switch value58// :10:13: note: previous value inside range here
59// :17:10: error: duplicate switch value '5'
38// :18:9: note: previous value here60// :18:9: note: previous value here
39// :27:10: error: duplicate switch value61// :27:10: error: duplicate switch value '6'
40// :26:9: note: previous value here62// :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");...@@ -2,7 +2,7 @@ const std = @import("std");
22
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;4 _ = 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")) {
6 std.process.exit(0);6 std.process.exit(0);
7 }7 }
8 std.process.exit(1);8 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");...@@ -2,7 +2,7 @@ const std = @import("std");
22
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;4 _ = 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")) {
6 std.process.exit(0);6 std.process.exit(0);
7 }7 }
8 std.process.exit(1);8 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 @@...@@ -1,7 +1,10 @@
1const std = @import("std");1const 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 {
4 cases.addCase(.{5 cases.addCase(.{
6 .params = params,
7 .target = target,
5 .name = "return",8 .name = "return",
6 .source =9 .source =
7 \\pub fn main() !void {10 \\pub fn main() !void {
...@@ -17,6 +20,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target....@@ -17,6 +20,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
17 });20 });
1821
19 cases.addCase(.{22 cases.addCase(.{
23 .params = params,
24 .target = target,
20 .name = "try return",25 .name = "try return",
21 .source =26 .source =
22 \\fn foo() !void {27 \\fn foo() !void {
...@@ -44,6 +49,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target....@@ -44,6 +49,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
44 },49 },
45 });50 });
46 cases.addCase(.{51 cases.addCase(.{
52 .params = params,
53 .target = target,
47 .name = "non-error return pops error trace",54 .name = "non-error return pops error trace",
48 .source =55 .source =
49 \\fn bar() !void {56 \\fn bar() !void {
...@@ -70,6 +77,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target....@@ -70,6 +77,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
70 });77 });
7178
72 cases.addCase(.{79 cases.addCase(.{
80 .params = params,
81 .target = target,
73 .name = "continue in while loop",82 .name = "continue in while loop",
74 .source =83 .source =
75 \\fn foo() !void {84 \\fn foo() !void {
...@@ -93,6 +102,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target....@@ -93,6 +102,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
93 });102 });
94103
95 cases.addCase(.{104 cases.addCase(.{
105 .params = params,
106 .target = target,
96 .name = "for loop pops error return trace",107 .name = "for loop pops error return trace",
97 .source =108 .source =
98 \\fn foo() !void { return error.FooError; }109 \\fn foo() !void { return error.FooError; }
...@@ -123,6 +134,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target....@@ -123,6 +134,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
123 });134 });
124135
125 cases.addCase(.{136 cases.addCase(.{
137 .params = params,
138 .target = target,
126 .name = "implicit continue in for loop pops stale error return trace",139 .name = "implicit continue in for loop pops stale error return trace",
127 .source =140 .source =
128 \\fn foo() !void { return error.FooError; }141 \\fn foo() !void { return error.FooError; }
...@@ -154,6 +167,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target....@@ -154,6 +167,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
154 });167 });
155168
156 cases.addCase(.{169 cases.addCase(.{
170 .params = params,
171 .target = target,
157 .name = "while loop pops error return trace",172 .name = "while loop pops error return trace",
158 .source =173 .source =
159 \\fn foo() !void { return error.FooError; }174 \\fn foo() !void { return error.FooError; }
...@@ -186,6 +201,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target....@@ -186,6 +201,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
186 });201 });
187202
188 cases.addCase(.{203 cases.addCase(.{
204 .params = params,
205 .target = target,
189 .name = "implicit continue in while loop pops stale error return trace",206 .name = "implicit continue in while loop pops stale error return trace",
190 .source =207 .source =
191 \\fn foo() !void { return error.FooError; }208 \\fn foo() !void { return error.FooError; }
...@@ -219,6 +236,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target....@@ -219,6 +236,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
219 });236 });
220237
221 cases.addCase(.{238 cases.addCase(.{
239 .params = params,
240 .target = target,
222 .name = "try return + handled catch/if-else",241 .name = "try return + handled catch/if-else",
223 .source =242 .source =
224 \\fn foo() !void {243 \\fn foo() !void {
...@@ -251,6 +270,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target....@@ -251,6 +270,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
251 });270 });
252271
253 cases.addCase(.{272 cases.addCase(.{
273 .params = params,
274 .target = target,
254 .name = "break from inline loop pops error return trace",275 .name = "break from inline loop pops error return trace",
255 .source =276 .source =
256 \\fn foo() !void { return error.FooBar; }277 \\fn foo() !void { return error.FooBar; }
...@@ -276,6 +297,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target....@@ -276,6 +297,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
276 });297 });
277298
278 cases.addCase(.{299 cases.addCase(.{
300 .params = params,
301 .target = target,
279 .name = "catch and re-throw error",302 .name = "catch and re-throw error",
280 .source =303 .source =
281 \\fn foo() !void {304 \\fn foo() !void {
...@@ -304,6 +327,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target....@@ -304,6 +327,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
304 });327 });
305328
306 cases.addCase(.{329 cases.addCase(.{
330 .params = params,
331 .target = target,
307 .name = "errors stored in var do not contribute to error trace",332 .name = "errors stored in var do not contribute to error trace",
308 .source =333 .source =
309 \\fn foo() !void {334 \\fn foo() !void {
...@@ -328,6 +353,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target....@@ -328,6 +353,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
328 });353 });
329354
330 cases.addCase(.{355 cases.addCase(.{
356 .params = params,
357 .target = target,
331 .name = "error stored in const has trace preserved for duration of block",358 .name = "error stored in const has trace preserved for duration of block",
332 .source =359 .source =
333 \\fn foo() !void { return error.TheSkyIsFalling; }360 \\fn foo() !void { return error.TheSkyIsFalling; }
...@@ -376,6 +403,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target....@@ -376,6 +403,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
376 });403 });
377404
378 cases.addCase(.{405 cases.addCase(.{
406 .params = params,
407 .target = target,
379 .name = "error passed to function has its trace preserved for duration of the call",408 .name = "error passed to function has its trace preserved for duration of the call",
380 .source =409 .source =
381 \\pub fn expectError(expected_error: anyerror, actual_error: anyerror!void) !void {410 \\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....@@ -418,6 +447,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
418 });447 });
419448
420 cases.addCase(.{449 cases.addCase(.{
450 .params = params,
451 .target = target,
421 .name = "try return from within catch",452 .name = "try return from within catch",
422 .source =453 .source =
423 \\fn foo() !void {454 \\fn foo() !void {
...@@ -455,6 +486,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target....@@ -455,6 +486,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
455 });486 });
456487
457 cases.addCase(.{488 cases.addCase(.{
489 .params = params,
490 .target = target,
458 .name = "try return from within if-else",491 .name = "try return from within if-else",
459 .source =492 .source =
460 \\fn foo() !void {493 \\fn foo() !void {
...@@ -492,6 +525,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target....@@ -492,6 +525,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
492 });525 });
493526
494 cases.addCase(.{527 cases.addCase(.{
528 .params = params,
529 .target = target,
495 .name = "try try return return",530 .name = "try try return return",
496 .source =531 .source =
497 \\fn foo() !void {532 \\fn foo() !void {
...@@ -534,6 +569,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target....@@ -534,6 +569,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
534 });569 });
535570
536 cases.addCase(.{571 cases.addCase(.{
572 .params = params,
573 .target = target,
537 .name = "error union switch with call operand",574 .name = "error union switch with call operand",
538 .source =575 .source =
539 \\pub fn main() !void {576 \\pub fn main() !void {
...@@ -579,6 +616,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target....@@ -579,6 +616,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
579 });616 });
580617
581 cases.addCase(.{618 cases.addCase(.{
619 .params = params,
620 .target = target,
582 .name = "trace through inline call",621 .name = "trace through inline call",
583 // The main function has two inline calls to ensure622 // The main function has two inline calls to ensure
584 // that inlinees in PDBs are properly deduplicated.623 // that inlinees in PDBs are properly deduplicated.
...@@ -595,7 +634,7 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target....@@ -595,7 +634,7 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
595 \\}634 \\}
596 ,635 ,
597 .expect_error = "ThisIsSoSad",636 .expect_error = "ThisIsSoSad",
598 .expect_trace = switch (os) {637 .expect_trace = switch (target.os.tag) {
599 // LLVM doesn't emit column info in the binary annotations for inlinee callees in PDBs,638 // LLVM doesn't emit column info in the binary annotations for inlinee callees in PDBs,
600 // so our expected result is slightly different for Windows than on other operating639 // so our expected result is slightly different for Windows than on other operating
601 // systems.640 // systems.
test/incremental/change_panic_handler_explicit+6
...@@ -23,6 +23,7 @@ pub const panic = struct {...@@ -23,6 +23,7 @@ pub const panic = struct {
23 pub const castToNull = no_panic.castToNull;23 pub const castToNull = no_panic.castToNull;
24 pub const incorrectAlignment = no_panic.incorrectAlignment;24 pub const incorrectAlignment = no_panic.incorrectAlignment;
25 pub const invalidErrorCode = no_panic.invalidErrorCode;25 pub const invalidErrorCode = no_panic.invalidErrorCode;
26 pub const unexpectedErrorCode = no_panic.unexpectedErrorCode;
26 pub const integerOutOfBounds = no_panic.integerOutOfBounds;27 pub const integerOutOfBounds = no_panic.integerOutOfBounds;
27 pub const shlOverflow = no_panic.shlOverflow;28 pub const shlOverflow = no_panic.shlOverflow;
28 pub const shrOverflow = no_panic.shrOverflow;29 pub const shrOverflow = no_panic.shrOverflow;
...@@ -36,6 +37,7 @@ pub const panic = struct {...@@ -36,6 +37,7 @@ pub const panic = struct {
36 pub const copyLenMismatch = no_panic.copyLenMismatch;37 pub const copyLenMismatch = no_panic.copyLenMismatch;
37 pub const memcpyAlias = no_panic.memcpyAlias;38 pub const memcpyAlias = no_panic.memcpyAlias;
38 pub const noreturnReturned = no_panic.noreturnReturned;39 pub const noreturnReturned = no_panic.noreturnReturned;
40 pub const loadUninstantiableType = no_panic.loadUninstantiableType;
39};41};
40fn myPanic(msg: []const u8, _: ?usize) noreturn {42fn myPanic(msg: []const u8, _: ?usize) noreturn {
41 var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});43 var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});
...@@ -71,6 +73,7 @@ pub const panic = struct {...@@ -71,6 +73,7 @@ pub const panic = struct {
71 pub const castToNull = no_panic.castToNull;73 pub const castToNull = no_panic.castToNull;
72 pub const incorrectAlignment = no_panic.incorrectAlignment;74 pub const incorrectAlignment = no_panic.incorrectAlignment;
73 pub const invalidErrorCode = no_panic.invalidErrorCode;75 pub const invalidErrorCode = no_panic.invalidErrorCode;
76 pub const unexpectedErrorCode = no_panic.unexpectedErrorCode;
74 pub const integerOutOfBounds = no_panic.integerOutOfBounds;77 pub const integerOutOfBounds = no_panic.integerOutOfBounds;
75 pub const shlOverflow = no_panic.shlOverflow;78 pub const shlOverflow = no_panic.shlOverflow;
76 pub const shrOverflow = no_panic.shrOverflow;79 pub const shrOverflow = no_panic.shrOverflow;
...@@ -84,6 +87,7 @@ pub const panic = struct {...@@ -84,6 +87,7 @@ pub const panic = struct {
84 pub const copyLenMismatch = no_panic.copyLenMismatch;87 pub const copyLenMismatch = no_panic.copyLenMismatch;
85 pub const memcpyAlias = no_panic.memcpyAlias;88 pub const memcpyAlias = no_panic.memcpyAlias;
86 pub const noreturnReturned = no_panic.noreturnReturned;89 pub const noreturnReturned = no_panic.noreturnReturned;
90 pub const loadUninstantiableType = no_panic.loadUninstantiableType;
87};91};
88fn myPanic(msg: []const u8, _: ?usize) noreturn {92fn myPanic(msg: []const u8, _: ?usize) noreturn {
89 var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});93 var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});
...@@ -119,6 +123,7 @@ pub const panic = struct {...@@ -119,6 +123,7 @@ pub const panic = struct {
119 pub const castToNull = no_panic.castToNull;123 pub const castToNull = no_panic.castToNull;
120 pub const incorrectAlignment = no_panic.incorrectAlignment;124 pub const incorrectAlignment = no_panic.incorrectAlignment;
121 pub const invalidErrorCode = no_panic.invalidErrorCode;125 pub const invalidErrorCode = no_panic.invalidErrorCode;
126 pub const unexpectedErrorCode = no_panic.unexpectedErrorCode;
122 pub const integerOutOfBounds = no_panic.integerOutOfBounds;127 pub const integerOutOfBounds = no_panic.integerOutOfBounds;
123 pub const shlOverflow = no_panic.shlOverflow;128 pub const shlOverflow = no_panic.shlOverflow;
124 pub const shrOverflow = no_panic.shrOverflow;129 pub const shrOverflow = no_panic.shrOverflow;
...@@ -132,6 +137,7 @@ pub const panic = struct {...@@ -132,6 +137,7 @@ pub const panic = struct {
132 pub const copyLenMismatch = no_panic.copyLenMismatch;137 pub const copyLenMismatch = no_panic.copyLenMismatch;
133 pub const memcpyAlias = no_panic.memcpyAlias;138 pub const memcpyAlias = no_panic.memcpyAlias;
134 pub const noreturnReturned = no_panic.noreturnReturned;139 pub const noreturnReturned = no_panic.noreturnReturned;
140 pub const loadUninstantiableType = no_panic.loadUninstantiableType;
135};141};
136fn myPanicNew(msg: []const u8, _: ?usize) noreturn {142fn myPanicNew(msg: []const u8, _: ?usize) noreturn {
137 var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});143 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 {...@@ -116,6 +116,26 @@ pub fn addCases(cases: *tests.LlvmIrContext) void {
116 "null_pointer_is_valid",116 "null_pointer_is_valid",
117 "store i16 42, ptr",117 "store i16 42, ptr",
118 }, .{});118 }, .{});
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 });
119}139}
120140
121const std = @import("std");141const std = @import("std");
test/llvm_targets.zig+2-2
...@@ -106,9 +106,9 @@ const targets = [_]std.Target.Query{...@@ -106,9 +106,9 @@ const targets = [_]std.Target.Query{
106 .{ .cpu_arch = .lanai, .os_tag = .freestanding, .abi = .none },106 .{ .cpu_arch = .lanai, .os_tag = .freestanding, .abi = .none },
107107
108 .{ .cpu_arch = .loongarch32, .os_tag = .freestanding, .abi = .none },108 .{ .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 },
110 // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .gnuf32 },110 // .{ .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 },
112 // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .musl },112 // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .musl },
113 // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .muslf32 },113 // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .muslf32 },
114 // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .muslsf },114 // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .muslsf },
test/src/Cases.zig+2-2
...@@ -491,7 +491,7 @@ pub fn lowerToBuildSteps(...@@ -491,7 +491,7 @@ pub fn lowerToBuildSteps(
491491
492 for (self.cases.items) |case| {492 for (self.cases.items) |case| {
493 for (options.test_filters) |test_filter| {493 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;
495 } else if (options.test_filters.len > 0) continue;495 } else if (options.test_filters.len > 0) continue;
496496
497 if (case.case.? == .Error and options.skip_compile_errors) continue;497 if (case.case.? == .Error and options.skip_compile_errors) continue;
...@@ -524,7 +524,7 @@ pub fn lowerToBuildSteps(...@@ -524,7 +524,7 @@ pub fn lowerToBuildSteps(
524524
525 if (options.test_target_filters.len > 0) {525 if (options.test_target_filters.len > 0) {
526 for (options.test_target_filters) |filter| {526 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;
528 } else continue;528 } else continue;
529 }529 }
530530
test/src/Debugger.zig+2-2
...@@ -2384,13 +2384,13 @@ fn addTest(...@@ -2384,13 +2384,13 @@ fn addTest(
2384) void {2384) void {
2385 if (db.options.test_filters.len > 0) {2385 if (db.options.test_filters.len > 0) {
2386 for (db.options.test_filters) |test_filter| {2386 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;
2388 } else return;2388 } else return;
2389 }2389 }
2390 if (db.options.test_target_filters.len > 0) {2390 if (db.options.test_target_filters.len > 0) {
2391 const triple_txt = target.resolved.query.zigTriple(db.b.allocator) catch @panic("OOM");2391 const triple_txt = target.resolved.query.zigTriple(db.b.allocator) catch @panic("OOM");
2392 for (db.options.test_target_filters) |filter| {2392 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;
2394 } else return;2394 } else return;
2395 }2395 }
2396 const files_wf = db.b.addWriteFiles();2396 const files_wf = db.b.addWriteFiles();
test/src/ErrorTrace.zig+120-53
...@@ -1,11 +1,81 @@...@@ -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
1b: *std.Build,12b: *std.Build,
2step: *Step,13step: *Step,
3test_filters: []const []const u8,14test_filters: []const []const u8,
4targets: []const std.Build.ResolvedTarget,15skip_non_native: bool,
5optimize_modes: []const OptimizeMode,16optimize_modes: []const OptimizeMode,
6convert_exe: *std.Build.Step.Compile,17convert_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
8pub const Case = struct {76pub const Case = struct {
77 params: *const CaseParameters,
78 target: *const std.Target,
9 name: []const u8,79 name: []const u8,
10 source: []const u8,80 source: []const u8,
11 expect_error: []const u8,81 expect_error: []const u8,
...@@ -22,50 +92,47 @@ pub const Case = struct {...@@ -22,50 +92,47 @@ pub const Case = struct {
22 pub const Backend = enum { llvm, selfhosted };92 pub const Backend = enum { llvm, selfhosted };
23};93};
2494
25pub fn addCase(self: *ErrorTrace, case: Case) void {95pub fn addCases(self: *ErrorTrace) void {
26 for (self.targets) |*target| {96 const b = self.b;
27 const triple: ?[]const u8 = if (target.query.isNative()) null else t: {97
28 break :t target.query.zigTriple(self.b.graph.arena) catch @panic("OOM");98 for (&param_sets) |*params| {
29 };99 const resolved_target = b.resolveTargetQuery(params.target);
30 for (self.optimize_modes) |optimize| {100
31 self.addCaseConfig(case, target, triple, optimize, .llvm);101 if (self.skip_non_native and !resolved_target.query.isNative()) continue;
32 }102
33 if (shouldTestNonLlvm(&target.result)) {103 // To avoid redundant testing, skip cross-compilation targets matching the host.
34 for (self.optimize_modes) |optimize| {104 if (resolved_target.result.os.tag == builtin.target.os.tag and
35 self.addCaseConfig(case, target, triple, optimize, .selfhosted);105 resolved_target.result.cpu.arch == builtin.target.cpu.arch)
36 }106 {
107 continue;
37 }108 }
38 }
39}
40109
41fn shouldTestNonLlvm(target: *const std.Target) bool {110 for (self.optimize_modes) |optimize| {
42 if (comptime builtin.cpu.arch.endian() == .big) return false; // https://github.com/ziglang/zig/issues/25961111 if (optimize == params.optimize) break;
43 return switch (target.cpu.arch) {112 } else return;
44 .x86_64 => switch (target.ofmt) {113
45 .elf => !target.os.tag.isBSD() and target.os.tag != .illumos,114 error_traces_cases.addCases(self, params, &resolved_target.result);
46 else => false,115 }
47 },
48 else => false,
49 };
50}116}
51117
52fn addCaseConfig(118/// Called from test/error_traces.zig
53 self: *ErrorTrace,119pub fn addCase(self: *ErrorTrace, case: Case) void {
54 case: Case,
55 target: *const std.Build.ResolvedTarget,
56 triple: ?[]const u8,
57 optimize: OptimizeMode,
58 backend: Case.Backend,
59) void {
60 const b = self.b;120 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
62 const error_tracing: bool = tracing: {129 const error_tracing: bool = tracing: {
63 if (optimize == .Debug) break :tracing true;130 if (params.optimize == .debug) break :tracing true;
64 if (backend != .llvm) break :tracing true;131 if (params.use_llvm == false) break :tracing true;
65 if (optimize == .ReleaseSmall) break :tracing false;132 if (params.optimize == .small) break :tracing false;
66 for (case.disable_trace_optimized) |disable| {133 for (case.disable_trace_optimized) |disable| {
67 const d_arch, const d_os = disable;134 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) {
69 // This particular configuration cannot do error tracing in optimized LLVM builds.136 // This particular configuration cannot do error tracing in optimized LLVM builds.
70 break :tracing false;137 break :tracing false;
71 }138 }
...@@ -73,16 +140,23 @@ fn addCaseConfig(...@@ -73,16 +140,23 @@ fn addCaseConfig(
73 break :tracing true;140 break :tracing true;
74 };141 };
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})", .{
77 case.name,151 case.name,
78 triple orelse "",152 triple orelse "",
79 if (triple != null) " " else "",153 if (triple != null) " " else "",
80 @tagName(optimize),154 params.optimize,
81 @tagName(backend),155 backend_string,
82 });156 });
83 if (self.test_filters.len > 0) {157 if (self.test_filters.len > 0) {
84 for (self.test_filters) |test_filter| {158 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;
86 } else return;160 } else return;
87 }161 }
88162
...@@ -92,19 +166,18 @@ fn addCaseConfig(...@@ -92,19 +166,18 @@ fn addCaseConfig(
92 .name = "test",166 .name = "test",
93 .root_module = b.createModule(.{167 .root_module = b.createModule(.{
94 .root_source_file = source_zig,168 .root_source_file = source_zig,
95 .optimize = optimize,169 .optimize = params.optimize,
96 .target = target.*,170 .target = .{ .result = target.*, .query = target_query },
97 .error_tracing = error_tracing,171 .error_tracing = error_tracing,
98 .strip = false,172 .strip = false,
99 }),173 }),
100 .use_llvm = switch (backend) {174 .use_llvm = params.use_llvm,
101 .llvm => true,175 .use_lld = params.use_lld,
102 .selfhosted => false,
103 },
104 });176 });
105 exe.bundle_ubsan_rt = false;177 exe.bundle_ubsan_rt = false;
106178
107 const run = b.addRunArtifact(exe);179 const run = b.addRunArtifact(exe);
180 run.skip_foreign_checks = true;
108 run.removeEnvironmentVariable("CLICOLOR_FORCE");181 run.removeEnvironmentVariable("CLICOLOR_FORCE");
109 run.setEnvironmentVariable("NO_COLOR", "1");182 run.setEnvironmentVariable("NO_COLOR", "1");
110 run.expectExitCode(1);183 run.expectExitCode(1);
...@@ -116,16 +189,10 @@ fn addCaseConfig(...@@ -116,16 +189,10 @@ fn addCaseConfig(
116 };189 };
117190
118 const check_run = b.addRunArtifact(self.convert_exe);191 const check_run = b.addRunArtifact(self.convert_exe);
192 check_run.skip_foreign_checks = true;
119 check_run.setName(annotated_case_name);193 check_run.setName(annotated_case_name);
120 check_run.addFileArg(run.captureStdErr(.{}));194 check_run.addFileArg(run.captureStdErr(.{}));
121 check_run.expectStdOutEqual(expected_stderr);195 check_run.expectStdOutEqual(expected_stderr);
122196
123 self.step.dependOn(&check_run.step);197 self.step.dependOn(&check_run.step);
124}198}
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 {...@@ -49,7 +49,7 @@ pub fn addTarget(libc: *const Libc, target: std.Build.ResolvedTarget) void {
49 if (libc.options.test_target_filters.len > 0) {49 if (libc.options.test_target_filters.len > 0) {
50 const triple_txt = target.query.zigTriple(libc.b.allocator) catch @panic("OOM");50 const triple_txt = target.query.zigTriple(libc.b.allocator) catch @panic("OOM");
51 for (libc.options.test_target_filters) |filter| {51 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;
53 } else return;53 } else return;
54 }54 }
5555
...@@ -82,7 +82,7 @@ pub fn addTarget(libc: *const Libc, target: std.Build.ResolvedTarget) void {...@@ -82,7 +82,7 @@ pub fn addTarget(libc: *const Libc, target: std.Build.ResolvedTarget) void {
8282
83 const annotated_case_name = libc.b.fmt("run libc-test {s} ({t})", .{ test_case.name, optimize });83 const annotated_case_name = libc.b.fmt("run libc-test {s} ({t})", .{ test_case.name, optimize });
84 for (libc.options.test_filters) |test_filter| {84 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;
86 } else if (libc.options.test_filters.len > 0) continue;86 } else if (libc.options.test_filters.len > 0) continue;
8787
88 const mod = libc.b.createModule(.{88 const mod = libc.b.createModule(.{
test/src/Link.zig+1-1
...@@ -8,7 +8,7 @@ use_lld: bool,...@@ -8,7 +8,7 @@ use_lld: bool,
8link_libc: bool,8link_libc: bool,
9test_filters: []const []const u8,9test_filters: []const []const u8,
10update_step: ?*Step.UpdateSourceFiles,10update_step: ?*Step.UpdateSourceFiles,
11updated_snapshots: std.StringArrayHashMapUnmanaged(void),11updated_snapshots: std.array_hash_map.String(void),
12max_rss: usize,12max_rss: usize,
1313
14pub fn includeTest(self: *Link, prefix: []const u8) ?Case {14pub 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 {...@@ -77,14 +77,14 @@ pub fn addCase(self: *LlvmIr, case: TestCase) void {
77 if (self.options.test_target_filters.len > 0) {77 if (self.options.test_target_filters.len > 0) {
78 const triple_txt = target.query.zigTriple(self.b.allocator) catch @panic("OOM");78 const triple_txt = target.query.zigTriple(self.b.allocator) catch @panic("OOM");
79 for (self.options.test_target_filters) |filter| {79 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;
81 } else return;81 } else return;
82 }82 }
8383
84 const name = std.fmt.allocPrint(self.b.allocator, "check llvm-ir {s}", .{case.name}) catch @panic("OOM");84 const name = std.fmt.allocPrint(self.b.allocator, "check llvm-ir {s}", .{case.name}) catch @panic("OOM");
85 if (self.options.test_filters.len > 0) {85 if (self.options.test_filters.len > 0) {
86 for (self.options.test_filters) |filter| {86 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;
88 } else return;88 } else return;
89 }89 }
9090
test/src/RunTranslatedC.zig+1-1
...@@ -68,7 +68,7 @@ pub fn addCase(self: *RunTranslatedCContext, case: *const TestCase) void {...@@ -68,7 +68,7 @@ pub fn addCase(self: *RunTranslatedCContext, case: *const TestCase) void {
6868
69 const annotated_case_name = fmt.allocPrint(self.b.allocator, "run-translated-c {s}", .{case.name}) catch unreachable;69 const annotated_case_name = fmt.allocPrint(self.b.allocator, "run-translated-c {s}", .{case.name}) catch unreachable;
70 for (self.test_filters) |test_filter| {70 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;
72 } else if (self.test_filters.len > 0) return;72 } else if (self.test_filters.len > 0) return;
7373
74 const write_src = b.addWriteFiles();74 const write_src = b.addWriteFiles();
test/src/StackTrace.zig+156-93
...@@ -1,10 +1,91 @@...@@ -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
1b: *std.Build,12b: *std.Build,
2step: *Step,13step: *Step,
3test_filters: []const []const u8,14test_filters: []const []const u8,
4targets: []const std.Build.ResolvedTarget,15skip_non_native: bool,
5convert_exe: *std.Build.Step.Compile,16convert_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
7const Config = struct {86const Config = struct {
87 params: *const CaseParameters,
88 target: *const std.Target,
8 name: []const u8,89 name: []const u8,
9 source: []const u8,90 source: []const u8,
10 /// Whether this test case expects to have unwind tables / frame pointers.91 /// Whether this test case expects to have unwind tables / frame pointers.
...@@ -26,42 +107,37 @@ const Config = struct {...@@ -26,42 +107,37 @@ const Config = struct {
26 expect_strip: []const u8,107 expect_strip: []const u8,
27};108};
28109
29pub fn addCase(self: *StackTrace, config: Config) void {110pub fn addCases(self: *StackTrace) void {
30 for (self.targets) |*target| {111 const b = self.b;
31 addCaseTarget(112
32 self,113 for (&param_sets) |*params| {
33 config,114 const resolved_target = b.resolveTargetQuery(params.target);
34 target,115
35 if (target.query.isNative()) null else t: {116 if (self.skip_non_native and !resolved_target.query.isNative()) continue;
36 break :t target.query.zigTriple(self.b.graph.arena) catch @panic("OOM");117
37 },118 // To avoid redundant testing, skip cross-compilation targets matching the host.
38 );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);
39 }126 }
40}127}
41fn addCaseTarget(128
42 self: *StackTrace,129/// Called from test/stack_traces.zig
43 config: Config,130pub fn addCase(self: *StackTrace, config: Config) void {
44 target: *const std.Build.ResolvedTarget,131 const params = config.params;
45 triple: ?[]const u8,132 const target = config.target;
46) void {133 const target_query = config.params.target;
47 const both_backends = b: {134
48 if (comptime builtin.cpu.arch.endian() == .big) break :b false; // https://github.com/ziglang/zig/issues/25961135 const triple: ?[]const u8 = if (target_query.isNative()) null else t: {
49 break :b switch (target.result.cpu.arch) {136 break :t target_query.zigTriple(self.b.graph.arena) catch @panic("OOM");
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,
60 };137 };
61 const both_libc = !std.os.targetRequiresLibC(&target.result);
62138
63 // See `std.debug.StackIterator.fp_usability` logic.139 // 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) {
65 .alpha,141 .alpha,
66 .csky,142 .csky,
67 .microblaze,143 .microblaze,
...@@ -83,20 +159,15 @@ fn addCaseTarget(...@@ -83,20 +159,15 @@ fn addCaseTarget(
83 .sparc,159 .sparc,
84 .sparc64,160 .sparc64,
85 => .ideal,161 => .ideal,
86 .aarch64 => if (target.result.os.tag.isDarwin()) .safe else .unsafe,162 .aarch64 => if (target.os.tag.isDarwin()) .safe else .unsafe,
87 else => .unsafe,163 else => .unsafe,
88 };164 };
89 const supports_unwind_tables = switch (target.result.os.tag) {165 const supports_unwind_tables = switch (target.os.tag) {
90 // x86-windows just has no way to do stack unwinding other then using frame pointers.166 // 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,
92 else => true,168 else => true,
93 };169 };
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
100 const UnwindInfo = packed struct(u2) {171 const UnwindInfo = packed struct(u2) {
101 tables: bool,172 tables: bool,
102 fp: bool,173 fp: bool,
...@@ -126,43 +197,33 @@ fn addCaseTarget(...@@ -126,43 +197,33 @@ fn addCaseTarget(
126 },197 },
127 };198 };
128199
129 for (use_llvm_vals) |use_llvm| {200 for (unwind_info_vals) |unwind_info| {
130 for (pie_vals) |pie| {201 if (unwind_info.tables and !supports_unwind_tables) continue;
131 for (link_libc_vals) |link_libc| {202 const strip = params.strip orelse switch (params.optimize) {
132 for (strip_debug_vals) |strip_debug| {203 .debug, .fast, .safe => false,
133 for (unwind_info_vals) |unwind_info| {204 .small => true,
134 if (unwind_info.tables and !supports_unwind_tables) continue;205 };
135 self.addCaseInstance(206 self.addCaseInstance(
136 target,207 .{ .result = target.*, .query = target_query },
137 triple,208 triple,
138 config.name,209 config.name,
139 config.source,210 config.source,
140 use_llvm,211 params,
141 pie,212 !unwind_info.tables and supports_unwind_tables,
142 link_libc,213 !unwind_info.fp,
143 strip_debug,214 config.expect_panic,
144 !unwind_info.tables and supports_unwind_tables,215 if (strip) config.expect_strip else config.expect,
145 !unwind_info.fp,216 );
146 config.expect_panic,
147 if (strip_debug) config.expect_strip else config.expect,
148 );
149 }
150 }
151 }
152 }
153 }217 }
154}218}
155219
156fn addCaseInstance(220fn addCaseInstance(
157 self: *StackTrace,221 self: *StackTrace,
158 target: *const std.Build.ResolvedTarget,222 resolved_target: std.Build.ResolvedTarget,
159 triple: ?[]const u8,223 triple: ?[]const u8,
160 name: []const u8,224 name: []const u8,
161 source: []const u8,225 source: []const u8,
162 use_llvm: bool,226 params: *const CaseParameters,
163 pie: ?bool,
164 link_libc: ?bool,
165 strip_debug: bool,
166 strip_unwind: bool,227 strip_unwind: bool,
167 omit_frame_pointer: bool,228 omit_frame_pointer: bool,
168 expect_panic: bool,229 expect_panic: bool,
...@@ -170,13 +231,6 @@ fn addCaseInstance(...@@ -170,13 +231,6 @@ fn addCaseInstance(
170) void {231) void {
171 const b = self.b;232 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
180 if (strip_unwind) {234 if (strip_unwind) {
181 // To enable this coverage, `std.Build.Step.ObjCopy` needs to be un-regressed and gain the235 // To enable this coverage, `std.Build.Step.ObjCopy` needs to be un-regressed and gain the
182 // ability to remove individual sections. `-fno-unwind-tables` is insufficient because it236 // ability to remove individual sections. `-fno-unwind-tables` is insufficient because it
...@@ -187,20 +241,34 @@ fn addCaseInstance(...@@ -187,20 +241,34 @@ fn addCaseInstance(
187 return;241 return;
188 }242 }
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
190 const annotated_case_name = b.fmt("check {s} ({s}{s}{s}{s}{s}{s}{s}{s})", .{258 const annotated_case_name = b.fmt("check {s} ({s}{s}{s}{s}{s}{s}{s}{s})", .{
191 name,259 name,
192 triple orelse "",260 triple orelse "",
193 if (triple != null) " " else "",261 if (triple != null) " " else "",
194 if (use_llvm) "llvm" else "selfhosted",262 backend_string,
195 if (pie == true) " pie" else "",263 if (params.pie == true) " pie" else "",
196 if (link_libc == true) " libc" else "",264 if (params.link_libc == true) " libc" else "",
197 if (strip_debug) " strip" else "",265 strip_string,
198 if (strip_unwind) " no_unwind" else "",266 if (strip_unwind) " no_unwind" else "",
199 if (omit_frame_pointer) " no_fp" else "",267 if (omit_frame_pointer) " no_fp" else "",
200 });268 });
201 if (self.test_filters.len > 0) {269 if (self.test_filters.len > 0) {
202 for (self.test_filters) |test_filter| {270 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;
204 } else return;272 } else return;
205 }273 }
206274
...@@ -211,24 +279,26 @@ fn addCaseInstance(...@@ -211,24 +279,26 @@ fn addCaseInstance(
211 .root_module = b.createModule(.{279 .root_module = b.createModule(.{
212 .root_source_file = source_zig,280 .root_source_file = source_zig,
213 .optimize = .Debug,281 .optimize = .Debug,
214 .target = target.*,282 .target = resolved_target,
215 .omit_frame_pointer = omit_frame_pointer,283 .omit_frame_pointer = omit_frame_pointer,
216 .link_libc = link_libc,284 .link_libc = params.link_libc,
217 .unwind_tables = if (strip_unwind) .none else null,285 .unwind_tables = if (strip_unwind) .none else null,
218 // make panics single-threaded so that they don't include a thread ID286 // make panics single-threaded so that they don't include a thread ID
219 .single_threaded = expect_panic,287 .single_threaded = expect_panic,
220 }),288 }),
221 .use_llvm = use_llvm,289 .use_llvm = params.use_llvm,
290 .use_lld = params.use_lld,
222 });291 });
223 exe.pie = pie;292 exe.pie = params.pie;
224 exe.bundle_ubsan_rt = false;293 exe.bundle_ubsan_rt = false;
225294
226 const run = b.addRunArtifact(exe);295 const run = b.addRunArtifact(exe);
296 run.skip_foreign_checks = true;
227 run.removeEnvironmentVariable("CLICOLOR_FORCE");297 run.removeEnvironmentVariable("CLICOLOR_FORCE");
228 run.setEnvironmentVariable("NO_COLOR", "1");298 run.setEnvironmentVariable("NO_COLOR", "1");
229 run.addCheck(.{ .expect_term = term: {299 run.addCheck(.{ .expect_term = term: {
230 if (!expect_panic) break :term .{ .exited = 0 };300 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 };
232 break :term .{ .signal = @fromBackingInt(@intCast(6)) };302 break :term .{ .signal = @fromBackingInt(@intCast(6)) };
233 } });303 } });
234 run.expectStdOutEqual("");304 run.expectStdOutEqual("");
...@@ -241,10 +311,3 @@ fn addCaseInstance(...@@ -241,10 +311,3 @@ fn addCaseInstance(
241311
242 self.step.dependOn(&check_run.step);312 self.step.dependOn(&check_run.step);
243}313}
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 {...@@ -90,7 +90,7 @@ pub fn addCase(self: *TranslateCContext, case: *const TestCase) void {
90 const translate_c_cmd = "translate-c";90 const translate_c_cmd = "translate-c";
91 const annotated_case_name = fmt.allocPrint(self.b.allocator, "{s} {s}", .{ translate_c_cmd, case.name }) catch unreachable;91 const annotated_case_name = fmt.allocPrint(self.b.allocator, "{s} {s}", .{ translate_c_cmd, case.name }) catch unreachable;
92 for (self.test_filters) |test_filter| {92 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;
94 } else if (self.test_filters.len > 0) return;94 } else if (self.test_filters.len > 0) return;
9595
96 const target = b.resolveTargetQuery(case.target);96 const target = b.resolveTargetQuery(case.target);
...@@ -99,7 +99,7 @@ pub fn addCase(self: *TranslateCContext, case: *const TestCase) void {...@@ -99,7 +99,7 @@ pub fn addCase(self: *TranslateCContext, case: *const TestCase) void {
99 const triple_txt = target.query.zigTriple(b.allocator) catch @panic("OOM");99 const triple_txt = target.query.zigTriple(b.allocator) catch @panic("OOM");
100100
101 for (self.test_target_filters) |filter| {101 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;
103 } else return;103 } else return;
104 }104 }
105105
test/src/convert-stack-trace.zig+3-3
...@@ -52,13 +52,13 @@ pub fn main(init: std.process.Init) !void {...@@ -52,13 +52,13 @@ pub fn main(init: std.process.Init) !void {
52 continue;52 continue;
53 }53 }
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 {
56 try w.writeAll(in_line);56 try w.writeAll(in_line);
57 continue;57 continue;
58 };58 };
59 const src_pos_start = b: {59 const src_pos_start = b: {
60 const postfix = ".zig:";60 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 {
62 try w.writeAll(in_line);62 try w.writeAll(in_line);
63 continue;63 continue;
64 };64 };
...@@ -89,7 +89,7 @@ pub fn main(init: std.process.Init) !void {...@@ -89,7 +89,7 @@ pub fn main(init: std.process.Init) !void {
89 // ...with that first '_' being replaced by its basename.89 // ...with that first '_' being replaced by its basename.
9090
91 const src_path = in_line[0..src_pos_start];91 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;
93 const symbol_start = addr_end + " in ".len;93 const symbol_start = addr_end + " in ".len;
94 try w.writeAll(in_line[basename_start..src_pos_end]);94 try w.writeAll(in_line[basename_start..src_pos_end]);
95 try w.writeAll(": [address] in ");95 try w.writeAll(": [address] in ");
test/stack_traces.zig+24-5
...@@ -1,7 +1,10 @@...@@ -1,7 +1,10 @@
1const std = @import("std");1const 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 {
4 cases.addCase(.{5 cases.addCase(.{
6 .params = params,
7 .target = target,
5 .name = "simple panic",8 .name = "simple panic",
6 .source =9 .source =
7 \\pub fn main() void {10 \\pub fn main() void {
...@@ -33,6 +36,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target....@@ -33,6 +36,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
33 });36 });
3437
35 cases.addCase(.{38 cases.addCase(.{
39 .params = params,
40 .target = target,
36 .name = "simple panic with no unwind strategy",41 .name = "simple panic with no unwind strategy",
37 .source =42 .source =
38 \\pub fn main() void {43 \\pub fn main() void {
...@@ -50,6 +55,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target....@@ -50,6 +55,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
50 });55 });
5156
52 cases.addCase(.{57 cases.addCase(.{
58 .params = params,
59 .target = target,
53 .name = "dump current trace",60 .name = "dump current trace",
54 .source =61 .source =
55 \\pub fn main() void {62 \\pub fn main() void {
...@@ -89,6 +96,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target....@@ -89,6 +96,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
89 });96 });
9097
91 cases.addCase(.{98 cases.addCase(.{
99 .params = params,
100 .target = target,
92 .name = "dump current trace with no unwind strategy",101 .name = "dump current trace with no unwind strategy",
93 .source =102 .source =
94 \\pub fn main() void {103 \\pub fn main() void {
...@@ -114,6 +123,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target....@@ -114,6 +123,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
114 });123 });
115124
116 cases.addCase(.{125 cases.addCase(.{
126 .params = params,
127 .target = target,
117 .name = "dump captured trace",128 .name = "dump captured trace",
118 .source =129 .source =
119 \\pub fn main() void {130 \\pub fn main() void {
...@@ -155,6 +166,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target....@@ -155,6 +166,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
155 });166 });
156167
157 cases.addCase(.{168 cases.addCase(.{
169 .params = params,
170 .target = target,
158 .name = "dump captured trace with no unwind strategy",171 .name = "dump captured trace with no unwind strategy",
159 .source =172 .source =
160 \\pub fn main() void {173 \\pub fn main() void {
...@@ -180,6 +193,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target....@@ -180,6 +193,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
180 });193 });
181194
182 cases.addCase(.{195 cases.addCase(.{
196 .params = params,
197 .target = target,
183 .name = "dump captured trace on thread",198 .name = "dump captured trace on thread",
184 .source =199 .source =
185 \\pub fn main() !void {200 \\pub fn main() !void {
...@@ -225,6 +240,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target....@@ -225,6 +240,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
225 });240 });
226241
227 cases.addCase(.{242 cases.addCase(.{
243 .params = params,
244 .target = target,
228 .name = "simple inline panic",245 .name = "simple inline panic",
229 // The main function has two inline calls to ensure246 // The main function has two inline calls to ensure
230 // that inlinees in PDBs are properly deduplicated.247 // that inlinees in PDBs are properly deduplicated.
...@@ -240,7 +257,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target....@@ -240,7 +257,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
240 ,257 ,
241 .unwind = .any,258 .unwind = .any,
242 .expect_panic = true,259 .expect_panic = true,
243 .expect = switch (os) {260 .expect = switch (target.os.tag) {
244 // LLVM doesn't emit column info in the binary annotations for inlinee callees in PDBs,261 // LLVM doesn't emit column info in the binary annotations for inlinee callees in PDBs,
245 // so the first location has only a row.262 // so the first location has only a row.
246 .windows =>263 .windows =>
...@@ -262,7 +279,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target....@@ -262,7 +279,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
262 \\ ^279 \\ ^
263 ,280 ,
264 },281 },
265 .expect_strip = switch (os) {282 .expect_strip = switch (target.os.tag) {
266 .windows =>283 .windows =>
267 \\panic: oh no284 \\panic: oh no
268 \\???:?:?: [address] in source.foo285 \\???:?:?: [address] in source.foo
...@@ -279,6 +296,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target....@@ -279,6 +296,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
279296
280 // Make sure all inline calls are resolved and in the right order!297 // Make sure all inline calls are resolved and in the right order!
281 cases.addCase(.{298 cases.addCase(.{
299 .params = params,
300 .target = target,
282 .name = "nested inline panic",301 .name = "nested inline panic",
283 .source =302 .source =
284 \\pub fn main() void {303 \\pub fn main() void {
...@@ -298,7 +317,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target....@@ -298,7 +317,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
298 .unwind = .any,317 .unwind = .any,
299 .expect_panic = true,318 .expect_panic = true,
300 // This switch serves a similar purpose as in "inline panic".319 // This switch serves a similar purpose as in "inline panic".
301 .expect = switch (os) {320 .expect = switch (target.os.tag) {
302 .windows =>321 .windows =>
303 \\panic: oh no322 \\panic: oh no
304 \\source.zig:11: [address] in baz323 \\source.zig:11: [address] in baz
...@@ -322,7 +341,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target....@@ -322,7 +341,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
322 \\ ^341 \\ ^
323 ,342 ,
324 },343 },
325 .expect_strip = switch (os) {344 .expect_strip = switch (target.os.tag) {
326 .windows =>345 .windows =>
327 \\panic: oh no346 \\panic: oh no
328 \\???:?:?: [address] in baz347 \\???:?:?: [address] in baz
test/standalone/build.zig+1-1
...@@ -31,6 +31,7 @@ pub fn build(b: *std.Build) void {...@@ -31,6 +31,7 @@ pub fn build(b: *std.Build) void {
31 const tools_target = b.resolveTargetQuery(.{});31 const tools_target = b.resolveTargetQuery(.{});
32 for ([_][]const u8{32 for ([_][]const u8{
33 // Alphabetically sorted. No need to build `tools/spirv/grammar.zig`.33 // Alphabetically sorted. No need to build `tools/spirv/grammar.zig`.
34 "../../tools/bsp.zig",
34 "../../tools/check_mingw.zig",35 "../../tools/check_mingw.zig",
35 "../../tools/dump-cov.zig",36 "../../tools/dump-cov.zig",
36 "../../tools/fetch_them_macos_headers.zig",37 "../../tools/fetch_them_macos_headers.zig",
...@@ -39,7 +40,6 @@ pub fn build(b: *std.Build) void {...@@ -39,7 +40,6 @@ pub fn build(b: *std.Build) void {
39 "../../tools/gen_parser_oracle.zig",40 "../../tools/gen_parser_oracle.zig",
40 "../../tools/gen_spirv_spec.zig",41 "../../tools/gen_spirv_spec.zig",
41 "../../tools/gen_stubs.zig",42 "../../tools/gen_stubs.zig",
42 "../../tools/generate_c_size_and_align_checks.zig",
43 "../../tools/generate_JSONTestSuite.zig",43 "../../tools/generate_JSONTestSuite.zig",
44 "../../tools/generate_linux_syscalls.zig",44 "../../tools/generate_linux_syscalls.zig",
45 "../../tools/process_headers.zig",45 "../../tools/process_headers.zig",
test/standalone/build.zig.zon-3
...@@ -187,9 +187,6 @@...@@ -187,9 +187,6 @@
187 .posix = .{187 .posix = .{
188 .path = "posix",188 .path = "posix",
189 },189 },
190 .debug_io_color = .{
191 .path = "debug_io_color",
192 },
193 .elf2 = .{190 .elf2 = .{
194 .path = "elf2",191 .path = "elf2",
195 },192 },
test/standalone/compiler_rt_panic/main.c+2-2
...@@ -1,11 +1,11 @@...@@ -1,11 +1,11 @@
1#include <stddef.h> 1#include <stddef.h>
2 2
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);
4 4
5char foo[128]; 5char foo[128];
6 6
7int main() { 7int main() {
8 __memset(&foo[0], 0xff, 128, 128); 8 __memset_chk(&foo[0], 0xff, 128, 128);
9 return foo[64]; 9 return foo[64];
10} 10}
11 11
test/standalone/config_header/build.zig+21
...@@ -51,6 +51,27 @@ pub fn build(b: *std.Build) void {...@@ -51,6 +51,27 @@ pub fn build(b: *std.Build) void {
51 });51 });
52 test_step.dependOn(&check_config_header_autoconf_at.step);52 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
54 const config_header_blank = b.addConfigHeader(75 const config_header_blank = b.addConfigHeader(
55 .{76 .{
56 .style = .blank,77 .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 {...@@ -11,11 +11,11 @@ pub fn build(b: *std.Build) !void {
11 const none_specified_mod = none_specified.module("dummy");11 const none_specified_mod = none_specified.module("dummy");
12 if (!none_specified_mod.resolved_target.?.query.eql(b.graph.host.query)) return error.TestFailed;12 if (!none_specified_mod.resolved_target.?.query.eql(b.graph.host.query)) return error.TestFailed;
13 const expected_optimize: std.builtin.OptimizeMode = switch (b.graph.release_mode) {13 const expected_optimize: std.builtin.OptimizeMode = switch (b.graph.release_mode) {
14 .off => .Debug,14 .off => .debug,
15 .any => unreachable,15 .any => unreachable,
16 .fast => .ReleaseFast,16 .fast => .fast,
17 .safe => .ReleaseSafe,17 .safe => .safe,
18 .small => .ReleaseSmall,18 .small => .small,
19 };19 };
20 if (none_specified_mod.optimize.? != expected_optimize) return error.TestFailed;20 if (none_specified_mod.optimize.? != expected_optimize) return error.TestFailed;
2121
...@@ -44,7 +44,7 @@ pub fn build(b: *std.Build) !void {...@@ -44,7 +44,7 @@ pub fn build(b: *std.Build) !void {
4444
45 const all_specified = b.dependency("other", .{45 const all_specified = b.dependency("other", .{
46 .target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu }),46 .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),
48 .bool = @as(bool, true),48 .bool = @as(bool, true),
49 .int = @as(i64, 123),49 .int = @as(i64, 123),
50 .float = @as(f64, 0.5),50 .float = @as(f64, 0.5),
...@@ -66,11 +66,11 @@ pub fn build(b: *std.Build) !void {...@@ -66,11 +66,11 @@ pub fn build(b: *std.Build) !void {
66 if (all_specified_mod.resolved_target.?.result.cpu.arch != .x86_64) return error.TestFailed;66 if (all_specified_mod.resolved_target.?.result.cpu.arch != .x86_64) return error.TestFailed;
67 if (all_specified_mod.resolved_target.?.result.os.tag != .windows) return error.TestFailed;67 if (all_specified_mod.resolved_target.?.result.os.tag != .windows) return error.TestFailed;
68 if (all_specified_mod.resolved_target.?.result.abi != .gnu) return error.TestFailed;68 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
71 const all_specified_optional = b.dependency("other", .{71 const all_specified_optional = b.dependency("other", .{
72 .target = @as(?std.Build.ResolvedTarget, b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu })),72 .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),
74 .bool = @as(?bool, true),74 .bool = @as(?bool, true),
75 .int = @as(?i64, 123),75 .int = @as(?i64, 123),
76 .float = @as(?f64, 0.5),76 .float = @as(?f64, 0.5),
...@@ -92,7 +92,7 @@ pub fn build(b: *std.Build) !void {...@@ -92,7 +92,7 @@ pub fn build(b: *std.Build) !void {
9292
93 const all_specified_literal = b.dependency("other", .{93 const all_specified_literal = b.dependency("other", .{
94 .target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu }),94 .target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu }),
95 .optimize = .ReleaseSafe,95 .optimize = .safe,
96 .bool = true,96 .bool = true,
97 .int = 123,97 .int = 123,
98 .float = 0.5,98 .float = 0.5,
...@@ -130,7 +130,7 @@ pub fn build(b: *std.Build) !void {...@@ -130,7 +130,7 @@ pub fn build(b: *std.Build) !void {
130 // to the same cached dependency instance.130 // to the same cached dependency instance.
131 const all_specified_alt = b.dependency("other", .{131 const all_specified_alt = b.dependency("other", .{
132 .target = @as(std.Target.Query, .{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu }),132 .target = @as(std.Target.Query, .{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu }),
133 .optimize = "ReleaseSafe",133 .optimize = "safe",
134 .bool = .true,134 .bool = .true,
135 .int = "123",135 .int = "123",
136 .float = @as(f16, 0.5),136 .float = @as(f16, 0.5),
test/standalone/glibc_compat/build.zig+2
...@@ -103,6 +103,8 @@ pub fn build(b: *std.Build) void {...@@ -103,6 +103,8 @@ pub fn build(b: *std.Build) void {
103 .{ .arch_os_abi = t },103 .{ .arch_os_abi = t },
104 ) catch unreachable);104 ) catch unreachable);
105105
106 if (target.result.cpu.arch.isLoongArch()) continue; // https://github.com/Vexu/arocc/issues/1096
107
106 const glibc_ver = target.result.os.version_range.linux.glibc;108 const glibc_ver = target.result.os.version_range.linux.glibc;
107109
108 // only build test if glibc version supports the architecture110 // 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 {...@@ -13,26 +13,26 @@ pub fn build(b: *std.Build) void {
13 var optimize_modes_buf: [4]std.builtin.OptimizeMode = undefined;13 var optimize_modes_buf: [4]std.builtin.OptimizeMode = undefined;
14 var optimize_modes_len: usize = 0;14 var optimize_modes_len: usize = 0;
15 if (!skip_debug) {15 if (!skip_debug) {
16 optimize_modes_buf[optimize_modes_len] = .Debug;16 optimize_modes_buf[optimize_modes_len] = .debug;
17 optimize_modes_len += 1;17 optimize_modes_len += 1;
18 }18 }
19 if (!skip_release_safe) {19 if (!skip_release_safe) {
20 optimize_modes_buf[optimize_modes_len] = .ReleaseSafe;20 optimize_modes_buf[optimize_modes_len] = .safe;
21 optimize_modes_len += 1;21 optimize_modes_len += 1;
22 }22 }
23 if (!skip_release_fast) {23 if (!skip_release_fast) {
24 optimize_modes_buf[optimize_modes_len] = .ReleaseFast;24 optimize_modes_buf[optimize_modes_len] = .fast;
25 optimize_modes_len += 1;25 optimize_modes_len += 1;
26 }26 }
27 if (!skip_release_small) {27 if (!skip_release_small) {
28 optimize_modes_buf[optimize_modes_len] = .ReleaseSmall;28 optimize_modes_buf[optimize_modes_len] = .small;
29 optimize_modes_len += 1;29 optimize_modes_len += 1;
30 }30 }
31 const optimize_modes = optimize_modes_buf[0..optimize_modes_len];31 const optimize_modes = optimize_modes_buf[0..optimize_modes_len];
3232
33 for (cases) |case| {33 for (cases) |case| {
34 for (optimize_modes) |optimize| {34 for (optimize_modes) |optimize| {
35 if (!case.all_modes and optimize != .Debug) continue;35 if (!case.all_modes and optimize != .debug) continue;
36 if (case.os_filter) |os_tag| {36 if (case.os_filter) |os_tag| {
37 if (os_tag != builtin.os.tag) continue;37 if (os_tag != builtin.os.tag) continue;
38 }38 }
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...@@ -147,8 +147,7 @@ fn spawnVerify(verify_path: [:0]const u16, cmd_line: [:0]const u16) !windows.DWO
147 break :spawn proc_info.hProcess;147 break :spawn proc_info.hProcess;
148 };148 };
149 defer windows.CloseHandle(child_proc);149 defer windows.CloseHandle(child_proc);
150 const infinite_timeout: windows.LARGE_INTEGER = std.math.minInt(windows.LARGE_INTEGER);150 switch (windows.ntdll.NtWaitForSingleObject(child_proc, .FALSE, null)) {
151 switch (windows.ntdll.NtWaitForSingleObject(child_proc, .FALSE, &infinite_timeout)) {
152 windows.NTSTATUS.WAIT_0 => {},151 windows.NTSTATUS.WAIT_0 => {},
153 .TIMEOUT => return error.WaitTimeOut,152 .TIMEOUT => return error.WaitTimeOut,
154 else => |status| return windows.unexpectedStatus(status),153 else => |status| return windows.unexpectedStatus(status),
test/tests.zig+129-177
...@@ -6,8 +6,6 @@ const OptimizeMode = std.builtin.OptimizeMode;...@@ -6,8 +6,6 @@ const OptimizeMode = std.builtin.OptimizeMode;
6const Step = std.Build.Step;6const Step = std.Build.Step;
77
8// Cases8// Cases
9const error_traces = @import("error_traces.zig");
10const stack_traces = @import("stack_traces.zig");
11const llvm_ir = @import("llvm_ir.zig");9const llvm_ir = @import("llvm_ir.zig");
12const libc = @import("libc.zig");10const libc = @import("libc.zig");
13const link = @import("link.zig");11const link = @import("link.zig");
...@@ -23,7 +21,7 @@ pub const LinkContext = @import("src/Link.zig");...@@ -23,7 +21,7 @@ pub const LinkContext = @import("src/Link.zig");
23const ModuleTestTarget = struct {21const ModuleTestTarget = struct {
24 linkage: ?std.builtin.LinkMode = null,22 linkage: ?std.builtin.LinkMode = null,
25 target: std.Target.Query = .{},23 target: std.Target.Query = .{},
26 optimize_mode: std.builtin.OptimizeMode = .Debug,24 optimize_mode: std.builtin.OptimizeMode = .debug,
27 link_libc: ?bool = null,25 link_libc: ?bool = null,
28 single_threaded: ?bool = null,26 single_threaded: ?bool = null,
29 use_llvm: ?bool = null,27 use_llvm: ?bool = null,
...@@ -57,38 +55,38 @@ const module_test_targets = blk: {...@@ -57,38 +55,38 @@ const module_test_targets = blk: {
57 },55 },
5856
59 .{57 .{
60 .optimize_mode = .ReleaseFast,58 .optimize_mode = .fast,
61 },59 },
62 .{60 .{
63 .link_libc = true,61 .link_libc = true,
64 .optimize_mode = .ReleaseFast,62 .optimize_mode = .fast,
65 },63 },
66 .{64 .{
67 .optimize_mode = .ReleaseFast,65 .optimize_mode = .fast,
68 .single_threaded = true,66 .single_threaded = true,
69 },67 },
7068
71 .{69 .{
72 .optimize_mode = .ReleaseSafe,70 .optimize_mode = .safe,
73 },71 },
74 .{72 .{
75 .link_libc = true,73 .link_libc = true,
76 .optimize_mode = .ReleaseSafe,74 .optimize_mode = .safe,
77 },75 },
78 .{76 .{
79 .optimize_mode = .ReleaseSafe,77 .optimize_mode = .safe,
80 .single_threaded = true,78 .single_threaded = true,
81 },79 },
8280
83 .{81 .{
84 .optimize_mode = .ReleaseSmall,82 .optimize_mode = .small,
85 },83 },
86 .{84 .{
87 .link_libc = true,85 .link_libc = true,
88 .optimize_mode = .ReleaseSmall,86 .optimize_mode = .small,
89 },87 },
90 .{88 .{
91 .optimize_mode = .ReleaseSmall,89 .optimize_mode = .small,
92 .single_threaded = true,90 .single_threaded = true,
93 },91 },
9492
...@@ -200,7 +198,7 @@ const module_test_targets = blk: {...@@ -200,7 +198,7 @@ const module_test_targets = blk: {
200 // },198 // },
201 // .use_llvm = false,199 // .use_llvm = false,
202 // .use_lld = false,200 // .use_lld = false,
203 // .optimize_mode = .ReleaseFast,201 // .optimize_mode = .fast,
204 // .strip = true,202 // .strip = true,
205 // .skip_modules = &.{"std"}, // TODO get these passing203 // .skip_modules = &.{"std"}, // TODO get these passing
206 //},204 //},
...@@ -213,7 +211,7 @@ const module_test_targets = blk: {...@@ -213,7 +211,7 @@ const module_test_targets = blk: {
213 // },211 // },
214 // .use_llvm = false,212 // .use_llvm = false,
215 // .use_lld = false,213 // .use_lld = false,
216 // .optimize_mode = .ReleaseFast,214 // .optimize_mode = .fast,
217 // .strip = true,215 // .strip = true,
218 // .skip_modules = &.{"std"}, // TODO get these passing216 // .skip_modules = &.{"std"}, // TODO get these passing
219 //},217 //},
...@@ -274,6 +272,15 @@ const module_test_targets = blk: {...@@ -274,6 +272,15 @@ const module_test_targets = blk: {
274 },272 },
275 .link_libc = true,273 .link_libc = true,
276 },274 },
275 .{
276 .target = .{
277 .cpu_arch = .arm,
278 .os_tag = .linux,
279 .abi = .musleabi,
280 .ofmt = .c,
281 },
282 .link_libc = true,
283 },
277 .{284 .{
278 .target = .{285 .target = .{
279 .cpu_arch = .arm,286 .cpu_arch = .arm,
...@@ -292,6 +299,15 @@ const module_test_targets = blk: {...@@ -292,6 +299,15 @@ const module_test_targets = blk: {
292 },299 },
293 .link_libc = true,300 .link_libc = true,
294 },301 },
302 .{
303 .target = .{
304 .cpu_arch = .arm,
305 .os_tag = .linux,
306 .abi = .musleabihf,
307 .ofmt = .c,
308 },
309 .link_libc = true,
310 },
295 .{311 .{
296 .target = .{312 .target = .{
297 .cpu_arch = .arm,313 .cpu_arch = .arm,
...@@ -341,6 +357,15 @@ const module_test_targets = blk: {...@@ -341,6 +357,15 @@ const module_test_targets = blk: {
341 },357 },
342 .link_libc = true,358 .link_libc = true,
343 },359 },
360 .{
361 .target = .{
362 .cpu_arch = .armeb,
363 .os_tag = .linux,
364 .abi = .musleabi,
365 .ofmt = .c,
366 },
367 .link_libc = true,
368 },
344 // Crashes in weird ways when applying relocations.369 // Crashes in weird ways when applying relocations.
345 // .{370 // .{
346 // .target = .{371 // .target = .{
...@@ -360,6 +385,15 @@ const module_test_targets = blk: {...@@ -360,6 +385,15 @@ const module_test_targets = blk: {
360 },385 },
361 .link_libc = true,386 .link_libc = true,
362 },387 },
388 .{
389 .target = .{
390 .cpu_arch = .armeb,
391 .os_tag = .linux,
392 .abi = .musleabihf,
393 .ofmt = .c,
394 },
395 .link_libc = true,
396 },
363 // Crashes in weird ways when applying relocations.397 // Crashes in weird ways when applying relocations.
364 // .{398 // .{
365 // .target = .{399 // .target = .{
...@@ -419,6 +453,23 @@ const module_test_targets = blk: {...@@ -419,6 +453,23 @@ const module_test_targets = blk: {
419 .abi = .none,453 .abi = .none,
420 },454 },
421 },455 },
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
423 .{474 .{
424 .target = .{475 .target = .{
...@@ -1107,6 +1158,15 @@ const module_test_targets = blk: {...@@ -1107,6 +1158,15 @@ const module_test_targets = blk: {
1107 },1158 },
1108 .link_libc = true,1159 .link_libc = true,
1109 },1160 },
1161 .{
1162 .target = .{
1163 .cpu_arch = .x86,
1164 .os_tag = .linux,
1165 .abi = .musl,
1166 .ofmt = .c,
1167 },
1168 .link_libc = true,
1169 },
1110 .{1170 .{
1111 .target = .{1171 .target = .{
1112 .cpu_arch = .x86,1172 .cpu_arch = .x86,
...@@ -1257,7 +1317,7 @@ const module_test_targets = blk: {...@@ -1257,7 +1317,7 @@ const module_test_targets = blk: {
1257 // },1317 // },
1258 // .use_llvm = false,1318 // .use_llvm = false,
1259 // .use_lld = false,1319 // .use_lld = false,
1260 // .optimize_mode = .ReleaseFast,1320 // .optimize_mode = .fast,
1261 // .strip = true,1321 // .strip = true,
1262 //},1322 //},
12631323
...@@ -1523,7 +1583,6 @@ const module_test_targets = blk: {...@@ -1523,7 +1583,6 @@ const module_test_targets = blk: {
1523 .os_tag = .wasi,1583 .os_tag = .wasi,
1524 .abi = .none,1584 .abi = .none,
1525 },1585 },
1526 .skip_modules = &.{"compiler-rt"},
1527 .use_llvm = false,1586 .use_llvm = false,
1528 .use_lld = false,1587 .use_lld = false,
1529 },1588 },
...@@ -1645,6 +1704,15 @@ const module_test_targets = blk: {...@@ -1645,6 +1704,15 @@ const module_test_targets = blk: {
1645 },1704 },
1646 .link_libc = true,1705 .link_libc = true,
1647 },1706 },
1707 .{
1708 .target = .{
1709 .cpu_arch = .x86,
1710 .os_tag = .windows,
1711 .abi = .gnu,
1712 .ofmt = .c,
1713 },
1714 .link_libc = true,
1715 },
16481716
1649 .{1717 .{
1650 .target = .{1718 .target = .{
...@@ -1961,7 +2029,6 @@ const c_abi_targets = blk: {...@@ -1961,7 +2029,6 @@ const c_abi_targets = blk: {
1961 .abi = .musl,2029 .abi = .musl,
1962 },2030 },
1963 .use_llvm = false,2031 .use_llvm = false,
1964 .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
1965 },2032 },
1966 .{2033 .{
1967 .target = .{2034 .target = .{
...@@ -1972,7 +2039,6 @@ const c_abi_targets = blk: {...@@ -1972,7 +2039,6 @@ const c_abi_targets = blk: {
1972 },2039 },
1973 .use_llvm = false,2040 .use_llvm = false,
1974 .strip = true,2041 .strip = true,
1975 .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
1976 },2042 },
1977 .{2043 .{
1978 .target = .{2044 .target = .{
...@@ -1983,7 +2049,6 @@ const c_abi_targets = blk: {...@@ -1983,7 +2049,6 @@ const c_abi_targets = blk: {
1983 },2049 },
1984 .use_llvm = false,2050 .use_llvm = false,
1985 .pic = true,2051 .pic = true,
1986 .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
1987 },2052 },
1988 .{2053 .{
1989 .target = .{2054 .target = .{
...@@ -2010,6 +2075,15 @@ const c_abi_targets = blk: {...@@ -2010,6 +2075,15 @@ const c_abi_targets = blk: {
2010 .abi = .musl,2075 .abi = .musl,
2011 },2076 },
2012 },2077 },
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
2014 // Windows Targets2088 // Windows Targets
20152089
...@@ -2028,7 +2102,6 @@ const c_abi_targets = blk: {...@@ -2028,7 +2102,6 @@ const c_abi_targets = blk: {
2028 .abi = .gnu,2102 .abi = .gnu,
2029 },2103 },
2030 .use_llvm = false,2104 .use_llvm = false,
2031 .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
2032 },2105 },
2033 .{2106 .{
2034 .target = .{2107 .target = .{
...@@ -2038,7 +2111,6 @@ const c_abi_targets = blk: {...@@ -2038,7 +2111,6 @@ const c_abi_targets = blk: {
2038 .abi = .gnu,2111 .abi = .gnu,
2039 },2112 },
2040 .use_llvm = false,2113 .use_llvm = false,
2041 .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
2042 },2114 },
2043 .{2115 .{
2044 .target = .{2116 .target = .{
...@@ -2048,7 +2120,6 @@ const c_abi_targets = blk: {...@@ -2048,7 +2120,6 @@ const c_abi_targets = blk: {
2048 .abi = .gnu,2120 .abi = .gnu,
2049 },2121 },
2050 .use_llvm = false,2122 .use_llvm = false,
2051 .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
2052 },2123 },
2053 .{2124 .{
2054 .target = .{2125 .target = .{
...@@ -2063,7 +2134,7 @@ const c_abi_targets = blk: {...@@ -2063,7 +2134,7 @@ const c_abi_targets = blk: {
20632134
2064const LinkTarget = struct {2135const LinkTarget = struct {
2065 target: std.Target.Query = .{},2136 target: std.Target.Query = .{},
2066 optimize_mode: std.builtin.OptimizeMode = .Debug,2137 optimize_mode: std.builtin.OptimizeMode = .debug,
2067 link_libc: bool = false,2138 link_libc: bool = false,
2068 use_llvm: bool = false,2139 use_llvm: bool = false,
2069 use_lld: bool = false,2140 use_lld: bool = false,
...@@ -2308,59 +2379,7 @@ pub fn isNative(actual_target: *const std.Build.ResolvedTarget, host: *const std...@@ -2308,59 +2379,7 @@ pub fn isNative(actual_target: *const std.Build.ResolvedTarget, host: *const std
2308 return true;2379 return true;
2309}2380}
23102381
2311/// For stack trace tests, we only test native by default, because external executors are pretty2382pub fn addStackTraceTests(b: *std.Build, test_filters: []const []const u8, skip_non_native: bool) *Step {
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 {
2364 const step = b.step("test-stack-traces", "Run the stack trace tests");2383 const step = b.step("test-stack-traces", "Run the stack trace tests");
23652384
2366 const convert_exe = b.addExecutable(.{2385 const convert_exe = b.addExecutable(.{
...@@ -2368,43 +2387,19 @@ pub fn addStackTraceTests(...@@ -2368,43 +2387,19 @@ pub fn addStackTraceTests(
2368 .root_module = b.createModule(.{2387 .root_module = b.createModule(.{
2369 .root_source_file = b.path("test/src/convert-stack-trace.zig"),2388 .root_source_file = b.path("test/src/convert-stack-trace.zig"),
2370 .target = b.graph.host,2389 .target = b.graph.host,
2371 .optimize = .Debug,2390 .optimize = .debug,
2372 }),2391 }),
2373 });2392 });
23742393
2375 const host_cases = b.allocator.create(StackTracesContext) catch @panic("OOM");2394 const stack_traces_context = b.allocator.create(StackTracesContext) catch @panic("OOM");
2376 host_cases.* = .{2395 stack_traces_context.* = .{
2377 .b = b,2396 .b = b,
2378 .step = step,2397 .step = step,
2379 .test_filters = test_filters,2398 .test_filters = test_filters,
2380 .targets = nativeAndCompatible32bit(b, skip_non_native),2399 .skip_non_native = skip_non_native,
2381 .convert_exe = convert_exe,2400 .convert_exe = convert_exe,
2382 };2401 };
2383 stack_traces.addCases(host_cases, b.graph.host.result.os.tag);2402 stack_traces_context.addCases();
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 }
24082403
2409 return step;2404 return step;
2410}2405}
...@@ -2422,56 +2417,24 @@ pub fn addErrorTraceTests(...@@ -2422,56 +2417,24 @@ pub fn addErrorTraceTests(
2422 .root_module = b.createModule(.{2417 .root_module = b.createModule(.{
2423 .root_source_file = b.path("test/src/convert-stack-trace.zig"),2418 .root_source_file = b.path("test/src/convert-stack-trace.zig"),
2424 .target = b.graph.host,2419 .target = b.graph.host,
2425 .optimize = .Debug,2420 .optimize = .debug,
2426 }),2421 }),
2427 });2422 });
24282423
2429 const host_cases = b.allocator.create(ErrorTracesContext) catch @panic("OOM");2424 const error_traces_context = b.allocator.create(ErrorTracesContext) catch @panic("OOM");
2430 host_cases.* = .{2425 error_traces_context.* = .{
2431 .b = b,2426 .b = b,
2432 .step = step,2427 .step = step,
2433 .test_filters = test_filters,2428 .test_filters = test_filters,
2434 .targets = nativeAndCompatible32bit(b, skip_non_native),2429 .skip_non_native = skip_non_native,
2435 .optimize_modes = optimize_modes,2430 .optimize_modes = optimize_modes,
2436 .convert_exe = convert_exe,2431 .convert_exe = convert_exe,
2437 };2432 };
2438 error_traces.addCases(host_cases, b.graph.host.result.os.tag);2433 error_traces_context.addCases();
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 }
24652434
2466 return step;2435 return step;
2467}2436}
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
2475pub fn addStandaloneTests(2438pub fn addStandaloneTests(
2476 b: *std.Build,2439 b: *std.Build,
2477 optimize_modes: []const OptimizeMode,2440 optimize_modes: []const OptimizeMode,
...@@ -2480,21 +2443,19 @@ pub fn addStandaloneTests(...@@ -2480,21 +2443,19 @@ pub fn addStandaloneTests(
2480 enable_symlinks_windows: bool,2443 enable_symlinks_windows: bool,
2481) *Step {2444) *Step {
2482 const step = b.step("test-standalone", "Run the standalone tests");2445 const step = b.step("test-standalone", "Run the standalone tests");
2483 if (compilerHasPackageManager(b)) {2446 const test_cases_dep_name = "standalone_test_cases";
2484 const test_cases_dep_name = "standalone_test_cases";2447 const test_cases_dep = b.dependency(test_cases_dep_name, .{
2485 const test_cases_dep = b.dependency(test_cases_dep_name, .{2448 .enable_ios_sdk = enable_ios_sdk,
2486 .enable_ios_sdk = enable_ios_sdk,2449 .enable_macos_sdk = enable_macos_sdk,
2487 .enable_macos_sdk = enable_macos_sdk,2450 .enable_symlinks_windows = enable_symlinks_windows,
2488 .enable_symlinks_windows = enable_symlinks_windows,2451 .simple_skip_debug = mem.findScalar(OptimizeMode, optimize_modes, .debug) == null,
2489 .simple_skip_debug = mem.indexOfScalar(OptimizeMode, optimize_modes, .Debug) == null,2452 .simple_skip_release_safe = mem.findScalar(OptimizeMode, optimize_modes, .safe) == null,
2490 .simple_skip_release_safe = mem.indexOfScalar(OptimizeMode, optimize_modes, .ReleaseSafe) == null,2453 .simple_skip_release_fast = mem.findScalar(OptimizeMode, optimize_modes, .fast) == null,
2491 .simple_skip_release_fast = mem.indexOfScalar(OptimizeMode, optimize_modes, .ReleaseFast) == null,2454 .simple_skip_release_small = mem.findScalar(OptimizeMode, optimize_modes, .small) == null,
2492 .simple_skip_release_small = mem.indexOfScalar(OptimizeMode, optimize_modes, .ReleaseSmall) == null,2455 });
2493 });2456 const test_cases_dep_step = test_cases_dep.builder.default_step;
2494 const test_cases_dep_step = test_cases_dep.builder.default_step;2457 test_cases_dep_step.name = b.graph.dupeString(test_cases_dep_name);
2495 test_cases_dep_step.name = b.dupe(test_cases_dep_name);2458 step.dependOn(test_cases_dep.builder.default_step);
2496 step.dependOn(test_cases_dep.builder.default_step);
2497 }
2498 return step;2459 return step;
2499}2460}
25002461
...@@ -2782,16 +2743,6 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {...@@ -2782,16 +2743,6 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
27822743
2783 const target = &resolved_target.result;2744 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
2795 if (std.mem.eql(u8, options.name, "libc")) {2746 if (std.mem.eql(u8, options.name, "libc")) {
2796 // The libc API tests obviously need to link libc. So for test2747 // The libc API tests obviously need to link libc. So for test
2797 // target entries where we wouldn't link libc by default, skip the2748 // 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 {...@@ -2816,7 +2767,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
28162767
2817 if (options.test_target_filters.len > 0) {2768 if (options.test_target_filters.len > 0) {
2818 for (options.test_target_filters) |filter| {2769 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;
2820 } else continue;2771 } else continue;
2821 }2772 }
28222773
...@@ -3057,7 +3008,7 @@ pub fn wouldUseLlvm(use_llvm: ?bool, query: std.Target.Query, optimize_mode: Opt...@@ -3057,7 +3008,7 @@ pub fn wouldUseLlvm(use_llvm: ?bool, query: std.Target.Query, optimize_mode: Opt
3057 if (use_llvm) |x| return x;3008 if (use_llvm) |x| return x;
3058 if (query.ofmt == .c) return false;3009 if (query.ofmt == .c) return false;
3059 switch (optimize_mode) {3010 switch (optimize_mode) {
3060 .Debug => {},3011 .debug => {},
3061 else => return true,3012 else => return true,
3062 }3013 }
3063 const cpu_arch = query.cpu_arch orelse builtin.cpu.arch;3014 const cpu_arch = query.cpu_arch orelse builtin.cpu.arch;
...@@ -3114,7 +3065,7 @@ pub fn addCAbiTests(b: *std.Build, options: CAbiTestOptions) *Step {...@@ -3114,7 +3065,7 @@ pub fn addCAbiTests(b: *std.Build, options: CAbiTestOptions) *Step {
31143065
3115 if (options.test_target_filters.len > 0) {3066 if (options.test_target_filters.len > 0) {
3116 for (options.test_target_filters) |filter| {3067 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;
3118 } else continue;3069 } else continue;
3119 }3070 }
31203071
...@@ -3203,7 +3154,7 @@ pub fn addLinkTests(b: *std.Build, options: LinkTestOptions) *Step {...@@ -3203,7 +3154,7 @@ pub fn addLinkTests(b: *std.Build, options: LinkTestOptions) *Step {
32033154
3204 if (options.test_target_filters.len > 0) {3155 if (options.test_target_filters.len > 0) {
3205 for (options.test_target_filters) |filter| {3156 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;
3207 } else continue;3158 } else continue;
3208 }3159 }
32093160
...@@ -3314,7 +3265,7 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step, test_filters: []cons...@@ -3314,7 +3265,7 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step, test_filters: []cons
3314 .root_module = b.createModule(.{3265 .root_module = b.createModule(.{
3315 .root_source_file = b.path("tools/incr-check.zig"),3266 .root_source_file = b.path("tools/incr-check.zig"),
3316 .target = b.graph.host,3267 .target = b.graph.host,
3317 .optimize = .Debug,3268 .optimize = .debug,
3318 }),3269 }),
3319 });3270 });
33203271
...@@ -3328,7 +3279,7 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step, test_filters: []cons...@@ -3328,7 +3279,7 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step, test_filters: []cons
3328 if (std.mem.endsWith(u8, entry.basename, ".swp")) continue;3279 if (std.mem.endsWith(u8, entry.basename, ".swp")) continue;
33293280
3330 for (test_filters) |test_filter| {3281 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;
3332 } else if (test_filters.len > 0) continue;3283 } else if (test_filters.len > 0) continue;
33333284
3334 switch (entry.kind) {3285 switch (entry.kind) {
...@@ -3354,10 +3305,11 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step, test_filters: []cons...@@ -3354,10 +3305,11 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step, test_filters: []cons
33543305
3355 run.addArg("--quiet"); // don't fill stderr telling us about skipped tests etc3306 run.addArg("--quiet"); // don't fill stderr telling us about skipped tests etc
33563307
3357 if (b.enable_qemu) run.addArg("-fqemu");3308 run.addThirdPartyEnabledArgDarling(.{ .enabled = "-fdarling" });
3358 if (b.enable_wine) run.addArg("-fwine");3309 run.addThirdPartyEnabledArgQemu(.{ .enabled = "-fqemu" });
3359 if (b.enable_wasmtime) run.addArg("-fwasmtime");3310 run.addThirdPartyEnabledArgRosetta(.{ .enabled = "-frosetta" });
3360 if (b.enable_darling) run.addArg("-fdarling");3311 run.addThirdPartyEnabledArgWasmtime(.{ .enabled = "-fwasmtime" });
3312 run.addThirdPartyEnabledArgWine(.{ .enabled = "-fwine" });
33613313
3362 run.addCheck(.{ .expect_term = .{ .exited = 0 } });3314 run.addCheck(.{ .expect_term = .{ .exited = 0 } });
3363 test_step.dependOn(&run.step);3315 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(...@@ -712,10 +712,10 @@ fn tokenizeAndPrintRaw(
712 next_tok_is_fn = false;712 next_tok_is_fn = false;
713713
714 const token = tokenizer.next();714 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| {
716 // render one comment716 // render one comment
717 const comment_start = index + comment_start_off;717 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");
719 const comment_end = if (comment_end_off) |o| comment_start + o else token.loc.start;719 const comment_end = if (comment_end_off) |o| comment_start + o else token.loc.start;
720720
721 try writeEscapedLines(out, src[index..comment_start]);721 try writeEscapedLines(out, src[index..comment_start]);
tools/doctest.zig+11-11
...@@ -383,7 +383,7 @@ fn printOutput(...@@ -383,7 +383,7 @@ fn printOutput(
383 fatal("example compile crashed", .{});383 fatal("example compile crashed", .{});
384 },384 },
385 }385 }
386 if (mem.indexOf(u8, result.stderr, error_match) == null) {386 if (mem.find(u8, result.stderr, error_match) == null) {
387 print("{s}\nExpected to find '{s}' in stderr\n", .{ result.stderr, error_match });387 print("{s}\nExpected to find '{s}' in stderr\n", .{ result.stderr, error_match });
388 fatal("example did not have expected compile error", .{});388 fatal("example did not have expected compile error", .{});
389 }389 }
...@@ -438,7 +438,7 @@ fn printOutput(...@@ -438,7 +438,7 @@ fn printOutput(
438 fatal("example compile crashed", .{});438 fatal("example compile crashed", .{});
439 },439 },
440 }440 }
441 if (mem.indexOf(u8, result.stderr, error_match) == null) {441 if (mem.find(u8, result.stderr, error_match) == null) {
442 print("{s}\nExpected to find '{s}' in stderr\n", .{ result.stderr, error_match });442 print("{s}\nExpected to find '{s}' in stderr\n", .{ result.stderr, error_match });
443 fatal("example did not have expected runtime safety error message", .{});443 fatal("example did not have expected runtime safety error message", .{});
444 }444 }
...@@ -513,7 +513,7 @@ fn printOutput(...@@ -513,7 +513,7 @@ fn printOutput(
513 fatal("example compile crashed", .{});513 fatal("example compile crashed", .{});
514 },514 },
515 }515 }
516 if (mem.indexOf(u8, result.stderr, error_match) == null) {516 if (mem.find(u8, result.stderr, error_match) == null) {
517 print("{s}\nExpected to find '{s}' in stderr\n", .{ result.stderr, error_match });517 print("{s}\nExpected to find '{s}' in stderr\n", .{ result.stderr, error_match });
518 fatal("example did not have expected compile error message", .{});518 fatal("example did not have expected compile error message", .{});
519 }519 }
...@@ -623,10 +623,10 @@ fn tokenizeAndPrint(arena: Allocator, out: *Writer, raw_src: []const u8) !void {...@@ -623,10 +623,10 @@ fn tokenizeAndPrint(arena: Allocator, out: *Writer, raw_src: []const u8) !void {
623 next_tok_is_fn = false;623 next_tok_is_fn = false;
624624
625 const token = tokenizer.next();625 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| {
627 // render one comment627 // render one comment
628 const comment_start = index + comment_start_off;628 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");
630 const comment_end = if (comment_end_off) |o| comment_start + o else token.loc.start;630 const comment_end = if (comment_end_off) |o| comment_start + o else token.loc.start;
631631
632 try writeEscapedLines(out, src[index..comment_start]);632 try writeEscapedLines(out, src[index..comment_start]);
...@@ -870,13 +870,13 @@ const Code = struct {...@@ -870,13 +870,13 @@ const Code = struct {
870};870};
871871
872fn stripManifest(source_bytes: []const u8) []const u8 {872fn stripManifest(source_bytes: []const u8) []const u8 {
873 const manifest_start = mem.lastIndexOf(u8, source_bytes, "\n\n// ") orelse873 const manifest_start = mem.findLast(u8, source_bytes, "\n\n// ") orelse
874 fatal("missing manifest comment", .{});874 fatal("missing manifest comment", .{});
875 return source_bytes[0 .. manifest_start + 1];875 return source_bytes[0 .. manifest_start + 1];
876}876}
877877
878fn parseManifest(arena: Allocator, source_bytes: []const u8) !Code {878fn parseManifest(arena: Allocator, source_bytes: []const u8) !Code {
879 const manifest_start = mem.lastIndexOf(u8, source_bytes, "\n\n// ") orelse879 const manifest_start = mem.findLast(u8, source_bytes, "\n\n// ") orelse
880 fatal("missing manifest comment", .{});880 fatal("missing manifest comment", .{});
881 var it = mem.tokenizeScalar(u8, source_bytes[manifest_start..], '\n');881 var it = mem.tokenizeScalar(u8, source_bytes[manifest_start..], '\n');
882 const first_line = skipPrefix(it.next().?);882 const first_line = skipPrefix(it.next().?);
...@@ -915,11 +915,11 @@ fn parseManifest(arena: Allocator, source_bytes: []const u8) !Code {...@@ -915,11 +915,11 @@ fn parseManifest(arena: Allocator, source_bytes: []const u8) !Code {
915 while (it.next()) |prefixed_line| {915 while (it.next()) |prefixed_line| {
916 const line = skipPrefix(prefixed_line);916 const line = skipPrefix(prefixed_line);
917 if (mem.startsWith(u8, line, "optimize=")) {917 if (mem.startsWith(u8, line, "optimize=")) {
918 mode = std.meta.stringToEnum(std.builtin.OptimizeMode, line["optimize=".len..]) orelse918 mode = std.builtin.Optimize.fromString(line["optimize=".len..]) orelse
919 fatal("bad optimization mode line: '{s}'", .{line});919 fatal("bad optimization mode line: {q}", .{line});
920 } else if (mem.startsWith(u8, line, "link_mode=")) {920 } else if (mem.startsWith(u8, line, "link_mode=")) {
921 link_mode = std.meta.stringToEnum(std.builtin.LinkMode, line["link_mode=".len..]) orelse921 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});
923 } else if (mem.startsWith(u8, line, "link_object=")) {923 } else if (mem.startsWith(u8, line, "link_object=")) {
924 try link_objects.append(arena, line["link_object=".len..]);924 try link_objects.append(arena, line["link_object=".len..]);
925 } else if (mem.startsWith(u8, line, "additional_option=")) {925 } else if (mem.startsWith(u8, line, "additional_option=")) {
...@@ -1104,7 +1104,7 @@ fn termColor(allocator: Allocator, input: []const u8) ![]u8 {...@@ -1104,7 +1104,7 @@ fn termColor(allocator: Allocator, input: []const u8) ![]u8 {
11041104
1105// Returns true if number is in slice.1105// Returns true if number is in slice.
1106fn in(slice: []const u8, number: u8) bool {1106fn in(slice: []const u8, number: u8) bool {
1107 return mem.indexOfScalar(u8, slice, number) != null;1107 return mem.findScalar(u8, slice, number) != null;
1108}1108}
11091109
1110fn run(1110fn run(
tools/fetch_them_macos_headers.zig+2-2
...@@ -187,8 +187,8 @@ fn fetchTarget(...@@ -187,8 +187,8 @@ fn fetchTarget(
187187
188 var it = mem.splitScalar(u8, headers_list_str, '\n');188 var it = mem.splitScalar(u8, headers_list_str, '\n');
189 while (it.next()) |line| {189 while (it.next()) |line| {
190 if (mem.lastIndexOf(u8, line, "clang") != null) continue;190 if (mem.findLast(u8, line, "clang") != null) continue;
191 if (mem.lastIndexOf(u8, line, prefix[0..])) |idx| {191 if (mem.findLast(u8, line, prefix[0..])) |idx| {
192 const out_rel_path = line[idx + prefix.len + 1 ..];192 const out_rel_path = line[idx + prefix.len + 1 ..];
193 const out_rel_path_stripped = mem.trim(u8, out_rel_path, " \\");193 const out_rel_path_stripped = mem.trim(u8, out_rel_path, " \\");
194 const dirname = Dir.path.dirname(out_rel_path_stripped) orelse ".";194 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 {...@@ -305,21 +305,23 @@ const Eval = struct {
305305
306 fn check(eval: *Eval, mr: *Io.File.MultiReader, update: Case.Update, prog_node: std.Progress.Node) !void {306 fn check(eval: *Eval, mr: *Io.File.MultiReader, update: Case.Update, prog_node: std.Progress.Node) !void {
307 const arena = eval.arena;307 const arena = eval.arena;
308 const stdout = mr.fileReader(0);308 const stdout = mr.reader(0);
309 const stderr = &mr.fileReader(1).interface;309 const stderr = mr.reader(1);
310 const Header = std.zig.Server.Message.Header;310
311 var client: std.zig.Client = .{
312 .in = stdout,
313 .out = undefined,
314 };
311315
312 while (true) {316 while (true) {
313 const header = stdout.interface.takeStruct(Header, .little) catch |err| switch (err) {317 const header = client.receiveMessageWithMultiReader(mr, .none) catch |err| switch (err) {
314 error.EndOfStream => break,318 error.Timeout => unreachable,
315 error.ReadFailed => return stdout.err.?,
316 };
317 const body = stdout.interface.take(header.bytes_len) catch |err| switch (err) {
318 // If this panic triggers it might be helpful to rework this319 // If this panic triggers it might be helpful to rework this
319 // code to print the stderr from the abnormally terminated child.320 // code to print the stderr from the abnormally terminated child.
320 error.EndOfStream => @panic("unexpected mid-message end of stream"),321 error.EndOfStream => @panic("unexpected mid-message end of stream"),
321 error.ReadFailed => return stdout.err.?,322 else => |e| return e,
322 };323 };
324 const body = client.in.take(header.bytes_len) catch unreachable;
323325
324 switch (header.tag) {326 switch (header.tag) {
325 .error_bundle => {327 .error_bundle => {
...@@ -448,7 +450,7 @@ const Eval = struct {...@@ -448,7 +450,7 @@ const Eval = struct {
448 const raw_filename = eb.nullTerminatedString(src.src_path);450 const raw_filename = eb.nullTerminatedString(src.src_path);
449 // We need to replace backslashes for consistency between platforms.451 // We need to replace backslashes for consistency between platforms.
450 const filename = name: {452 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;
452 const copied = try eval.arena.dupe(u8, raw_filename);454 const copied = try eval.arena.dupe(u8, raw_filename);
453 std.mem.replaceScalar(u8, copied, '\\', '/');455 std.mem.replaceScalar(u8, copied, '\\', '/');
454 break :name copied;456 break :name copied;
...@@ -605,12 +607,13 @@ const Eval = struct {...@@ -605,12 +607,13 @@ const Eval = struct {
605607
606 fn requestUpdate(eval: *Eval) !void {608 fn requestUpdate(eval: *Eval) !void {
607 const io = eval.io;609 const io = eval.io;
608 const header: std.zig.Client.Message.Header = .{610
609 .tag = .update,611 var w = eval.child.stdin.?.writerStreaming(io, &.{});
610 .bytes_len = 0,612 var client: std.zig.Client = .{
613 .in = undefined,
614 .out = &w.interface,
611 };615 };
612 var w = eval.child.stdin.?.writer(io, &.{});616 client.serveBodylessMessage(.update) catch |err| switch (err) {
613 w.interface.writeStruct(header, .little) catch |err| switch (err) {
614 error.WriteFailed => return w.err.?,617 error.WriteFailed => return w.err.?,
615 };618 };
616 }619 }
...@@ -618,22 +621,23 @@ const Eval = struct {...@@ -618,22 +621,23 @@ const Eval = struct {
618 fn end(eval: *Eval, mr: *Io.File.MultiReader) !void {621 fn end(eval: *Eval, mr: *Io.File.MultiReader) !void {
619 requestExit(eval.child, eval);622 requestExit(eval.child, eval);
620623
621 const stdout = mr.fileReader(0);624 var client: std.zig.Client = .{
622 const Header = std.zig.Server.Message.Header;625 .in = mr.reader(0),
626 .out = undefined,
627 };
623628
624 while (true) {629 while (true) {
625 const header = stdout.interface.takeStruct(Header, .little) catch |err| switch (err) {630 const header = client.receiveMessageWithMultiReader(mr, .none) catch |err| switch (err) {
626 error.EndOfStream => break,631 error.Timeout => unreachable,
627 error.ReadFailed => return stdout.err.?,632 error.EndOfStream => |e| {
628 };633 if (client.in.bufferedLen() == 0) break;
629 stdout.interface.discardAll(header.bytes_len) catch |err| switch (err) {634 return e;
630 error.ReadFailed => return stdout.err.?,635 },
631 error.EndOfStream => |e| return e,636 else => |e| return e,
632 };637 };
638 try client.in.discardAll(header.bytes_len);
633 }639 }
634640
635 try mr.fillRemaining(.none);
636
637 const stderr = mr.reader(1).buffered();641 const stderr = mr.reader(1).buffered();
638 if (stderr.len > 0) eval.fatal("unexpected stderr:\n{s}", .{stderr});642 if (stderr.len > 0) eval.fatal("unexpected stderr:\n{s}", .{stderr});
639 }643 }
...@@ -773,7 +777,7 @@ const Case = struct {...@@ -773,7 +777,7 @@ const Case = struct {
773 .backend = backend,777 .backend = backend,
774 });778 });
775 } else if (std.mem.eql(u8, key, "module")) {779 } else if (std.mem.eql(u8, key, "module")) {
776 const split_idx = std.mem.indexOfScalar(u8, val, '=') orelse780 const split_idx = std.mem.findScalar(u8, val, '=') orelse
777 fatal("line {d}: module does not include file", .{line_n});781 fatal("line {d}: module does not include file", .{line_n});
778 const name = val[0..split_idx];782 const name = val[0..split_idx];
779 const file = val[split_idx + 1 ..];783 const file = val[split_idx + 1 ..];
...@@ -899,12 +903,12 @@ fn requestExit(child: *std.process.Child, eval: *Eval) void {...@@ -899,12 +903,12 @@ fn requestExit(child: *std.process.Child, eval: *Eval) void {
899 if (child.stdin == null) return;903 if (child.stdin == null) return;
900 const io = eval.io;904 const io = eval.io;
901905
902 const header: std.zig.Client.Message.Header = .{906 var w = eval.child.stdin.?.writerStreaming(io, &.{});
903 .tag = .exit,907 var client: std.zig.Client = .{
904 .bytes_len = 0,908 .in = undefined,
909 .out = &w.interface,
905 };910 };
906 var w = eval.child.stdin.?.writer(io, &.{});911 client.serveBodylessMessage(.exit) catch |err| switch (err) {
907 w.interface.writeStruct(header, .little) catch |err| switch (err) {
908 error.WriteFailed => switch (w.err.?) {912 error.WriteFailed => switch (w.err.?) {
909 error.BrokenPipe => {},913 error.BrokenPipe => {},
910 else => |e| eval.fatal("failed to send exit: {t}", .{e}),914 else => |e| eval.fatal("failed to send exit: {t}", .{e}),
...@@ -979,7 +983,7 @@ fn rand64(io: Io) u64 {...@@ -979,7 +983,7 @@ fn rand64(io: Io) u64 {
979fn parseTargetQueryAndBackend(input_str: []const u8, err_prefix: []const u8) struct { std.Target.Query, Backend } {983fn parseTargetQueryAndBackend(input_str: []const u8, err_prefix: []const u8) struct { std.Target.Query, Backend } {
980 const fatal = std.process.fatal;984 const fatal = std.process.fatal;
981985
982 const split_idx = std.mem.lastIndexOfScalar(u8, input_str, '-') orelse986 const split_idx = std.mem.findScalarLast(u8, input_str, '-') orelse
983 fatal("{s}target does not include backend", .{err_prefix});987 fatal("{s}target does not include backend", .{err_prefix});
984988
985 const query = input_str[0..split_idx];989 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...@@ -319,7 +319,7 @@ fn walk(arena: Allocator, io: Io, tokenizer: *Tokenizer, out_dir: Dir, w: anytyp
319 return parseError(tokenizer, code_kind_tok, "unrecognized code kind: {s}", .{code_kind_str});319 return parseError(tokenizer, code_kind_tok, "unrecognized code kind: {s}", .{code_kind_str});
320 }320 }
321321
322 var mode: std.builtin.OptimizeMode = .Debug;322 var mode: std.builtin.OptimizeMode = .debug;
323 var link_objects = std.array_list.Managed([]const u8).init(arena);323 var link_objects = std.array_list.Managed([]const u8).init(arena);
324 var target_str: ?[]const u8 = null;324 var target_str: ?[]const u8 = null;
325 var link_libc = false;325 var link_libc = false;
...@@ -403,7 +403,7 @@ fn walk(arena: Allocator, io: Io, tokenizer: *Tokenizer, out_dir: Dir, w: anytyp...@@ -403,7 +403,7 @@ fn walk(arena: Allocator, io: Io, tokenizer: *Tokenizer, out_dir: Dir, w: anytyp
403 },403 },
404 }404 }
405405
406 if (mode != .Debug)406 if (mode != .debug)
407 try code.print("// optimize={s}\n", .{@tagName(mode)});407 try code.print("// optimize={s}\n", .{@tagName(mode)});
408408
409 for (link_objects.items) |link_object| {409 for (link_objects.items) |link_object| {
tools/process_headers.zig+2
...@@ -36,6 +36,8 @@ const glibc_targets = [_]LibCTarget{...@@ -36,6 +36,8 @@ const glibc_targets = [_]LibCTarget{
36 .{ .arch = .aarch64_be, .abi = .gnu, .dest = "aarch64-linux-gnu" },36 .{ .arch = .aarch64_be, .abi = .gnu, .dest = "aarch64-linux-gnu" },
37 .{ .arch = .csky, .abi = .gnueabi, .dest = "csky-linux-gnu" },37 .{ .arch = .csky, .abi = .gnueabi, .dest = "csky-linux-gnu" },
38 .{ .arch = .csky, .abi = .gnueabihf, .dest = "csky-linux-gnu" },38 .{ .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" },
39 .{ .arch = .loongarch64, .abi = .gnu, .dest = "loongarch-linux-gnu" },41 .{ .arch = .loongarch64, .abi = .gnu, .dest = "loongarch-linux-gnu" },
40 .{ .arch = .loongarch64, .abi = .gnusf, .dest = "loongarch-linux-gnu" },42 .{ .arch = .loongarch64, .abi = .gnusf, .dest = "loongarch-linux-gnu" },
41 .{ .arch = .m68k, .abi = .gnu },43 .{ .arch = .m68k, .abi = .gnu },
tools/update_clang_options.zig+1-1
...@@ -599,7 +599,7 @@ const known_options = [_]KnownOpt{...@@ -599,7 +599,7 @@ const known_options = [_]KnownOpt{
599const blacklisted_options = [_][]const u8{};599const blacklisted_options = [_][]const u8{};
600600
601fn knownOption(name: []const u8) ?[]const u8 {601fn 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;
603 for (known_options) |item| {603 for (known_options) |item| {
604 if (std.mem.eql(u8, chopped_name, item.name)) {604 if (std.mem.eql(u8, chopped_name, item.name)) {
605 return item.ident;605 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)...@@ -99,7 +99,7 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8)
9999
100 var it = mem.splitSequence(u8, line, " ");100 var it = mem.splitSequence(u8, line, " ");
101 while (it.next()) |property| {101 while (it.next()) |property| {
102 const i = mem.indexOf(u8, property, "=").?;102 const i = mem.find(u8, property, "=").?;
103 const key = property[0..i];103 const key = property[0..i];
104 const value = property[i + 1 ..];104 const value = property[i + 1 ..];
105 if (mem.eql(u8, key, "width")) {105 if (mem.eql(u8, key, "width")) {
tools/update_glibc.zig+1
...@@ -36,6 +36,7 @@ const exempt_extensions = [_][]const u8{...@@ -36,6 +36,7 @@ const exempt_extensions = [_][]const u8{
36 // These are the start files we use when targeting glibc <= 2.33.36 // These are the start files we use when targeting glibc <= 2.33.
37 "-2.33.S",37 "-2.33.S",
38 "-2.33.c",38 "-2.33.c",
39 "-2.32.c",
39};40};
4041
41pub fn main(init: std.process.Init) !void {42pub fn main(init: std.process.Init) !void {